diff --git a/Apps/W1/EDocumentConnectors/Continia/app/app.json b/Apps/W1/EDocumentConnectors/Continia/app/app.json
new file mode 100644
index 0000000000..5fa45933bb
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/app.json
@@ -0,0 +1,46 @@
+{
+ "id": "31ef535a-1182-4354-98e8-e0e66a587055",
+ "name": "E-Document Connector - Continia",
+ "publisher": "Microsoft",
+ "brief": "E-Document Connector - Continia",
+ "description": "E-Document Connector - Continia",
+ "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",
+ "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"
+ }
+ ],
+ "internalsVisibleTo": [
+ {
+ "id": "769158cc-9498-42cf-b3a3-e5be4333f8b7",
+ "name": "E-Document Connector - Continia Tests",
+ "publisher": "Microsoft"
+ }
+ ],
+ "screenshots": [],
+ "platform": "26.0.0.0",
+ "idRanges": [
+ {
+ "from": 6380,
+ "to": 6399
+ }
+ ],
+ "resourceExposurePolicy": {
+ "allowDebugging": true,
+ "allowDownloadingSource": true,
+ "includeSourceInSymbolFile": true
+ },
+ "application": "26.0.0.0",
+ "target": "OnPrem",
+ "features": [
+ "TranslationFile"
+ ]
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/API Requests/ContiniaAPIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/app/src/API Requests/ContiniaAPIRequests.Codeunit.al
new file mode 100644
index 0000000000..566f5892bc
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/API Requests/ContiniaAPIRequests.Codeunit.al
@@ -0,0 +1,1083 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using Microsoft.eServices.EDocument;
+using System.Utilities;
+using System.Text;
+using Microsoft.eServices.EDocument.Integration.Send;
+using Microsoft.Foundation.Address;
+using Microsoft.Foundation.Company;
+using Microsoft.eServices.EDocument.Integration.Receive;
+
+codeunit 6393 "Continia Api Requests"
+{
+ Access = Internal;
+
+ Permissions = tabledata "Continia Network Profile" = rimd,
+ tabledata "Continia Network Identifier" = rimd,
+ tabledata "Continia Participation" = rimd,
+ tabledata "Continia Activated Net. Prof." = rimd,
+ tabledata "E-Document" = m;
+
+ #region Get Network Profiles from Continia Delivery Network Api
+ internal procedure GetNetworkProfiles(Network: Enum "Continia E-Delivery Network")
+ var
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ IsLastPage: Boolean;
+ HttpResponse: HttpResponseMessage;
+ CurrPage: Integer;
+ PageSize: Integer;
+ begin
+ CurrPage := 0;
+ PageSize := 100;
+ IsLastPage := false;
+ repeat
+ CurrPage += 1;
+ if ExecuteRequest('GET', ApiUrlMgt.NetworkProfilesUrl(Network, CurrPage, PageSize), HttpResponse) then
+ IsLastPage := HandleNetworkProfileResponse(HttpResponse, Network, PageSize);
+ until IsLastPage;
+ end;
+
+ local procedure HandleNetworkProfileResponse(var HttpResponse: HttpResponseMessage; NetworkName: Enum "Continia E-Delivery Network"; PageSize: Integer) IsLastPage: Boolean
+ var
+ NetworkProfile: Record "Continia Network Profile";
+ Insert: Boolean;
+ NetworkProfileId: Guid;
+ i: Integer;
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ TempXMLNode: XmlNode;
+ TempXMLNode2: XmlNode;
+ XMLNodeList: XmlNodeList;
+ begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody <> '' then begin
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ ResponseXmlDoc.SelectNodes('/network_profiles/network_profile', XMLNodeList);
+ for i := 1 to XMLNodeList.Count do begin
+ if XMLNodeList.Count < PageSize then
+ IsLastPage := true;
+ XMLNodeList.Get(i, TempXMLNode);
+
+ TempXMLNode.SelectSingleNode('network_profile_id', TempXMLNode2);
+
+ NetworkProfileId := StrSubstNo('{%1}', TempXMLNode2.AsXmlElement().InnerText);
+
+ if NetworkProfile.Get(NetworkProfileId) then
+ Insert := false
+ else begin
+ NetworkProfile.Init();
+ NetworkProfile.Id := NetworkProfileId;
+ Insert := true;
+ end;
+
+ NetworkProfile.Network := NetworkName;
+
+ if TempXMLNode.SelectSingleNode('description', TempXMLNode2) then
+ NetworkProfile.Description := CopyStr(TempXMLNode2.AsXmlElement().InnerText, 1, MaxStrLen(NetworkProfile.Description));
+
+ if TempXMLNode.SelectSingleNode('document_identifier', TempXMLNode2) then
+ NetworkProfile."Document Identifier" := CopyStr(TempXMLNode2.AsXmlElement().InnerText, 1, MaxStrLen(NetworkProfile."Document Identifier"));
+
+ if TempXMLNode.SelectSingleNode('mandatory', TempXMLNode2) then
+ NetworkProfile.Mandatory := TempXMLNode2.AsXmlElement().InnerText = 'true';
+
+ if TempXMLNode.SelectSingleNode('mandatory_in_country_iso3166', TempXMLNode2) then
+ NetworkProfile."Mandatory for Country" := CopyStr(TempXMLNode2.AsXmlElement().InnerText, 1, MaxStrLen(NetworkProfile."Mandatory for Country"));
+
+ if TempXMLNode.SelectSingleNode('process_identifier', TempXMLNode2) then
+ NetworkProfile."Process Identifier" := CopyStr(TempXMLNode2.AsXmlElement().InnerText, 1, MaxStrLen(NetworkProfile."Process Identifier"));
+
+ if TempXMLNode.SelectSingleNode('enabled', TempXMLNode2) then
+ NetworkProfile.Enabled := TempXMLNode2.AsXmlElement().InnerText = 'true'
+ else
+ NetworkProfile.Enabled := true;
+
+ if Insert then
+ NetworkProfile.Insert()
+ else
+ NetworkProfile.Modify();
+ end;
+ end;
+ end;
+ #endregion
+
+ #region Get Network Id Types from Continia Delivery Network Api
+ internal procedure GetNetworkIdTypes(Network: Enum "Continia E-Delivery Network")
+ var
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ IsLastPage: Boolean;
+ HttpResponse: HttpResponseMessage;
+ CurrPage: Integer;
+ PageSize: Integer;
+ begin
+ CurrPage := 0;
+ PageSize := 100;
+ IsLastPage := false;
+ repeat
+ CurrPage += 1;
+ if ExecuteRequest('GET', ApiUrlMgt.NetworkIdentifiersUrl(Network, CurrPage, PageSize), HttpResponse) then
+ IsLastPage := HandleNetworkIdTypeResponse(HttpResponse, Network, PageSize);
+ until IsLastPage;
+ end;
+
+ local procedure HandleNetworkIdTypeResponse(var HttpResponse: HttpResponseMessage; NetworkName: Enum "Continia E-Delivery Network"; PageSize: Integer) IsLastPage: Boolean
+ var
+ NetworkIdentifier: Record "Continia Network Identifier";
+ Insert: Boolean;
+ NetworkIdentifierId: Guid;
+ i: Integer;
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ TempXMLNode: XmlNode;
+ TempXMLNode2: XmlNode;
+ XMLNodeList: XmlNodeList;
+ begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody <> '' then begin
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ ResponseXmlDoc.SelectNodes('/network_id_types/network_id_type', XMLNodeList);
+ for i := 1 to XMLNodeList.Count do begin
+ if XMLNodeList.Count < PageSize then
+ IsLastPage := true;
+ XMLNodeList.Get(i, TempXMLNode);
+
+ TempXMLNode.SelectSingleNode('network_id_type_id', TempXMLNode2);
+
+ NetworkIdentifierId := StrSubstNo('{%1}', TempXMLNode2.AsXmlElement().InnerText);
+
+ if NetworkIdentifier.Get(NetworkIdentifierId) then
+ Insert := false
+ else begin
+ NetworkIdentifier.Init();
+ NetworkIdentifier.Id := NetworkIdentifierId;
+ Insert := true;
+ end;
+
+ NetworkIdentifier.Network := NetworkName;
+
+ if TempXMLNode.SelectSingleNode('code_iso6523-1', TempXMLNode2) then
+ NetworkIdentifier."Identifier Type Id" := CopyStr(TempXMLNode2.AsXmlElement().InnerText, 1, MaxStrLen(NetworkIdentifier."Identifier Type Id"));
+
+ if TempXMLNode.SelectSingleNode('default_in_country_iso3166', TempXMLNode2) then
+ NetworkIdentifier."Default in Country" := CopyStr(TempXMLNode2.AsXmlElement().InnerText, 1, MaxStrLen(NetworkIdentifier."Default in Country"));
+
+ if TempXMLNode.SelectSingleNode('description', TempXMLNode2) then
+ NetworkIdentifier.Description := CopyStr(TempXMLNode2.AsXmlElement().InnerText, 1, MaxStrLen(NetworkIdentifier.Description));
+
+ if TempXMLNode.SelectSingleNode('icd_code', TempXMLNode2) then
+ NetworkIdentifier."ICD Code" := TempXMLNode2.AsXmlElement().InnerText = 'true';
+
+ if TempXMLNode.SelectSingleNode('network_id_type_id', TempXMLNode2) then
+ NetworkIdentifier.Id := TempXMLNode2.AsXmlElement().InnerText;
+
+ if TempXMLNode.SelectSingleNode('scheme_id', TempXMLNode2) then
+ NetworkIdentifier."Scheme Id" := CopyStr(TempXMLNode2.AsXmlElement().InnerText, 1, MaxStrLen(NetworkIdentifier."Scheme Id"));
+
+ if TempXMLNode.SelectSingleNode('vat_in_country_iso3166', TempXMLNode2) then
+ NetworkIdentifier."VAT in Country" := CopyStr(TempXMLNode2.AsXmlElement().InnerText, 1, MaxStrLen(NetworkIdentifier."VAT in Country"));
+
+ if TempXMLNode.SelectSingleNode('validation_rule', TempXMLNode2) then
+ NetworkIdentifier."Validation Rule" := CopyStr(TempXMLNode2.AsXmlElement().InnerText, 1, MaxStrLen(NetworkIdentifier."Validation Rule"));
+
+ if TempXMLNode.SelectSingleNode('enabled', TempXMLNode2) then
+ NetworkIdentifier.Enabled := TempXMLNode2.AsXmlElement().InnerText = 'true'
+ else
+ NetworkIdentifier.Enabled := true;
+
+ if NetworkIdentifier."Default in Country" <> '' then
+ if NetworkIdentifier."Default in Country" = GetCurrentCountryCode() then
+ NetworkIdentifier.Default := true;
+
+ if Insert then
+ NetworkIdentifier.Insert()
+ else
+ NetworkIdentifier.Modify();
+ end;
+ end;
+ end;
+ #endregion
+
+ #region Participation endpoints in Continia Delivery Network
+ internal procedure GetParticipation(var Participation: Record "Continia Participation")
+ var
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ HttpResponse: HttpResponseMessage;
+ begin
+ if ExecuteRequest('GET', ApiUrlMgt.SingleParticipationUrl(Participation.Network, Participation.Id), HttpResponse) then
+ HandleParticipationResponse(HttpResponse, Participation);
+ end;
+
+ internal procedure PostParticipation(var TempParticipation: Record "Continia Participation" temporary) ParticipationGuid: Guid;
+ var
+ Participation: Record "Continia Participation";
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ HttpResponse: HttpResponseMessage;
+ HttpContentData: Text;
+ begin
+ HttpContentData := GetParticipationRequest(TempParticipation, false);
+
+ if ExecuteRequest('POST', ApiUrlMgt.ParticipationUrl(TempParticipation.Network), HttpContentData, HttpResponse) then begin
+ Participation := TempParticipation;
+ Participation.Insert();
+ HandleParticipationResponse(HttpResponse, Participation);
+ exit(Participation.Id);
+ end;
+ end;
+
+ internal procedure PatchParticipation(var TempParticipation: Record "Continia Participation" temporary)
+ var
+ Participation: Record "Continia Participation";
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ HttpResponse: HttpResponseMessage;
+ HttpContentData: Text;
+ begin
+ HttpContentData := GetParticipationRequest(TempParticipation, true);
+
+ if ExecuteRequest('PATCH', ApiUrlMgt.SingleParticipationUrl(TempParticipation.Network, TempParticipation.Id), HttpContentData, HttpResponse) then begin
+ Participation.Get(TempParticipation.RecordId);
+ HandleParticipationResponse(HttpResponse, Participation);
+ end;
+ end;
+
+ internal procedure DeleteParticipation(var Participation: Record "Continia Participation")
+ var
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ HttpResponse: HttpResponseMessage;
+ begin
+ if ExecuteRequest('DELETE', ApiUrlMgt.SingleParticipationUrl(Participation.Network, Participation.Id), HttpResponse) then
+ case HttpResponse.HttpStatusCode of
+ 200:
+ Participation.Delete(true);
+ 202:
+ begin
+ Participation."Registration Status" := Participation."Registration Status"::Disabled;
+ Participation.Modify();
+ end;
+ end;
+ end;
+
+ local procedure GetParticipationRequest(Participation: Record "Continia Participation"; IncludeTimestamp: Boolean) RequestBody: Text
+ var
+ CredentialManagement: Codeunit "Continia Credential Management";
+ AddressNode: XmlElement;
+ CompanyIdNode: XmlElement;
+ CompanyNameNode: XmlElement;
+ ContactEmailNode: XmlElement;
+ ContactNameNode: XmlElement;
+ ContactPhoneNode: XmlElement;
+ CountryCodeNode: XmlElement;
+ NetworkIdTypeNode: XmlElement;
+ NetworkIdValueNode: XmlElement;
+ PostCodeNode: XmlElement;
+ PublishInRegistryNode: XmlElement;
+ RegistrantNameNode: XmlElement;
+ RootNode: XmlElement;
+ StatusNode: XmlElement;
+ TimestampNode: XmlElement;
+ VatRegistrationNoNode: XmlElement;
+ ParticipationTypeNode: XmlElement;
+ ParticipationTypeEnumLbl: Label 'MicrosoftConnector', Locked = true;
+ begin
+ RootNode := XmlElement.Create('participation');
+
+ AddressNode := XmlElement.Create('address');
+ AddressNode.Add(XmlText.Create(Participation.Address));
+ RootNode.Add(AddressNode);
+
+ CompanyIdNode := XmlElement.Create('business_central_company_code');
+ CompanyIdNode.Add(XmlText.Create(GetGuidAsText(CredentialManagement.GetCompanyId())));
+ RootNode.Add(CompanyIdNode);
+
+ CompanyNameNode := XmlElement.Create('company_name');
+ CompanyNameNode.Add(XmlText.Create(Participation."Company Name"));
+ RootNode.Add(CompanyNameNode);
+
+ ContactEmailNode := XmlElement.Create('contact_email');
+ ContactEmailNode.Add(XmlText.Create(Participation."Signatory Email"));
+ RootNode.Add(ContactEmailNode);
+
+ ContactNameNode := XmlElement.Create('contact_name');
+ ContactNameNode.Add(XmlText.Create(Participation."Signatory Name"));
+ RootNode.Add(ContactNameNode);
+
+ ContactPhoneNode := XmlElement.Create('contact_phone');
+ ContactPhoneNode.Add(XmlText.Create(Participation."Contact Phone No."));
+ RootNode.Add(ContactPhoneNode);
+
+ CountryCodeNode := XmlElement.Create('country_code_iso3166');
+ CountryCodeNode.Add(XmlText.Create(Participation."Country/Region Code"));
+ RootNode.Add(CountryCodeNode);
+
+ NetworkIdTypeNode := XmlElement.Create('network_id_type_id');
+ NetworkIdTypeNode.Add(XmlText.Create(Participation."Identifier Type Id"));
+ RootNode.Add(NetworkIdTypeNode);
+
+ NetworkIdValueNode := XmlElement.Create('network_id_value');
+ NetworkIdValueNode.Add(XmlText.Create(Participation."Identifier Value"));
+ RootNode.Add(NetworkIdValueNode);
+
+ if not IsNullGuid(Participation.Id) then begin
+ NetworkIdTypeNode := XmlElement.Create('participation_id');
+ NetworkIdTypeNode.Add(XmlText.Create(GetGuidAsText(Participation.Id)));
+ RootNode.Add(NetworkIdTypeNode);
+ end;
+
+ ParticipationTypeNode := XmlElement.Create('participation_type');
+ ParticipationTypeNode.Add(XmlText.Create(ParticipationTypeEnumLbl));
+ RootNode.Add(ParticipationTypeNode);
+
+ PostCodeNode := XmlElement.Create('post_code');
+ PostCodeNode.Add(XmlText.Create(Participation."Post Code"));
+ RootNode.Add(PostCodeNode);
+
+ PublishInRegistryNode := XmlElement.Create('publish_in_registry');
+ if Participation."Publish in Registry" then
+ PublishInRegistryNode.Add(XmlText.Create('true'))
+ else
+ PublishInRegistryNode.Add(XmlText.Create('false'));
+
+ RootNode.Add(PublishInRegistryNode);
+
+ RegistrantNameNode := XmlElement.Create('registrant_name');
+ RegistrantNameNode.Add(XmlText.Create(Participation."Your Name"));
+ RootNode.Add(RegistrantNameNode);
+
+ StatusNode := XmlElement.Create('status');
+ StatusNode.Add(XmlText.Create(Participation.GetParticipApiStatusEnumValue(false)));
+ RootNode.Add(StatusNode);
+
+ if IncludeTimestamp then begin
+ TimestampNode := XmlElement.Create('timestamp');
+ TimestampNode.Add(XmlText.Create(Participation."Cdn Timestamp"));
+ RootNode.Add(TimestampNode);
+ end;
+
+ VatRegistrationNoNode := XmlElement.Create('vat_registration_no');
+ VatRegistrationNoNode.Add(XmlText.Create(Participation."VAT Registration No."));
+ RootNode.Add(VatRegistrationNoNode);
+
+ RootNode.WriteTo(RequestBody);
+ end;
+
+ local procedure HandleParticipationResponse(var HttpResponse: HttpResponseMessage; var Participation: Record "Continia Participation")
+ var
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ AddressNode: XmlNode;
+ CompanyNameNode: XmlNode;
+ ContactEmailNode: XmlNode;
+ ContactNameNode: XmlNode;
+ ContactPhoneNode: XmlNode;
+ CountryCodeNode: XmlNode;
+ CreatedNode: XmlNode;
+ ParicipationIdNode: XmlNode;
+ PostCodeNode: XmlNode;
+ PublishInRegistryNode: XmlNode;
+ RegistrantNameNode: XmlNode;
+ StatusNode: XmlNode;
+ TimestampNode: XmlNode;
+ UpdatedNode: XmlNode;
+ VatRegistrationNoNode: XmlNode;
+ begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody = '' then
+ exit;
+
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+
+ ResponseXmlDoc.SelectSingleNode('/participation/company_name', CompanyNameNode);
+ Participation."Company Name" := CopyStr(CompanyNameNode.AsXmlElement().InnerText, 1, MaxStrLen(Participation."Company Name"));
+
+ ResponseXmlDoc.SelectSingleNode('/participation/vat_registration_no', VatRegistrationNoNode);
+ Participation."VAT Registration No." := CopyStr(VatRegistrationNoNode.AsXmlElement().InnerText, 1, MaxStrLen(Participation."VAT Registration No."));
+
+ ResponseXmlDoc.SelectSingleNode('/participation/address', AddressNode);
+ Participation.Address := CopyStr(AddressNode.AsXmlElement().InnerText, 1, MaxStrLen(Participation.Address));
+
+ ResponseXmlDoc.SelectSingleNode('/participation/post_code', PostCodeNode);
+ Participation."Post Code" := CopyStr(PostCodeNode.AsXmlElement().InnerText, 1, MaxStrLen(Participation."Post Code"));
+
+ ResponseXmlDoc.SelectSingleNode('/participation/country_code_iso3166', CountryCodeNode);
+ Participation."Country/Region Code" := CopyStr(CountryCodeNode.AsXmlElement().InnerText, 1, MaxStrLen(Participation."Country/Region Code"));
+
+ ResponseXmlDoc.SelectSingleNode('/participation/registrant_name', RegistrantNameNode);
+ Participation."Your Name" := CopyStr(RegistrantNameNode.AsXmlElement().InnerText, 1, MaxStrLen(Participation."Your Name"));
+
+ ResponseXmlDoc.SelectSingleNode('/participation/contact_name', ContactNameNode);
+ Participation."Signatory Name" := CopyStr(ContactNameNode.AsXmlElement().InnerText, 1, MaxStrLen(Participation."Signatory Name"));
+
+ ResponseXmlDoc.SelectSingleNode('/participation/contact_phone', ContactPhoneNode);
+ Participation."Contact Phone No." := CopyStr(ContactPhoneNode.AsXmlElement().InnerText, 1, MaxStrLen(Participation."Contact Phone No."));
+
+ ResponseXmlDoc.SelectSingleNode('/participation/contact_email', ContactEmailNode);
+ Participation."Signatory Email" := CopyStr(ContactEmailNode.AsXmlElement().InnerText, 1, MaxStrLen(Participation."Signatory Email"));
+
+ ResponseXmlDoc.SelectSingleNode('/participation/publish_in_registry', PublishInRegistryNode);
+ if LowerCase(PublishInRegistryNode.AsXmlElement().InnerText) = 'true' then
+ Participation."Publish in Registry" := true
+ else
+ Participation."Publish in Registry" := false;
+
+ ResponseXmlDoc.SelectSingleNode('/participation/publish_in_registry', PublishInRegistryNode);
+ if LowerCase(PublishInRegistryNode.AsXmlElement().InnerText) = 'true' then
+ Participation."Publish in Registry" := true
+ else
+ Participation."Publish in Registry" := false;
+
+ ResponseXmlDoc.SelectSingleNode('/participation/participation_id', ParicipationIdNode);
+ Evaluate(Participation.Id, ParicipationIdNode.AsXmlElement().InnerText);
+
+ ResponseXmlDoc.SelectSingleNode('/participation/status', StatusNode);
+ Participation.ValidateCdnStatus(StatusNode.AsXmlElement().InnerText);
+
+ ResponseXmlDoc.SelectSingleNode('/participation/created_utc', CreatedNode);
+ Evaluate(Participation.Created, CreatedNode.AsXmlElement().InnerText, 9);
+
+ ResponseXmlDoc.SelectSingleNode('/participation/updated_utc', UpdatedNode);
+ Evaluate(Participation.Updated, UpdatedNode.AsXmlElement().InnerText, 9);
+
+ ResponseXmlDoc.SelectSingleNode('/participation/timestamp', TimestampNode);
+ Participation."Cdn Timestamp" := CopyStr(TimestampNode.AsXmlElement().InnerText, 1, MaxStrLen(Participation."Cdn Timestamp"));
+
+ Participation.Modify();
+ end;
+ #endregion
+
+ #region Participation Profiles endpoints in Continia Delivery Network
+ internal procedure PostParticipationProfile(var TempActivatedNetworkProfile: Record "Continia Activated Net. Prof." temporary; ParticipationGuid: Guid) ActivatedNetworkProfileGuid: Guid
+ var
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ HttpResponse: HttpResponseMessage;
+ HttpContentData: Text;
+ begin
+ HttpContentData := GetParticipationProfilesRequest(TempActivatedNetworkProfile);
+
+ if ExecuteRequest('POST', ApiUrlMgt.ParticipationProfilesUrl(TempActivatedNetworkProfile.Network, ParticipationGuid), HttpContentData, HttpResponse) then begin
+ ActivatedNetProf := TempActivatedNetworkProfile;
+ ActivatedNetProf.Insert();
+ UpdateParticipationProfile(HttpResponse, ActivatedNetProf);
+ exit(ActivatedNetProf.Id);
+ end;
+ end;
+
+ internal procedure PatchParticipationProfile(var TempActivatedNetworkProfile: Record "Continia Activated Net. Prof." temporary; ParticipationGuid: Guid)
+ var
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ HttpResponse: HttpResponseMessage;
+ HttpContentData: Text;
+ begin
+ HttpContentData := GetParticipationProfilesRequest(TempActivatedNetworkProfile);
+
+ if ExecuteRequest('PATCH', ApiUrlMgt.SingleParticipationProfileUrl(TempActivatedNetworkProfile.Network, ParticipationGuid, TempActivatedNetworkProfile.Id), HttpContentData, HttpResponse) then begin
+ ActivatedNetProf.Get(TempActivatedNetworkProfile.RecordId);
+ UpdateParticipationProfile(HttpResponse, ActivatedNetProf);
+ end;
+ end;
+
+ internal procedure DeleteParticipationProfile(var ActivatedNetworkProfile: Record "Continia Activated Net. Prof."; ParticipationGuid: Guid)
+ var
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ HttpResponse: HttpResponseMessage;
+ begin
+ if ExecuteRequest('DELETE', ApiUrlMgt.SingleParticipationProfileUrl(ActivatedNetworkProfile.Network, ParticipationGuid, ActivatedNetworkProfile.Id), HttpResponse) then begin
+ ActivatedNetworkProfile.Validate(Disabled, CreateDateTime(Today, Time));
+ ActivatedNetworkProfile.Modify();
+ end;
+ end;
+
+ internal procedure GetAllParticipationProfiles(Participation: Record "Continia Participation")
+ var
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ IsLastPage: Boolean;
+ HttpResponse: HttpResponseMessage;
+ CurrPage: Integer;
+ PageSize: Integer;
+ begin
+ CurrPage := 0;
+ PageSize := 100;
+ IsLastPage := false;
+ repeat
+ CurrPage += 1;
+ if ExecuteRequest('GET', ApiUrlMgt.ParticipationProfilesUrl(Participation.Network, Participation.Id, CurrPage, PageSize), HttpResponse) then begin
+ HandleApiError(HttpResponse);
+ IsLastPage := ReadParticipationProfilesResponse(HttpResponse, Participation, PageSize);
+ end;
+ until IsLastPage;
+ end;
+
+ local procedure ReadParticipationProfilesResponse(var HttpResponse: HttpResponseMessage; Participation: Record "Continia Participation"; PageSize: Integer) IsLastPage: Boolean
+ var
+ i: Integer;
+ NodeCount: Integer;
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ Node: XmlNode;
+ NodeList: XmlNodeList;
+ begin
+ IsLastPage := false;
+
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody = '' then
+ exit;
+
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ ResponseXmlDoc.SelectNodes('/participation_profiles/participation_profile', NodeList);
+
+ NodeCount := NodeList.Count;
+ if NodeCount < PageSize then
+ IsLastPage := true;
+
+ for i := 1 to NodeCount do begin
+ NodeList.Get(i, Node);
+ CreateOrUpdateParticipProfiles(Participation, Node);
+ end;
+ end;
+
+ local procedure GetParticipationProfilesRequest(ActivatedNetworkProfile: Record "Continia Activated Net. Prof.") RequestBody: Text
+ var
+ ParticipationProfileNode: XmlElement;
+ ProfileDirectionNode: XmlElement;
+ ProfileIdNode: XmlElement;
+ begin
+ ParticipationProfileNode := XmlElement.Create('participation_profile');
+
+ ProfileDirectionNode := XmlElement.Create('direction');
+ ProfileDirectionNode.Add(XmlText.Create(ActivatedNetworkProfile.GetParticipApiDirectionEnum()));
+ ParticipationProfileNode.Add(ProfileDirectionNode);
+
+ ProfileIdNode := XmlElement.Create('network_profile_id');
+ ProfileIdNode.Add(XmlText.Create(GetGuidAsText(ActivatedNetworkProfile."Network Profile Id")));
+ ParticipationProfileNode.Add(ProfileIdNode);
+
+ ParticipationProfileNode.WriteTo(RequestBody);
+ end;
+
+ local procedure CreateOrUpdateParticipProfiles(Participation: Record "Continia Participation"; ProfilesNode: XmlNode)
+ var
+ ActivatedNetworkProfile: Record "Continia Activated Net. Prof.";
+ ProfileGuid: Guid;
+ CreatedNode: XmlNode;
+ DirectionNode: XmlNode;
+ DisabledNode: XmlNode;
+ ParticipationProfileIdNode: XmlNode;
+ ProfileIdNode: XmlNode;
+ UpdatedNode: XmlNode;
+ begin
+ ProfilesNode.SelectSingleNode('network_profile_id', ProfileIdNode);
+ Evaluate(ProfileGuid, ProfileIdNode.AsXmlElement().InnerText);
+ if not ActivatedNetworkProfile.Get(Participation.Network, Participation."Identifier Type Id", Participation."Identifier Value", ProfileGuid) then begin
+ ActivatedNetworkProfile.Init();
+ ActivatedNetworkProfile.Network := Participation.Network;
+ ActivatedNetworkProfile."Identifier Type Id" := Participation."Identifier Type Id";
+ ActivatedNetworkProfile."Identifier Value" := Participation."Identifier Value";
+ ActivatedNetworkProfile."Network Profile Id" := ProfileGuid;
+ ActivatedNetworkProfile.Insert();
+ end;
+
+ ProfilesNode.SelectSingleNode('participation_profile_id', ParticipationProfileIdNode);
+ Evaluate(ActivatedNetworkProfile.Id, ParticipationProfileIdNode.AsXmlElement().InnerText);
+
+ ProfilesNode.SelectSingleNode('direction', DirectionNode);
+ ActivatedNetworkProfile.ValidateApiDirection(DirectionNode.AsXmlElement().InnerText);
+
+ ProfilesNode.SelectSingleNode('created_utc', CreatedNode);
+ Evaluate(ActivatedNetworkProfile.Created, CreatedNode.AsXmlElement().InnerText, 9);
+
+ ProfilesNode.SelectSingleNode('updated_utc', UpdatedNode);
+ Evaluate(ActivatedNetworkProfile.Updated, UpdatedNode.AsXmlElement().InnerText, 9);
+
+ if ProfilesNode.SelectSingleNode('disabled_utc', DisabledNode) then
+ Evaluate(ActivatedNetworkProfile.Disabled, DisabledNode.AsXmlElement().InnerText, 9)
+ else
+ Clear(ActivatedNetworkProfile.Disabled);
+
+ ActivatedNetworkProfile.Modify();
+ end;
+
+ local procedure UpdateParticipationProfile(var HttpResponse: HttpResponseMessage; var ActivatedNetworkProfile: Record "Continia Activated Net. Prof.")
+ var
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ CreatedNode: XmlNode;
+ DirectionNode: XmlNode;
+ DisabledNode: XmlNode;
+ ProfileIdNode: XmlNode;
+ UpdatedNode: XmlNode;
+ begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody = '' then
+ exit;
+
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ ResponseXmlDoc.SelectSingleNode('/participation_profile/participation_profile_id', ProfileIdNode);
+ Evaluate(ActivatedNetworkProfile.Id, ProfileIdNode.AsXmlElement().InnerText);
+
+ ResponseXmlDoc.SelectSingleNode('/participation_profile/direction', DirectionNode);
+ ActivatedNetworkProfile.ValidateApiDirection(DirectionNode.AsXmlElement().InnerText);
+
+ ResponseXmlDoc.SelectSingleNode('/participation_profile/created_utc', CreatedNode);
+ Evaluate(ActivatedNetworkProfile.Created, CreatedNode.AsXmlElement().InnerText, 9);
+
+ ResponseXmlDoc.SelectSingleNode('/participation_profile/updated_utc', UpdatedNode);
+ Evaluate(ActivatedNetworkProfile.Updated, UpdatedNode.AsXmlElement().InnerText, 9);
+
+ if ResponseXmlDoc.SelectSingleNode('/participation_profile/disabled_utc', DisabledNode) then
+ Evaluate(ActivatedNetworkProfile.Disabled, DisabledNode.AsXmlElement().InnerText)
+ else
+ Clear(ActivatedNetworkProfile.Disabled);
+
+ ActivatedNetworkProfile.Modify();
+ end;
+ #endregion
+
+ #region Participation Profiles Lookup endpoints in Continia Delivery Network
+ internal procedure CheckProfilesNotRegistered(var TempParticipation: Record "Continia Participation" temporary)
+ var
+ NetworkIdentifier: Record "Continia Network Identifier";
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ HttpResponse: HttpResponseMessage;
+ begin
+ NetworkIdentifier := TempParticipation.GetNetworkIdentifier();
+
+ if ExecuteRequest('GET', ApiUrlMgt.ParticipationLookupUrl(TempParticipation.Network, NetworkIdentifier."Identifier Type Id", TempParticipation."Identifier Value"), HttpResponse) then
+ HandleProfilesLookupResponse(HttpResponse, TempParticipation);
+ end;
+
+ local procedure HandleProfilesLookupResponse(var HttpResponse: HttpResponseMessage; var TempParticipation: Record "Continia Participation" temporary)
+ var
+ ErrorInfo: ErrorInfo;
+ ProfileGuid: Guid;
+ i: Integer;
+ j: Integer;
+ AccessPointEmail: Text;
+ AccessPointErrText: Text;
+ AccessPointName: Text;
+ DetailedErrText: Text;
+ RegisteredProfilesErrText: Text;
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ AccessPointNode: XmlNode;
+ APEmailNode: XmlNode;
+ APNameNode: XmlNode;
+ ProfileId: XmlNode;
+ ProfileNode: XmlNode;
+ ProfileDescriptionNode: XmlNode;
+ AccessPointNodeList: XmlNodeList;
+ ProfilesNodeList: XmlNodeList;
+ begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody = '' then
+ exit;
+
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ ResponseXmlDoc.SelectNodes('/participation_lookups/participation_lookup/external_access_points/access_point', AccessPointNodeList);
+ for i := 1 to AccessPointNodeList.Count do begin
+ AccessPointNodeList.Get(i, AccessPointNode);
+ AccessPointNode.SelectNodes('supported_profiles/network_profile', ProfilesNodeList);
+ for j := 1 to ProfilesNodeList.Count do begin
+ ProfilesNodeList.Get(j, ProfileNode);
+ if ProfileNode.SelectSingleNode('network_profile_id', ProfileId) then begin
+ Evaluate(ProfileGuid, ProfileId.AsXmlElement().InnerText);
+ ProfileNode.SelectSingleNode('description', ProfileDescriptionNode);
+ AccessPointNode.SelectSingleNode('name', APNameNode);
+ AccessPointNode.SelectSingleNode('email', APEmailNode);
+ AccessPointName := APNameNode.AsXmlElement().InnerText;
+ AccessPointEmail := APEmailNode.AsXmlElement().InnerText;
+
+ RegisteredProfilesErrText += StrSubstNo('%1 //', ProfileDescriptionNode.AsXmlElement().InnerText);
+ end;
+ end;
+
+ if RegisteredProfilesErrText <> '' then begin
+ AccessPointErrText := StrSubstNo(AccessPointDetailedErr, AccessPointName, AccessPointEmail, RegisteredProfilesErrText);
+ DetailedErrText += StrSubstNo('%1 // //', AccessPointErrText);
+ end
+ end;
+
+ if RegisteredProfilesErrText <> '' then begin
+ ErrorInfo.Title := ParticipationAlreadyRegisteredTitleErr;
+ ErrorInfo.Message := StrSubstNo(ParticipationAlreadyRegisteredErr, TempParticipation.Network, TempParticipation."Identifier Type Id", TempParticipation."Identifier Value");
+ ErrorInfo.DetailedMessage(DetailedErrText);
+ Error(ErrorInfo);
+ end
+ end;
+ #endregion
+
+ #region Get Documents for current company
+ internal procedure GetDocumentsForCompany(ReceiveContext: Codeunit ReceiveContext): Boolean
+ var
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ CredentialManagement: Codeunit "Continia Credential Management";
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ CurrPage: Integer;
+ PageSize: Integer;
+ Success: Boolean;
+ begin
+ CurrPage := 1;
+ PageSize := 100; // only get 100 documents at a time.
+
+ Success := ExecuteRequest('GET', ApiUrlMgt.DocumentsForCompanyUrl(CredentialManagement.GetCompanyId(), CurrPage, PageSize, true), HttpRequest, HttpResponse);
+ ReceiveContext.Http().SetHttpRequestMessage(HttpRequest);
+ ReceiveContext.Http().SetHttpResponseMessage(HttpResponse);
+ exit(Success);
+ end;
+ #endregion
+
+ #region Send Documents
+ internal procedure SendDocument(EDocument: Record "E-Document"; SendContext: Codeunit SendContext): Boolean
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ CredentialManagement: Codeunit "Continia Credential Management";
+ Base64Convert: Codeunit "Base64 Convert";
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ TempBlob: Codeunit "Temp Blob";
+ HttpResponse: HttpResponseMessage;
+ HttpRequest: HttpRequestMessage;
+ ReadStream: InStream;
+ HttpContentData: Text;
+ DocumentBase64Node: XmlElement;
+ RootNode: XmlElement;
+ Success: Boolean;
+ begin
+ ConnectionSetup.Get();
+
+ TempBlob := SendContext.GetTempBlob();
+
+ RootNode := XmlElement.Create('unprocessed_document_request');
+ DocumentBase64Node := XmlElement.Create('base64_data');
+ TempBlob.CreateInStream(ReadStream);
+ DocumentBase64Node.Add(XmlText.Create(Base64Convert.ToBase64(ReadStream)));
+ RootNode.Add(DocumentBase64Node);
+
+ RootNode.WriteTo(HttpContentData);
+
+ Success := ExecuteRequest('POST', ApiUrlMgt.PostDocumentsUrl(CredentialManagement.GetCompanyId()), HttpContentData, HttpRequest, HttpResponse);
+ SendContext.Http().SetHttpRequestMessage(HttpRequest);
+ SendContext.Http().SetHttpResponseMessage(HttpResponse);
+
+ if Success then begin
+ SetEDocumentGuid(EDocument."Entry No", GetDocumentGuid(HttpResponse));
+ exit(true);
+ end;
+ end;
+
+ local procedure SetEDocumentGuid(EDocEntryNo: Integer; DocumentId: Guid)
+ var
+ EDocument: Record "E-Document";
+ begin
+ if IsNullGuid(DocumentId) then
+ exit;
+ if not EDocument.Get(EDocEntryNo) then
+ exit;
+ EDocument."Continia Document Id" := DocumentId;
+ EDocument.Modify();
+ end;
+
+ local procedure GetDocumentGuid(var HttpResponse: HttpResponseMessage) DocumentGuid: Guid
+ var
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ DocumentGuidNode: XmlNode;
+ begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody = '' then
+ exit;
+
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ ResponseXmlDoc.SelectSingleNode('/id_result/id', DocumentGuidNode);
+ Evaluate(DocumentGuid, DocumentGuidNode.AsXmlElement().InnerText);
+ exit(DocumentGuid);
+ end;
+ #endregion
+
+ #region Get Technical response
+ internal procedure GetTechnicalResponse(var EDocument: Record "E-Document"; SendContext: Codeunit SendContext): Boolean
+ var
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ EDocumentErrorHelper: Codeunit "E-Document Error Helper";
+ SuccessfulStatusTok: Label 'SuccessEnum', Locked = true;
+ ErrorStatusTok: Label 'ErrorEnum', Locked = true;
+ DocumentStatus: Text;
+ EDocumentDescription: Text;
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ DocumentStatusNode: XmlNode;
+ ErrorCodeNode: XmlNode;
+ ErrorMessageNode: XmlNode;
+ TechnicalResponseNode: XmlNode;
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ Success: Boolean;
+ begin
+ Success := ExecuteRequest('GET', ApiUrlMgt.TechnicalResponseUrl(EDocument."Continia Document Id"), HttpRequest, HttpResponse);
+ SendContext.Http().SetHttpRequestMessage(HttpRequest);
+ SendContext.Http().SetHttpResponseMessage(HttpResponse);
+ if Success then begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody = '' then
+ exit(false);
+
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ ResponseXmlDoc.SelectSingleNode('/technical_response', TechnicalResponseNode);
+
+ if not TechnicalResponseNode.SelectSingleNode('document_status', DocumentStatusNode) then
+ exit(false);
+
+ DocumentStatus := DocumentStatusNode.AsXmlElement().InnerText;
+ case DocumentStatus of
+ SuccessfulStatusTok:
+ begin
+ MarkDocumentAsProcessed(EDocument."Continia Document Id");
+ exit(true);
+ end;
+ ErrorStatusTok:
+ begin
+ if TechnicalResponseNode.SelectSingleNode('error_code', ErrorCodeNode) and TechnicalResponseNode.SelectSingleNode('error_message', ErrorMessageNode) then
+ EDocumentDescription := StrSubstNo('%1 - %2', ErrorCodeNode.AsXmlElement().InnerText, ErrorMessageNode.AsXmlElement().InnerText);
+ EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, EDocumentDescription);
+ MarkDocumentAsProcessed(EDocument."Continia Document Id");
+ exit(false);
+ end;
+ end;
+ exit(false);
+ end;
+ end;
+ #endregion;
+
+ #region Get Document Business Responses
+ internal procedure GetBusinessResponses(DocumentGuid: Guid; ActionContext: Codeunit ActionContext): Boolean
+ var
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ Success: Boolean;
+ begin
+ Success := ExecuteRequest('GET', ApiUrlMgt.BusinessResponseUrl(DocumentGuid), HttpRequest, HttpResponse);
+ ActionContext.Http().SetHttpRequestMessage(HttpRequest);
+ ActionContext.Http().SetHttpResponseMessage(HttpResponse);
+ exit(Success);
+ end;
+ #endregion
+
+ #region Perform actions on document
+ // Cancel document
+ internal procedure CancelDocument(DocumentGuid: Guid; ActionContext: Codeunit ActionContext): Boolean
+ var
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ Success: Boolean;
+ begin
+ Success := PerformActionOnDocument(DocumentGuid, 'CancelEnum', HttpRequest, HttpResponse);
+ if Success then
+ ActionContext.Status().SetStatus(Enum::"E-Document Service Status"::Canceled);
+
+ ActionContext.Http().SetHttpRequestMessage(HttpRequest);
+ ActionContext.Http().SetHttpResponseMessage(HttpResponse);
+ exit(Success);
+ end;
+
+ // Mark document as processed
+ internal procedure MarkDocumentAsProcessed(DocumentGuid: Guid): Boolean
+ var
+ ReceiveContext: Codeunit ReceiveContext;
+ begin
+ exit(MarkDocumentAsProcessed(DocumentGuid, ReceiveContext));
+ end;
+
+ internal procedure MarkDocumentAsProcessed(DocumentGuid: Guid; ReceiveContext: Codeunit ReceiveContext): Boolean
+ var
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ Success: Boolean;
+ begin
+ Success := PerformActionOnDocument(DocumentGuid, 'MarkAsProcessedEnum', HttpRequest, HttpResponse);
+ ReceiveContext.Http().SetHttpRequestMessage(HttpRequest);
+ ReceiveContext.Http().SetHttpResponseMessage(HttpResponse);
+ exit(Success);
+ end;
+
+ internal procedure PerformActionOnDocument(DocumentGuid: Guid; Action: Text; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean
+ var
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ HttpContentData: Text;
+ ActionNode: XmlElement;
+ RootNode: XmlElement;
+ begin
+ RootNode := XmlElement.Create('document_action_request');
+
+ ActionNode := XmlElement.Create('action');
+ ActionNode.Add(XmlText.Create(Action));
+ RootNode.Add(ActionNode);
+
+ RootNode.WriteTo(HttpContentData);
+
+ exit(ExecuteRequest('POST', ApiUrlMgt.DocumentActionUrl(DocumentGuid), HttpContentData, HttpRequest, HttpResponse));
+ end;
+ #endregion
+
+ #region Helper functions
+ internal procedure DownloadFileFromUrl(Url: Text; ReceiveContext: Codeunit ReceiveContext)
+ var
+ HttpClient: HttpClient;
+ ReadStream: InStream;
+ WriteStream: OutStream;
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ Success: Boolean;
+ begin
+ Success := HttpClient.Get(Url, HttpResponse);
+ ReceiveContext.Http().SetHttpRequestMessage(HttpRequest);
+ ReceiveContext.Http().SetHttpResponseMessage(HttpResponse);
+ if not Success then
+ exit;
+ ReceiveContext.GetTempBlob().CreateOutStream(WriteStream);
+ HttpResponse.Content.ReadAs(ReadStream);
+ CopyStream(WriteStream, ReadStream);
+ end;
+
+ local procedure ExecuteRequest(Method: Text; Url: Text; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean
+ var
+ HttpContentData: Text;
+ begin
+ exit(ExecuteRequest(Method, Url, HttpContentData, HttpRequest, HttpResponse));
+ end;
+
+ local procedure ExecuteRequest(Method: Text; Url: Text; var HttpResponse: HttpResponseMessage): Boolean
+ var
+ HttpRequest: HttpRequestMessage;
+ HttpContentData: Text;
+ begin
+ exit(ExecuteRequest(Method, Url, HttpContentData, HttpRequest, HttpResponse));
+ end;
+
+ local procedure ExecuteRequest(Method: Text; Url: Text; HttpContentData: Text; var HttpResponse: HttpResponseMessage): Boolean
+ var
+ HttpRequest: HttpRequestMessage;
+ begin
+ exit(ExecuteRequest(Method, Url, HttpContentData, HttpRequest, HttpResponse));
+ end;
+
+ local procedure ExecuteRequest(Method: Text; Url: Text; HttpContentData: Text; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean
+ var
+ SessionManager: Codeunit "Continia Session Manager";
+ HttpClient: HttpClient;
+ HttpContent: HttpContent;
+ HttpContentHeaders: HttpHeaders;
+ HttpHeaders: HttpHeaders;
+ AccessTokenValue: SecretText;
+ begin
+ HttpRequest.GetHeaders(HttpHeaders);
+ AccessTokenValue := SecretStrSubstNo('Bearer %1', SessionManager.GetAccessToken());
+
+ HttpHeaders.Add('Authorization', AccessTokenValue);
+ HttpHeaders.Add('Accept', 'application/xml;charset=utf-8');
+ HttpRequest.Method(Method);
+ HttpRequest.SetRequestUri(Url);
+
+ if HttpContentData <> '' then begin
+ HttpContent.WriteFrom(HttpContentData);
+ HttpContent.GetHeaders(HttpContentHeaders);
+ if HttpContentHeaders.Contains('Content-Type') then
+ HttpContentHeaders.Remove('Content-Type');
+ HttpContentHeaders.Add('Content-Type', 'application/xml');
+ HttpRequest.Content := HttpContent;
+ end;
+
+ if HttpClient.Send(HttpRequest, HttpResponse) then
+ exit(HandleApiError(HttpResponse));
+ end;
+
+ internal procedure HandleApiError(var HttpResponse: HttpResponseMessage): Boolean
+ var
+ HttpStatusCode: Integer;
+ ResponseBody: Text;
+ ResponseBodyXML: XmlDocument;
+ begin
+ HttpStatusCode := HttpResponse.HttpStatusCode;
+ if HttpStatusCode in [200, 201, 202] then
+ exit(true);
+
+ HttpResponse.Content().ReadAs(ResponseBody);
+ if ResponseBody <> '' then
+ if not XmlDocument.ReadFrom(ResponseBody, ResponseBodyXML) then
+ exit(ThrowError(UnexpectedApiErr));
+
+ ReadErrorResponse(ResponseBodyXML, HttpStatusCode);
+ end;
+
+ internal procedure ReadErrorResponse(var ResponseXML: XmlDocument; HttpStatusCode: Integer): Boolean
+ var
+ ApiErrorCode: Text;
+ ApiErrorMessage: Text;
+ ErrorCodeNode: XmlNode;
+ ErrorMessageNode: XmlNode;
+ begin
+ if not ResponseXML.SelectSingleNode('/error/code', ErrorCodeNode) then
+ exit(ThrowError(UnexpectedApiErr));
+
+ if not ResponseXML.SelectSingleNode('/error/message', ErrorMessageNode) then
+ exit(ThrowError(UnexpectedApiErr));
+
+ ApiErrorCode := ErrorCodeNode.AsXmlElement().InnerText;
+ ApiErrorMessage := ErrorMessageNode.AsXmlElement().InnerText;
+
+ case HttpStatusCode of
+ 500, 501:
+ exit(ThrowError(StrSubstNo(Error500Err, ApiErrorCode, ApiErrorMessage)));
+ 400, 401, 402, 404, 409, 422:
+ exit(ThrowError(StrSubstNo(ApiErr, ApiErrorCode, ApiErrorMessage)));
+ else
+ exit(ThrowError(UnexpectedApiErr));
+ end;
+ end;
+
+ local procedure ThrowError(ErrorMsg: Text): Boolean
+ begin
+ if SuppressError then
+ exit;
+
+ Error(ErrorMsg);
+ end;
+
+ local procedure GetCurrentCountryCode(): Code[10]
+ var
+ CompanyInformation: Record "Company Information";
+ CountryRegion: Record "Country/Region";
+ begin
+ CompanyInformation.Get();
+ if CompanyInformation."Country/Region Code" = '' then
+ exit('');
+
+ if CountryRegion.Get(CompanyInformation."Country/Region Code") then
+ exit(CountryRegion."ISO Code");
+ end;
+
+ internal procedure GetGuidAsText(Value: Guid): Text[36]
+ begin
+ exit(CopyStr(Format(Value, 0, 4), 1, 36))
+ end;
+
+ internal procedure SetSuppressError(NewSuppressError: Boolean)
+ begin
+ SuppressError := NewSuppressError;
+ end;
+ #endregion
+
+ var
+ SuppressError: Boolean;
+ AccessPointDetailedErr: Label 'Access Point: %1// Contact Email: %2// Registered Profiles://%3', Comment = '%1 = Access Point Name, %2 = Access Point Email, %3 = Registered Profiles';
+ ApiErr: Label 'The Continia Delivery Network API returned the following error: Error Code %1 - %2', Comment = '%1 = Continia Delivery Network Error Code, %2 = Error Message';
+ Error500Err: Label 'The Continia Delivery Network API returned the following system error: Error Code %1 - %2', Comment = '%1 = Continia Delivery Network Error Code, %2 = Error Message';
+ ParticipationAlreadyRegisteredErr: Label 'There is already a registration in %1 network with the identifier type %2 and value %3.', Comment = '%1 = Network Name, %2 = Identifier Type, %3 = Identifier Value';
+ ParticipationAlreadyRegisteredTitleErr: Label 'Registration Already Exists';
+ UnexpectedApiErr: Label 'There was an unexpected error while communicating with the Continia Delivery Network API.';
+
+
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/API Requests/ContiniaAPIURLMgt.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/app/src/API Requests/ContiniaAPIURLMgt.Codeunit.al
new file mode 100644
index 0000000000..094d2690a5
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/API Requests/ContiniaAPIURLMgt.Codeunit.al
@@ -0,0 +1,233 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using System.Environment;
+
+codeunit 6392 "Continia Api Url Mgt."
+{
+ Access = Internal;
+
+ internal procedure NetworkProfilesUrl(Network: Enum "Continia E-Delivery Network"; Page: Integer; PageSize: Integer): Text
+ var
+ ProfilesUrlLbl: Label '%1/networks/%2/profiles.xml?page=%3&page_size=%4', Locked = true;
+ begin
+ exit(StrSubstNo(ProfilesUrlLbl, CdnBaseUrl(), GetNetworkNameAsText(Network), Page, PageSize));
+ end;
+
+ internal procedure NetworkIdentifiersUrl(Network: Enum "Continia E-Delivery Network"; Page: Integer; PageSize: Integer): Text
+ var
+ IdentifiersUrlLbl: Label '%1/networks/%2/id_types.xml?page=%3&page_size=%4', Locked = true;
+ begin
+ exit(StrSubstNo(IdentifiersUrlLbl, CdnBaseUrl(), GetNetworkNameAsText(Network), Page, PageSize));
+ end;
+
+ internal procedure ParticipationUrl(Network: Enum "Continia E-Delivery Network"): Text
+ var
+ ParticipationUrlLbl: Label '%1/networks/%2/participations.xml', Locked = true;
+ begin
+ exit(StrSubstNo(ParticipationUrlLbl, CdnBaseUrl(), GetNetworkNameAsText(Network)))
+ end;
+
+ internal procedure SingleParticipationUrl(Network: Enum "Continia E-Delivery Network"; ParticipationGuid: Guid): Text
+ var
+ SingleParticipationUrlLbl: Label '%1/networks/%2/participations/%3.xml', Locked = true;
+ begin
+ exit(StrSubstNo(SingleParticipationUrlLbl, CdnBaseUrl(), GetNetworkNameAsText(Network), GetGuidAsText(ParticipationGuid)))
+ end;
+
+ internal procedure ParticipationProfilesUrl(Network: Enum "Continia E-Delivery Network"; ParticipationGuid: Guid): Text
+ var
+ ParticipationProfilesUrlLbl: Label '%1/networks/%2/participations/%3/profiles.xml', Locked = true;
+ begin
+ exit(StrSubstNo(ParticipationProfilesUrlLbl, CdnBaseUrl(), GetNetworkNameAsText(Network), GetGuidAsText(ParticipationGuid)))
+ end;
+
+ internal procedure ParticipationProfilesUrl(Network: Enum "Continia E-Delivery Network"; ParticipationGuid: Guid; Page: Integer; PageSize: Integer): Text
+ var
+ ParticipationProfilesUrlPagesLbl: Label '%1/networks/%2/participations/%3/profiles.xml?page=%4&page_size=%5', Locked = true;
+ begin
+ exit(StrSubstNo(ParticipationProfilesUrlPagesLbl, CdnBaseUrl(), GetNetworkNameAsText(Network), GetGuidAsText(ParticipationGuid), Page, PageSize))
+ end;
+
+ internal procedure SingleParticipationProfileUrl(Network: Enum "Continia E-Delivery Network"; ParticipationGuid: Guid; ProfileGuid: Guid): Text
+ var
+ SingleParticipationProfileUrlLbl: Label '%1/networks/%2/participations/%3/profiles/%4.xml', Locked = true;
+ begin
+ exit(StrSubstNo(SingleParticipationProfileUrlLbl, CdnBaseUrl(), GetNetworkNameAsText(Network), GetGuidAsText(ParticipationGuid), GetGuidAsText(ProfileGuid)))
+ end;
+
+ internal procedure ParticipationLookupUrl(Network: Enum "Continia E-Delivery Network"; IdType: Text[4]; IdValue: Text[50]): Text
+ var
+ ParticipationLookupUrlLbl: Label '%1/networks/%2/participation_lookups.xml?id_type=%3&id_value=%4', Locked = true;
+ begin
+ exit(StrSubstNo(ParticipationLookupUrlLbl, CdnBaseUrl(), GetNetworkNameAsText(Network), IdType, IdValue))
+ end;
+
+ internal procedure DocumentsForCompanyUrl(CompanyGuid: Guid; Page: Integer; PageSize: Integer; Incoming: Boolean): Text
+ var
+ DirectionQueryTxt: Text;
+ DocumentsForCompanyUrlLbl: Label '%1/documents.xml?business_central_company_code=%2&page=%3&page_size=%4&direction=%5', Locked = true;
+ begin
+ if Incoming then
+ DirectionQueryTxt := 'IncomingEnum'
+ else
+ DirectionQueryTxt := 'OutgoingEnum';
+ exit(StrSubstNo(DocumentsForCompanyUrlLbl, CdnBaseUrl(), GetGuidAsText(CompanyGuid), Page, PageSize, DirectionQueryTxt))
+ end;
+
+ internal procedure DocumentActionUrl(DocumentGuid: Guid): Text
+ var
+ DocumentActionUrlLbl: Label '%1/documents/%2/action.xml', Locked = true;
+ begin
+ exit(StrSubstNo(DocumentActionUrlLbl, CdnBaseUrl(), GetGuidAsText(DocumentGuid)))
+ end;
+
+ internal procedure PostDocumentsUrl(CompanyGuid: Guid): Text
+ var
+ PostDocumentsUrlLbl: Label '%1/documents.xml?business_central_company_code=%2', Locked = true;
+ begin
+ exit(StrSubstNo(PostDocumentsUrlLbl, CdnBaseUrl(), GetGuidAsText(CompanyGuid)))
+ end;
+
+ internal procedure TechnicalResponseUrl(DocumentGuid: Guid): Text
+ var
+ TechnicalResponseUrlLbl: Label '%1/documents/%2/technical_response.xml', Locked = true;
+ begin
+ exit(StrSubstNo(TechnicalResponseUrlLbl, CdnBaseUrl(), GetGuidAsText(DocumentGuid)))
+ end;
+
+ internal procedure BusinessResponseUrl(DocumentGuid: Guid): Text
+ var
+ BusinessResponseUrlLbl: Label '%1/documents/%2/business_responses.xml', Locked = true;
+ begin
+ exit(StrSubstNo(BusinessResponseUrlLbl, CdnBaseUrl(), GetGuidAsText(DocumentGuid)))
+ end;
+
+ internal procedure PartnerAccessTokenUrl(): Text
+ var
+ PartnerAccessTokenUrlLbl: Label '%1/partner/PartnerZoneLogin', Locked = true;
+ begin
+ exit(StrSubstNo(PartnerAccessTokenUrlLbl, COBaseUrl()));
+ end;
+
+ internal procedure PartnerZoneUrl(): Text
+ var
+ PartnerAccessTokenUrlLbl: Label '%1/partner/PartnerZoneConnect', Locked = true;
+ begin
+ exit(StrSubstNo(PartnerAccessTokenUrlLbl, COBaseUrl()));
+ end;
+
+ internal procedure ClientAccessTokenUrl(): Text
+ var
+ ClientAccessTokenUrlLbl: Label '%1/oauth/token/', Locked = true;
+ begin
+ exit(StrSubstNo(ClientAccessTokenUrlLbl, COBaseUrl()));
+ end;
+
+ internal procedure ClientEnvironmentInitializeUrl(): Text
+ var
+ ClientEnvironmentInitializeUrlLbl: Label '%1/core/initializeV3', Locked = true;
+ begin
+ exit(StrSubstNo(ClientEnvironmentInitializeUrlLbl, COBaseUrl()));
+ end;
+
+ internal procedure UpdateSubscriptionUrl(): Text
+ var
+ UpdateSubscriptionUrlLbl: Label '%1/core/UpdateSubscription', Locked = true;
+ begin
+ exit(StrSubstNo(UpdateSubscriptionUrlLbl, COBaseUrl()));
+ end;
+
+ internal procedure GetSubscriptionUrl(): Text
+ var
+ GetSubscriptionUrlLbl: Label '%1/core/GetSubscriptions', Locked = true;
+ begin
+ exit(StrSubstNo(GetSubscriptionUrlLbl, COBaseUrl()));
+ end;
+
+ internal procedure GetAcceptCompanyLicenseUrl(): Text
+ var
+ GetAcceptCompanyLicenseUrlLbl: Label '%1/core/AcceptCompanyLicense', Locked = true;
+ begin
+ exit(StrSubstNo(GetAcceptCompanyLicenseUrlLbl, COBaseUrl()));
+ end;
+
+ internal procedure GetUpdateCompanyInfoUrl(): Text
+ var
+ GetUpdateCompanyInfoUrlLbl: Label '%1/core/UpdateInvoicingInformation', Locked = true;
+ begin
+ exit(StrSubstNo(GetUpdateCompanyInfoUrlLbl, COBaseUrl()));
+ end;
+
+ local procedure COBaseUrl() Url: Text
+ var
+ Handled: Boolean;
+ begin
+ OnGetCOBaseUrl(Url, Handled);
+ if Handled then
+ exit(Url);
+
+ exit('https://auth.continiaonline.com/api/v1');
+ end;
+
+
+ internal procedure CdnBaseUrl() Url: Text
+ var
+ EnvironmentInformation: Codeunit "Environment Information";
+ Handled: Boolean;
+ LocalizedBaseUrl: Text;
+ begin
+ OnGetCdnBaseUrl(Url, Handled);
+ if Handled then
+ exit(Url);
+
+ LocalizedBaseUrl := GetBaseUrlForLocalization(EnvironmentInformation.GetApplicationFamily());
+ if LocalizedBaseUrl <> '' then
+ exit(LocalizedBaseUrl)
+ else
+ exit('https://cdnapi.continiaonline.com/api/v1.0');
+
+ end;
+
+ local procedure GetBaseUrlForLocalization(Localization: Text): Text
+ begin
+ OnBeforeGetBaseUrlForLocalization(Localization);
+
+ case Localization of
+ 'NZ', 'AU':
+ exit('https://aue-cdnapi.continiaonline.com/api/v1.0/');
+ 'NL':
+ exit('https://weu-cdnapi.continiaonline.com/api/v1.0/');
+ end;
+ end;
+
+ internal procedure GetNetworkNameAsText(NetworkName: Enum "Continia E-Delivery Network"): Text
+ begin
+ exit(NetworkName.Names.Get(NetworkName.Ordinals.IndexOf(NetworkName.AsInteger())).ToLower());
+ end;
+
+ internal procedure GetGuidAsText(Value: Guid): Text[36]
+ begin
+ exit(CopyStr(DelChr(Value, '<>', '{}'), 1, 36))
+ end;
+
+
+ [IntegrationEvent(false, false)]
+ local procedure OnGetCOBaseUrl(var ReturnUrl: Text; var Handled: Boolean)
+ begin
+ end;
+
+ [IntegrationEvent(false, false)]
+ local procedure OnGetCdnBaseUrl(var ReturnUrl: Text; var Handled: Boolean)
+ begin
+ end;
+
+ [IntegrationEvent(false, false)]
+ local procedure OnBeforeGetBaseUrlForLocalization(var Localization: Text)
+ begin
+ end;
+
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/ContiniaIntegration.EnumExt.al b/Apps/W1/EDocumentConnectors/Continia/app/src/ContiniaIntegration.EnumExt.al
new file mode 100644
index 0000000000..bb88f757df
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/ContiniaIntegration.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.Continia;
+
+using Microsoft.eServices.EDocument.Integration;
+using Microsoft.eServices.EDocument.Integration.Interfaces;
+
+enumextension 6390 "Continia Integration" extends "Service Integration"
+{
+ value(6390; Continia)
+ {
+ Implementation = IDocumentSender = "Continia Integration Impl.", IDocumentReceiver = "Continia Integration Impl.";
+ }
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaConnectionSetup.Table.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaConnectionSetup.Table.al
new file mode 100644
index 0000000000..e09f2e0ecb
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaConnectionSetup.Table.al
@@ -0,0 +1,193 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+table 6390 "Continia Connection Setup"
+{
+ Access = Internal;
+ DataClassification = CustomerContent;
+ DataPerCompany = false;
+ Extensible = false;
+
+ fields
+ {
+ field(1; PK; Code[10])
+ {
+ Caption = 'Primary Key';
+ }
+ field(3; "Client Id"; Guid)
+ {
+ Caption = 'Client Id';
+ DataClassification = EndUserIdentifiableInformation;
+ }
+ field(4; "Client Secret"; Guid)
+ {
+ Caption = 'Client Secret';
+ DataClassification = EndUserIdentifiableInformation;
+ }
+ field(5; "Local Client Identifier"; Code[50])
+ {
+ Caption = 'Local Client Identifier';
+ DataClassification = EndUserIdentifiableInformation;
+ Editable = false;
+ }
+ field(6; "Access Token"; Guid)
+ {
+ Caption = 'Access Token';
+ }
+ field(7; "Token Timestamp"; DateTime)
+ {
+ Caption = 'Token Timestamp';
+ }
+ field(8; "Expires In (ms)"; Integer)
+ {
+ Caption = 'Expires In (ms)';
+ }
+ field(9; "Subscription Status"; Enum "Continia Subscription Status")
+ {
+ Caption = 'Subscription Status';
+ ToolTip = 'Specifies the status of the Continia subscription.';
+ }
+ field(10; "No. Of Participations"; Integer)
+ {
+ CalcFormula = count("Continia Participation");
+ Caption = 'No. Of Participations';
+ Editable = false;
+ FieldClass = FlowField;
+ ToolTip = 'Specifies the number of participations for the current company in the Continia Delivery Network.';
+ }
+ }
+
+ keys
+ {
+ key(Key1; PK)
+ {
+ Clustered = true;
+ }
+ }
+
+ internal procedure GetClientId(): SecretText
+ var
+ CredentialManagement: Codeunit "Continia Credential Management";
+ begin
+ exit(CredentialManagement.GetIsolatedStorageValue("Client Id", DataScope::Module));
+ end;
+
+ internal procedure GetClientSecret(): SecretText
+ var
+ CredentialManagement: Codeunit "Continia Credential Management";
+ begin
+ exit(CredentialManagement.GetIsolatedStorageValue("Client Secret", DataScope::Module));
+ end;
+
+ internal procedure SetClientId(Value: SecretText) UsedNewKey: Boolean
+ var
+ CredentialManagement: Codeunit "Continia Credential Management";
+ begin
+ exit(CredentialManagement.SetIsolatedStorageValue("Client Id", Value, DataScope::Module));
+ end;
+
+ internal procedure SetClientSecret(Value: SecretText) UsedNewKey: Boolean
+ var
+ CredentialManagement: Codeunit "Continia Credential Management";
+ begin
+ exit(CredentialManagement.SetIsolatedStorageValue("Client Secret", Value, DataScope::Module));
+ end;
+
+ internal procedure GetAccessTokenValue(): SecretText
+ var
+ CredentialManagement: Codeunit "Continia Credential Management";
+ begin
+ exit(CredentialManagement.GetIsolatedStorageValue("Access Token", DataScope::Module));
+ end;
+
+ local procedure AccessTokenHasValue(): Boolean
+ var
+ CredentialManagement: Codeunit "Continia Credential Management";
+ begin
+ exit(CredentialManagement.HasIsolatedStorageValue("Access Token", DataScope::Module));
+ end;
+
+ internal procedure SetAccessTokenValue(Value: SecretText) UsedNewKey: Boolean
+ var
+ CredentialManagement: Codeunit "Continia Credential Management";
+ begin
+ exit(CredentialManagement.SetIsolatedStorageValue("Access Token", Value, DataScope::Module));
+ end;
+
+ internal procedure DeleteAccessTokenValue(): Boolean
+ var
+ CredentialManagement: Codeunit "Continia Credential Management";
+ begin
+ "Token Timestamp" := 0DT;
+ "Expires In (ms)" := 0;
+ Modify();
+ exit(CredentialManagement.DeleteIsolatedStorageValue("Access Token", DataScope::Module));
+ end;
+
+ internal procedure ClearToken()
+ begin
+ if Get() then
+ DeleteAccessTokenValue();
+ end;
+
+ internal procedure AcquireTokenFromCache(var NewAccessTokenValue: SecretText; var NewTokenTimestamp: DateTime; var NewExpiresIn: Integer; var NewNextUpdateInMs: Integer; Refresh: Boolean): Boolean
+ var
+ TokenExpiresIn: Integer;
+ begin
+ Clear(NewTokenTimestamp);
+ Clear(NewAccessTokenValue);
+
+ if Get() then
+ if AccessTokenHasValue() then
+ if "Token Timestamp" <> 0DT then begin
+ if Refresh then
+ TokenExpiresIn := GetTokenRefreshRateInMs("Expires In (ms)")
+ else
+ TokenExpiresIn := GetTokenExpiresInMs("Expires In (ms)");
+
+ if ((CurrentDateTime - "Token Timestamp") < TokenExpiresIn) then begin
+ NewAccessTokenValue := GetAccessTokenValue();
+ NewTokenTimestamp := "Token Timestamp";
+ NewExpiresIn := "Expires In (ms)";
+ NewNextUpdateInMs := GetTokenRefreshRateInMs("Expires In (ms)");
+ exit(true);
+ end;
+ end;
+ end;
+
+ internal procedure SetAccessToken(Token: SecretText; ExpiresIn: Integer)
+ var
+ HasData: Boolean;
+ begin
+ ReadIsolation := IsolationLevel::UpdLock;
+ HasData := Get();
+
+ "Token Timestamp" := CurrentDateTime;
+ "Expires In (ms)" := GetTokenExpiresInMs(ExpiresIn);
+ SetAccessTokenValue(Token);
+
+ if HasData then
+ Modify()
+ else
+ Insert();
+ end;
+
+ local procedure GetTokenRefreshRateInMs(ExpiresIn: Integer): Integer
+ var
+ RefreshRate: Decimal;
+ begin
+ RefreshRate := 0.25;
+ exit(Round((ExpiresIn * RefreshRate), 100, '='));
+ end;
+
+ internal procedure GetTokenExpiresInMs(ExpiresIn: Integer): Integer
+ var
+ RefreshRate: Decimal;
+ begin
+ RefreshRate := 0.95;
+ exit(Round((ExpiresIn * RefreshRate), 100, '='));
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaEDocument.TableExt.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaEDocument.TableExt.al
new file mode 100644
index 0000000000..c7ce96c93e
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaEDocument.TableExt.al
@@ -0,0 +1,13 @@
+tableextension 6391 "Continia E-Document" extends "E-Document"
+{
+ fields
+ {
+ field(6391; "Continia Document Id"; Guid)
+ {
+ DataClassification = CustomerContent;
+ Caption = 'Continia Document Id';
+ ToolTip = 'Specifies the unique identifier in the Continia Delivery Network.';
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaEDocumentProcessing.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaEDocumentProcessing.Codeunit.al
new file mode 100644
index 0000000000..8d2bf7b3d8
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaEDocumentProcessing.Codeunit.al
@@ -0,0 +1,281 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using Microsoft.eServices.EDocument;
+using Microsoft.eServices.EDocument.Integration.Receive;
+using Microsoft.eServices.EDocument.Integration.Send;
+using System.Telemetry;
+using System.Utilities;
+
+codeunit 6391 "Continia EDocument Processing"
+{
+ Access = Internal;
+
+ internal procedure SendEDocument(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; SendContext: Codeunit SendContext)
+ var
+ EDocumentServiceStatus: Record "E-Document Service Status";
+ ApiRequests: Codeunit "Continia Api Requests";
+ FeatureTelemetry: Codeunit "Feature Telemetry";
+ begin
+ EDocumentServiceStatus.Get(EDocument."Entry No", EDocumentService.Code);
+
+ case EDocumentServiceStatus.Status of
+ EDocumentServiceStatus.Status::Exported:
+ ApiRequests.SendDocument(EDocument, SendContext);
+ EDocumentServiceStatus.Status::"Sending Error":
+ if IsNullGuid(EDocument."Continia Document Id") then
+ ApiRequests.SendDocument(EDocument, SendContext);
+ end;
+
+ FeatureTelemetry.LogUptake('', ExternalServiceTok, Enum::"Feature Uptake Status"::Used);
+ end;
+
+ internal procedure GetTechnicalResponse(var EDocument: Record "E-Document"; SendContext: Codeunit SendContext): Boolean
+ var
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ ApiRequests.SetSuppressError(true);
+
+ exit(ApiRequests.GetTechnicalResponse(EDocument, SendContext));
+ end;
+
+ internal procedure GetLastDocumentBusinessResponses(var EDocument: Record "E-Document"; ActionContext: Codeunit ActionContext) Updated: Boolean
+ var
+ ApiRequests: Codeunit "Continia Api Requests";
+ EDocumentErrorHelper: Codeunit "E-Document Error Helper";
+ Success: Boolean;
+ StatusDescription: Text;
+ begin
+ ApiRequests.SetSuppressError(true);
+ Success := ApiRequests.GetBusinessResponses(EDocument."Continia Document Id", ActionContext);
+ if not Success then
+ exit(false);
+
+ if IsDocumentApproved(ActionContext.Http().GetHttpResponseMessage()) then begin
+ ActionContext.Status().SetStatus(Enum::"E-Document Service Status"::Approved);
+ exit(true);
+ end;
+
+ if IsDocumentRejected(ActionContext.Http().GetHttpResponseMessage(), StatusDescription) then begin
+ ActionContext.Status().SetStatus(Enum::"E-Document Service Status"::Rejected);
+ if StatusDescription <> '' then
+ EDocumentErrorHelper.LogWarningMessage(EDocument, EDocument, EDocument."Entry No", StatusDescription);
+ exit(true);
+ end;
+ end;
+
+ local procedure IsDocumentApproved(HttpResponse: HttpResponseMessage): Boolean
+ var
+ ResponseCode: Text;
+ StatusDescription: Text;
+ BusinessResponses: XmlNodeList;
+ BusinessResponseNode: XmlNode;
+ i: Integer;
+ IsApproved: Boolean;
+ begin
+ if not GetBusinessResponses(HttpResponse, BusinessResponses) then
+ exit(false);
+
+ for i := 1 to BusinessResponses.Count do begin
+ BusinessResponses.Get(i, BusinessResponseNode);
+ ResponseCode := GetResponseCodeFromBusinessResponse(BusinessResponseNode, StatusDescription);
+ if IsResponseCodeRejected(ResponseCode) then
+ exit(false);
+
+ if IsResponseCodeApproved(ResponseCode) then
+ IsApproved := true;
+ end;
+
+ exit(IsApproved);
+ end;
+
+ local procedure IsDocumentRejected(HttpResponse: HttpResponseMessage; var StatusDescription: Text): Boolean
+ var
+ BusinessResponses: XmlNodeList;
+ BusinessResponseNode: XmlNode;
+ ResponseCode: Text;
+ i: Integer;
+ begin
+ if not GetBusinessResponses(HttpResponse, BusinessResponses) then
+ exit(false);
+
+ for i := 1 to BusinessResponses.Count do begin
+ BusinessResponses.Get(i, BusinessResponseNode);
+ ResponseCode := GetResponseCodeFromBusinessResponse(BusinessResponseNode, StatusDescription);
+ if IsResponseCodeRejected(ResponseCode) then
+ exit(true);
+ end;
+ end;
+
+ local procedure GetResponseCodeFromBusinessResponse(BusinessResponseNode: XmlNode; var StatusDescription: Text) ResponseCode: Text
+ var
+ TempNode: XmlNode;
+ Reason: Text;
+ ReasonCode: Text;
+ begin
+ if BusinessResponseNode.SelectSingleNode('response_code', TempNode) then
+ ResponseCode := TempNode.AsXmlElement().InnerText;
+
+ if BusinessResponseNode.SelectSingleNode('reason_code', TempNode) then
+ ReasonCode := TempNode.AsXmlElement().InnerText;
+
+ if BusinessResponseNode.SelectSingleNode('reason', TempNode) then
+ Reason := TempNode.AsXmlElement().InnerText;
+
+ if (ReasonCode = '') and (Reason = '') then begin
+ if IsResponseCodeRejected(ResponseCode) then
+ StatusDescription := UnknownRejectionReasonErr
+ end else
+ StatusDescription := StrSubstNo(ReasonLbl, ReasonCode, Reason);
+ end;
+
+ local procedure GetBusinessResponses(HttpResponse: HttpResponseMessage; var BusinessResponses: XmlNodeList): Boolean
+ var
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody = '' then
+ exit(false);
+
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+
+ if not ResponseXmlDoc.SelectNodes('/document_business_responses/document_business_response', BusinessResponses) then
+ exit(false);
+
+ exit(BusinessResponses.Count > 0)
+ end;
+
+ local procedure IsResponseCodeApproved(ResponseCode: Text): Boolean
+ begin
+ exit(ResponseCode in ['AP', 'CA', 'PD', 'BusinessAccept']);
+ end;
+
+ local procedure IsResponseCodeRejected(ResponseCode: Text): Boolean
+ begin
+ exit(ResponseCode in ['RE', 'BusinessReject']);
+ end;
+
+ procedure ReceiveDocuments(var EDocumentService: Record "E-Document Service"; ReceivedEDocuments: Codeunit "Temp Blob List"; ReceiveContext: Codeunit ReceiveContext)
+ var
+ TempBlob: Codeunit "Temp Blob";
+ ApiRequests: Codeunit "Continia Api Requests";
+ OutStream: OutStream;
+ ContentData: Text;
+ DocumentResponse: XmlDocument;
+ DocumentNodeList: XmlNodeList;
+ DocumentNode: XmlNode;
+ i: Integer;
+ begin
+ if not ApiRequests.GetDocumentsForCompany(ReceiveContext) then
+ exit;
+
+ ReceiveContext.Http().GetHttpResponseMessage().Content.ReadAs(ContentData);
+
+ if not XmlDocument.ReadFrom(ContentData, DocumentResponse) then
+ exit;
+
+ if not DocumentResponse.SelectNodes('/documents/document', DocumentNodeList) then
+ exit;
+
+ for i := 1 to DocumentNodeList.Count do begin
+ DocumentNodeList.Get(i, DocumentNode);
+ // Check if the document should be processed with current EDocumentService
+ if DocumentSupportedByEDocumentService(EDocumentService, DocumentNode) then begin
+ Clear(TempBlob);
+ TempBlob.CreateOutStream(OutStream, TextEncoding::UTF8);
+ DocumentNode.WriteTo(OutStream);
+ ReceivedEDocuments.Add(TempBlob);
+ end;
+ end;
+ end;
+
+ local procedure DocumentSupportedByEDocumentService(EDocumentService: Record "E-Document Service"; DocumentNode: XmlNode): Boolean
+ var
+ ActivatedNetworkProfile: Record "Continia Activated Net. Prof.";
+ ParticipationProfileIdNode: XmlNode;
+ ParticipationNetworkProfileId: Guid;
+ begin
+ DocumentNode.SelectSingleNode('participation_profile_id', ParticipationProfileIdNode);
+ Evaluate(ParticipationNetworkProfileId, ParticipationProfileIdNode.AsXmlElement().InnerText);
+
+ ActivatedNetworkProfile.SetCurrentKey(Id);
+ ActivatedNetworkProfile.SetRange(Id, ParticipationNetworkProfileId);
+ if not ActivatedNetworkProfile.FindFirst() then
+ exit(false);
+
+ if EDocumentService.Code = ActivatedNetworkProfile."E-Document Service Code" then
+ exit(true);
+ end;
+
+ procedure DownloadDocument(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; DocumentMetadata: Codeunit "Temp Blob"; ReceiveContext: Codeunit ReceiveContext)
+ var
+ ApiRequests: Codeunit "Continia Api Requests";
+ XMLFileToken: Text;
+ XmlDocNode: XmlNode;
+ XMLFileTokenNode: XmlNode;
+ XMLDocumentIdNode: XmlNode;
+ InStream: InStream;
+ DocumentInfoXml: XmlDocument;
+ CurrentEDocumentNode: XmlNode;
+ begin
+ DocumentMetadata.CreateInStream(InStream, TextEncoding::UTF8);
+ XmlDocument.ReadFrom(InStream, DocumentInfoXml);
+ DocumentInfoXml.SelectSingleNode('document', CurrentEDocumentNode);
+
+ CurrentEDocumentNode.SelectSingleNode('document_id', XMLDocumentIdNode);
+ Evaluate(EDocument."Continia Document Id", XMLDocumentIdNode.AsXmlElement().InnerText);
+ EDocument.Modify();
+
+ CurrentEDocumentNode.SelectSingleNode('xml_document', XmlDocNode);
+ XmlDocNode.SelectSingleNode('file_token', XMLFileTokenNode);
+ XMLFileToken := XMLFileTokenNode.AsXmlElement().InnerText;
+
+ // Download XML file from XMLFileToken and save to TempBlob
+ ApiRequests.DownloadFileFromUrl(XMLFileToken, ReceiveContext);
+ end;
+
+ internal procedure MarkFetched(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var DocumentBlob: Codeunit "Temp Blob"; ReceiveContext: Codeunit ReceiveContext)
+ var
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ // Mark document as processed in Continia Online
+ ApiRequests.MarkDocumentAsProcessed( EDocument."Continia Document Id", ReceiveContext);
+ end;
+
+ procedure GetCancellationStatus(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; ActionContext: Codeunit ActionContext) Success: Boolean
+ var
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ exit(ApiRequests.CancelDocument(EDocument."Continia Document Id", ActionContext));
+ end;
+
+ [EventSubscriber(ObjectType::Page, Page::"E-Document Service", OnAfterValidateEvent, "Service Integration V2", true, true)]
+ local procedure OnAfterValidateServiceIntegration(var Rec: Record "E-Document Service")
+ begin
+ if Rec."Service Integration V2" <> Rec."Service Integration V2"::Continia then
+ exit;
+
+ if Rec."Document Format" = Rec."Document Format"::"Data Exchange" then
+ Error(DocumentFormatUnsupportedErr);
+ end;
+
+ [EventSubscriber(ObjectType::Page, Page::"E-Document Service", OnAfterValidateEvent, "Export Format", true, true)]
+ local procedure OnAfterValidateDocumentFormat(var Rec: Record "E-Document Service")
+ begin
+ if Rec."Service Integration V2" <> Rec."Service Integration V2"::Continia then
+ exit;
+
+ if Rec."Document Format" = Rec."Document Format"::"Data Exchange" then
+ Error(DocumentFormatUnsupportedErr);
+ end;
+
+ var
+ ExternalServiceTok: Label 'ExternalServiceConnector', Locked = true;
+ UnknownRejectionReasonErr: Label 'Unknown rejection reason';
+ ReasonLbl: Label 'Reason: %1 - %2', Comment = '%1 - Reason code, %2 - Reason description';
+ DocumentFormatUnsupportedErr: Label 'Data Exchange is not supported with the Continia Service Integration in this version';
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaEnvCleanupSubscr.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaEnvCleanupSubscr.Codeunit.al
new file mode 100644
index 0000000000..7fda2de999
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaEnvCleanupSubscr.Codeunit.al
@@ -0,0 +1,37 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using System.DataAdministration;
+using System.Environment;
+
+codeunit 6398 "Continia Env. Cleanup Subscr."
+{
+ Access = Internal;
+
+ [EventSubscriber(ObjectType::Codeunit, Codeunit::"Environment Cleanup", OnClearCompanyConfig, '', false, false)]
+ local procedure CleanupCompanyConfiguration(CompanyName: Text; SourceEnv: Enum "Environment Type"; DestinationEnv: Enum "Environment Type")
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ Participation: Record "Continia Participation";
+ ParticipationProfiles: Record "Continia Activated Net. Prof.";
+ EnvironmentInformation: Codeunit "Environment Information";
+ begin
+ if not EnvironmentInformation.IsSaaSInfrastructure() then
+ exit;
+
+ if CompanyName = '' then
+ exit;
+
+ ConnectionSetup.ChangeCompany(CompanyName);
+ ConnectionSetup.DeleteAll();
+
+ Participation.ChangeCompany(CompanyName);
+ Participation.DeleteAll();
+
+ ParticipationProfiles.ChangeCompany(CompanyName);
+ ParticipationProfiles.DeleteAll();
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaExtConnectionSetup.Page.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaExtConnectionSetup.Page.al
new file mode 100644
index 0000000000..8d52d2de2d
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaExtConnectionSetup.Page.al
@@ -0,0 +1,163 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using System.Environment;
+
+page 6390 "Continia Ext. Connection Setup"
+{
+ ApplicationArea = Basic, Suite;
+ Caption = 'Continia E-Document External Connection Setup';
+ DeleteAllowed = false;
+ Editable = false;
+ Extensible = false;
+ InsertAllowed = false;
+ ModifyAllowed = false;
+ PageType = Card;
+ SourceTable = "Continia Connection Setup";
+ UsageCategory = None;
+
+ layout
+ {
+ area(Content)
+ {
+ group(General)
+ {
+ field(SubscriptionStatus; Rec."Subscription Status")
+ {
+ Editable = false;
+ ShowMandatory = true;
+ }
+ field(NoOfParticipations; Rec."No. Of Participations")
+ {
+ ShowMandatory = true;
+
+ trigger OnDrillDown()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ Participations: Page "Continia Participations";
+ ProgressWindow: Dialog;
+ begin
+ ProgressWindow.Open(ProcessingWindowMsg);
+ if Participation.FindSet() then
+ repeat
+ ApiRequests.GetParticipation(Participation);
+ ApiRequests.GetAllParticipationProfiles(Participation);
+ until Participation.Next() = 0;
+
+ ProgressWindow.Close();
+ Participations.Run();
+ end;
+ }
+ }
+ }
+ }
+
+ actions
+ {
+ area(Promoted)
+ {
+ actionref(RegisterNewActionRef; RegisterNewParticipation) { }
+ group(SubscriptionGroup)
+ {
+ Caption = 'Subscription';
+ actionref(EditCompanyInformationActionRef; EditCompanyInformation) { }
+ actionref(CancelSubscriptionActionRef; CancelSubscription) { }
+ }
+ }
+ area(Processing)
+ {
+ action(RegisterNewParticipation)
+ {
+ Caption = 'Register new participation';
+ Enabled = CanEditParticipation;
+ Image = New;
+ ToolTip = 'Register a new participation in the Continia Delivery Network.';
+
+ trigger OnAction()
+ var
+ OnboardingWizard: Page "Continia Onboarding Wizard";
+ begin
+ OnboardingWizard.Run();
+ CurrPage.Update(false);
+ end;
+ }
+ action(EditCompanyInformation)
+ {
+ Caption = 'Edit Company Information';
+ Enabled = ActionsEnabled and CanEditParticipation;
+ Image = Company;
+ ToolTip = 'Edit the company information for the Continia subscription.';
+
+ trigger OnAction()
+ var
+ ActivationMgt: Codeunit "Continia Subscription Mgt.";
+ OnBoardingWizard: Page "Continia Onboarding Wizard";
+ RunScenario: Enum "Continia Wizard Scenario";
+ begin
+ if ActivationMgt.HasOtherAppsInSubscription() then
+ Message(UseContiniaSolutionMgtMsg)
+ else begin
+ OnBoardingWizard.SetRunScenario(RunScenario::EditSubscriptionInfo);
+ OnBoardingWizard.Run();
+ end;
+ end;
+ }
+ action(CancelSubscription)
+ {
+ Caption = 'Cancel Subscription';
+ Enabled = ActionsEnabled and CanEditParticipation;
+ Image = Cancel;
+ Ellipsis = true;
+ ToolTip = 'Cancels the Continia subscription. You will not be able to send or receive e-documents using the Continia Delivery Network anymore.';
+
+ trigger OnAction()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ ActivationMgt: Codeunit "Continia Subscription Mgt.";
+ begin
+ if Confirm(UnsubscribeQst) then begin
+ if Participation.FindSet() then
+ repeat
+ ApiRequests.DeleteParticipation(Participation);
+ until Participation.Next() = 0;
+
+ ActivationMgt.Unsubscribe(true);
+ CurrPage.Update(false);
+ end
+ end;
+ }
+ }
+ }
+
+ trigger OnOpenPage()
+ var
+ OnboardingHelper: Codeunit "Continia Onboarding Helper";
+ EnvironmentInformation: Codeunit "Environment Information";
+ begin
+ if not EnvironmentInformation.IsSaaSInfrastructure() then
+ Error(NotSupportedOnPremisesErr);
+
+ CanEditParticipation := OnboardingHelper.HasModifyPermissionOnParticipation();
+ if not Rec.Get() then begin
+ Rec.Init();
+ Rec.Insert()
+ end;
+ end;
+
+ trigger OnAfterGetRecord()
+ begin
+ ActionsEnabled := true;
+ end;
+
+ var
+ ActionsEnabled, CanEditParticipation : Boolean;
+ UnsubscribeQst: Label 'Are you sure you want to cancel the subscription? You will not be able to send or receive e-documents using the Continia Delivery Network anymore.';
+ UseContiniaSolutionMgtMsg: Label 'There are other Continia apps in this subscription. In these cases you can only change the company information from the Continia Solution Management page.';
+ ProcessingWindowMsg: Label 'Updating data from Continia Online';
+ NotSupportedOnPremisesErr: Label 'The Continia E-Document Service is not supported in on-premises environments.';
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaIntegrationImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaIntegrationImpl.Codeunit.al
new file mode 100644
index 0000000000..d99512ba6d
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Implementation/ContiniaIntegrationImpl.Codeunit.al
@@ -0,0 +1,93 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using System.Utilities;
+using Microsoft.EServices.EDocument;
+using Microsoft.eServices.EDocument.Integration.Receive;
+using Microsoft.eServices.EDocument.Integration.Send;
+using Microsoft.eServices.EDocument.Integration.Interfaces;
+
+codeunit 6390 "Continia Integration Impl." implements IDocumentSender, IDocumentResponseHandler, IDocumentReceiver, ISentDocumentActions, IReceivedDocumentMarker
+{
+ Access = Internal;
+
+ #region IDocumentSender
+
+ procedure Send(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; SendContext: Codeunit SendContext)
+ var
+ EDocumentProcessing: Codeunit "Continia EDocument Processing";
+ begin
+ EDocumentProcessing.SendEDocument(EDocument, EDocumentService, SendContext);
+ end;
+
+ procedure GetResponse(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; SendContext: Codeunit SendContext): Boolean
+ var
+ EDocumentProcessing: Codeunit "Continia EDocument Processing";
+ begin
+ exit(EDocumentProcessing.GetTechnicalResponse(EDocument, SendContext));
+ end;
+
+ #endregion
+
+ #region IDocumentReceiver
+
+ procedure ReceiveDocuments(var EDocumentService: Record "E-Document Service"; DocumentsMetadata: Codeunit "Temp Blob List"; ReceiveContext: Codeunit ReceiveContext)
+ var
+ EDocumentProcessing: Codeunit "Continia EDocument Processing";
+ begin
+ EDocumentProcessing.ReceiveDocuments(EDocumentService, DocumentsMetadata, ReceiveContext);
+ end;
+
+ procedure DownloadDocument(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; DocumentMetadata: Codeunit "Temp Blob"; ReceiveContext: Codeunit ReceiveContext)
+ var
+ EDocumentProcessing: Codeunit "Continia EDocument Processing";
+ begin
+ EDocumentProcessing.DownloadDocument(EDocument, EDocumentService, DocumentMetadata, ReceiveContext);
+ end;
+
+ #endregion
+
+ #region IReceivedDocumentMarker
+
+ procedure MarkFetched(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var DocumentBlob: Codeunit "Temp Blob"; ReceiveContext: Codeunit ReceiveContext)
+ var
+ EDocumentProcessing: Codeunit "Continia EDocument Processing";
+ begin
+ EDocumentProcessing.MarkFetched(EDocument, EDocumentService, DocumentBlob, ReceiveContext);
+ end;
+
+ #endregion
+
+ #region ISentDocumentActions
+
+ procedure GetApprovalStatus(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; ActionContext: Codeunit ActionContext): Boolean
+ var
+ EDocumentProcessing: Codeunit "Continia EDocument Processing";
+ begin
+ exit(EDocumentProcessing.GetLastDocumentBusinessResponses(EDocument, ActionContext));
+ end;
+
+ procedure GetCancellationStatus(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; ActionContext: Codeunit ActionContext): Boolean
+ var
+ EDocumentProcessing: Codeunit "Continia EDocument Processing";
+ begin
+ exit(EDocumentProcessing.GetCancellationStatus(EDocument, EDocumentService, ActionContext));
+ end;
+
+ #endregion
+
+ [EventSubscriber(ObjectType::Page, Page::"E-Document Service", OnBeforeOpenServiceIntegrationSetupPage, '', false, false)]
+ local procedure OnBeforeOpenServiceIntegrationSetupPage(EDocumentService: Record "E-Document Service"; var IsServiceIntegrationSetupRun: Boolean)
+ var
+ ExtConnectionSetup: Page "Continia Ext. Connection Setup";
+ begin
+ if EDocumentService."Service Integration V2" <> EDocumentService."Service Integration V2"::Continia then
+ exit;
+
+ ExtConnectionSetup.Run();
+ IsServiceIntegrationSetupRun := true;
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaEDeliveryNetwork.Enum.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaEDeliveryNetwork.Enum.al
new file mode 100644
index 0000000000..686ed1cf1f
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaEDeliveryNetwork.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.Continia;
+
+enum 6390 "Continia E-Delivery Network"
+{
+ Access = Internal;
+ Extensible = false;
+
+ value(0; Peppol)
+ {
+ Caption = 'Peppol';
+ }
+ value(1; Nemhandel)
+ {
+ Caption = 'NemHandel';
+ }
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaNetworkIdList.Page.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaNetworkIdList.Page.al
new file mode 100644
index 0000000000..191eb61abd
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaNetworkIdList.Page.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.Continia;
+
+page 6395 "Continia Network Id. List"
+{
+ ApplicationArea = All;
+ Caption = 'Network Identifier List';
+ DeleteAllowed = false;
+ Editable = false;
+ Extensible = false;
+ InsertAllowed = false;
+ LinksAllowed = false;
+ ModifyAllowed = false;
+ PageType = List;
+ ShowFilter = false;
+ SourceTable = "Continia Network Identifier";
+ SourceTableView = sorting("Scheme Id") order(ascending);
+ UsageCategory = None;
+
+ layout
+ {
+ area(Content)
+ {
+ repeater(Group)
+ {
+ field("Network Name"; Rec.Network) { }
+ field("Scheme Id"; Rec."Scheme Id") { }
+ field(Description; Rec.Description) { }
+ field("Identifier Type Id"; Rec."Identifier Type Id") { }
+ }
+ }
+ }
+
+ actions
+ {
+ area(Processing)
+ {
+ action(GetContiniaNetworkIdTypes)
+ {
+ Caption = 'Import Network ID Types';
+ Image = Import;
+ ToolTip = 'Imports all the Network ID Types from Continia API.';
+
+ trigger OnAction()
+ var
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ ApiRequests.GetNetworkIdTypes(Enum::"Continia E-Delivery Network"::Peppol);
+ ApiRequests.GetNetworkIdTypes(Enum::"Continia E-Delivery Network"::Nemhandel);
+ end;
+ }
+ }
+
+ }
+}
+
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaNetworkIdentifier.Table.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaNetworkIdentifier.Table.al
new file mode 100644
index 0000000000..a66220c133
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaNetworkIdentifier.Table.al
@@ -0,0 +1,74 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+table 6393 "Continia Network Identifier"
+{
+ Access = Internal;
+ Caption = 'Network Identifier';
+ DataClassification = SystemMetadata;
+ DrillDownPageId = "Continia Network Id. List";
+
+ fields
+ {
+ field(1; Id; Guid)
+ {
+ Caption = 'ID';
+ }
+ field(2; Network; Enum "Continia E-Delivery Network")
+ {
+ Caption = 'Network';
+ ToolTip = 'Specifies the Network Name of the Network Identifier.';
+ }
+ field(3; "Identifier Type Id"; Text[4])
+ {
+ Caption = 'Identifier Type Id';
+ ToolTip = 'Specifies the EAS code of the identifier type.';
+ }
+ field(4; Description; Text[250])
+ {
+ Caption = 'Description';
+ ToolTip = 'Specifies the description of the identifier type.';
+ }
+ field(5; "Scheme Id"; Text[50])
+ {
+ Caption = 'Scheme Id';
+ ToolTip = 'Specifies the scheme Id of the identifier type.';
+ }
+ field(10; Default; Boolean)
+ {
+ Caption = 'Default';
+ }
+ field(11; "Default in Country"; Code[10])
+ {
+ Caption = 'Default in Country';
+ }
+ field(12; "VAT in Country"; Code[10])
+ {
+ Caption = 'VAT Identification in Country';
+ }
+ field(13; "ICD Code"; Boolean)
+ {
+ Caption = 'ICD Code';
+ }
+ field(14; "Validation Rule"; Text[50])
+ {
+ Caption = 'Validation Rule';
+ }
+ field(21; Enabled; Boolean)
+ {
+ Caption = 'Enabled';
+ }
+ }
+
+ keys
+ {
+ key(Key1; Id)
+ {
+ Clustered = true;
+ }
+ key(Key2; "Scheme Id") { }
+ }
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaNetworkProfile.Table.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaNetworkProfile.Table.al
new file mode 100644
index 0000000000..dd71ea9f60
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaNetworkProfile.Table.al
@@ -0,0 +1,65 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+table 6394 "Continia Network Profile"
+{
+ Access = Internal;
+ Caption = 'Network Profile';
+ DataClassification = SystemMetadata;
+ DrillDownPageId = "Continia Network Profile List";
+
+ fields
+ {
+ field(1; Id; Guid)
+ {
+ Caption = 'ID';
+ }
+ field(2; Network; Enum "Continia E-Delivery Network")
+ {
+ Caption = 'Network Name';
+ ToolTip = 'Specifies the network name of the profile.';
+ }
+ field(3; "Process Identifier"; Text[250])
+ {
+ Caption = 'Process Identifier';
+ ToolTip = 'Specifies the process identifier value of the profile.';
+ }
+ field(4; "Document Identifier"; Text[250])
+ {
+ Caption = 'Document Identifier';
+ ToolTip = 'Specifies the document identifier value of the profile.';
+ }
+ field(5; Description; Text[250])
+ {
+ Caption = 'Description';
+ ToolTip = 'Specifies the description of the network profile.';
+ }
+ field(6; "Customization Id"; Text[250])
+ {
+ Caption = 'Customization Id';
+ }
+ field(10; Enabled; Boolean)
+ {
+ Caption = 'Enabled';
+ }
+ field(13; Mandatory; Boolean)
+ {
+ Caption = 'Mandatory';
+ }
+ field(14; "Mandatory for Country"; Code[50])
+ {
+ Caption = 'Mandatory for Country';
+ }
+ }
+
+ keys
+ {
+ key(Key1; Id)
+ {
+ Clustered = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaNetworkProfileList.Page.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaNetworkProfileList.Page.al
new file mode 100644
index 0000000000..a8404a0a3d
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaNetworkProfileList.Page.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.Continia;
+
+page 6396 "Continia Network Profile List"
+{
+ ApplicationArea = All;
+ Caption = 'Network Profiles';
+ DeleteAllowed = false;
+ Editable = false;
+ Extensible = false;
+ InsertAllowed = false;
+ LinksAllowed = false;
+ ModifyAllowed = false;
+ PageType = List;
+ SourceTable = "Continia Network Profile";
+ UsageCategory = None;
+
+ layout
+ {
+ area(Content)
+ {
+ repeater(Group)
+ {
+ field(Network; Rec.Network) { }
+ field(Description; Rec.Description) { }
+ field("Process Identifier"; Rec."Process Identifier") { }
+ field("Document Identifier"; Rec."Document Identifier") { }
+ }
+ }
+ }
+
+ actions
+ {
+ area(Processing)
+ {
+ action(GetNetworkProfiles)
+ {
+ Caption = 'Import Network Profiles';
+ Image = Import;
+ ToolTip = 'Imports all the Network Profiles from Continia API.';
+
+ trigger OnAction()
+ var
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ ApiRequests.GetNetworkProfiles(Enum::"Continia E-Delivery Network"::Peppol);
+ ApiRequests.GetNetworkProfiles(Enum::"Continia E-Delivery Network"::Nemhandel);
+ end;
+ }
+ }
+
+ }
+}
+
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaProfileDirection.Enum.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaProfileDirection.Enum.al
new file mode 100644
index 0000000000..94aab852ce
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Metadata/ContiniaProfileDirection.Enum.al
@@ -0,0 +1,24 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+enum 6391 "Continia Profile Direction"
+{
+ Access = Internal;
+ Extensible = false;
+
+ value(0; Outbound)
+ {
+ Caption = 'Outbound';
+ }
+ value(1; Inbound)
+ {
+ Caption = 'Inbound';
+ }
+ value(2; Both)
+ {
+ Caption = 'Both';
+ }
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ConEDoCServProfSel.Table.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ConEDoCServProfSel.Table.al
new file mode 100644
index 0000000000..1a2654a6b6
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ConEDoCServProfSel.Table.al
@@ -0,0 +1,144 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+table 6395 "Con. E-Doc. Serv. Prof. Sel."
+{
+ Access = Internal;
+ Caption = 'E-Document Service Network Profile Selection';
+ DataClassification = CustomerContent;
+ TableType = Temporary;
+
+ fields
+ {
+ field(1; Network; Enum "Continia E-Delivery Network")
+ {
+ Caption = 'Network';
+ ToolTip = 'Specifies E-Document Network.';
+ }
+ field(2; "Identifier Type Id"; Guid)
+ {
+ Caption = 'Identifier Type Id';
+ TableRelation = "Continia Network Identifier".Id where(Network = field(Network));
+ ToolTip = 'Specifies ID of E-Document Identifier Type.';
+ }
+ field(3; "Identifier Value"; Code[50])
+ {
+ Caption = 'Identifier Value';
+ ToolTip = 'Specifies E-Document Identifier Value.';
+ }
+ field(4; "Network Profile Id"; Guid)
+ {
+ Caption = 'Network Profile Id';
+ TableRelation = "Continia Network Profile".Id where(Network = field(Network));
+ ToolTip = 'Specifies ID of E-Document INetwork Profile.';
+ }
+ field(5; Indent; Integer)
+ {
+ Caption = 'Indent';
+ ToolTip = 'Specifies tree view indentation.';
+ }
+ field(6; "Participation Description"; Text[100])
+ {
+ Caption = 'Participation';
+ ToolTip = 'Specifies a description of Participation';
+ }
+ field(7; Description; Text[250])
+ {
+ Caption = 'Description';
+ ToolTip = 'Specifies a description of Network Profile.';
+ }
+ field(8; "Network Name"; Text[100])
+ {
+ Caption = 'Network';
+ ToolTip = 'Specifies E-Document Network Name';
+ }
+ field(9; "Profile Direction"; Text[100])
+ {
+ Caption = 'Profile Direction';
+ ToolTip = 'Specifies the direction of the profile.';
+ }
+ field(10; "E-Document Service Code"; Code[20])
+ {
+ Caption = 'E-Document Service Code';
+ ToolTip = 'Specifies the E-Document Service that would be linked to selected Network Profile.';
+ }
+ field(11; "Is Profile"; Boolean)
+ {
+ Caption = 'Is Profile';
+ ToolTip = 'Specifies if the record represents Network Profile.';
+ }
+ }
+ keys
+ {
+ key(PK; Network, "Identifier Type Id", "Identifier Value", "Network Profile Id")
+ {
+ Clustered = true;
+ }
+ }
+
+ internal procedure FillNetwork(ActivatedNetProf: Record "Continia Activated Net. Prof.")
+ var
+ EmptyGuid: Guid;
+ begin
+ Init();
+ Network := ActivatedNetProf.Network;
+ "Identifier Type Id" := EmptyGuid;
+ "Identifier Value" := '';
+ "Network Profile Id" := EmptyGuid;
+ "Network Name" := Format(ActivatedNetProf.Network);
+ Indent := 0;
+ InsertIfPossible();
+ end;
+
+ internal procedure FillParticipation(ActivatedNetProf: Record "Continia Activated Net. Prof.")
+ var
+ Participation: Record "Continia Participation";
+ EmptyGuid: Guid;
+ begin
+ if not Participation.Get(ActivatedNetProf.Network, ActivatedNetProf."Identifier Type Id", ActivatedNetProf."Identifier Value") then
+ exit;
+ Init();
+ Network := Participation.Network;
+ "Identifier Type Id" := Participation."Identifier Type Id";
+ "Identifier Value" := Participation."Identifier Value";
+ "Network Profile Id" := EmptyGuid;
+ "Participation Description" := GetParticipationDescription(Participation);
+ Indent := 1;
+ InsertIfPossible();
+ end;
+
+ internal procedure FillNetworkProfile(ActivatedNetProf: Record "Continia Activated Net. Prof.")
+ begin
+ ActivatedNetProf.CalcFields("Network Profile Description");
+ Init();
+ Network := ActivatedNetProf.Network;
+ "Identifier Type Id" := ActivatedNetProf."Identifier Type Id";
+ "Identifier Value" := ActivatedNetProf."Identifier Value";
+ "Network Profile Id" := ActivatedNetProf."Network Profile Id";
+ "Profile Direction" := Format(ActivatedNetProf."Profile Direction");
+ "E-Document Service Code" := ActivatedNetProf."E-Document Service Code";
+ Description := ActivatedNetProf."Network Profile Description";
+ Indent := 2;
+ "Is Profile" := true;
+ Insert(false);
+ end;
+
+ local procedure GetParticipationDescription(Participation: Record "Continia Participation"): Text[100]
+ var
+ NetworkIdentifier: Record "Continia Network Identifier";
+ ParticipationDescriptionPatternTxt: Label '%1 %2', Comment = '%1 - Scheme Id, %2 - Identifier Value';
+ begin
+ NetworkIdentifier := Participation.GetNetworkIdentifier();
+ exit(StrSubstNo(ParticipationDescriptionPatternTxt, NetworkIdentifier."Scheme Id", Participation."Identifier Value"));
+ end;
+
+ local procedure InsertIfPossible()
+ begin
+ if Find() then
+ exit;
+ Insert(false);
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ConEDocServNetProfiles.Page.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ConEDocServNetProfiles.Page.al
new file mode 100644
index 0000000000..3da5ec43ce
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ConEDocServNetProfiles.Page.al
@@ -0,0 +1,185 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using System.Utilities;
+
+page 6397 "Con. E-Doc. Serv. Net.Profiles"
+{
+ ApplicationArea = All;
+ Caption = 'E-Document Service Network Profiles';
+ Editable = false;
+ Extensible = false;
+ PageType = List;
+ Permissions = tabledata "Continia Activated Net. Prof." = RIMD;
+ SourceTable = "Continia Activated Net. Prof.";
+ UsageCategory = None;
+
+ layout
+ {
+ area(Content)
+ {
+ repeater(Group)
+ {
+ field(Network; NetworkName)
+ {
+ Caption = 'Network';
+ ToolTip = 'Specifies Network name of the Network Profile.';
+ }
+ field(Participation; ParticipationInfo)
+ {
+ Caption = 'Participation';
+ ToolTip = 'Specifies information about the Participation of the Network Profile.';
+ }
+ field("Network Profile Description"; Rec."Network Profile Description") { }
+ field("Profile Direction"; Rec."Profile Direction") { }
+ }
+ }
+ }
+
+ actions
+ {
+ area(Promoted)
+ {
+ actionref(AddCreation; Add) { }
+ actionref(RemoveProcessing; Remove) { }
+ }
+ area(Creation)
+ {
+ action(Add)
+ {
+ Caption = 'Add';
+ Image = Add;
+ Scope = Repeater;
+ ToolTip = 'Adds network profiles to the E-Document Service.';
+
+ trigger OnAction()
+ begin
+ AddNetworkProfile();
+ end;
+ }
+ }
+ area(Processing)
+ {
+ action(Remove)
+ {
+ Caption = 'Remove';
+ Image = Delete;
+ Scope = Repeater;
+ ToolTip = 'Removes selected network profiles from E-Document Service.';
+
+ trigger OnAction()
+ begin
+ RemoveNetworkProfiles();
+ end;
+ }
+ }
+ }
+
+ trigger OnAfterGetRecord()
+ var
+ NetworkIdentifier: Record "Continia Network Identifier";
+ ParticipationInfoPatternTxt: Label '%1 %2', Comment = '%1 - Scheme Id, %2 - Identifier Value';
+ TemporaryParticipationInfo: Text;
+ begin
+ ResetPreviousRecordParticipationInfo();
+ Clear(ParticipationInfo);
+ Clear(NetworkName);
+ if NetworkIdentifier.Get(Rec."Identifier Type Id") then
+ TemporaryParticipationInfo := StrSubstNo(ParticipationInfoPatternTxt, NetworkIdentifier."Scheme Id", Rec."Identifier Value");
+
+ if PreviousRecordParticipationInfo = TemporaryParticipationInfo then
+ exit;
+ PreviousRecordParticipationInfo := TemporaryParticipationInfo;
+ ParticipationInfo := TemporaryParticipationInfo;
+ NetworkName := Format(Rec.Network);
+ end;
+
+ internal procedure SetEDocumentServiceCode(PassedEDocumentServiceCode: Code[20])
+ begin
+ EDocumentServiceCode := PassedEDocumentServiceCode;
+ end;
+
+ local procedure AddNetworkProfile()
+ var
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ EDocServiceNetProfSel: Page "Con. E-Doc. Serv. Prof. Sel.";
+ SelectedNetworkNames: List of [Text];
+ begin
+ EDocServiceNetProfSel.SetEDocumentServiceCode(EDocumentServiceCode);
+ EDocServiceNetProfSel.FillRecords();
+ EDocServiceNetProfSel.LookupMode(true);
+ if EDocServiceNetProfSel.RunModal() <> Action::LookupOK then
+ exit;
+
+ EDocServiceNetProfSel.GetSelectedProfilesAndNetworks(ActivatedNetProf, SelectedNetworkNames);
+ if HandleMultipleNetworkNames(SelectedNetworkNames) then
+ UpdateNetworkProfilesBySelection(ActivatedNetProf);
+ CurrPage.Update();
+ end;
+
+ local procedure RemoveNetworkProfiles()
+ var
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ begin
+ CurrPage.SetSelectionFilter(ActivatedNetProf);
+ ActivatedNetProf.ModifyAll("E-Document Service Code", '', true);
+ CurrPage.Update();
+ end;
+
+ local procedure UpdateNetworkProfilesBySelection(var ActivatedNetProf: Record "Continia Activated Net. Prof.")
+ begin
+ if ActivatedNetProf.FindSet() then
+ repeat
+ ActivatedNetProf.Validate("E-Document Service Code", EDocumentServiceCode);
+ ActivatedNetProf.Modify(true);
+ until ActivatedNetProf.Next() = 0;
+ end;
+
+ local procedure HandleMultipleNetworkNames(var SelectedNetworkNames: List of [Text]): Boolean
+ var
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ConfirmManagement: Codeunit "Confirm Management";
+ LinkedNetworkNames: List of [Text];
+ SelectedNetworkName: Text;
+ InitialCountOfLinkedNetworks: Integer;
+ DifferentLinkedAndSelectedNetworkNamesQst: Label 'You have selected Network Profile(s) that belong to different Networks than those already linked to the E-Document Service. Are you sure you want to proceed?';
+ MultipleNetworksSelectedQst: Label 'You have selected Network Profiles from %1 different Networks. Are you sure you want to proceed?', Comment = '%1 - Number of selected Networks';
+ begin
+ LinkedNetworkNames := ActivatedNetProf.GetEDocServiceNetworkNames(EDocumentServiceCode);
+ InitialCountOfLinkedNetworks := LinkedNetworkNames.Count();
+
+ foreach SelectedNetworkName in SelectedNetworkNames do
+ if not LinkedNetworkNames.Contains(SelectedNetworkName) then
+ LinkedNetworkNames.Add(SelectedNetworkName);
+
+ if (LinkedNetworkNames.Count() > InitialCountOfLinkedNetworks) and (InitialCountOfLinkedNetworks > 0) then
+ if not ConfirmManagement.GetResponse(DifferentLinkedAndSelectedNetworkNamesQst) then
+ exit;
+
+ if SelectedNetworkNames.Count() > 1 then
+ if not ConfirmManagement.GetResponse(StrSubstNo(MultipleNetworksSelectedQst, SelectedNetworkNames.Count())) then
+ exit;
+ exit(true);
+ end;
+
+ local procedure ResetPreviousRecordParticipationInfo()
+ var
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ begin
+ ActivatedNetProf.SetView(Rec.GetView());
+ if not ActivatedNetProf.FindFirst() then
+ exit;
+ if Rec.RecordId() = ActivatedNetProf.RecordId() then
+ Clear(PreviousRecordParticipationInfo);
+ end;
+
+ var
+ EDocumentServiceCode: Code[20];
+ ParticipationInfo: Text;
+ PreviousRecordParticipationInfo: Text;
+ NetworkName: Text;
+
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ConEDocServProfSel.Page.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ConEDocServProfSel.Page.al
new file mode 100644
index 0000000000..76ffe4eeb8
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ConEDocServProfSel.Page.al
@@ -0,0 +1,74 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+page 6398 "Con. E-Doc. Serv. Prof. Sel."
+{
+ ApplicationArea = All;
+ Caption = 'E-Document Service Network Profile Selection';
+ Editable = false;
+ Extensible = false;
+ PageType = List;
+ SourceTable = "Con. E-Doc. Serv. Prof. Sel.";
+ SourceTableTemporary = true;
+ UsageCategory = None;
+
+ layout
+ {
+ area(Content)
+ {
+ repeater(Group)
+ {
+ IndentationColumn = Rec.Indent;
+ ShowAsTree = true;
+
+ field(Network; Rec."Network Name") { }
+ field("Participation Description"; Rec."Participation Description") { }
+ field(Description; Rec.Description) { }
+ field("Profile Direction"; Rec."Profile Direction") { }
+ field("E-Document Service Code"; Rec."E-Document Service Code") { }
+ }
+ }
+ }
+
+ internal procedure FillRecords(): Boolean
+ var
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ begin
+ ActivatedNetProf.SetFilter("E-Document Service Code", '<>%1', EDocumentServiceCode);
+ if ActivatedNetProf.FindSet() then
+ repeat
+ Rec.FillNetworkProfile(ActivatedNetProf);
+ Rec.FillParticipation(ActivatedNetProf);
+ Rec.FillNetwork(ActivatedNetProf);
+ until ActivatedNetProf.Next() = 0;
+ end;
+
+ internal procedure GetSelectedProfilesAndNetworks(var ActivatedNetProf: Record "Continia Activated Net. Prof."; var SelectedNetworkNames: List of [Text])
+ begin
+ ActivatedNetProf.Reset();
+ Clear(SelectedNetworkNames);
+
+ CurrPage.SetSelectionFilter(Rec);
+ if Rec.FindSet() then
+ repeat
+ if Rec."Is Profile" then begin
+ if ActivatedNetProf.Get(Rec.Network, Rec."Identifier Type Id", Rec."Identifier Value", Rec."Network Profile Id") then
+ ActivatedNetProf.Mark(true);
+ if not SelectedNetworkNames.Contains(Format(Rec.Network)) then
+ SelectedNetworkNames.Add(Format(Rec.Network));
+ end;
+ until Rec.Next() = 0;
+ ActivatedNetProf.MarkedOnly(true);
+ end;
+
+ internal procedure SetEDocumentServiceCode(PassedEDocumentServiceCode: Code[20])
+ begin
+ EDocumentServiceCode := PassedEDocumentServiceCode;
+ end;
+
+ var
+ EDocumentServiceCode: Code[20];
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaEDocumentService.PageExt.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaEDocumentService.PageExt.al
new file mode 100644
index 0000000000..4133c2ec84
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaEDocumentService.PageExt.al
@@ -0,0 +1,46 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using Microsoft.eServices.EDocument;
+using Microsoft.eServices.EDocument.Integration;
+
+pageextension 6390 "Continia E-Document Service" extends "E-Document Service"
+{
+ layout
+ {
+ addlast(General)
+ {
+ group(NetworkProfiles)
+ {
+ ShowCaption = false;
+ Visible = Rec."Service Integration V2" = Enum::"Service Integration"::Continia;
+
+ field("No. Of Network Profiles"; Rec."No. Of Network Profiles")
+ {
+ ApplicationArea = Basic, Suite;
+ ToolTip = 'Specifies the number of Continia network profiles associated with the E-Document Service.';
+
+ trigger OnDrillDown()
+ begin
+ OpenNetworkProfiles();
+ CurrPage.Update();
+ end;
+ }
+ }
+ }
+ }
+
+ local procedure OpenNetworkProfiles()
+ var
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ EDocServiceNetProfiles: Page "Con. E-Doc. Serv. Net.Profiles";
+ begin
+ ActivatedNetProf.SetRange("E-Document Service Code", Rec.Code);
+ EDocServiceNetProfiles.SetTableView(ActivatedNetProf);
+ EDocServiceNetProfiles.SetEDocumentServiceCode(Rec.Code);
+ EDocServiceNetProfiles.RunModal();
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaEDocumentService.TableExt.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaEDocumentService.TableExt.al
new file mode 100644
index 0000000000..26adf0f767
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaEDocumentService.TableExt.al
@@ -0,0 +1,21 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using Microsoft.eServices.EDocument;
+
+tableextension 6390 "Continia E-Document Service" extends "E-Document Service"
+{
+ fields
+ {
+ field(6390; "No. Of Network Profiles"; Integer)
+ {
+ CalcFormula = count("Continia Activated Net. Prof." where("E-Document Service Code" = field(Code)));
+ Caption = 'No. Of Network Profiles';
+ Editable = false;
+ FieldClass = FlowField;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaOnboardingHelper.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaOnboardingHelper.Codeunit.al
new file mode 100644
index 0000000000..c6c49dd8bd
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaOnboardingHelper.Codeunit.al
@@ -0,0 +1,634 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using Microsoft.Foundation.Address;
+using Microsoft.Foundation.Company;
+using Microsoft.eServices.EDocument;
+using System.Utilities;
+
+codeunit 6394 "Continia Onboarding Helper"
+{
+ Access = Internal;
+ Permissions = tabledata "Continia Network Profile" = rimd,
+ tabledata "Continia Network Identifier" = rimd,
+ tabledata "Continia Participation" = rimd,
+ tabledata "Continia Activated Net. Prof." = rimd;
+
+ internal procedure InitializeGeneralScenario(var TempCompanyContact: Record "Continia Participation" temporary; var TempParticipation: Record "Continia Participation" temporary; var ParticipationCountyVisible: Boolean; var ContactInfoCountyVisible: Boolean; var SkipCompanyInformation: Boolean; var IdentifierTypeDesc: Text)
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ FormatAddress: Codeunit "Format Address";
+ begin
+ TempCompanyContact.Init();
+ TempCompanyContact.Insert();
+
+ ParticipationCountyVisible := FormatAddress.UseCounty(TempParticipation."Country/Region Code");
+ ContactInfoCountyVisible := FormatAddress.UseCounty(TempCompanyContact."Country/Region Code");
+
+ if AreClientCredentialsValid() then begin
+ ShowProgressWindow(UpdatingDataProgressMsg);
+ GetNetworkMetadata(false);
+ GetContactInformation(TempCompanyContact, false);
+ CloseProgressWindow();
+ end;
+
+ FillParticipationWithCompanyInfo(TempParticipation, IdentifierTypeDesc);
+
+ if ConnectionSetup.Get() then
+ if (TempCompanyContact."Company Name" <> '') and (ConnectionSetup."Subscription Status" = ConnectionSetup."Subscription Status"::Subscription) then
+ SkipCompanyInformation := true;
+ end;
+
+ internal procedure GetContactInformation(var TempParticipationCompanyContact: Record "Continia Participation" temporary; ShowProgress: Boolean)
+ var
+ ActivationMgt: Codeunit "Continia Subscription Mgt.";
+ begin
+ if ShowProgress then
+ ShowProgressWindow(UpdatingDataProgressMsg);
+
+ ActivationMgt.GetClientInfoApp(TempParticipationCompanyContact, true);
+ if ShowProgress then
+ CloseProgressWindow();
+ end;
+
+ internal procedure AreClientCredentialsValid(): Boolean
+ var
+ CredentialManagement: Codeunit "Continia Credential Management";
+ begin
+ exit(CredentialManagement.IsClientCredentialsValid());
+ end;
+
+ internal procedure InitializeClient(PartnerUserName: Text; PartnerPassword: SecretText) PartnerId: Code[20]
+ var
+ ActivationMgt: Codeunit "Continia Subscription Mgt.";
+ begin
+ ShowProgressWindow(SendingDataProgressMsg);
+ ActivationMgt.InitializeContiniaClient(PartnerUserName, PartnerPassword, PartnerId);
+ AreClientCredentialsValid();
+ CloseProgressWindow();
+ end;
+
+ internal procedure GetNetworkMetadata(ShowProgress: Boolean)
+ var
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ if MetaDataLoaded then
+ exit;
+
+ if ShowProgress then
+ ShowProgressWindow(UpdatingDataProgressMsg);
+
+ ApiRequests.GetNetworkIdTypes(Enum::"Continia E-Delivery Network"::Peppol);
+ ApiRequests.GetNetworkIdTypes(Enum::"Continia E-Delivery Network"::Nemhandel);
+
+ ApiRequests.GetNetworkProfiles(Enum::"Continia E-Delivery Network"::Peppol);
+ ApiRequests.GetNetworkProfiles(Enum::"Continia E-Delivery Network"::Nemhandel);
+
+ if ShowProgress then
+ CloseProgressWindow();
+
+ MetaDataLoaded := true;
+ end;
+
+ internal procedure FillParticipationWithCompanyInfo(var TempParticipation: Record "Continia Participation" temporary; var IdentifierTypeDesc: Text)
+ var
+ CompanyInfo: Record "Company Information";
+ CountryRegion: Record "Country/Region";
+ begin
+ CompanyInfo.Get();
+ TempParticipation.Init();
+ if MetaDataLoaded then
+ SetDefaultIdentifierData(TempParticipation, IdentifierTypeDesc);
+
+ TempParticipation."Company Name" := CompanyInfo.Name;
+ TempParticipation."VAT Registration No." := CompanyInfo."VAT Registration No.";
+ TempParticipation.Address := CompanyInfo.Address;
+ TempParticipation."Post Code" := CompanyInfo."Post Code";
+ TempParticipation."Country/Region Code" := CompanyInfo."Country/Region Code";
+ if CountryRegion.Get(CompanyInfo."Country/Region Code") then begin
+ TempParticipation."Country/Region Code" := CountryRegion."ISO Code";
+ TempParticipation.County := CompanyInfo.County;
+ end;
+
+ TempParticipation."Your Name" := 'N/A';
+ TempParticipation."Contact Email" := 'N/A';
+ TempParticipation."Contact Name" := 'N/A';
+ TempParticipation."Contact Phone No." := 'N/A';
+ end;
+
+ internal procedure SetDefaultIdentifierData(var TempParticipation: Record "Continia Participation" temporary; var IdentifierTypeDesc: Text)
+ var
+ CompanyInformation: Record "Company Information";
+ NetworkIdentifier: Record "Continia Network Identifier";
+ EmptyGuid: Guid;
+ begin
+ CompanyInformation.Get();
+
+ Clear(NetworkIdentifier);
+ NetworkIdentifier.SetRange(Network, TempParticipation.Network);
+ if TempParticipation."Country/Region Code" <> '' then
+ NetworkIdentifier.SetRange("Default in Country", TempParticipation."Country/Region Code")
+ else
+ NetworkIdentifier.SetRange(Default, true);
+
+ if NetworkIdentifier.FindFirst() then begin
+ TempParticipation."Identifier Type Id" := NetworkIdentifier.Id;
+ TempParticipation."Identifier Value" := CompanyInformation."VAT Registration No.";
+ IdentifierTypeDesc := NetworkIdentifier."Scheme Id";
+ end else begin
+ TempParticipation."Identifier Type Id" := EmptyGuid;
+ TempParticipation."Identifier Value" := '';
+ IdentifierTypeDesc := '';
+ end;
+ end;
+
+ internal procedure ValidateIdentifierType(var TempParticipation: Record "Continia Participation" temporary; var IdentifierTypeDesc: Text)
+ var
+ NetworkIdentifier: Record "Continia Network Identifier";
+ begin
+ if IdentifierTypeDesc <> '' then begin
+ NetworkIdentifier.SetRange(Network, TempParticipation.Network);
+ NetworkIdentifier.SetRange(Enabled, true);
+ NetworkIdentifier.SetRange("Scheme Id", IdentifierTypeDesc);
+ NetworkIdentifier.FindFirst();
+ TempParticipation."Identifier Type Id" := NetworkIdentifier.Id;
+ IdentifierTypeDesc := NetworkIdentifier."Scheme Id";
+ end;
+ end;
+
+ internal procedure LookupIdentifierType(var TempParticipation: Record "Continia Participation" temporary; var IdentifierTypeDesc: Text): Boolean
+ var
+ NetworkIdentifier: Record "Continia Network Identifier";
+ NetworkIdentifierList: Page "Continia Network Id. List";
+ begin
+ Clear(NetworkIdentifier);
+ NetworkIdentifier.SetRange(Network, TempParticipation.Network);
+ NetworkIdentifier.SetRange(Enabled, true);
+ NetworkIdentifierList.SetTableView(NetworkIdentifier);
+ NetworkIdentifierList.LookupMode(true);
+
+ if NetworkIdentifierList.RunModal() = Action::LookupOK then begin
+ NetworkIdentifierList.GetRecord(NetworkIdentifier);
+ IdentifierTypeDesc := NetworkIdentifier."Scheme Id";
+ TempParticipation."Identifier Type Id" := NetworkIdentifier.Id;
+ exit(true);
+ end;
+ end;
+
+ internal procedure ValidateIdentifierValue(var TempParticipation: Record "Continia Participation" temporary)
+ var
+ NetworkIdentifier: Record "Continia Network Identifier";
+ RegEx: Codeunit Regex;
+ begin
+ if NetworkIdentifier.Get(TempParticipation."Identifier Type Id") then
+ if not RegEx.IsMatch(TempParticipation."Identifier Value", NetworkIdentifier."Validation Rule") then
+ Error(InvalidIdentifierValueErr, TempParticipation."Identifier Value", NetworkIdentifier."Validation Rule");
+ end;
+
+ internal procedure GetCurrentActivatedProfiles(var TempParticipation: Record "Continia Participation" temporary; var TempActivatedProfiles: Record "Continia Activated Net. Prof." temporary)
+ var
+ ActivatedProfiles: Record "Continia Activated Net. Prof.";
+ begin
+ ActivatedProfiles.SetRange(Network, TempParticipation.Network);
+ ActivatedProfiles.SetRange("Identifier Type Id", TempParticipation."Identifier Type Id");
+ ActivatedProfiles.SetRange("Identifier Value", TempParticipation."Identifier Value");
+ if ActivatedProfiles.FindSet() then
+ repeat
+ TempActivatedProfiles.Init();
+ TempActivatedProfiles := ActivatedProfiles;
+ TempActivatedProfiles.Insert();
+ until ActivatedProfiles.Next() = 0;
+ end;
+
+ internal procedure InitializeNetworkProfiles(var TempParticipation: Record "Continia Participation" temporary; var TempActivatedProfiles: Record "Continia Activated Net. Prof." temporary)
+ var
+ NetworkProfile: Record "Continia Network Profile";
+ begin
+ NetworkProfile.SetRange(Network, TempParticipation.Network);
+ NetworkProfile.SetRange(Mandatory, true);
+ NetworkProfile.SetFilter("Mandatory for Country", '%1|%2', '', TempParticipation."Country/Region Code");
+ NetworkProfile.SetRange(Enabled, true);
+ if NetworkProfile.FindSet() then
+ repeat
+ TempActivatedProfiles.Init();
+ TempActivatedProfiles."Network Profile Id" := NetworkProfile.Id;
+ TempActivatedProfiles.Insert();
+ until NetworkProfile.Next() = 0;
+ end;
+
+ internal procedure IsCompanyInfoValid(var TempCompanyContact: Record "Continia Participation" temporary): Boolean
+ begin
+ if TempCompanyContact."Company Name" = '' then
+ exit(false);
+
+ if TempCompanyContact."VAT Registration No." = '' then
+ exit(false);
+
+ if TempCompanyContact.Address = '' then
+ exit(false);
+
+ if TempCompanyContact."Post Code" = '' then
+ exit(false);
+
+ if TempCompanyContact."Country/Region Code" = '' then
+ exit(false);
+
+ if TempCompanyContact."Contact Name" = '' then
+ exit(false);
+
+ if TempCompanyContact."Contact Email" = '' then
+ exit(false);
+
+ if TempCompanyContact."Contact Phone No." = '' then
+ exit(false);
+
+ exit(true);
+ end;
+
+ internal procedure IsParticipationInfoValid(var TempParticipation: Record "Continia Participation" temporary): Boolean
+ begin
+ if TempParticipation."Company Name" = '' then
+ exit(false);
+
+ if TempParticipation."VAT Registration No." = '' then
+ exit(false);
+
+ if TempParticipation.Address = '' then
+ exit(false);
+
+ if TempParticipation."Post Code" = '' then
+ exit(false);
+
+ if TempParticipation."Country/Region Code" = '' then
+ exit(false);
+
+ if TempParticipation."Signatory Name" = '' then
+ exit(false);
+
+ if TempParticipation."Signatory Email" = '' then
+ exit(false);
+
+ exit(true);
+ end;
+
+ internal procedure UpdateParticipation(var TempParticipation: Record "Continia Participation" temporary)
+ var
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ if IsParticipationChanged(TempParticipation) then begin
+ ShowProgressWindow(SendingDataProgressMsg);
+ ApiRequests.PatchParticipation(TempParticipation);
+ CloseProgressWindow();
+ end;
+ end;
+
+ internal procedure UpdateProfiles(var TempParticipation: Record "Continia Participation" temporary; var TempActivatedProfiles: Record "Continia Activated Net. Prof." temporary)
+ var
+ ActivatedProfiles: Record "Continia Activated Net. Prof.";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ ShowProgressWindow(SendingDataProgressMsg);
+ if TempActivatedProfiles.FindSet() then
+ repeat
+ if IsNullGuid(TempActivatedProfiles."Identifier Type Id") and (TempActivatedProfiles."Identifier Value" = '') then
+ TempActivatedProfiles.Rename(TempParticipation.Network, TempParticipation."Identifier Type Id", TempParticipation."Identifier Value", TempActivatedProfiles."Network Profile Id");
+ if ActivatedProfiles.Get(TempActivatedProfiles.RecordId) then begin
+ if (TempActivatedProfiles."Profile Direction" <> ActivatedProfiles."Profile Direction") or (TempActivatedProfiles.Disabled <> ActivatedProfiles.Disabled) then
+ ApiRequests.PatchParticipationProfile(TempActivatedProfiles, TempParticipation.Id);
+ if TempActivatedProfiles."E-Document Service Code" <> ActivatedProfiles."E-Document Service Code" then begin
+ ActivatedProfiles."E-Document Service Code" := TempActivatedProfiles."E-Document Service Code";
+ ActivatedProfiles.Modify(true);
+ end;
+ end else
+ ApiRequests.PostParticipationProfile(TempActivatedProfiles, TempParticipation.Id);
+ until TempActivatedProfiles.Next() = 0;
+
+ ActivatedProfiles.SetRange("Identifier Type Id", TempParticipation."Identifier Type Id");
+ ActivatedProfiles.SetRange("Identifier Value", TempParticipation."Identifier Value");
+ ActivatedProfiles.SetRange(Network, TempParticipation.Network);
+ if ActivatedProfiles.FindSet() then
+ repeat
+ if not TempActivatedProfiles.Get(ActivatedProfiles.RecordId) then
+ ApiRequests.DeleteParticipationProfile(ActivatedProfiles, TempParticipation.Id);
+ until ActivatedProfiles.Next() = 0;
+
+ CloseProgressWindow();
+ end;
+
+ internal procedure RegisterParticipation(var TempParticipation: Record "Continia Participation" temporary; var TempActivatedProfiles: Record "Continia Activated Net. Prof." temporary)
+ var
+ CompanyInfo: Record "Company Information";
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ ParticipationGuid: Guid;
+ begin
+ ShowProgressWindow(SendingDataProgressMsg);
+ ParticipationGuid := ApiRequests.PostParticipation(TempParticipation);
+ Participation.SetRange(Id, ParticipationGuid);
+ Participation.FindFirst();
+
+ TempActivatedProfiles.FindSet();
+ repeat
+ ApiRequests.PostParticipationProfile(TempActivatedProfiles, ParticipationGuid);
+ until TempActivatedProfiles.Next() = 0;
+
+ Participation.Validate("Registration Status", Participation."Registration Status"::InProcess);
+ Participation.Modify();
+
+ ApiRequests.PatchParticipation(Participation);
+
+ if Participation.Network = Participation.Network::Nemhandel then begin
+ CompanyInfo.Get();
+ if CompanyInfo."Registration No." = '' then begin
+ CompanyInfo."Registration No." := CopyStr(Participation."Identifier Value", 1, 20);
+ CompanyInfo.Modify();
+ end;
+ end;
+ CloseProgressWindow();
+ end;
+
+ internal procedure IsParticipationChanged(var TempParticipation: Record "Continia Participation" temporary): Boolean
+ var
+ Participation: Record "Continia Participation";
+ begin
+ if not Participation.Get(TempParticipation.Network, TempParticipation."Identifier Type Id", TempParticipation."Identifier Value") then
+ exit(true);
+
+ if TempParticipation.Address <> Participation.Address then
+ exit(true);
+
+ if TempParticipation."Company Name" <> Participation."Company Name" then
+ exit(true);
+
+ if TempParticipation."VAT Registration No." <> Participation."VAT Registration No." then
+ exit(true);
+
+ if TempParticipation."Country/Region Code" <> Participation."Country/Region Code" then
+ exit(true);
+
+ if TempParticipation."Post Code" <> Participation."Post Code" then
+ exit(true);
+
+ if TempParticipation.County <> Participation.County then
+ exit(true);
+
+ if TempParticipation."Signatory Email" <> Participation."Signatory Email" then
+ exit(true);
+
+ if TempParticipation."Signatory Name" <> Participation."Signatory Name" then
+ exit(true);
+
+ if TempParticipation."Registration Status" <> Participation."Registration Status" then
+ exit(true);
+ end;
+
+ internal procedure CreateSubscription(var TempCompanyContact: Record "Continia Participation" temporary)
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ SubscriptionMgt: Codeunit "Continia Subscription Mgt.";
+ SubscriptionState: Enum "Continia Subscription Status";
+ begin
+ ShowProgressWindow(SendingDataProgressMsg);
+ SubscriptionState := SubscriptionState::Subscription;
+ if SubscriptionMgt.UpdateSubscription(SubscriptionState, TempCompanyContact, true) then begin
+ SubscriptionMgt.AcceptCompanyLicense(CompanyName);
+ ConnectionSetup.Get();
+ ConnectionSetup."Subscription Status" := SubscriptionState;
+ ConnectionSetup.Modify();
+ end;
+ CloseProgressWindow();
+ end;
+
+ internal procedure UpdateSubscriptionInfo(var TempCompanyContact: Record "Continia Participation" temporary)
+ var
+ SubscriptionMgt: Codeunit "Continia Subscription Mgt.";
+ begin
+ ShowProgressWindow(SendingDataProgressMsg);
+ if not IsSubscribed() then
+ CreateSubscription(TempCompanyContact)
+ else
+ SubscriptionMgt.UpdateClientInformation(TempCompanyContact);
+ CloseProgressWindow();
+ end;
+
+ internal procedure IsSubscribed(): Boolean
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ begin
+ ConnectionSetup.Get();
+ exit(ConnectionSetup."Subscription Status" = ConnectionSetup."Subscription Status"::Subscription);
+ end;
+
+ #region Simple User Choice functions
+ internal procedure AddInvoiceCreditMemoProfiles(var TempParticipation: Record "Continia Participation" temporary; ProfileDirection: Enum "Continia Profile Direction"; var ActivatedProfiles: Record "Continia Activated Net. Prof." temporary)
+ begin
+ case TempParticipation.Network of
+ "Continia E-Delivery Network"::Peppol:
+ AddPeppolInvoiceCreditMemoProfiles(TempParticipation, ActivatedProfiles, ProfileDirection);
+ "Continia E-Delivery Network"::Nemhandel:
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:www.nesubl.eu:profiles:profile5:ver2.0', '');
+ end;
+ end;
+
+ local procedure AddPeppolInvoiceCreditMemoProfiles(var TempParticipation: Record "Continia Participation" temporary; var ActivatedProfiles: Record "Continia Activated Net. Prof."; ProfileDirection: Enum "Continia Profile Direction")
+ begin
+ case TempParticipation."Country/Region Code" of
+ 'DE':
+ PopulateDEInvoiceCreditMemoProfiles(TempParticipation, ActivatedProfiles, ProfileDirection);
+ 'NL':
+ PopulateNLInvoiceCreditMemoProfiles(TempParticipation, ActivatedProfiles, ProfileDirection);
+ end;
+
+ //PEPPOL Credit Note (BIS 3.0)
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0',
+ 'urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1');
+ //PEPPOL Cross Industry Invoice (BIS 3.0)
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0',
+ 'urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::D16B');
+ //PEPPOL Invoice (BIS 3.0)
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0',
+ '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');
+ end;
+
+ local procedure PopulateDEInvoiceCreditMemoProfiles(var TempParticipation: Record "Continia Participation" temporary; var ActivatedProfiles: Record "Continia Activated Net. Prof."; ProfileDirection: Enum "Continia Profile Direction")
+ var
+ NetworkProfile: Record "Continia Network Profile";
+ begin
+ NetworkProfile.SetRange(Network, TempParticipation.Network);
+ NetworkProfile.SetRange("Mandatory for Country", 'DE');
+ if NetworkProfile.FindSet() then
+ repeat
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection, NetworkProfile."Process Identifier", NetworkProfile."Document Identifier");
+ until NetworkProfile.Next() = 0;
+ end;
+
+ local procedure PopulateNLInvoiceCreditMemoProfiles(var TempParticipation: Record "Continia Participation" temporary; var ActivatedProfiles: Record "Continia Activated Net. Prof."; ProfileDirection: Enum "Continia Profile Direction")
+ begin
+ //SI-UBL 2.0 Credit Note
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0',
+ 'urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:fdc:nen.nl:nlcius:v1.0::2.1');
+ //SI-UBLÂ 2.0Â Invoice
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0',
+ 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:nen.nl:nlcius:v1.0::2.1');
+ end;
+
+ internal procedure AddInvoiceResponseProfiles(var TempParticipation: Record "Continia Participation" temporary; ProfileDirection: Enum "Continia Profile Direction"; var ActivatedProfiles: Record "Continia Activated Net. Prof.")
+ begin
+ case TempParticipation.Network of
+ "Continia E-Delivery Network"::Peppol:
+ PopulatePeppolInvoiceResponseProfiles(TempParticipation, ActivatedProfiles, ProfileDirection);
+ "Continia E-Delivery Network"::Nemhandel:
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'Procurement-BilSim-1.0', '');
+ end;
+ end;
+
+ local procedure PopulatePeppolInvoiceResponseProfiles(var TempParticipation: Record "Continia Participation" temporary; var ActivatedProfiles: Record "Continia Activated Net. Prof."; ProfileDirection: Enum "Continia Profile Direction")
+ begin
+ //PEPPOL Invoice Response (BIS 3.0)
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:fdc:peppol.eu:poacc:bis:invoice_response:3',
+ 'urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2::ApplicationResponse##urn:fdc:peppol.eu:poacc:trns:invoice_response:3::2.1');
+ end;
+
+ internal procedure AddOrderOnlyProfiles(var TempParticipation: Record "Continia Participation" temporary; ProfileDirection: Enum "Continia Profile Direction"; var ActivatedProfiles: Record "Continia Activated Net. Prof.")
+ begin
+ case TempParticipation.Network of
+ "Continia E-Delivery Network"::Peppol:
+ PopulatePeppolOrderOnlyProfiles(TempParticipation, ActivatedProfiles, ProfileDirection);
+ "Continia E-Delivery Network"::Nemhandel:
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:www.nesubl.eu:profiles:profile3:ver2.0', '');
+ end;
+ end;
+
+ local procedure PopulatePeppolOrderOnlyProfiles(var TempParticipation: Record "Continia Participation" temporary; var ActivatedProfiles: Record "Continia Activated Net. Prof."; ProfileDirection: Enum "Continia Profile Direction")
+ begin
+ case TempParticipation."Country/Region Code" of
+ 'NO':
+ //EHF Advanced Order Initiation 3.0
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:fdc:anskaffelser.no:2019:ehf:postaward:g3:02:1.0',
+ 'urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##urn:fdc:peppol.eu:poacc:trns:order:3:extended:urn:fdc:anskaffelser.no:2019:ehf:spec:3.0::2.2');
+ end;
+
+ //PEPPOL Order Only (BIS 3.0)
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:fdc:peppol.eu:poacc:bis:order_only:3',
+ 'urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##urn:fdc:peppol.eu:poacc:trns:order:3::2.1');
+ end;
+
+ internal procedure AddOrderProfiles(var TempParticipation: Record "Continia Participation" temporary; ProfileDirection: Enum "Continia Profile Direction"; var ActivatedProfiles: Record "Continia Activated Net. Prof.")
+ begin
+ case TempParticipation.Network of
+ "Continia E-Delivery Network"::Peppol:
+ PopulatePeppolOrderProfiles(TempParticipation, ActivatedProfiles, ProfileDirection);
+ "Continia E-Delivery Network"::Nemhandel:
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'Procurement-OrdSim-1.0', '');
+ end;
+ end;
+
+ local procedure PopulatePeppolOrderProfiles(var TempParticipation: Record "Continia Participation" temporary; var ActivatedProfiles: Record "Continia Activated Net. Prof."; ProfileDirection: Enum "Continia Profile Direction")
+ begin
+ case TempParticipation."Country/Region Code" of
+ 'NO':
+ //EHF Advanced Order Initiation 3.0
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:fdc:anskaffelser.no:2019:ehf:postaward:g3:02:1.0',
+ 'urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##urn:fdc:peppol.eu:poacc:trns:order:3:extended:urn:fdc:anskaffelser.no:2019:ehf:spec:3.0::2.2');
+ end;
+
+ //PEPPOL Order (BIS 3.0)
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:fdc:peppol.eu:poacc:bis:ordering:3',
+ 'urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##urn:fdc:peppol.eu:poacc:trns:order:3::2.1');
+ end;
+
+ internal procedure AddOrderResponseProfiles(var TempParticipation: Record "Continia Participation" temporary; ProfileDirection: Enum "Continia Profile Direction"; var ActivatedProfiles: Record "Continia Activated Net. Prof.")
+ begin
+ if TempParticipation.Network = "Continia E-Delivery Network"::Peppol then
+ PopulatePeppolOrderResponseProfiles(TempParticipation, ActivatedProfiles, ProfileDirection);
+ end;
+
+ local procedure PopulatePeppolOrderResponseProfiles(var TempParticipation: Record "Continia Participation" temporary; var ActivatedProfiles: Record "Continia Activated Net. Prof."; ProfileDirection: Enum "Continia Profile Direction")
+ begin
+ case TempParticipation."Country/Region Code" of
+ 'NO':
+ //EHF Advanced Order Response 3.0
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:fdc:anskaffelser.no:2019:ehf:postaward:g3:02:1.0',
+ 'urn:oasis:names:specification:ubl:schema:xsd:OrderResponse-2::OrderResponse##urn:fdc:peppol.eu:poacc:trns:order_response:3:extended:urn:fdc:anskaffelser.no:2019:ehf:spec:3.0::2.2');
+ end;
+
+ //PEPPOL Order Response (BIS 3.0)
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'urn:fdc:peppol.eu:poacc:bis:ordering:3',
+ 'urn:oasis:names:specification:ubl:schema:xsd:OrderResponse-2::OrderResponse##urn:fdc:peppol.eu:poacc:trns:order_response:3::2.1');
+ end;
+
+ internal procedure AddInvoiceAndOrderProfiles(var TempParticipation: Record "Continia Participation" temporary; ProfileDirection: Enum "Continia Profile Direction"; var ActivatedProfiles: Record "Continia Activated Net. Prof.")
+ begin
+ if TempParticipation.Network = "Continia E-Delivery Network"::Nemhandel then
+ AddNetworkProfileByIdentifiers(TempParticipation, ActivatedProfiles, ProfileDirection,
+ 'Procurement-OrdSim-BilSim-1.0', '');
+ end;
+
+ local procedure AddNetworkProfileByIdentifiers(var TempParticipation: Record "Continia Participation" temporary; var ActivatedProfiles: Record "Continia Activated Net. Prof."; ProfileDirection: Enum "Continia Profile Direction"; ProcessIdentifier: Text;
+ DocumentIdentifier: Text)
+ var
+ NetworkProfile: Record "Continia Network Profile";
+ begin
+ NetworkProfile.SetRange(Network, TempParticipation.Network);
+ NetworkProfile.SetRange("Process Identifier", ProcessIdentifier);
+ if DocumentIdentifier <> '' then
+ NetworkProfile.SetRange("Document Identifier", DocumentIdentifier);
+
+ if NetworkProfile.FindFirst() then begin
+ ActivatedProfiles.Init();
+ ActivatedProfiles.Network := NetworkProfile.Network;
+ ActivatedProfiles."Identifier Type Id" := TempParticipation."Identifier Type Id";
+ ActivatedProfiles."Identifier Value" := TempParticipation."Identifier Value";
+ ActivatedProfiles."Network Profile Id" := NetworkProfile.Id;
+ ActivatedProfiles."Profile Direction" := ProfileDirection;
+ ActivatedProfiles.Insert();
+ end;
+ end;
+
+ #endregion
+
+ local procedure ShowProgressWindow(ProgressMsg: Text)
+ begin
+ ProgressDialogWindow.Open(ProgressMsg);
+ end;
+
+ procedure HasModifyPermissionOnParticipation(): Boolean
+ var
+ EDocService: Record "E-Document Service";
+ begin
+ exit(EDocService.WritePermission);
+ end;
+
+ local procedure CloseProgressWindow()
+ begin
+ ProgressDialogWindow.Close();
+ end;
+
+ var
+
+ ProgressDialogWindow: Dialog;
+ MetaDataLoaded: Boolean;
+ SendingDataProgressMsg: Label 'Sending data to Continia Online';
+ UpdatingDataProgressMsg: Label 'Updating data from Continia Online';
+ InvalidIdentifierValueErr: Label 'The %1 of the participation is invalid (Rule: ''%2'').', Comment = '%1 = The current identifier value of the participation, %2 = The regular expression rule that the identifier value must match';
+
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaOnboardingWizard.Page.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaOnboardingWizard.Page.al
new file mode 100644
index 0000000000..bedc09d30d
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaOnboardingWizard.Page.al
@@ -0,0 +1,1148 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using System.Email;
+using Microsoft.Foundation.Address;
+
+page 6393 "Continia Onboarding Wizard"
+{
+ ApplicationArea = All;
+ Caption = 'Continia Delivery Network Onboarding';
+ DeleteAllowed = false;
+ Extensible = false;
+ InsertAllowed = false;
+ PageType = NavigatePage;
+
+ layout
+ {
+ area(Content)
+ {
+ group(FirstPage)
+ {
+ Caption = '';
+ Visible = FirstStepVisible;
+ group(IntroductionGroup)
+ {
+ Caption = 'Welcome to the Continia Delivery Network onboarding guide.';
+ Visible = FirstStepVisible;
+ group(Start1)
+ {
+ InstructionalText = 'Continia Delivery Network integrates seamlessly with various electronic data exchange networks, such as the PEPPOL eDelivery Network. This allows you to send and receive documents directly from Business Central if your vendors and customers are also connected to these networks.';
+ ShowCaption = false;
+ }
+ group(Start2)
+ {
+ InstructionalText = 'This guide will help you register your company as a participant in the Continia Delivery Network.';
+ ShowCaption = false;
+ }
+ }
+ group(IntroductionGroup2)
+ {
+ Caption = 'Let''s go!';
+ group(Start3)
+ {
+ Caption = '';
+ InstructionalText = 'Choose Next to get started.';
+ }
+ }
+ }
+ group(PartnerDetailsPage)
+ {
+ Caption = '';
+ Visible = PartnerDetailsStepVisible;
+ group(PartnerDetails)
+ {
+ Caption = 'Partner details';
+ Visible = PartnerDetailsStepVisible;
+ group(PartnerDetails1)
+ {
+ InstructionalText = 'To continue, you will need the assistance of your partner. Please have your partner enter their Continia PartnerZone credentials:';
+ ShowCaption = false;
+ }
+ }
+ field(PartnerUserName; PartnerUserName)
+ {
+ Caption = 'PartnerZone Username';
+ ShowMandatory = true;
+ ToolTip = 'Please enter the email used when logging in to Continia PartnerZone.';
+
+ trigger OnValidate()
+ var
+ MailManagement: Codeunit "Mail Management";
+ begin
+ if PartnerUserName <> '' then
+ MailManagement.CheckValidEmailAddress(PartnerUserName);
+ end;
+ }
+ field(PartnerPassword; PartnerPassword)
+ {
+ Caption = 'PartnerZone Password';
+ ExtendedDatatype = Masked;
+ ShowMandatory = true;
+ ToolTip = 'Please enter the password used when logging in to Continia PartnerZone. If you do not have a PartnerZone login, please contact Continia.';
+
+ trigger OnValidate()
+ begin
+ if PartnerPassword = '' then
+ Error(NoPasswordErr);
+ end;
+ }
+ field(PartnerPwdLinkLabel; PartnerReqPwdTxt)
+ {
+ Editable = false;
+ ShowCaption = false;
+
+ trigger OnDrillDown()
+ begin
+ Hyperlink('https://partnerzone.continia.com/request-reset-password');
+ end;
+ }
+ field(PartnerNewRegLabel; PartnerRegAsNewTxt)
+ {
+ Editable = false;
+ ShowCaption = false;
+
+ trigger OnDrillDown()
+ begin
+ Hyperlink('https://pz.continia.com/partner-application-form/');
+ end;
+ }
+ }
+ group(LegalCompanyInformationPage)
+ {
+ Caption = '';
+ Visible = LegalCompanyInformationStepVisible;
+ group(LegalCompanyInformation)
+ {
+ Caption = 'Legal company information';
+ Visible = LegalCompanyInformationStepVisible;
+ group(LegalCompanyInformation1)
+ {
+ InstructionalText = 'Please provide the legal information of the company you want to register in the network.';
+ ShowCaption = false;
+ field("Company Name"; TempParticipation."Company Name")
+ {
+ Caption = 'Company Name';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the legal name of the company that you want to join to the network.';
+
+ trigger OnValidate()
+ begin
+ NextActionEnabled := LicenseTermsAccepted and OnboardingHelper.IsParticipationInfoValid(TempParticipation);
+ end;
+ }
+ field("VAT Registration No."; TempParticipation."VAT Registration No.")
+ {
+ Caption = 'VAT Registration No.';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the VAT registration number of the company that you want to join to the network.';
+
+ trigger OnValidate()
+ begin
+ NextActionEnabled := LicenseTermsAccepted and OnboardingHelper.IsParticipationInfoValid(TempParticipation);
+ end;
+ }
+ field(Address; TempParticipation.Address)
+ {
+ Caption = 'Address';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the legal address of the company that you want to join to the network.';
+
+ trigger OnValidate()
+ begin
+ NextActionEnabled := LicenseTermsAccepted and OnboardingHelper.IsParticipationInfoValid(TempParticipation);
+ end;
+ }
+ field("Post Code"; TempParticipation."Post Code")
+ {
+ Caption = 'Post Code';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the legal post code of the company that you want to join to the network.';
+
+ trigger OnValidate()
+ begin
+ NextActionEnabled := LicenseTermsAccepted and OnboardingHelper.IsParticipationInfoValid(TempParticipation);
+ end;
+ }
+ group(CountyGroup)
+ {
+ ShowCaption = false;
+ Visible = CountyVisible;
+ field(County; TempParticipation.County)
+ {
+ Caption = 'County';
+ CaptionClass = '5,1,' + TempParticipation."Country/Region Code";
+ ToolTip = 'Specifies the legal county of the company that you want to join to the network.';
+ }
+ }
+ field("Country/Region Code"; TempParticipation."Country/Region Code")
+ {
+ Caption = 'Country/Region Code';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the legal country code of the company that you want to join to the network. Must be stated in the ISO 3166-1 format.';
+
+ trigger OnValidate()
+ var
+ FormatAddress: Codeunit "Format Address";
+ begin
+ CountyVisible := FormatAddress.UseCounty(TempParticipation."Country/Region Code");
+ NextActionEnabled := LicenseTermsAccepted and OnboardingHelper.IsParticipationInfoValid(TempParticipation);
+ end;
+ }
+ group(CompanySignatory)
+ {
+ Caption = 'Company Signatory (e.g. CEO)';
+ field("Signatory Name"; TempParticipation."Signatory Name")
+ {
+ Caption = 'Signatory Name';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the name of the company signatory.';
+
+ trigger OnValidate()
+ begin
+ NextActionEnabled := LicenseTermsAccepted and OnboardingHelper.IsParticipationInfoValid(TempParticipation);
+ end;
+ }
+ field("Signatory Email"; TempParticipation."Signatory Email")
+ {
+ Caption = 'Email Address';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the email of the company signatory.';
+
+ trigger OnValidate()
+ begin
+ NextActionEnabled := LicenseTermsAccepted and OnboardingHelper.IsParticipationInfoValid(TempParticipation);
+ end;
+ }
+ }
+ }
+ group(LegalCompanyInformation2)
+ {
+ InstructionalText = 'Please verify that all the company details you provided are accurate. This information is essential for Continia to meet its legal obligations, perform its KYC processes and data processing requirements. Inaccurate or insufficient information can delay our verification processes or result in account suspension. If any details change, update the information promptly to avoid service disruptions.';
+ ShowCaption = false;
+ }
+ group(LegalCompanyInformation3)
+ {
+ InstructionalText = 'By continuing, you confirm the accuracy of the above information and accept Continia Software License Terms and Terms of Service.';
+ ShowCaption = false;
+
+ field(LicenseTerms; LicenseTermsAccepted)
+ {
+ Caption = 'I confirm';
+ ToolTip = 'Specifies your confirmation to the license terms.';
+
+ trigger OnValidate()
+ begin
+ NextActionEnabled := LicenseTermsAccepted and OnboardingHelper.IsParticipationInfoValid(TempParticipation);
+ end;
+ }
+ }
+ }
+ }
+ group(CompanyContactInformationPage)
+ {
+ Caption = '';
+ Visible = CompanyContactInformationStepVisible;
+ group(CompanyContactInformation)
+ {
+ Caption = 'Company contact information';
+ Visible = CompanyContactInformationStepVisible;
+ group(CompanyContactInformation1)
+ {
+ InstructionalText = 'Please provide the company contact information.';
+ ShowCaption = false;
+ field(CompanyContactName; TempCompanyContact."Company Name")
+ {
+ Caption = 'Company Name';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the legal name of the company that you want to join to the network.';
+
+ trigger OnValidate()
+ begin
+ SetButtonBehaviourCompanyContactInformation();
+ end;
+ }
+ field(CompanyContactVAT; TempCompanyContact."VAT Registration No.")
+ {
+ Caption = 'VAT Registration No.';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the VAT registration number of the company that you want to join to the network.';
+
+ trigger OnValidate()
+ begin
+ TempCompanyContact.Validate("VAT Registration No.");
+ SetButtonBehaviourCompanyContactInformation();
+ end;
+ }
+ field(CompanyContactAddress; TempCompanyContact.Address)
+ {
+ Caption = 'Address';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the legal address of the company that you want to join to the network.';
+
+ trigger OnValidate()
+ begin
+ SetButtonBehaviourCompanyContactInformation();
+ end;
+ }
+ field(CompanyContactPostCode; TempCompanyContact."Post Code")
+ {
+ Caption = 'Post Code';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the legal post code of the company that you want to join to the network.';
+
+ trigger OnValidate()
+ begin
+ SetButtonBehaviourCompanyContactInformation();
+ end;
+ }
+ group(CompanyContactCountyGroup)
+ {
+ ShowCaption = false;
+ Visible = ContactCountyVisible;
+ field(CompanyContactCounty; TempCompanyContact.County)
+ {
+ Caption = 'County';
+ CaptionClass = '5,1,' + TempCompanyContact."Country/Region Code";
+ ToolTip = 'Specifies the legal county of the company that you want to join to the network.';
+ }
+ }
+ field(CompanyContactCountryRegion; TempCompanyContact."Country/Region Code")
+ {
+ Caption = 'Country/Region Code';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the legal country code of the company that you want to join to the network. Must be stated in the ISO 3166-1 format.';
+
+ trigger OnLookup(var Text: Text): Boolean
+ var
+ FormatAddress: Codeunit "Format Address";
+ begin
+ TempCompanyContact.LookupCountryRegion();
+ TempCompanyContact.Validate("Country/Region Code");
+ ContactCountyVisible := FormatAddress.UseCounty(TempCompanyContact."Country/Region Code");
+ end;
+
+ trigger OnValidate()
+ var
+ FormatAddress: Codeunit "Format Address";
+ begin
+ TempCompanyContact.Validate("Country/Region Code");
+ ContactCountyVisible := FormatAddress.UseCounty(TempCompanyContact."Country/Region Code");
+ SetButtonBehaviourCompanyContactInformation();
+ end;
+ }
+ group(CompanyContactPerson)
+ {
+ Caption = 'Company Contact Person';
+ field(CompanyContactPersonName; TempCompanyContact."Contact Name")
+ {
+ Caption = 'Name';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the name of the contact person in the company.';
+
+ trigger OnValidate()
+ begin
+ SetButtonBehaviourCompanyContactInformation();
+ end;
+ }
+ field(CompanyContactPersonEmail; TempCompanyContact."Contact Email")
+ {
+ Caption = 'Email Address';
+ ExtendedDatatype = EMail;
+ ShowMandatory = true;
+ ToolTip = 'Specifies the email address of the contact person in the company.';
+
+ trigger OnValidate()
+ begin
+ TempCompanyContact.Validate("Contact Email");
+ SetButtonBehaviourCompanyContactInformation();
+ end;
+ }
+ field(CompanyContactPersonPhoneNo; TempCompanyContact."Contact Phone No.")
+ {
+ Caption = 'Phone No.';
+ ExtendedDatatype = PhoneNo;
+ ShowMandatory = true;
+ ToolTip = 'Specifies the telephone number of the contact person in the company.';
+
+ trigger OnValidate()
+ begin
+ TempCompanyContact.Validate("Contact Phone No.");
+ SetButtonBehaviourCompanyContactInformation();
+ end;
+ }
+ }
+ }
+ }
+ }
+ group(NetworkDetailsPage)
+ {
+ Caption = '';
+ Visible = NetworkDetailsStepVisible;
+ group(NetworkDetails)
+ {
+ Caption = 'To register the company in an electronic document network, please provide the following information:';
+ Visible = NetworkDetailsStepVisible;
+ group(NetworkDetails1)
+ {
+ InstructionalText = 'Specify the network you want to be registered as a participant in.';
+ ShowCaption = false;
+ }
+ field(Network; TempParticipation.Network)
+ {
+ Caption = 'Network';
+ ToolTip = 'Specifies the network name where the participation is in.';
+
+ trigger OnValidate()
+ begin
+ OnboardingHelper.SetDefaultIdentifierData(TempParticipation, IdentifierTypeDesc);
+ end;
+ }
+ group(NetworkDetails2)
+ {
+ InstructionalText = 'Specify how the company should be identified in the network.';
+ ShowCaption = false;
+ }
+ field(IdentifierTypeDesc; IdentifierTypeDesc)
+ {
+ Caption = 'Identifier Type';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the type of identifier used to identify the company in the network.';
+
+ trigger OnValidate()
+ begin
+ OnboardingHelper.ValidateIdentifierType(TempParticipation, IdentifierTypeDesc);
+ end;
+
+ trigger OnLookup(var Text: Text): Boolean
+ begin
+ exit(OnboardingHelper.LookupIdentifierType(TempParticipation, Text));
+ end;
+ }
+ field(CompanyIdentifierValue; TempParticipation."Identifier Value")
+ {
+ Caption = 'Identifier Value';
+ ShowMandatory = true;
+ ToolTip = 'Specifies the value of the identifier used to identify the company in the network.';
+
+ trigger OnValidate()
+ begin
+ OnboardingHelper.ValidateIdentifierValue(TempParticipation);
+ end;
+ }
+ }
+ group(NextDocumentTypes)
+ {
+ InstructionalText = 'Choose Next to set up the document types you would like to exchange within the network.';
+ ShowCaption = false;
+ Visible = NetworkDetailsStepVisible;
+ }
+ }
+ group(DocumentTypesPage)
+ {
+ Caption = '';
+ Visible = DocumentTypesStepVisible;
+ group(DocumentTypes)
+ {
+ Caption = 'What types of documents would you like to exchange within the network?';
+ Visible = DocumentTypesStepVisible;
+ group(SalesServiceDocuments)
+ {
+ Caption = 'Sales/Service Documents';
+ field(SendInvoiceCreditMemo; SendInvoiceCreditMemo)
+ {
+ Caption = 'Send Invoice / Credit Memo';
+ ToolTip = 'Specifies whether the company can send invoices and credit memos to other companies in the network.';
+ }
+ field(ReceiveInvoiceResponse; ReceiveInvoiceResponse)
+ {
+ Caption = 'Receive Invoice Response';
+ ToolTip = 'Specifies whether the company can receive invoice responses from other companies in the network.';
+ }
+ field(ReceiveOrder; ReceiveOrder)
+ {
+ Caption = 'Receive Order';
+ ToolTip = 'Specifies whether the company can receive orders from other companies in the network.';
+ }
+ field(SendOrderResponse; SendOrderResponse)
+ {
+ Caption = 'Send Order Response';
+ ToolTip = 'Specifies whether the company can send order responses to other companies in the network.';
+ }
+ }
+ group(PurchaseDocuments)
+ {
+ Caption = 'Purchase Documents';
+ field(ReceiveInvoiceCreditMemo; ReceiveInvoiceCreditMemo)
+ {
+ Caption = 'Receive Invoice / Credit Memo';
+ ToolTip = 'Specifies whether the company can receive invoices and credit memos from other companies in the network.';
+ }
+ field(SendInvoiceResponse; SendInvoiceResponse)
+ {
+ Caption = 'Send Invoice Response';
+ ToolTip = 'Specifies whether the company can send invoice responses to other companies in the network.';
+ }
+ field(SendOrder; SendOrder)
+ {
+ Caption = 'Send Order';
+ ToolTip = 'Specifies whether the company can send orders to other companies in the network.';
+ }
+ field(ReceiveOrderResponse; ReceiveOrderResponse)
+ {
+ Caption = 'Receive Order Response';
+ ToolTip = 'Specifies whether the company can receive order responses from other companies in the network.';
+ }
+ }
+
+ }
+ }
+ group(AdvancedSetupPage)
+ {
+ Caption = '';
+ Visible = AdvancedSetupStepVisible;
+ group(AdvancedSetup)
+ {
+ Caption = 'Advanced Setup';
+ Visible = AdvancedSetupStepVisible;
+ group(AdvancedSetup1)
+ {
+ InstructionalText = 'Use the list below to configure the network profiles you want to register.';
+ ShowCaption = false;
+ }
+ part(SelectProfilesPeppol; "Continia Profile Selection") { }
+ }
+ }
+ group(FinalPage)
+ {
+ Caption = '';
+ Visible = FinalStepVisible;
+ group("That's it!")
+ {
+ Caption = 'That''s it!';
+ Visible = FinalStepVisible and (RunScenario = RunScenario::General);
+ group(FinalPage1)
+ {
+ InstructionalText = 'Choose Finish to submit your registration to join the Continia Delivery Network.';
+ ShowCaption = false;
+ }
+ group(FinalPage2)
+ {
+ InstructionalText = 'Continia will validate the information you have provided and notify you once your registration has been approved. Please note that this is a manual process, which may take 1–2 working days to complete.';
+ ShowCaption = false;
+ }
+ group(FinalPage3)
+ {
+ InstructionalText = 'You can always check the status of your registration on the E-Document External Connection Setup page.';
+ ShowCaption = false;
+ }
+ }
+ group(ThatsItEdit)
+ {
+ Caption = 'That''s it!';
+ Visible = FinalStepVisible and (RunScenario = RunScenario::EditParticipation);
+ group(EditFinalPage1)
+ {
+ InstructionalText = 'Choose Finish to send the new registration information to Continia Delivery Network.';
+ ShowCaption = false;
+ }
+ group(EditFinalPage2)
+ {
+ InstructionalText = 'You can always check the status of your registration on the E-Document External Connection Setup page.';
+ ShowCaption = false;
+ }
+ }
+ }
+ }
+ }
+
+ actions
+ {
+ area(Processing)
+ {
+ action(ActionBack)
+ {
+ ApplicationArea = Basic, Suite;
+ Caption = 'Back';
+ Enabled = BackActionEnabled;
+ Image = PreviousRecord;
+ InFooterBar = true;
+ ToolTip = 'Go back to the previous page.';
+ Visible = BackActionVisible;
+
+ trigger OnAction()
+ begin
+ MoveBack(false);
+ end;
+ }
+ action(ActionNext)
+ {
+ ApplicationArea = Basic, Suite;
+ Caption = 'Next';
+ Enabled = NextActionEnabled;
+ Image = NextRecord;
+ InFooterBar = true;
+ ToolTip = 'Go to the next page.';
+ Visible = NextActionVisible;
+
+ trigger OnAction()
+ begin
+ MoveNext(false);
+ end;
+ }
+ action(ActionAdvancedSetup)
+ {
+ ApplicationArea = Basic, Suite;
+ Caption = 'Advanced Setup';
+ Enabled = AdvancedSetupActionEnabled;
+ Image = NextRecord;
+ InFooterBar = true;
+ ToolTip = 'Open the list of network profiles to register.';
+ Visible = AdvancedSetupActionEnabled;
+
+ trigger OnAction()
+ begin
+ MoveStep(false, 1, false);
+ end;
+ }
+ action(ActionFinish)
+ {
+ ApplicationArea = Basic, Suite;
+ Caption = 'Finish';
+ Enabled = FinishActionEnabled;
+ Image = Approve;
+ InFooterBar = true;
+ ToolTip = 'Complete the onboarding.';
+
+ trigger OnAction()
+ begin
+ FinishAction();
+ end;
+ }
+ }
+ }
+
+ trigger OnOpenPage()
+ begin
+ if not OnboardingHelper.HasModifyPermissionOnParticipation() then
+ Error(MissingSetupPermissionErr);
+
+ case RunScenario of
+ RunScenario::General:
+ OnboardingHelper.InitializeGeneralScenario(TempCompanyContact, TempParticipation, CountyVisible, ContactCountyVisible, SkipCompanyInformation, IdentifierTypeDesc);
+ RunScenario::EditSubscriptionInfo:
+ begin
+ OnboardingHelper.GetContactInformation(TempCompanyContact, true);
+ Step := Step::CompanyContactInformation;
+ CurrPage.Caption := EditSubscriptionPageCaptionLbl;
+ end;
+ RunScenario::EditParticipation:
+ begin
+ SetActivatedProfiles();
+ Step := Step::LegalCompanyInformation;
+ end;
+ else
+ Step := Step::Start;
+ end;
+ EnableControls();
+ end;
+
+ local procedure FinishAction()
+ begin
+ case RunScenario of
+ RunScenario::EditSubscriptionInfo:
+ if OnboardingHelper.IsCompanyInfoValid(TempCompanyContact) then begin
+ OnboardingHelper.UpdateSubscriptionInfo(TempCompanyContact);
+ CurrPage.Close();
+ end;
+ RunScenario::EditParticipation:
+ begin
+ if not OnboardingHelper.IsSubscribed() then
+ OnboardingHelper.CreateSubscription(TempCompanyContact);
+
+ OnboardingHelper.UpdateParticipation(TempParticipation);
+ UpdateProfiles();
+ CurrPage.Close();
+ end;
+ RunScenario::General:
+ begin
+ if not SkipCompanyInformation then begin
+ if TempCompanyContact."Partner Id" = '' then
+ TempCompanyContact."Partner Id" := PartnerId;
+ OnboardingHelper.CreateSubscription(TempCompanyContact);
+ end;
+ RegisterParticipation();
+ CurrPage.Close();
+ end;
+ else
+ CurrPage.Close();
+ end;
+ end;
+
+ local procedure MoveNext(CurrentStepSkipped: Boolean)
+ begin
+ case RunScenario of
+ RunScenario::EditParticipation:
+ case Step of
+ Step::LegalCompanyInformation:
+ if not OnboardingHelper.IsSubscribed() then
+ MoveStep(true, 1, CurrentStepSkipped)
+ else
+ MoveStep(false, 4, CurrentStepSkipped);
+ Step::CompanyContactInformation:
+ if not OnboardingHelper.IsSubscribed() then
+ MoveStep(true, 2, CurrentStepSkipped)
+ else
+ MoveStep(false, 3, CurrentStepSkipped);
+ else
+ if (Step = Step::DocumentTypes) and not CurrentStepSkipped then
+ MoveStep(false, 2, CurrentStepSkipped)
+ else
+ MoveStep(false, 1, CurrentStepSkipped);
+ end;
+ else
+ if (Step = Step::DocumentTypes) and not CurrentStepSkipped then
+ MoveStep(false, 2, CurrentStepSkipped)
+ else
+ MoveStep(false, 1, CurrentStepSkipped);
+ end;
+ end;
+
+ local procedure MoveBack(CurrentStepSkipped: Boolean)
+ begin
+ case RunScenario of
+ RunScenario::EditParticipation:
+ case Step of
+ Step::LegalCompanyInformation:
+ exit;
+ Step::AdvancedSetup:
+ if not OnboardingHelper.IsSubscribed() then
+ MoveStep(true, 2, CurrentStepSkipped)
+ else
+ MoveStep(true, 4, CurrentStepSkipped);
+ else
+ MoveStep(true, 1, CurrentStepSkipped);
+ end;
+ else
+ MoveStep(true, LastStepsForward, CurrentStepSkipped);
+ end;
+ end;
+
+ local procedure MoveStep(Backwards: Boolean; Steps: Integer; CurrentStepSkipped: Boolean)
+ begin
+ OnBeforeMoveStep(Backwards, Steps, CurrentStepSkipped);
+ if Backwards then begin
+ LastStepsForward := 1;
+ Step -= Steps;
+ end else begin
+ LastStepsForward := Steps;
+ Step += Steps;
+ end;
+
+ EnableControls();
+ OnAfterMoveStep(Backwards);
+ end;
+
+ local procedure OnBeforeMoveStep(Backwards: Boolean; Steps: Integer; CurrentStepSkipped: Boolean)
+ begin
+ if (Step = Step::PartnerDetails) and not Backwards and not CurrentStepSkipped then
+ PartnerId := OnboardingHelper.InitializeClient(PartnerUserName, PartnerPassword);
+
+ if (Step = Step::NetworkDetails) then
+ if not Backwards and not CurrentStepSkipped then begin
+ ValidateIdentifierData();
+ InitializeNetworkProfiles();
+ end;
+
+ if (Step = Step::AdvancedSetup) and not Backwards and not CurrentStepSkipped then
+ ValidateParticipationProfiles();
+ if (Step = Step::DocumentTypes) and not Backwards and (Steps = 2) then
+ ValidateParticipationProfiles();
+ if (Step = Step::DocumentTypes) and (not Backwards) and (not CurrentStepSkipped) then
+ PopulateNetworkProfilesByUserSelection();
+ end;
+
+ local procedure OnAfterMoveStep(Backwards: Boolean)
+ begin
+ if Step = Step::PartnerDetails then begin
+ if not OnboardingHelper.AreClientCredentialsValid() then
+ exit;
+ // Skip Step
+ if Backwards then
+ MoveBack(true)
+ else
+ MoveNext(true);
+ end;
+
+ if Step = Step::NetworkDetails then begin
+ ParticipationNetwork := TempParticipation.Network;
+ ParticipationIdentifierValue := TempParticipation."Identifier Value";
+ if IsNullGuid(TempParticipation."Identifier Type Id") then
+ OnboardingHelper.SetDefaultIdentifierData(TempParticipation, IdentifierTypeDesc);
+ end;
+
+ if (Step = Step::LegalCompanyInformation) then
+ OnboardingHelper.GetNetworkMetadata(true);
+
+ if (Step = Step::CompanyContactInformation) then begin
+ if not SkipCompanyInformation then
+ exit;
+
+ if Backwards then
+ MoveBack(true)
+ else
+ MoveNext(true);
+ end;
+ end;
+
+ local procedure EnableControls()
+ begin
+ ResetControls();
+
+ case Step of
+ Step::Start:
+ ShowStartStep();
+ Step::PartnerDetails:
+ ShowPartnerDetailsStep();
+ Step::LegalCompanyInformation:
+ ShowLegalCompanyInformationStep();
+ Step::CompanyContactInformation:
+ ShowCompanyContactInformationStep();
+ Step::NetworkDetails:
+ ShowNetworkDetailsStep();
+ Step::DocumentTypes:
+ ShowDocumentTypesStep();
+ Step::AdvancedSetup:
+ ShowAdvancedSetupStep();
+ Step::Finish:
+ ShowFinalStep();
+ end;
+ end;
+
+ local procedure ShowStartStep()
+ begin
+ FirstStepVisible := true;
+ PartnerDetailsStepVisible := false;
+ LegalCompanyInformationStepVisible := false;
+ CompanyContactInformationStepVisible := false;
+ NetworkDetailsStepVisible := false;
+ DocumentTypesStepVisible := false;
+ AdvancedSetupStepVisible := false;
+ FinalStepVisible := false;
+
+ BackActionEnabled := false;
+ NextActionEnabled := true;
+ FinishActionEnabled := false;
+ AdvancedSetupActionEnabled := false;
+ end;
+
+ local procedure ShowPartnerDetailsStep()
+ begin
+ FirstStepVisible := false;
+ PartnerDetailsStepVisible := true;
+ LegalCompanyInformationStepVisible := false;
+ CompanyContactInformationStepVisible := false;
+ NetworkDetailsStepVisible := false;
+ DocumentTypesStepVisible := false;
+ AdvancedSetupStepVisible := false;
+ FinalStepVisible := false;
+
+ BackActionEnabled := true;
+ NextActionEnabled := true;
+ FinishActionEnabled := false;
+ AdvancedSetupActionEnabled := false;
+ end;
+
+ local procedure ShowLegalCompanyInformationStep()
+ begin
+ FirstStepVisible := false;
+ PartnerDetailsStepVisible := false;
+ LegalCompanyInformationStepVisible := true;
+ CompanyContactInformationStepVisible := false;
+ NetworkDetailsStepVisible := false;
+ DocumentTypesStepVisible := false;
+ AdvancedSetupStepVisible := false;
+ FinalStepVisible := false;
+
+ BackActionEnabled := RunScenario <> RunScenario::EditParticipation;
+ NextActionEnabled := LicenseTermsAccepted and OnboardingHelper.IsParticipationInfoValid(TempParticipation);
+ FinishActionEnabled := false;
+ AdvancedSetupActionEnabled := false;
+ end;
+
+ local procedure ShowCompanyContactInformationStep()
+ begin
+ FirstStepVisible := false;
+ PartnerDetailsStepVisible := false;
+ LegalCompanyInformationStepVisible := false;
+ CompanyContactInformationStepVisible := true;
+ NetworkDetailsStepVisible := false;
+ DocumentTypesStepVisible := false;
+ AdvancedSetupStepVisible := false;
+ FinalStepVisible := false;
+ BackActionEnabled := true;
+ NextActionEnabled := OnboardingHelper.IsCompanyInfoValid(TempCompanyContact);
+ FinishActionEnabled := false;
+ AdvancedSetupActionEnabled := false;
+
+ if RunScenario = RunScenario::EditSubscriptionInfo then begin
+ BackActionVisible := false;
+ NextActionVisible := false;
+ FinishActionEnabled := OnboardingHelper.IsCompanyInfoValid(TempCompanyContact);
+ end
+ end;
+
+ local procedure ShowNetworkDetailsStep()
+ begin
+ FirstStepVisible := false;
+ PartnerDetailsStepVisible := false;
+ LegalCompanyInformationStepVisible := false;
+ CompanyContactInformationStepVisible := false;
+ NetworkDetailsStepVisible := true;
+ DocumentTypesStepVisible := false;
+ AdvancedSetupStepVisible := false;
+ FinalStepVisible := false;
+
+ BackActionEnabled := true;
+ NextActionEnabled := true;
+ FinishActionEnabled := false;
+ AdvancedSetupActionEnabled := false;
+ end;
+
+ local procedure ShowDocumentTypesStep()
+ begin
+ FirstStepVisible := false;
+ PartnerDetailsStepVisible := false;
+ LegalCompanyInformationStepVisible := false;
+ CompanyContactInformationStepVisible := false;
+ NetworkDetailsStepVisible := false;
+ DocumentTypesStepVisible := true;
+ AdvancedSetupStepVisible := false;
+ FinalStepVisible := false;
+
+ BackActionEnabled := true;
+ NextActionEnabled := true;
+ FinishActionEnabled := false;
+ AdvancedSetupActionEnabled := true;
+ end;
+
+ local procedure ShowAdvancedSetupStep()
+ begin
+ FirstStepVisible := false;
+ PartnerDetailsStepVisible := false;
+ LegalCompanyInformationStepVisible := false;
+ CompanyContactInformationStepVisible := false;
+ NetworkDetailsStepVisible := false;
+ DocumentTypesStepVisible := false;
+ AdvancedSetupStepVisible := true;
+ FinalStepVisible := false;
+
+ BackActionEnabled := true;
+ NextActionEnabled := true;
+ FinishActionEnabled := false;
+ AdvancedSetupActionEnabled := false;
+ end;
+
+ local procedure ShowFinalStep()
+ begin
+ FirstStepVisible := false;
+ PartnerDetailsStepVisible := false;
+ LegalCompanyInformationStepVisible := false;
+ CompanyContactInformationStepVisible := false;
+ NetworkDetailsStepVisible := false;
+ DocumentTypesStepVisible := false;
+ AdvancedSetupStepVisible := false;
+ FinalStepVisible := true;
+
+ BackActionEnabled := true;
+ NextActionEnabled := false;
+ FinishActionEnabled := true;
+ AdvancedSetupActionEnabled := false;
+ end;
+
+ local procedure ResetControls()
+ begin
+ BackActionEnabled := true;
+ NextActionEnabled := true;
+ BackActionVisible := true;
+ NextActionVisible := true;
+ AdvancedSetupActionEnabled := false;
+
+ FirstStepVisible := false;
+ PartnerDetailsStepVisible := false;
+ LegalCompanyInformationStepVisible := false;
+ CompanyContactInformationStepVisible := false;
+ NetworkDetailsStepVisible := false;
+ DocumentTypesStepVisible := false;
+ AdvancedSetupStepVisible := false;
+ FinalStepVisible := false;
+ end;
+
+ local procedure UpdateProfiles()
+ var
+ TempActivatedProfiles: Record "Continia Activated Net. Prof." temporary;
+ begin
+ CurrPage.SelectProfilesPeppol.Page.GetProfileSelection(TempActivatedProfiles);
+ OnboardingHelper.UpdateProfiles(TempParticipation, TempActivatedProfiles);
+ end;
+
+ local procedure RegisterParticipation()
+ var
+ TempActivatedProfiles: Record "Continia Activated Net. Prof." temporary;
+ begin
+ CurrPage.SelectProfilesPeppol.Page.GetProfileSelection(TempActivatedProfiles);
+ OnboardingHelper.RegisterParticipation(TempParticipation, TempActivatedProfiles);
+ end;
+
+ local procedure InitializeNetworkProfiles()
+ var
+ TempActivatedProfiles: Record "Continia Activated Net. Prof." temporary;
+ begin
+ OnboardingHelper.InitializeNetworkProfiles(TempParticipation, TempActivatedProfiles);
+
+ CurrPage.SelectProfilesPeppol.Page.ClearProfileSelections();
+ CurrPage.SelectProfilesPeppol.Page.SetProfileSelection(TempActivatedProfiles);
+ end;
+
+ local procedure SetActivatedProfiles()
+ var
+ TempActivatedProfiles: Record "Continia Activated Net. Prof." temporary;
+ begin
+ OnboardingHelper.GetCurrentActivatedProfiles(TempParticipation, TempActivatedProfiles);
+
+ CurrPage.SelectProfilesPeppol.Page.ClearProfileSelections();
+ CurrPage.SelectProfilesPeppol.Page.SetCurrentNetwork(TempParticipation.Network);
+ CurrPage.SelectProfilesPeppol.Page.SetProfileSelection(TempActivatedProfiles);
+ end;
+
+ local procedure ValidateIdentifierData()
+ begin
+ TempParticipation.TestField("Identifier Type Id");
+ TempParticipation.TestField("Identifier Value");
+ OnboardingHelper.ValidateIdentifierValue(TempParticipation);
+ end;
+
+ local procedure ValidateParticipationProfiles()
+ var
+ TempActivatedProfiles: Record "Continia Activated Net. Prof." temporary;
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ CurrPage.SelectProfilesPeppol.Page.GetProfileSelection(TempActivatedProfiles);
+
+ if TempActivatedProfiles.Count = 0 then
+ Error(MustChooseAProfileErr);
+
+ // Check if the profiles are not already registered, the function will thrown an error if any profiles are already registered
+ ApiRequests.CheckProfilesNotRegistered(TempParticipation);
+ end;
+
+ internal procedure SetRunScenario(ParamRunScenario: Enum "Continia Wizard Scenario")
+ begin
+ RunScenario := ParamRunScenario;
+ end;
+
+ internal procedure SetParticipation(ParamParticipation: Record "Continia Participation")
+ begin
+ TempParticipation := ParamParticipation;
+ if TempParticipation."Registration Status" in [TempParticipation."Registration Status"::Disabled, TempParticipation."Registration Status"::Rejected, TempParticipation."Registration Status"::Draft] then
+ TempParticipation."Registration Status" := TempParticipation."Registration Status"::InProcess; // Reactivate the participation
+ TempParticipation.Insert();
+ end;
+
+ local procedure SetButtonBehaviourCompanyContactInformation()
+ begin
+ if RunScenario = RunScenario::EditSubscriptionInfo then begin
+ NextActionVisible := false;
+ BackActionVisible := false;
+ FinishActionEnabled := OnboardingHelper.IsCompanyInfoValid(TempCompanyContact);
+ end else
+ NextActionEnabled := OnboardingHelper.IsCompanyInfoValid(TempCompanyContact);
+ end;
+
+ local procedure PopulateNetworkProfilesByUserSelection()
+ var
+ TempActivatedProfiles: Record "Continia Activated Net. Prof." temporary;
+ begin
+ TempActivatedProfiles.DeleteAll();
+
+ GetSelectedNetworksProfiles(TempActivatedProfiles);
+ CurrPage.SelectProfilesPeppol.Page.SetCurrentNetwork(TempParticipation.Network);
+ CurrPage.SelectProfilesPeppol.Page.ClearProfileSelections();
+ CurrPage.SelectProfilesPeppol.Page.SetProfileSelection(TempActivatedProfiles);
+ end;
+
+ local procedure GetSelectedNetworksProfiles(var ActivatedProfiles: Record "Continia Activated Net. Prof." temporary)
+ var
+ ProfileDirection: Enum "Continia Profile Direction";
+ begin
+ if SendInvoiceCreditMemo or ReceiveInvoiceCreditMemo then
+ OnboardingHelper.AddInvoiceCreditMemoProfiles(TempParticipation, GetNetworkProfileDirection(SendInvoiceCreditMemo, ReceiveInvoiceCreditMemo), ActivatedProfiles);
+
+ if SendInvoiceResponse or ReceiveInvoiceResponse then begin
+ case TempParticipation.Network of
+ TempParticipation.Network::Peppol:
+ ProfileDirection := GetNetworkProfileDirection(SendInvoiceResponse, ReceiveInvoiceResponse);
+ TempParticipation.Network::Nemhandel:
+ ProfileDirection := GetNetworkProfileDirection(SendInvoiceCreditMemo, ReceiveInvoiceCreditMemo);
+ end;
+ OnboardingHelper.AddInvoiceResponseProfiles(TempParticipation, ProfileDirection, ActivatedProfiles);
+ end;
+
+ if (SendOrder or ReceiveOrder) and (not (SendOrderResponse or ReceiveOrderResponse)) then
+ OnboardingHelper.AddOrderOnlyProfiles(TempParticipation, GetNetworkProfileDirection(SendOrder, ReceiveOrder), ActivatedProfiles);
+
+ if (SendOrder or ReceiveOrder) and (SendOrderResponse or ReceiveInvoiceResponse) then
+ OnboardingHelper.AddOrderProfiles(TempParticipation, GetNetworkProfileDirection(SendOrder, ReceiveOrder), ActivatedProfiles);
+
+ if SendOrderResponse or ReceiveOrderResponse then
+ OnboardingHelper.AddOrderResponseProfiles(TempParticipation, GetNetworkProfileDirection(SendOrderResponse, ReceiveOrderResponse), ActivatedProfiles);
+
+ if (SendInvoiceCreditMemo or ReceiveInvoiceCreditMemo) and (SendOrder or ReceiveOrder) then
+ OnboardingHelper.AddInvoiceAndOrderProfiles(TempParticipation, GetNetworkProfileDirection(SendInvoiceCreditMemo or SendOrder, ReceiveInvoiceCreditMemo or ReceiveOrder), ActivatedProfiles);
+ end;
+
+ local procedure GetNetworkProfileDirection(Send: Boolean; Receive: Boolean): Enum "Continia Profile Direction"
+ begin
+ case true of
+ Receive and Send:
+ exit("Continia Profile Direction"::Both);
+ Receive and (not Send):
+ exit("Continia Profile Direction"::Inbound);
+ Send and (not Receive):
+ exit("Continia Profile Direction"::Outbound);
+ end;
+ end;
+
+ var
+ TempCompanyContact: Record "Continia Participation" temporary;
+ TempParticipation: Record "Continia Participation" temporary;
+ OnboardingHelper: Codeunit "Continia Onboarding Helper";
+ AdvancedSetupActionEnabled, BackActionEnabled, FinishActionEnabled, NextActionEnabled : Boolean;
+ AdvancedSetupStepVisible, BackActionVisible, CompanyContactInformationStepVisible, DocumentTypesStepVisible, FinalStepVisible, FirstStepVisible, LegalCompanyInformationStepVisible, NetworkDetailsStepVisible, NextActionVisible, PartnerDetailsStepVisible : Boolean;
+ ContactCountyVisible, CountyVisible : Boolean;
+ LicenseTermsAccepted: Boolean;
+ ReceiveInvoiceCreditMemo, ReceiveInvoiceResponse, ReceiveOrder, ReceiveOrderResponse, SendInvoiceCreditMemo, SendInvoiceResponse, SendOrder, SendOrderResponse : Boolean;
+ SkipCompanyInformation: Boolean;
+ ParticipationNetwork: Enum "Continia E-Delivery Network";
+ RunScenario: Enum "Continia Wizard Scenario";
+ LastStepsForward: Integer;
+ EditSubscriptionPageCaptionLbl: Label 'Company Contact Information';
+ MustChooseAProfileErr: Label 'You must select one or more network profiles.';
+ NoPasswordErr: Label 'Please enter a password.';
+ PartnerRegAsNewTxt: Label 'Not a partner?';
+ PartnerReqPwdTxt: Label 'Forgot the password?';
+ MissingSetupPermissionErr: Label 'You do not have permissions to modify or create a participation';
+ Step: Option Start,PartnerDetails,LegalCompanyInformation,CompanyContactInformation,NetworkDetails,DocumentTypes,AdvancedSetup,Finish;
+ IdentifierTypeDesc: Text;
+ ParticipationIdentifierValue: Text;
+ [NonDebuggable]
+ PartnerPassword: Text;
+ [NonDebuggable]
+ PartnerUserName: Text;
+ [NonDebuggable]
+ PartnerId: Code[20];
+
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaParticipation.Table.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaParticipation.Table.al
new file mode 100644
index 0000000000..b1b8561b00
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaParticipation.Table.al
@@ -0,0 +1,290 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using System.Email;
+using Microsoft.Finance.VAT.Registration;
+using Microsoft.Foundation.Address;
+
+table 6391 "Continia Participation"
+{
+ Access = Internal;
+ Caption = 'Participation';
+ DataClassification = CustomerContent;
+ LookupPageId = "Continia Participations";
+ Permissions = tabledata "Continia Activated Net. Prof." = rimd;
+
+ fields
+ {
+ field(1; Network; Enum "Continia E-Delivery Network")
+ {
+ Caption = 'Network';
+ ToolTip = 'Specifies the network name where the participation is in.';
+ }
+ field(2; "Identifier Type Id"; Guid)
+ {
+ Caption = 'Identifier Type';
+ TableRelation = "Continia Network Identifier".Id where(Network = field(Network));
+ }
+ field(3; "Identifier Value"; Code[50])
+ {
+ Caption = 'Identifier Value';
+ ToolTip = 'Specifies the value of the identifier used to identify the company in the network.';
+ }
+ field(10; "Company Name"; Text[100])
+ {
+ Caption = 'Company Name';
+ ToolTip = 'Specifies the legal name of the company that you want to join to the network.';
+ }
+ field(11; "VAT Registration No."; Text[20])
+ {
+ Caption = 'VAT Registration No.';
+ ToolTip = 'Specifies the VAT registration number of the company that you want to join to the network.';
+
+ trigger OnValidate()
+ var
+ VATRegNoFormat: Record "VAT Registration No. Format";
+ begin
+ "VAT Registration No." := UpperCase("VAT Registration No.");
+ if "VAT Registration No." = xRec."VAT Registration No." then
+ exit;
+ if not VATRegNoFormat.Test("VAT Registration No.", "Country/Region Code", '', Database::"Continia Participation") then
+ exit;
+ end;
+ }
+ field(12; Address; Text[100])
+ {
+ Caption = 'Address';
+ ToolTip = 'Specifies the legal address of the company that you want to join to the network.';
+ }
+ field(13; "Post Code"; Code[20])
+ {
+ Caption = 'Post Code';
+ ToolTip = 'Specifies the legal post code of the company that you want to join to the network.';
+ }
+ field(14; "Country/Region Code"; Code[10])
+ {
+ Caption = 'Country/Region Code';
+ ToolTip = 'Specifies the legal country code of the company that you want to join to the network. Must be stated in the ISO 3166-1 format.';
+
+ trigger OnLookup()
+ begin
+ LookupCountryRegion();
+ ValidateCountryRegion();
+ Validate("VAT Registration No.");
+ end;
+
+ trigger OnValidate()
+ begin
+ ValidateCountryRegion();
+ Validate("VAT Registration No.");
+ end;
+ }
+ field(15; County; Text[30])
+ {
+ Caption = 'County';
+ CaptionClass = '5,1,' + "Country/Region Code";
+ ToolTip = 'Specifies the legal county of the company that you want to join to the network.';
+ }
+ field(16; "Your Name"; Text[100])
+ {
+ Caption = 'Your Name';
+ }
+ field(17; "Contact Name"; Text[100])
+ {
+ Caption = 'Name';
+ ToolTip = 'Specifies the name of the contact person in the company.';
+ }
+ field(18; "Contact Phone No."; Text[30])
+ {
+ Caption = 'Phone No.';
+ ExtendedDatatype = PhoneNo;
+ ToolTip = 'Specifies the telephone number of the contact person in the company.';
+
+ trigger OnValidate()
+ var
+ PhoneNumber: Text[30];
+ begin
+ PhoneNumber := DelChr("Contact Phone No.", '=', '0123456789+');
+ if PhoneNumber <> '' then
+ Error(InvalidPhoneNoErr, "Contact Phone No.");
+ end;
+ }
+ field(19; "Contact Email"; Text[80])
+ {
+ Caption = 'Email Address';
+ ExtendedDatatype = EMail;
+ ToolTip = 'Specifies the email address of the contact person in the company.';
+
+ trigger OnValidate()
+ var
+ MailManagement: Codeunit "Mail Management";
+ begin
+ if "Contact Email" <> '' then
+ MailManagement.CheckValidEmailAddress("Contact Email");
+ end;
+ }
+ field(20; "Publish in Registry"; Boolean)
+ {
+ Caption = 'Publish data in Registry';
+ }
+ field(21; "Registration Status"; Enum "Continia Registration Status")
+ {
+ Caption = 'Registration Status';
+ ToolTip = 'Specifies the registration status of the participation.';
+ }
+ field(22; "Signatory Name"; Text[100])
+ {
+ Caption = 'Signatory Name';
+ ToolTip = 'Specifies the name of the company signatory.';
+ }
+ field(23; "Signatory Email"; Text[80])
+ {
+ Caption = 'Email Address';
+ ToolTip = 'Specifies the email of the company signatory.';
+
+ trigger OnValidate()
+ var
+ MailManagement: Codeunit "Mail Management";
+ begin
+ if "Signatory Email" <> '' then
+ MailManagement.CheckValidEmailAddress("Signatory Email");
+ end;
+ }
+ field(30; Id; Guid)
+ {
+ Caption = 'ID';
+ DataClassification = SystemMetadata;
+ ToolTip = 'Specifies the unique identifier of the participation in the Continia Delivery Network.';
+ }
+ field(31; Created; DateTime)
+ {
+ Caption = 'Created Date-Time';
+ DataClassification = SystemMetadata;
+ ToolTip = 'Specifies the date and time when the participation was created.';
+ }
+ field(32; Updated; DateTime)
+ {
+ Caption = 'Updated Date-Time';
+ DataClassification = SystemMetadata;
+ ToolTip = 'Specifies the date and time when the participation was last updated.';
+ }
+ field(33; "Cdn Timestamp"; Text[250])
+ {
+ Caption = 'CDN Timestamp';
+ DataClassification = SystemMetadata;
+ }
+ field(34; "Published in Registry"; Boolean)
+ {
+ Caption = 'Published in Registry';
+ DataClassification = SystemMetadata;
+ }
+ field(40; "Identifier Scheme Id"; Text[50])
+ {
+ CalcFormula = lookup("Continia Network Identifier"."Scheme Id" where(Id = field("Identifier Type Id")));
+ Caption = 'Identifier Type';
+ Editable = false;
+ FieldClass = FlowField;
+ ToolTip = 'Specifies the type of identifier used for the participation.';
+ }
+ field(50; "Partner Id"; Code[20])
+ {
+ Caption = 'Partner Id';
+ Editable = false;
+ ExtendedDatatype = Masked;
+ }
+ }
+
+ keys
+ {
+ key(Key1; Network, "Identifier Type Id", "Identifier Value")
+ {
+ Clustered = true;
+ }
+ key(Key2; Id) { }
+ }
+
+ internal procedure LookupCountryRegion()
+ var
+ CountryRegion: Record "Country/Region";
+ CountriesRegions: Page "Countries/Regions";
+ begin
+ CountriesRegions.LookupMode := true;
+ if CountriesRegions.RunModal() = Action::LookupOK then begin
+ CountriesRegions.GetRecord(CountryRegion);
+ "Country/Region Code" := CountryRegion."ISO Code";
+ end;
+ end;
+
+ internal procedure ValidateCountryRegion()
+ var
+ CountryRegion: Record "Country/Region";
+ begin
+ if "Country/Region Code" = '' then
+ exit;
+
+#pragma warning disable AA0210
+ CountryRegion.SetRange("ISO Code", "Country/Region Code");
+#pragma warning restore AA0210
+#pragma warning disable AA0175
+ CountryRegion.FindFirst(); // Throws the standard error if not found.
+#pragma warning restore AA0175
+ end;
+
+ internal procedure ValidateCdnStatus(Status: Text)
+ begin
+ case Status of
+ 'DraftEnum':
+ Validate("Registration Status", "Registration Status"::Draft);
+ 'InProcessEnum', 'ApprovedEnum', 'SuspendedEnum', 'ErrorEnum':
+ Validate("Registration Status", "Registration Status"::InProcess);
+ 'ConnectedEnum':
+ Validate("Registration Status", "Registration Status"::Connected);
+ 'RejectedEnum':
+ Validate("Registration Status", "Registration Status"::Rejected);
+ 'DisabledEnum':
+ Validate("Registration Status", "Registration Status"::Disabled);
+ end;
+ end;
+
+ internal procedure GetParticipApiStatusEnumValue(Suspended: Boolean): Text
+ begin
+ if Suspended then
+ exit('SuspendedEnum');
+
+ case "Registration Status" of
+ "Registration Status"::Draft:
+ exit('DraftEnum');
+ "Registration Status"::InProcess:
+ exit('InProcessEnum');
+ "Registration Status"::Connected:
+ exit('ConnectedEnum');
+ "Registration Status"::Rejected:
+ exit('RejectedEnum');
+ "Registration Status"::Disabled:
+ exit('DisabledEnum');
+ end;
+ end;
+
+ internal procedure GetNetworkIdentifier() NetworkIdentifier: Record "Continia Network Identifier"
+ begin
+ NetworkIdentifier.SetRange(Id, "Identifier Type Id");
+ NetworkIdentifier.FindFirst();
+ exit(NetworkIdentifier);
+ end;
+
+ trigger OnDelete()
+ var
+ ActivatedProfiles: Record "Continia Activated Net. Prof.";
+ begin
+ ActivatedProfiles.SetRange(Network, Rec.Network);
+ ActivatedProfiles.SetRange("Identifier Type Id", Rec."Identifier Type Id");
+ ActivatedProfiles.SetRange("Identifier Value", Rec."Identifier Value");
+ ActivatedProfiles.DeleteAll();
+ end;
+
+ var
+ InvalidPhoneNoErr: Label 'The phone number "%1" is not valid', Comment = '%1 - Telephone number';
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaProfileSelection.Page.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaProfileSelection.Page.al
new file mode 100644
index 0000000000..07a5e44ac3
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaProfileSelection.Page.al
@@ -0,0 +1,154 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+page 6394 "Continia Profile Selection"
+{
+ ApplicationArea = All;
+ Caption = 'Network Profile Selection';
+ DelayedInsert = true;
+ PageType = ListPart;
+ SourceTable = "Continia Activated Net. Prof.";
+ SourceTableTemporary = true;
+
+ layout
+ {
+ area(Content)
+ {
+ repeater(Group)
+ {
+ field("Profile Name"; ProfileName)
+ {
+ Caption = 'Profile Name';
+ Lookup = true;
+ ToolTip = 'Specifies the name of the profile.';
+ Width = 20;
+
+ trigger OnLookup(var Text: Text): Boolean
+ var
+ NetworkProfile: Record "Continia Network Profile";
+ NetworkProfileList: Page "Continia Network Profile List";
+ begin
+ NetworkProfile.FilterGroup(2);
+ NetworkProfile.SetRange(Network, CurrentNetwork);
+ NetworkProfile.FilterGroup(0);
+ NetworkProfileList.LookupMode(true);
+
+ if not IsNullGuid(Rec."Network Profile Id") then
+ NetworkProfile.Get(Rec."Network Profile Id")
+ else
+ if Text <> '' then
+ NetworkProfile.SetFilter(Description, StrSubstNo('@*%1*', Text));
+
+ NetworkProfileList.SetTableView(NetworkProfile);
+ NetworkProfileList.SetRecord(NetworkProfile);
+ if NetworkProfileList.RunModal() = Action::LookupOK then begin
+ NetworkProfileList.GetRecord(NetworkProfile);
+ Rec."Network Profile Id" := NetworkProfile.Id;
+ ProfileName := NetworkProfile.Description;
+ Text := NetworkProfile.Description;
+ exit(true);
+ end;
+ end;
+ }
+ field("Profile Direction"; Rec."Profile Direction")
+ {
+ trigger OnValidate()
+ begin
+ ValidateProfileDirection();
+ end;
+ }
+ field("E-Document Service Code"; Rec."E-Document Service Code") { }
+ }
+ }
+ }
+
+ var
+ ParticipConnected: Boolean;
+ EditRemoveNetworkProfileErr: Label 'The following network profiles are about to be unregistered: %1.\\Do you want to continue?', Comment = '%1 - Profile Name';
+ ValueChangedInfoMsg: Label 'Please be aware that when changing %1 your participation must go through the approval process with Continia before you can send or receive network documents.\\This can take up to 2 days.', Comment = '%1 - Participation description';
+ ProfileName: Text;
+
+ trigger OnAfterGetRecord()
+ begin
+ if not IsNullGuid(Rec."Network Profile Id") then begin
+ Rec.CalcFields("Network Profile Description");
+ ProfileName := Rec."Network Profile Description";
+ end else
+ ProfileName := '';
+ end;
+
+ trigger OnNewRecord(BelowxRec: Boolean)
+ begin
+ ProfileName := '';
+ end;
+
+ local procedure ValidateProfileDirection()
+ begin
+ if not ParticipConnected then
+ exit;
+
+ if (xRec."Profile Direction" = xRec."Profile Direction"::Outbound) and
+ (Rec."Profile Direction" in [Rec."Profile Direction"::Both, Rec."Profile Direction"::Inbound])
+ then
+ if not Confirm(StrSubstNo(ValueChangedInfoMsg, StrSubstNo(Rec.FieldCaption("Profile Direction"),
+ xRec."Profile Direction", Rec."Profile Direction")))
+ then
+ Error('');
+
+ if ((xRec."Profile Direction" in [xRec."Profile Direction"::Both, xRec."Profile Direction"::Inbound])) and
+ (Rec."Profile Direction" = Rec."Profile Direction"::Outbound)
+ then
+ if not Confirm(StrSubstNo(EditRemoveNetworkProfileErr, ProfileName)) then
+ Error('');
+ end;
+
+ internal procedure ClearProfileSelections()
+ begin
+ Rec.Reset();
+ Rec.DeleteAll();
+ end;
+
+ internal procedure GetProfileSelection(var ActivatedNetworkProfiles: Record "Continia Activated Net. Prof." temporary)
+ begin
+ Clear(ActivatedNetworkProfiles);
+
+ if Rec.FindSet() then
+ repeat
+ ActivatedNetworkProfiles.Init();
+ ActivatedNetworkProfiles.TransferFields(Rec, true);
+ ActivatedNetworkProfiles.Insert();
+ until Rec.Next() = 0;
+ if not ActivatedNetworkProfiles.IsEmpty() then
+ ActivatedNetworkProfiles.FindFirst();
+ end;
+
+ internal procedure SetProfileSelection(var ActivatedNetworkProfiles: Record "Continia Activated Net. Prof." temporary)
+ var
+ Original: Record "Continia Activated Net. Prof.";
+ begin
+ Original := ActivatedNetworkProfiles;
+ ActivatedNetworkProfiles.SetFilter(Disabled, '=%1', 0DT);
+ if ActivatedNetworkProfiles.FindSet() then
+ repeat
+ Rec.Init();
+ Rec.TransferFields(ActivatedNetworkProfiles, true);
+ Rec.Insert();
+ until ActivatedNetworkProfiles.Next() = 0;
+ ActivatedNetworkProfiles.SetRange(Disabled);
+ CurrPage.Update(false);
+
+ ActivatedNetworkProfiles := Original;
+ end;
+
+ internal procedure SetCurrentNetwork(NewCurrentNetwork: Enum "Continia E-Delivery Network")
+ begin
+ CurrentNetwork := NewCurrentNetwork;
+ end;
+
+ var
+ CurrentNetwork: Enum "Continia E-Delivery Network";
+}
+
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaWizardScenario.Enum.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaWizardScenario.Enum.al
new file mode 100644
index 0000000000..be7dd224d4
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Onboarding/ContiniaWizardScenario.Enum.al
@@ -0,0 +1,24 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+enum 6392 "Continia Wizard Scenario"
+{
+ Access = Internal;
+ Extensible = false;
+
+ value(0; General)
+ {
+ Caption = 'General';
+ }
+ value(1; EditSubscriptionInfo)
+ {
+ Caption = 'Edit Company Contact Information';
+ }
+ value(2; EditParticipation)
+ {
+ Caption = 'Edit Participation and Profiles';
+ }
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Participation Setup/ContiniaActivatedNetProf.Table.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Participation Setup/ContiniaActivatedNetProf.Table.al
new file mode 100644
index 0000000000..82b4d6fa58
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Participation Setup/ContiniaActivatedNetProf.Table.al
@@ -0,0 +1,132 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using Microsoft.eServices.EDocument;
+
+table 6392 "Continia Activated Net. Prof."
+{
+ Access = Internal;
+ Caption = 'Activated Network Profile';
+ DataClassification = CustomerContent;
+
+ fields
+ {
+ field(1; Network; Enum "Continia E-Delivery Network")
+ {
+ Caption = 'Network';
+ ToolTip = 'Specifies E-Document Network.';
+ }
+ field(2; "Identifier Type Id"; Guid)
+ {
+ Caption = 'Identifier Type Id';
+ TableRelation = "Continia Network Identifier".Id where(Network = field(Network));
+ }
+ field(3; "Identifier Value"; Code[50])
+ {
+ Caption = 'Identifier Value';
+ }
+ field(4; "Network Profile Id"; Guid)
+ {
+ Caption = 'Network Profile Id';
+ TableRelation = "Continia Network Profile".Id where(Network = field(Network));
+ }
+ field(5; "Profile Direction"; Enum "Continia Profile Direction")
+ {
+ Caption = 'Profile Direction';
+ ToolTip = 'Specifies the direction of the profile.';
+ }
+ field(6; Id; Guid)
+ {
+ Caption = 'ID';
+ DataClassification = SystemMetadata;
+ }
+ field(7; Created; DateTime)
+ {
+ Caption = 'Created Date-Time';
+ DataClassification = SystemMetadata;
+ }
+ field(8; Updated; DateTime)
+ {
+ Caption = 'Updated Date-Time';
+ DataClassification = SystemMetadata;
+ }
+ field(9; Disabled; DateTime)
+ {
+ Caption = 'Disabled Date-Time';
+ DataClassification = SystemMetadata;
+ }
+ field(10; "Network Profile Description"; Text[250])
+ {
+ CalcFormula = lookup("Continia Network Profile".Description where(Id = field("Network Profile Id")));
+ Caption = 'Profile Description';
+ Editable = false;
+ FieldClass = FlowField;
+ ToolTip = 'Specifies the description of the profile.';
+ }
+ field(11; "E-Document Service Code"; Code[20])
+ {
+ Caption = 'E-Document Service Code';
+ TableRelation = "E-Document Service";
+ ToolTip = 'Specifies the E-Document Service that would be linked to selected Network Profile.';
+ }
+ }
+
+ keys
+ {
+ key(PK; Network, "Identifier Type Id", "Identifier Value", "Network Profile Id")
+ {
+ Clustered = true;
+ }
+ key(Key2; Id) { }
+ }
+
+ internal procedure ValidateApiDirection(Direction: Text)
+ begin
+ case Direction of
+ 'BothEnum':
+ Validate("Profile Direction", "Profile Direction"::Both);
+ 'InboundEnum':
+ Validate("Profile Direction", "Profile Direction"::Inbound);
+ 'OutboundEnum':
+ Validate("Profile Direction", "Profile Direction"::Outbound);
+ end;
+ end;
+
+ internal procedure GetParticipApiDirectionEnum(): Text
+ begin
+ case "Profile Direction" of
+ "Profile Direction"::Both:
+ exit('BothEnum');
+ "Profile Direction"::Inbound:
+ exit('InboundEnum');
+ "Profile Direction"::Outbound:
+ exit('OutboundEnum');
+ end;
+ end;
+
+ internal procedure GetNetworkProfile(var NetworkProfile: Record "Continia Network Profile"): Boolean
+ begin
+ if not IsNullGuid("Network Profile Id") then
+ exit(NetworkProfile.Get("Network Profile Id"));
+ end;
+
+ internal procedure FilterByParticipation(Participation: Record "Continia Participation")
+ begin
+ SetRange(Network, Participation.Network);
+ SetRange("Identifier Type Id", Participation."Identifier Type Id");
+ SetRange("Identifier Value", Participation."Identifier Value");
+ end;
+
+ internal procedure GetEDocServiceNetworkNames(EDocServiceNames: Text) NetworkNames: List of [Text]
+ begin
+ SetRange("E-Document Service Code", EDocServiceNames);
+ if FindSet() then
+ repeat
+ if not NetworkNames.Contains(Format(Network)) then
+ NetworkNames.Add(Format(Network));
+ until Next() = 0;
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Participation Setup/ContiniaActiveProfiles.Page.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Participation Setup/ContiniaActiveProfiles.Page.al
new file mode 100644
index 0000000000..18ef04dcf5
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Participation Setup/ContiniaActiveProfiles.Page.al
@@ -0,0 +1,33 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+page 6392 "Continia Active Profiles"
+{
+ ApplicationArea = All;
+ Caption = 'Active Network Profile';
+ Extensible = false;
+ PageType = ListPart;
+ SourceTable = "Continia Activated Net. Prof.";
+ SourceTableView = where(Disabled = filter(0DT));
+
+ layout
+ {
+ area(Content)
+ {
+ repeater(Group)
+ {
+ field("Network Profile Description"; Rec."Network Profile Description")
+ {
+ Editable = false;
+ Width = 20;
+ }
+ field("Profile Direction"; Rec."Profile Direction") { }
+ }
+ }
+ }
+
+}
+
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Participation Setup/ContiniaParticipations.Page.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Participation Setup/ContiniaParticipations.Page.al
new file mode 100644
index 0000000000..b88aefffee
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Participation Setup/ContiniaParticipations.Page.al
@@ -0,0 +1,119 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+page 6391 "Continia Participations"
+{
+ ApplicationArea = Basic, Suite;
+ Caption = 'Continia Participations';
+ Editable = false;
+ Extensible = false;
+ PageType = List;
+ SourceTable = "Continia Participation";
+ UsageCategory = None;
+
+ layout
+ {
+ area(Content)
+ {
+ repeater(ParticipationsGroup)
+ {
+ field(RegistrationStatus; Rec."Registration Status") { }
+ field(Network; Rec.Network) { }
+ field(IdentifierType; Rec."Identifier Scheme Id") { }
+ field(IdentifierValue; Rec."Identifier Value") { }
+ field(Created; Rec.Created) { }
+ field(Updated; Rec.Updated) { }
+ field(Id; Rec.Id) { }
+ }
+ }
+ area(FactBoxes)
+ {
+ part(ActiveProfiles; "Continia Active Profiles")
+ {
+ SubPageLink = Network = field(Network), "Identifier Type Id" = field("Identifier Type Id"), "Identifier Value" = field("Identifier Value");
+ }
+ }
+ }
+
+ actions
+ {
+ area(Promoted)
+ {
+ actionref(RegisterNewActionRef; RegisterNewParticipation) { }
+ actionref(EditActioNRef; EditParticipation) { }
+ actionref(DeleteActioNRef; DeleteParticipation) { }
+ }
+ area(Processing)
+ {
+ action(RegisterNewParticipation)
+ {
+ Caption = 'Register';
+ Enabled = CanEditParticipation;
+ Image = New;
+ ToolTip = 'Register a new participation in the Continia Delivery Network.';
+
+ trigger OnAction()
+ var
+ OnboardingWizard: Page "Continia Onboarding Wizard";
+ begin
+ OnboardingWizard.Run();
+ end;
+ }
+ action(EditParticipation)
+ {
+ Caption = 'Edit';
+ Enabled = ActionsEnabled and CanEditParticipation;
+ Image = Edit;
+ ToolTip = 'Edit the participation in the Continia Delivery Network.';
+
+ trigger OnAction()
+ var
+ OnBoardingWizard: Page "Continia Onboarding Wizard";
+ RunScenario: Enum "Continia Wizard Scenario";
+ begin
+ OnBoardingWizard.SetRunScenario(RunScenario::EditParticipation); //Update Participation and profiles
+ OnBoardingWizard.SetParticipation(Rec);
+ OnBoardingWizard.Run();
+ CurrPage.Update(false);
+ end;
+
+ }
+ action(DeleteParticipation)
+ {
+ Caption = 'Unregister';
+ Enabled = ActionsEnabled and CanEditParticipation;
+ Image = Delete;
+ ToolTip = 'Unregister the participation in the Continia Delivery Network.';
+
+ trigger OnAction()
+ var
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ if Rec."Registration Status" = Rec."Registration Status"::Draft then
+ Rec.Delete()
+ else
+ ApiRequests.DeleteParticipation(Rec);
+ end;
+ }
+ }
+ }
+
+ var
+ ActionsEnabled: Boolean;
+ CanEditParticipation: Boolean;
+
+ trigger OnOpenPage()
+ var
+ OnboardingHelper: Codeunit "Continia Onboarding Helper";
+ begin
+ CanEditParticipation := OnboardingHelper.HasModifyPermissionOnParticipation();
+ end;
+
+ trigger OnAfterGetRecord()
+ begin
+ ActionsEnabled := true;
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Participation Setup/ContiniaRegistrationStatus.Enum.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Participation Setup/ContiniaRegistrationStatus.Enum.al
new file mode 100644
index 0000000000..1fda946276
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Participation Setup/ContiniaRegistrationStatus.Enum.al
@@ -0,0 +1,32 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+enum 6394 "Continia Registration Status"
+{
+ Access = Internal;
+ Extensible = false;
+
+ value(0; Draft)
+ {
+ Caption = 'Draft';
+ }
+ value(1; InProcess)
+ {
+ Caption = 'Pending approval';
+ }
+ value(2; Connected)
+ {
+ Caption = 'Connected';
+ }
+ value(3; Rejected)
+ {
+ Caption = 'Rejected';
+ }
+ value(4; Disabled)
+ {
+ Caption = 'Disabled';
+ }
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnEdit.PermissionSet.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnEdit.PermissionSet.al
new file mode 100644
index 0000000000..22141b35c7
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnEdit.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.Continia;
+
+permissionset 6392 ContEDocConnEdit
+{
+ Access = Public;
+ Assignable = true;
+ Caption = 'Continia E-Document Connector - Edit';
+ IncludedPermissionSets = ContEDocConnRead;
+
+ Permissions = tabledata "Continia Connection Setup" = IM,
+ tabledata "Continia Participation" = imd,
+ tabledata "Continia Activated Net. Prof." = imd,
+ tabledata "Continia Network Identifier" = imd,
+ tabledata "Continia Network Profile" = imd,
+ tabledata "Con. E-Doc. Serv. Prof. Sel." = imd;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnObjects.PermissionSet.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnObjects.PermissionSet.al
new file mode 100644
index 0000000000..ee379eeb0e
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnObjects.PermissionSet.al
@@ -0,0 +1,23 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+permissionset 6390 ContEDocConnObjects
+{
+ Access = Public;
+ Assignable = false;
+ Caption = 'Continia E-Document Connector - Objects';
+
+ Permissions = table "Continia Connection Setup" = X,
+ page "Continia Ext. Connection Setup" = X,
+ codeunit "Continia Integration Impl." = X,
+ codeunit "Continia EDocument Processing" = X,
+ codeunit "Continia Api Url Mgt." = X,
+ codeunit "Continia Api Requests" = X,
+ codeunit "Continia Onboarding Helper" = X,
+ codeunit "Continia Credential Management" = X,
+ codeunit "Continia Session Manager" = X,
+ codeunit "Continia Subscription Mgt." = X;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnRead.PermissionSet.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnRead.PermissionSet.al
new file mode 100644
index 0000000000..42cbe666ff
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnRead.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.Continia;
+
+permissionset 6391 ContEDocConnRead
+{
+ Access = Public;
+ Assignable = true;
+ Caption = 'Continia E-Document Connector - Read';
+ IncludedPermissionSets = ContEDocConnObjects;
+
+ Permissions = tabledata "Continia Connection Setup" = R,
+ tabledata "Continia Participation" = R,
+ tabledata "Continia Activated Net. Prof." = R,
+ tabledata "Continia Network Identifier" = R,
+ tabledata "Continia Network Profile" = R,
+ tabledata "Con. E-Doc. Serv. Prof. Sel." = R;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnectorEdit.PermissionSetExt.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnectorEdit.PermissionSetExt.al
new file mode 100644
index 0000000000..683bb85ed9
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnectorEdit.PermissionSetExt.al
@@ -0,0 +1,12 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using System.Security.AccessControl;
+
+permissionsetextension 6391 "Cont. EDoc. Connector - Edit" extends "D365 BASIC"
+{
+ IncludedPermissionSets = ContEDocConnEdit;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnectorRead.PermissionSetExt.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnectorRead.PermissionSetExt.al
new file mode 100644
index 0000000000..ce44c15b94
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Permissions/ContEDocConnectorRead.PermissionSetExt.al
@@ -0,0 +1,12 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using System.Security.AccessControl;
+
+permissionsetextension 6390 "Cont. EDoc. Connector - Read" extends "D365 READ"
+{
+ IncludedPermissionSets = ContEDocConnRead;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Subscription and Access/ContiniaCredentialManagement.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Subscription and Access/ContiniaCredentialManagement.Codeunit.al
new file mode 100644
index 0000000000..b1a1bcc869
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Subscription and Access/ContiniaCredentialManagement.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.Continia;
+
+using System.Environment;
+
+codeunit 6395 "Continia Credential Management"
+{
+ Access = Internal;
+
+ internal procedure IsClientCredentialsValid(): Boolean
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ begin
+ if ConnectionSetup.Get() then
+ exit((not ConnectionSetup.GetClientId().IsEmpty()) and (not ConnectionSetup.GetClientSecret().IsEmpty()));
+ end;
+
+ [NonDebuggable]
+ internal procedure GetClientCredentialsApiBodyString(): Text
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ CredentialsStringPlaceholderTok: Label 'grant_type=password&username=%1&password=%2', Comment = '%1 - Client Id, %2 - Client Secret', Locked = true;
+ begin
+ if IsClientCredentialsValid() then begin
+ ConnectionSetup.Get();
+ exit(StrSubstNo(CredentialsStringPlaceholderTok, ConnectionSetup.GetClientId().Unwrap(), ConnectionSetup.GetClientSecret().Unwrap()));
+ end;
+ end;
+
+ internal procedure InsertClientCredentials(ClientId: SecretText; ClientSecret: SecretText; TenantSubscriptionId: Code[50])
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ SessionManager: Codeunit "Continia Session Manager";
+ begin
+ if not ConnectionSetup.Get() then
+ ConnectionSetup.Insert();
+
+ ConnectionSetup.SetClientId(ClientId);
+ ConnectionSetup.SetClientSecret(ClientSecret);
+ ConnectionSetup."Local Client Identifier" := TenantSubscriptionId;
+ ConnectionSetup.Modify();
+ SessionManager.ClearAccessToken();
+ SessionManager.RefreshClientIdentifier();
+ end;
+
+ internal procedure GetIsolatedStorageValue(ValueKey: Text; DataScope: DataScope) Value: SecretText
+ begin
+ if not HasIsolatedStorageValue(ValueKey, DataScope) then
+ exit;
+
+ IsolatedStorage.Get(ValueKey, DataScope, Value);
+ end;
+
+ [NonDebuggable]
+ internal procedure HasIsolatedStorageValue(ValueKey: Text; DataScope: DataScope): Boolean
+ begin
+ exit(IsolatedStorage.Contains(ValueKey, DataScope));
+ end;
+
+ internal procedure SetIsolatedStorageValue(var ValueKey: Guid; Value: SecretText; DataScope: DataScope) NewKey: Boolean
+ begin
+ if IsNullGuid(ValueKey) then
+ NewKey := true;
+ if NewKey then
+ ValueKey := CreateGuid();
+
+ IsolatedStorage.Set(ValueKey, Value, DataScope);
+ end;
+
+ internal procedure DeleteIsolatedStorageValue(var ValueKey: Guid; DataScope: DataScope): Boolean
+ begin
+ if IsNullGuid(ValueKey) then
+ exit;
+ exit(IsolatedStorage.Delete(ValueKey, DataScope));
+ end;
+
+ internal procedure GetCompanyGuidAsText(): Text[36]
+ begin
+ exit(CopyStr(LowerCase(Format(GetCompanyId())), 2, 36));
+ end;
+
+ internal procedure GetCompanyId(): Guid
+ var
+ Company: Record Company;
+ begin
+ Company.Get(CompanyName);
+ exit(Company.Id);
+ end;
+
+ internal procedure GetAppCode(): Text[10]
+ begin
+ exit('COMSEDOC')
+ end;
+
+ internal procedure GetAppVersion(): Text[10]
+ var
+ ModInfo: ModuleInfo;
+ AppVer: Version;
+ MajorMinorVersion: Text;
+ Version: Integer;
+ begin
+ NavApp.GetCurrentModuleInfo(ModInfo);
+ AppVer := ModInfo.AppVersion;
+ MajorMinorVersion := Format(AppVer.Major) + Format(AppVer.Minor);
+ Evaluate(Version, PadStr(MajorMinorVersion, 6, '0'));
+ exit(Format(Version));
+ end;
+
+ internal procedure GetAppFullName(): Text[80]
+ begin
+ exit('Continia Microsoft E-Document Connector')
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Subscription and Access/ContiniaSessionManager.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Subscription and Access/ContiniaSessionManager.Codeunit.al
new file mode 100644
index 0000000000..ea79d77e5c
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Subscription and Access/ContiniaSessionManager.Codeunit.al
@@ -0,0 +1,122 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+codeunit 6396 "Continia Session Manager"
+{
+ Access = Internal;
+ SingleInstance = true;
+
+ var
+ ClientCredentialLoaded: Boolean;
+ IsAccessTokenLoaded: Boolean;
+ AccessTokenRequested: DateTime;
+ AccessTokenExpiresInMs: Integer;
+ NextAccessTokenUpdateInMs: Integer;
+ CachedAccessToken: SecretText;
+ ClientIdentifier: SecretText;
+
+ internal procedure ClearAccessToken()
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ begin
+ Clear(CachedAccessToken);
+ AccessTokenRequested := 0DT;
+ IsAccessTokenLoaded := false;
+ if CurrentClientType <> ClientType::ChildSession then
+ ConnectionSetup.ClearToken();
+ end;
+
+ internal procedure RefreshClientIdentifier()
+ begin
+ ClientCredentialLoaded := false;
+ GetClientIdentifier();
+ end;
+
+ internal procedure GetClientIdentifier(): SecretText
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ begin
+ if ClientCredentialLoaded then
+ exit(ClientIdentifier);
+
+ Clear(ClientIdentifier);
+ if ConnectionSetup.Get() then
+ ClientIdentifier := ConnectionSetup.GetClientId();
+
+ ClientCredentialLoaded := true;
+ exit(ClientIdentifier);
+ end;
+
+ [NonDebuggable]
+ internal procedure GetAccessToken() AccessTokenValue: SecretText
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ begin
+ // Get token from Cache if possible
+ if IsAccessTokenLoaded then
+ if AccessTokenRequested > CreateDateTime(Today, Time) - NextAccessTokenUpdateInMs then
+ exit(CachedAccessToken);
+
+ if ConnectionSetup.AcquireTokenFromCache(CachedAccessToken, AccessTokenRequested, AccessTokenExpiresInMs, NextAccessTokenUpdateInMs, true) then begin
+ IsAccessTokenLoaded := true;
+ exit(CachedAccessToken);
+ end;
+ // Not found in cache - make new request to Online
+ if AcquireToken(false) then
+ exit(CachedAccessToken);
+
+ // Fallback code Allow the access token to live for 23 hours
+ if ConnectionSetup.AcquireTokenFromCache(CachedAccessToken, AccessTokenRequested, AccessTokenExpiresInMs, NextAccessTokenUpdateInMs, false) then begin
+ IsAccessTokenLoaded := true;
+ exit(CachedAccessToken);
+ end else
+ if AcquireToken(true) then
+ exit(CachedAccessToken);
+ end;
+
+ local procedure AcquireToken(ShowError: Boolean): Boolean
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ ActivationMgt: Codeunit "Continia Subscription Mgt.";
+ ExpiresIn: Integer;
+ AccessTokenValue: Text;
+ begin
+ ClearLastError();
+ if not ActivationMgt.TryAcquireClientToken(AccessTokenValue, ExpiresIn) then
+ if ShowError then
+ Error(GetLastErrorText())
+ else
+ exit(false);
+
+ if ShouldSaveToken() then
+ ConnectionSetup.SetAccessToken(AccessTokenValue, ExpiresIn);
+
+ Clear(CachedAccessToken);
+ AccessTokenRequested := 0DT;
+
+ // Add to cache
+ CachedAccessToken := AccessTokenValue;
+ AccessTokenExpiresInMs := ExpiresIn;
+ if ShouldSaveToken() then
+ AccessTokenRequested := ConnectionSetup."Token Timestamp"
+ else
+ AccessTokenRequested := CurrentDateTime;
+
+ IsAccessTokenLoaded := true;
+ exit(true);
+ end;
+
+ local procedure ShouldSaveToken(): Boolean
+ begin
+ if CurrentClientType = ClientType::ChildSession then
+ exit(false);
+
+ if GetCurrentModuleExecutionContext() <> ExecutionContext::Normal then
+ exit(false);
+
+ exit(true);
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Subscription and Access/ContiniaSubscriptionMgt.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Subscription and Access/ContiniaSubscriptionMgt.Codeunit.al
new file mode 100644
index 0000000000..5ad6ce66b1
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Subscription and Access/ContiniaSubscriptionMgt.Codeunit.al
@@ -0,0 +1,842 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+using System.Environment;
+using System.Azure.Identity;
+using Microsoft.Foundation.Company;
+using System.Security.AccessControl;
+using Microsoft.CRM.Team;
+using System.Email;
+using System.Security.User;
+
+codeunit 6397 "Continia Subscription Mgt."
+{
+ Access = Internal;
+
+ var
+ ApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ ClientCredentialsMissingErr: Label 'Client credentials missing.';
+ CreateClientErrTitleErr: Label 'Failed to create client credentials';
+ ExpectedStatusOKErr: Label 'Could not connect to Continia Online.\Invalid response, expected Status = OK';
+ InvalidClientCredErr: Label 'Client credentials for Continia Online are invalid or missing.';
+ InvalidPartnerCredErr: Label 'Partner credentials for Continia PartnerZone are invalid or missing.';
+ RequestFailedErr: Label 'Request sent to Continia Online failed: %1', Comment = '%1 - Error Message from Continia Online';
+
+ [NonDebuggable]
+ internal procedure GetClientAccessToken(): SecretText
+ var
+ SessionManager: Codeunit "Continia Session Manager";
+ begin
+ exit(SessionManager.GetAccessToken());
+ end;
+
+ [NonDebuggable]
+ internal procedure InitializeContiniaClient(PartnerUserName: Text; PartnerPassword: SecretText; var PartnerId: Code[20]) Updated: Boolean
+ var
+ HttpClient: HttpClient;
+ HttpContent: HttpContent;
+ HttpHeaders: HttpHeaders;
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ PartnerAccessToken: SecretText;
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ begin
+ // Validate input
+ if (PartnerUserName = '') or (PartnerPassword.Unwrap() = '') then
+ Error(InvalidPartnerCredErr);
+
+ HttpRequest.GetHeaders(HttpHeaders);
+ HttpHeaders.Add('Accept', 'application/xml;charset=utf-8');
+ HttpRequest.Method('POST');
+ HttpRequest.SetRequestUri(ApiUrlMgt.PartnerAccessTokenUrl());
+ HttpContent.WriteFrom(GetPartnerZoneConnectRequestBody(PartnerUserName, PartnerPassword));
+ HttpContent.GetHeaders(HttpHeaders);
+ if HttpHeaders.Contains('Content-Type') then
+ HttpHeaders.Remove('Content-Type');
+ HttpHeaders.Add('Content-Type', 'application/xml');
+
+ HttpRequest.Content := HttpContent;
+ HttpClient.Send(HttpRequest, HttpResponse);
+ if HttpResponse.IsSuccessStatusCode then begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody <> '' then
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ end;
+ PartnerAccessToken := HandlePartnerZoneAccessTokenResponse(ResponseXmlDoc);
+
+ if InitializeContiniaClient(PartnerAccessToken) then
+ exit(CheckPartnerAndGetPartnerId(PartnerUserName, PartnerPassword, PartnerId));
+ end;
+
+ [NonDebuggable]
+ internal procedure CheckPartnerAndGetPartnerId(PartnerUserName: Text; PartnerPassword: SecretText; var PartnerId: Code[20]): Boolean
+ var
+ SessionManager: Codeunit "Continia Session Manager";
+ HttpClient: HttpClient;
+ HttpContent: HttpContent;
+ HttpHeaders: HttpHeaders;
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ PartnerIdNode: XmlNode;
+ ErrorNode: XmlNode;
+ begin
+ // Validate input
+ if (PartnerUserName = '') or (PartnerPassword.Unwrap() = '') then
+ Error(InvalidPartnerCredErr);
+
+ HttpRequest.GetHeaders(HttpHeaders);
+ HttpHeaders.Add('Accept', 'application/xml;charset=utf-8');
+ HttpRequest.Method('POST');
+ HttpRequest.SetRequestUri(ApiUrlMgt.PartnerZoneUrl());
+ HttpContent.WriteFrom(GetPartnerZoneConnectRequestBody(PartnerUserName, PartnerPassword));
+
+ HttpHeaders.Add('Authorization', SecretStrSubstNo('Bearer %1', SessionManager.GetAccessToken()));
+
+ HttpContent.GetHeaders(HttpHeaders);
+ if HttpHeaders.Contains('Content-Type') then
+ HttpHeaders.Remove('Content-Type');
+ HttpHeaders.Add('Content-Type', 'application/xml');
+
+ HttpRequest.Content := HttpContent;
+ HttpClient.Send(HttpRequest, HttpResponse);
+ if HttpResponse.IsSuccessStatusCode then begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody <> '' then
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ end;
+
+ if ResponseXmlDoc.SelectSingleNode('Error/@Message', ErrorNode) then
+ if ErrorNode.AsXmlAttribute().Value <> '' then
+ Error(InvalidPartnerCredErr);
+
+ if ResponseXmlDoc.SelectSingleNode('PartnerZoneConnectResponse/@Msid', PartnerIdNode) then begin
+ PartnerId := CopyStr(PartnerIdNode.AsXmlAttribute().Value, 1, MaxStrLen(PartnerId));
+ exit(true);
+ end;
+ end;
+
+ [NonDebuggable]
+ local procedure InitializeContiniaClient(PartnerAccessToken: SecretText): Boolean
+ var
+ AzureADTenant: Codeunit "Azure AD Tenant";
+ CredentialManagement: Codeunit "Continia Credential Management";
+ SessionManager: Codeunit "Continia Session Manager";
+ EnvironmentInformation: Codeunit "Environment Information";
+ HttpClient: HttpClient;
+ HttpContent: HttpContent;
+ HttpHeaders: HttpHeaders;
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ ClientId: SecretText;
+ ClientSecret: SecretText;
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ begin
+ if CredentialManagement.IsClientCredentialsValid() then
+ exit(false);
+
+ SessionManager.ClearAccessToken();
+ SessionManager.RefreshClientIdentifier();
+
+ HttpRequest.GetHeaders(HttpHeaders);
+ HttpHeaders.Add('Accept', 'application/xml;charset=utf-8');
+ HttpHeaders.Add('PartnerZone', PartnerAccessToken);
+ if EnvironmentInformation.IsSaaSInfrastructure() then
+ HttpHeaders.Add('x-AzureTenantId', AzureADTenant.GetAadTenantId());
+ HttpRequest.Method('POST');
+ HttpRequest.SetRequestUri(ApiUrlMgt.ClientEnvironmentInitializeUrl());
+ HttpContent.WriteFrom(GetInitializeCredentialRequestBody());
+ HttpContent.GetHeaders(HttpHeaders);
+ if HttpHeaders.Contains('Content-Type') then
+ HttpHeaders.Remove('Content-Type');
+ HttpHeaders.Add('Content-Type', 'application/xml');
+
+ HttpRequest.Content := HttpContent;
+ HttpClient.Send(HttpRequest, HttpResponse);
+ if HttpResponse.IsSuccessStatusCode then begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody <> '' then
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ end;
+ HandleInitializeCredentialResponse(ResponseXmlDoc, ClientId, ClientSecret);
+ CredentialManagement.InsertClientCredentials(ClientId, ClientSecret, GetTenantSubscriptionId());
+ Commit(); // Requires commit to store the credentials
+ SessionManager.RefreshClientIdentifier();
+ exit(true);
+ end;
+
+ [NonDebuggable]
+ local procedure HandlePartnerZoneAccessTokenResponse(ResponseXmlDoc: XmlDocument): Text
+ var
+ TempXmlNode: XmlNode;
+ begin
+ if ResponseXmlDoc.SelectSingleNode('Error/@Message', TempXmlNode) then
+ if TempXmlNode.AsXmlAttribute().Value <> '' then
+ Error(InvalidPartnerCredErr);
+ if not ResponseXmlDoc.SelectSingleNode('PartnerZoneToken/@Value', TempXmlNode) then
+ Error(InvalidPartnerCredErr);
+ exit(TempXmlNode.AsXmlAttribute().Value);
+ end;
+
+ [NonDebuggable]
+ local procedure GetPartnerZoneConnectRequestBody(PartnerUserName: Text; PartnerPassword: SecretText) RequestBody: Text
+ var
+ PartnerRequestElement: XmlElement;
+ begin
+ PartnerRequestElement := XmlElement.Create('PartnerZoneConnectRequest');
+ PartnerRequestElement.SetAttribute('Email', PartnerUserName);
+ PartnerRequestElement.SetAttribute('Password', PartnerPassword.Unwrap());
+ PartnerRequestElement.WriteTo(RequestBody);
+ end;
+
+ [NonDebuggable]
+ local procedure GetInitializeCredentialRequestBody() RequestBody: Text
+ var
+ CompanyInfo: Record "Company Information";
+ AzureADTenant: Codeunit "Azure AD Tenant";
+ EnvironmentInformation: Codeunit "Environment Information";
+ TenantSubscriptionId: Code[50];
+ ClientName: Text;
+ EnvironmentName: Text;
+ OwnerAzureId: Text;
+ InitializeCredentialsElement: XmlElement;
+ begin
+ TenantSubscriptionId := GetTenantSubscriptionId();
+
+ CompanyInfo.Get();
+ CompanyInfo.TestField(Name);
+ ClientName := CompanyInfo.Name;
+
+ OwnerAzureId := AzureADTenant.GetAadTenantId();
+
+ EnvironmentName := EnvironmentInformation.GetEnvironmentName();
+
+ InitializeCredentialsElement := XmlElement.Create('InitializeCredentialsV3');
+ InitializeCredentialsElement.SetAttribute('AzureId', TenantSubscriptionId);
+ InitializeCredentialsElement.SetAttribute('OwnerAzureId', OwnerAzureId);
+ InitializeCredentialsElement.SetAttribute('Name', ClientName);
+ InitializeCredentialsElement.SetAttribute('UserName', UserId());
+ InitializeCredentialsElement.SetAttribute('EnvironmentName', EnvironmentName);
+ InitializeCredentialsElement.WriteTo(RequestBody);
+ end;
+
+ [NonDebuggable]
+ internal procedure GetClientInfoApp(var ClientInfo: Record "Continia Participation" temporary; ShowError: Boolean) Success: Boolean
+ var
+ CredentialMgt: Codeunit "Continia Credential Management";
+ ContactPerson: XmlNode;
+ SubscriptionNode: XmlNode;
+ SubscriptionResponse: XmlNode;
+ TempXMLNode: XmlNode;
+ InvoiceDetailsXMLPathLbl: Label 'Subscriptions/Subscription[@AppCode=''%1'']/InvoicingDetails', Locked = true, Comment = '%1 - App Code';
+ ContactPersonXMLPathLbl: Label 'Subscriptions/Subscription[@AppCode=''%1'']/ContactPerson', Locked = true, Comment = '%1 - App Code';
+ SubscriptionDetailsXMLPathLbl: Label 'Subscriptions/Subscription[@AppCode=''%1'']', Locked = true, Comment = '%1 - App Code';
+ begin
+ GetSubscription(SubscriptionResponse, ShowError);
+
+ if SubscriptionResponse.SelectSingleNode(StrSubstNo(SubscriptionDetailsXMLPathLbl, CredentialMgt.GetAppCode()), SubscriptionNode) then begin
+ SubscriptionNode.SelectSingleNode('@PartnerId', TempXMLNode);
+ ClientInfo."Partner Id" := CopyStr(TempXMLNode.AsXmlAttribute().Value, 1, MaxStrLen(ClientInfo."Partner Id"));
+
+ if SubscriptionResponse.SelectSingleNode(StrSubstNo(InvoiceDetailsXMLPathLbl, CredentialMgt.GetAppCode()), SubscriptionNode) then begin
+
+ SubscriptionNode.SelectSingleNode('@CompanyName', TempXMLNode);
+ ClientInfo."Company Name" := CopyStr(TempXMLNode.AsXmlAttribute().Value, 1, MaxStrLen(ClientInfo."Company Name"));
+
+ SubscriptionNode.SelectSingleNode('@CompanyAddress', TempXMLNode);
+ ClientInfo.Address := CopyStr(TempXMLNode.AsXmlAttribute().Value, 1, MaxStrLen(ClientInfo.Address));
+
+ SubscriptionNode.SelectSingleNode('@PostalCode', TempXMLNode);
+ ClientInfo."Post Code" := CopyStr(TempXMLNode.AsXmlAttribute().Value, 1, MaxStrLen(ClientInfo."Post Code"));
+
+ SubscriptionNode.SelectSingleNode('@Country', TempXMLNode);
+ ClientInfo.County := CopyStr(TempXMLNode.AsXmlAttribute().Value, 1, MaxStrLen(ClientInfo.County));
+
+ SubscriptionNode.SelectSingleNode('@CountryIsoCode', TempXMLNode);
+ ClientInfo."Country/Region Code" := CopyStr(TempXMLNode.AsXmlAttribute().Value, 1, MaxStrLen(ClientInfo."Country/Region Code"));
+
+ SubscriptionNode.SelectSingleNode('@VatRegNo', TempXMLNode);
+ ClientInfo."VAT Registration No." := CopyStr(TempXMLNode.AsXmlAttribute().Value, 1, MaxStrLen(ClientInfo."VAT Registration No."));
+
+ SubscriptionNode.SelectSingleNode('@Email', TempXMLNode);
+ ClientInfo."Contact Email" := CopyStr(TempXMLNode.AsXmlAttribute().Value, 1, MaxStrLen(ClientInfo."Contact Email"));
+
+ SubscriptionNode.SelectSingleNode('@PhoneNo', TempXMLNode);
+ ClientInfo."Contact Phone No." := CopyStr(TempXMLNode.AsXmlAttribute().Value, 1, MaxStrLen(ClientInfo."Contact Phone No."));
+
+
+
+ end;
+ if SubscriptionResponse.SelectSingleNode(StrSubstNo(ContactPersonXMLPathLbl, CredentialMgt.GetAppCode()), ContactPerson) then begin
+ ContactPerson.SelectSingleNode('@Name', TempXMLNode);
+ ClientInfo."Contact Name" := CopyStr(TempXMLNode.AsXmlAttribute().Value, 1, MaxStrLen(ClientInfo."Contact Name"));
+
+ ContactPerson.SelectSingleNode('@Email', TempXMLNode);
+ ClientInfo."Contact Email" := CopyStr(TempXMLNode.AsXmlAttribute().Value, 1, MaxStrLen(ClientInfo."Contact Email"));
+ end;
+ if not ClientInfo.Modify() then
+ ClientInfo.Insert();
+
+ Success := true;
+ end;
+ end;
+
+
+ [NonDebuggable]
+ internal procedure HasOtherAppsInSubscription(): Boolean
+ var
+ CredentialMgt: Codeunit "Continia Credential Management";
+ SubscriptionNode: XmlNode;
+ SubscriptionResponse: XmlNode;
+ AppCodeSubscriptionXMLPathLbl: Label 'Subscriptions/Subscription[@AppCode!=''%1'']', Locked = true, Comment = '%1 - App Code';
+ begin
+ GetSubscription(SubscriptionResponse, true);
+
+ exit(SubscriptionResponse.SelectSingleNode(StrSubstNo(AppCodeSubscriptionXMLPathLbl, CredentialMgt.GetAppCode()), SubscriptionNode));
+ end;
+
+ [NonDebuggable]
+ internal procedure GetSubscription(var SubscriptionResponse: XmlNode; ShowError: Boolean) Success: Boolean
+ var
+ AzureADTenant: Codeunit "Azure AD Tenant";
+ CredentialMgt: Codeunit "Continia Credential Management";
+ SessionManager: Codeunit "Continia Session Manager";
+ EnvironmentInformation: Codeunit "Environment Information";
+ HttpClient: HttpClient;
+ HttpHeaders: HttpHeaders;
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ begin
+ if not CredentialMgt.IsClientCredentialsValid() then
+ exit(false);
+
+ HttpRequest.GetHeaders(HttpHeaders);
+ HttpHeaders.Add('Accept', 'application/xml;charset=utf-8');
+ HttpHeaders.Add('Authorization', SecretStrSubstNo('Bearer %1', SessionManager.GetAccessToken()));
+ HttpHeaders.Add('x-continia-companyguid', CredentialMgt.GetCompanyGuidAsText());
+ HttpHeaders.Add('x-continia-version', '1500');
+ if EnvironmentInformation.IsSaaSInfrastructure() then
+ HttpHeaders.Add('x-AzureTenantId', AzureADTenant.GetAadTenantId());
+
+ HttpRequest.Method('GET');
+ HttpRequest.SetRequestUri(ApiUrlMgt.GetSubscriptionUrl());
+
+ HttpClient.Timeout := 6000;
+ HttpClient.Send(HttpRequest, HttpResponse);
+ if HttpResponse.IsSuccessStatusCode then begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody <> '' then
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+
+ if ResponseXmlDoc.SelectSingleNode('/SubscriptionResponse', SubscriptionResponse) then
+ exit(true);
+ end;
+
+ exit(VerifyResponse(ResponseXmlDoc, ShowError));
+ end;
+
+ [NonDebuggable]
+ internal procedure Unsubscribe(ShowError: Boolean) Success: Boolean
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ TempCompanyInfo: Record "Continia Participation" temporary;
+ SubscriptionStatus: Enum "Continia Subscription Status";
+ begin
+ SubscriptionStatus := SubscriptionStatus::Unsubscribed;
+ if not GetClientInfoApp(TempCompanyInfo, ShowError) then
+ exit;
+ if not UpdateSubscription(SubscriptionStatus, TempCompanyInfo, ShowError) then
+ exit;
+
+ ConnectionSetup.Get();
+ ConnectionSetup."Subscription Status" := SubscriptionStatus;
+ ConnectionSetup.Modify();
+ end;
+
+ [NonDebuggable]
+ internal procedure UpdateSubscription(SubscriptionState: Enum "Continia Subscription Status"; var ClientInfo: Record "Continia Participation" temporary; ShowError: Boolean) Success: Boolean
+ var
+ AzureADTenant: Codeunit "Azure AD Tenant";
+ CredentialManagement: Codeunit "Continia Credential Management";
+ SessionManager: Codeunit "Continia Session Manager";
+ EnvironmentInformation: Codeunit "Environment Information";
+ HttpClient: HttpClient;
+ HttpContent: HttpContent;
+ HttpHeaders: HttpHeaders;
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ begin
+ if not CredentialManagement.IsClientCredentialsValid() then
+ exit(false);
+
+ HttpRequest.GetHeaders(HttpHeaders);
+ HttpHeaders.Add('Accept', 'application/xml;charset=utf-8');
+ HttpHeaders.Add('Authorization', SecretStrSubstNo('Bearer %1', SessionManager.GetAccessToken()));
+ HttpHeaders.Add('x-continia-companyguid', CredentialManagement.GetCompanyGuidAsText());
+ HttpHeaders.Add('x-continia-version', '1500');
+ if EnvironmentInformation.IsSaaSInfrastructure() then
+ HttpHeaders.Add('x-AzureTenantId', AzureADTenant.GetAadTenantId());
+
+ HttpRequest.Method('POST');
+ HttpRequest.SetRequestUri(ApiUrlMgt.UpdateSubscriptionUrl());
+ HttpContent.WriteFrom(GetUpdateSubscriptionBody(SubscriptionState, ClientInfo));
+ HttpContent.GetHeaders(HttpHeaders);
+ if HttpHeaders.Contains('Content-Type') then
+ HttpHeaders.Remove('Content-Type');
+ HttpHeaders.Add('Content-Type', 'application/xml');
+
+ HttpRequest.Content := HttpContent;
+
+
+ HttpClient.Timeout := 6000;
+ HttpClient.Send(HttpRequest, HttpResponse);
+ if HttpResponse.IsSuccessStatusCode then begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody <> '' then
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ end;
+
+ exit(VerifyResponse(ResponseXmlDoc, ShowError));
+ end;
+
+ [NonDebuggable]
+ local procedure VerifyResponse(ResponseXmlDoc: XmlDocument; ShowError: Boolean): Boolean
+ var
+ ErrorMessage: Text;
+ ResponseStatus: Text;
+ ErrorMessageAttr: XmlAttribute;
+ ResponseStatusAttr: XmlAttribute;
+ EmptyResponseNode: XmlNode;
+ ErrorNode: XmlNode;
+ begin
+ if ResponseXmlDoc.SelectSingleNode('EmptyResponse', EmptyResponseNode) then
+ if EmptyResponseNode.AsXmlElement().Attributes().Get('Status', ResponseStatusAttr) then
+ ResponseStatus := ResponseStatusAttr.Value;
+
+ if ResponseXmlDoc.SelectSingleNode('Error', ErrorNode) then
+ if ErrorNode.AsXmlElement().Attributes().Get('Message', ErrorMessageAttr) then
+ ErrorMessage := ErrorMessageAttr.Value;
+
+ if ErrorMessage <> '' then
+ if ShowError then
+ Error(ErrorMessage)
+ else
+ exit(false);
+
+ if ResponseStatus <> 'OK' then
+ if ShowError then
+ Error(ExpectedStatusOKErr)
+ else
+ exit(false);
+
+ exit(true);
+ end;
+
+
+ [NonDebuggable]
+ local procedure GetUpdateSubscriptionBody(SubscriptionState: Enum "Continia Subscription Status"; var ClientInfo: Record "Continia Participation" temporary) RequestBody: Text
+ var
+ AppMgt: Codeunit "Application System Constants";
+ CredentialMgt: Codeunit "Continia Credential Management";
+ ContactPerson: XmlElement;
+ InvoicingDetails: XmlElement;
+ Module: XmlElement;
+ Modules: XmlElement;
+ UpdateSubscriptionRequest: XmlElement;
+ begin
+ UpdateSubscriptionRequest := XmlElement.Create('UpdateSubscriptionRequest');
+ UpdateSubscriptionRequest.SetAttribute('AppCode', CredentialMgt.GetAppCode());
+ UpdateSubscriptionRequest.SetAttribute('AppVersion', CredentialMgt.GetAppVersion());
+ UpdateSubscriptionRequest.SetAttribute('AppVersionText', CredentialMgt.GetAppFullName());
+ UpdateSubscriptionRequest.SetAttribute('CoreVersion', CredentialMgt.GetAppVersion());
+ UpdateSubscriptionRequest.SetAttribute('CoreVersionText', CredentialMgt.GetAppFullName());
+ UpdateSubscriptionRequest.SetAttribute('NavVersion', GetTenantApplicationVersion());
+ UpdateSubscriptionRequest.SetAttribute('NavVersionText', AppMgt.ApplicationVersion());
+ UpdateSubscriptionRequest.SetAttribute('State', Format(MapOnlineSubscriptionState(SubscriptionState)));
+ UpdateSubscriptionRequest.SetAttribute('UserId', UserId);
+ UpdateSubscriptionRequest.SetAttribute('UserEmail', GetUserNotificationEmail());
+ UpdateSubscriptionRequest.SetAttribute('PartnerId', ClientInfo."Partner Id");
+
+ if ClientInfo."Company Name" <> '' then begin
+ InvoicingDetails := XmlElement.Create('InvoicingDetails');
+ InvoicingDetails.SetAttribute('CompanyName', ClientInfo."Company Name");
+ InvoicingDetails.SetAttribute('CompanyAddress', ClientInfo.Address);
+ InvoicingDetails.SetAttribute('PostalCode', ClientInfo."Post Code");
+ InvoicingDetails.SetAttribute('Country', ClientInfo.County);
+ InvoicingDetails.SetAttribute('CountryIsoCode', ClientInfo."Country/Region Code");
+ InvoicingDetails.SetAttribute('VatRegNo', ClientInfo."VAT Registration No.");
+ InvoicingDetails.SetAttribute('Email', ClientInfo."Contact Email");
+ InvoicingDetails.SetAttribute('PhoneNo', ClientInfo."Contact Phone No.");
+ UpdateSubscriptionRequest.Add(InvoicingDetails);
+
+ ContactPerson := XmlElement.Create('ContactPerson');
+ ContactPerson.SetAttribute('Name', ClientInfo."Contact Name");
+ ContactPerson.SetAttribute('Email', ClientInfo."Contact Email");
+ UpdateSubscriptionRequest.Add(ContactPerson);
+ end;
+
+ Modules := XmlElement.Create('Modules');
+ Module := XmlElement.Create('Module');
+ Module.SetAttribute('Code', 'ESSENTIAL');
+ Module.SetAttribute('State', '1');
+ Modules.Add(Module);
+ UpdateSubscriptionRequest.Add(Modules);
+
+ UpdateSubscriptionRequest.WriteTo(RequestBody);
+ end;
+
+ [NonDebuggable]
+ internal procedure AcceptCompanyLicense(CompanyName: Text): Boolean
+ var
+ CredentialManagement: Codeunit "Continia Credential Management";
+ SessionManager: Codeunit "Continia Session Manager";
+ HttpClient: HttpClient;
+ HttpContent: HttpContent;
+ HttpHeaders: HttpHeaders;
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ begin
+ if not CredentialManagement.IsClientCredentialsValid() then
+ exit(false);
+
+ HttpRequest.GetHeaders(HttpHeaders);
+ HttpHeaders.Add('Accept', 'application/xml;charset=utf-8');
+ HttpHeaders.Add('Authorization', SecretStrSubstNo('Bearer %1', SessionManager.GetAccessToken()));
+ HttpHeaders.Add('x-continia-companyguid', CredentialManagement.GetCompanyGuidAsText());
+
+ HttpRequest.Method('POST');
+ HttpRequest.SetRequestUri(ApiUrlMgt.GetAcceptCompanyLicenseUrl());
+ HttpContent.WriteFrom(GetAcceptCompanyLicenseBody(CompanyName));
+ HttpContent.GetHeaders(HttpHeaders);
+ if HttpHeaders.Contains('Content-Type') then
+ HttpHeaders.Remove('Content-Type');
+ HttpHeaders.Add('Content-Type', 'application/xml');
+
+ HttpRequest.Content := HttpContent;
+
+ HttpClient.Timeout := 6000;
+ HttpClient.Send(HttpRequest, HttpResponse);
+ if HttpResponse.IsSuccessStatusCode then begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody <> '' then
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ end;
+
+ exit(VerifyResponse(ResponseXmlDoc, true));
+ end;
+
+ [NonDebuggable]
+ local procedure GetAcceptCompanyLicenseBody(CompanyName: Text) RequestBody: Text
+ var
+ CredentialMgt: Codeunit "Continia Credential Management";
+ AcceptCompanyLicenseRequest: XmlElement;
+ begin
+ AcceptCompanyLicenseRequest := XmlElement.Create('AcceptCompanyLicenseRequest');
+ AcceptCompanyLicenseRequest.SetAttribute('CompanyName', CompanyName);
+ AcceptCompanyLicenseRequest.SetAttribute('AppCode', CredentialMgt.GetAppCode());
+ AcceptCompanyLicenseRequest.WriteTo(RequestBody);
+ end;
+
+ [NonDebuggable]
+ internal procedure UpdateClientInformation(var ClientInfo: Record "Continia Participation" temporary): Boolean
+ var
+ CredentialManagement: Codeunit "Continia Credential Management";
+ SessionManager: Codeunit "Continia Session Manager";
+ AzureADTenant: Codeunit "Azure AD Tenant";
+ EnvironmentInformation: Codeunit "Environment Information";
+ HttpClient: HttpClient;
+ HttpContent: HttpContent;
+ HttpHeaders: HttpHeaders;
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ begin
+ if not CredentialManagement.IsClientCredentialsValid() then
+ exit(false);
+
+ HttpRequest.GetHeaders(HttpHeaders);
+ HttpHeaders.Add('Accept', 'application/xml;charset=utf-8');
+ HttpHeaders.Add('Authorization', SecretStrSubstNo('Bearer %1', SessionManager.GetAccessToken()));
+ HttpHeaders.Add('x-continia-companyguid', CredentialManagement.GetCompanyGuidAsText());
+ HttpHeaders.Add('x-continia-version', '1500');
+ if EnvironmentInformation.IsSaaSInfrastructure() then
+ HttpHeaders.Add('x-AzureTenantId', AzureADTenant.GetAadTenantId());
+
+ HttpRequest.Method('POST');
+ HttpRequest.SetRequestUri(ApiUrlMgt.GetUpdateCompanyInfoUrl());
+ HttpContent.WriteFrom(GetClientInfoUpdateRequest(ClientInfo));
+ HttpContent.GetHeaders(HttpHeaders);
+ if HttpHeaders.Contains('Content-Type') then
+ HttpHeaders.Remove('Content-Type');
+ HttpHeaders.Add('Content-Type', 'application/xml');
+
+ HttpRequest.Content := HttpContent;
+
+ HttpClient.Timeout := 6000;
+ HttpClient.Send(HttpRequest, HttpResponse);
+ if HttpResponse.IsSuccessStatusCode then begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody <> '' then
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ end;
+
+ exit(VerifyResponse(ResponseXmlDoc, true));
+ end;
+
+ [NonDebuggable]
+ local procedure GetClientInfoUpdateRequest(var ClientInfo: Record "Continia Participation" temporary) RequestBody: Text
+ var
+ CompanyInfoRequest: XmlElement;
+ CompanyInfo: XmlElement;
+ ContactPerson: XmlElement;
+ begin
+ CompanyInfoRequest := XmlElement.Create('InvoicingInformationRequest');
+ CompanyInfo := XmlElement.Create('InvoicingDetails');
+ CompanyInfo.SetAttribute('CompanyName', ClientInfo."Company Name");
+ CompanyInfo.SetAttribute('CompanyAddress', ClientInfo.Address);
+ CompanyInfo.SetAttribute('PostalCode', ClientInfo."Post Code");
+ CompanyInfo.SetAttribute('Country', ClientInfo.County);
+ CompanyInfo.SetAttribute('CountryIsoCode', ClientInfo."Country/Region Code");
+ CompanyInfo.SetAttribute('VatRegNo', ClientInfo."VAT Registration No.");
+ CompanyInfo.SetAttribute('Email', ClientInfo."Contact Email");
+ CompanyInfo.SetAttribute('PhoneNo', ClientInfo."Contact Phone No.");
+ CompanyInfo.SetAttribute('UserId', UserId);
+ CompanyInfoRequest.Add(CompanyInfo);
+
+ ContactPerson := XmlElement.Create('ContactPerson');
+ ContactPerson.SetAttribute('Name', ClientInfo."Contact Name");
+ ContactPerson.SetAttribute('Email', ClientInfo."Contact Email");
+ CompanyInfoRequest.Add(ContactPerson);
+
+ CompanyInfoRequest.WriteTo(RequestBody);
+ end;
+
+ [NonDebuggable]
+ internal procedure GetUserNotificationEmail(): Text[250]
+ var
+ SalespersonPurchaser: Record "Salesperson/Purchaser";
+ User: Record User;
+ UserSetup: Record "User Setup";
+ MailManagement: Codeunit "Mail Management";
+ begin
+ User.SetCurrentKey("User Name");
+ User.SetRange("User Name", UserId);
+ if User.FindFirst() then begin
+ if MailManagement.CheckValidEmailAddress(User."Authentication Email") then
+ exit(User."Authentication Email");
+ if UserSetup.Get(User."User Name") then begin
+ if MailManagement.CheckValidEmailAddress(UserSetup."E-Mail") then
+ exit(UserSetup."E-Mail");
+ if SalespersonPurchaser.Get(UserSetup."Salespers./Purch. Code") then
+ if MailManagement.CheckValidEmailAddress(SalespersonPurchaser."E-Mail") then
+ exit(SalespersonPurchaser."E-Mail");
+ end;
+ end;
+ end;
+
+ [NonDebuggable]
+ local procedure GetTenantSubscriptionId(): Code[50]
+ var
+ AzureADTenant: Codeunit "Azure AD Tenant";
+ EnvironmentInformation: Codeunit "Environment Information";
+ AadTenantId: Text;
+ begin
+ if EnvironmentInformation.IsSaaSInfrastructure() then
+ if EnvironmentInformation.IsProduction() then begin
+ AadTenantId := AzureADTenant.GetAadTenantId();
+ if (AadTenantId <> '') and (AadTenantId.ToLower() = 'common') then
+ exit(CopyStr(AadTenantId, 1, 50));
+ end;
+ exit(CopyStr(LowerCase(CopyStr(Format(CreateGuid()), 2, 36)), 1, 50))
+ end;
+
+ [NonDebuggable]
+ local procedure HandleInitializeCredentialResponse(ResponseXmlDoc: XmlDocument; var ClientId: SecretText; var ClientSecret: SecretText)
+ var
+ CredentialsAreMissing: Boolean;
+ CreateCredentialErrorInfo: ErrorInfo;
+ ErrorMessage: Text;
+ TempXmlNode: XmlNode;
+ begin
+ CreateCredentialErrorInfo.Title := CreateClientErrTitleErr;
+ CreateCredentialErrorInfo.Verbosity := Verbosity::Error;
+ CreateCredentialErrorInfo.DataClassification := DataClassification::SystemMetadata;
+
+ if ResponseXmlDoc.SelectSingleNode('Error/@Message', TempXmlNode) then
+ ErrorMessage := TempXmlNode.AsXmlAttribute().Value;
+ if ErrorMessage <> '' then begin
+ CreateCredentialErrorInfo.Message := StrSubstNo(RequestFailedErr, ErrorMessage);
+ Error(CreateCredentialErrorInfo);
+ end;
+
+ if ResponseXmlDoc.SelectSingleNode('InitializeCredentialsResponse/@ClientId', TempXmlNode) then
+ ClientId := TempXmlNode.AsXmlAttribute().Value
+ else
+ CredentialsAreMissing := true;
+
+ if ResponseXmlDoc.SelectSingleNode('InitializeCredentialsResponse/@ClientPassword', TempXmlNode) then
+ ClientSecret := TempXmlNode.AsXmlAttribute().Value
+ else
+ CredentialsAreMissing := true;
+
+ if CredentialsAreMissing then begin
+ CreateCredentialErrorInfo.Message := ClientCredentialsMissingErr;
+ Error(CreateCredentialErrorInfo);
+ end;
+ end;
+
+ [TryFunction]
+ [NonDebuggable]
+ internal procedure TryAcquireClientToken(var AccessTokenValue: Text; var ExpiresInMs: Integer)
+ var
+ CredentialManagement: Codeunit "Continia Credential Management";
+ HttpClient: HttpClient;
+ HttpContent: HttpContent;
+ HttpHeaders: HttpHeaders;
+ HttpRequest: HttpRequestMessage;
+ HttpResponse: HttpResponseMessage;
+ ExpiresIn: Integer;
+ Credentials: Text;
+ ResponseBody: Text;
+ ResponseXmlDoc: XmlDocument;
+ begin
+ HttpRequest.GetHeaders(HttpHeaders);
+ HttpHeaders.Add('Accept', 'application/xml;charset=utf-8');
+ HttpHeaders.Add('x-continia-check', 'true');
+ Credentials := CredentialManagement.GetClientCredentialsApiBodyString();
+ HttpRequest.Method('POST');
+ HttpRequest.SetRequestUri(ApiUrlMgt.ClientAccessTokenUrl());
+ HttpContent.WriteFrom(Credentials);
+ HttpRequest.Content := HttpContent;
+ HttpClient.Send(HttpRequest, HttpResponse);
+ if HttpResponse.IsSuccessStatusCode then begin
+ HttpResponse.Content.ReadAs(ResponseBody);
+ if ResponseBody <> '' then
+ XmlDocument.ReadFrom(ResponseBody, ResponseXmlDoc);
+ end;
+ HandleClientAccessTokenResponse(ResponseXmlDoc, AccessTokenValue, ExpiresIn);
+ ExpiresInMs := ExpiresIn * 1000;
+ end;
+
+ [NonDebuggable]
+ local procedure HandleClientAccessTokenResponse(ResponseXmlDoc: XmlDocument; var AccessTokenValue: Text; var ExpiresIn: Integer): Text
+ var
+ CredentialsAreMissing: Boolean;
+ CreateCredentialErrorInfo: ErrorInfo;
+ ErrorMessage: Text;
+ TempXmlNode: XmlNode;
+ begin
+ if ResponseXmlDoc.SelectSingleNode('Error/@Message', TempXmlNode) then
+ ErrorMessage := TempXmlNode.AsXmlAttribute().Value;
+ if ErrorMessage <> '' then begin
+ CreateCredentialErrorInfo.Message := StrSubstNo(RequestFailedErr, ErrorMessage);
+ Error(CreateCredentialErrorInfo);
+ end;
+
+ if ResponseXmlDoc.SelectSingleNode('Token/@AccessToken', TempXmlNode) then
+ AccessTokenValue := TempXmlNode.AsXmlAttribute().Value
+ else
+ CredentialsAreMissing := true;
+
+ if ResponseXmlDoc.SelectSingleNode('Token/@ExpiresIn', TempXmlNode) then
+ Evaluate(ExpiresIn, TempXmlNode.AsXmlAttribute().Value);
+
+ if CredentialsAreMissing then begin
+ CreateCredentialErrorInfo.Message := InvalidClientCredErr;
+ Error(CreateCredentialErrorInfo);
+ end;
+ end;
+
+ [NonDebuggable]
+ local procedure MapOnlineSubscriptionState(SubscriptionStatus: Enum "Continia Subscription Status"): Integer
+ begin
+ case SubscriptionStatus of
+ SubscriptionStatus::Subscription:
+ exit(1);
+ SubscriptionStatus::Unsubscribed:
+ exit(2);
+ end;
+ end;
+
+ [NonDebuggable]
+ internal procedure GetTenantApplicationVersion(): Text
+ var
+ MajorMinorVersion: Code[100];
+ Version: Integer;
+ begin
+ MajorMinorVersion := GetTenantMajorApplicationVersion() + GetTenantMinorApplicationVersion();
+ Evaluate(Version, PadStr(MajorMinorVersion, 6, '0'));
+ exit(Format(Version));
+ end;
+
+ [NonDebuggable]
+ internal procedure GetTenantMajorApplicationVersion(): Code[50]
+ var
+ thisModule: ModuleInfo;
+ BaseAppId: Text;
+ completeVersion: Version;
+ begin
+ BaseAppId := '437dbf0e-84ff-417a-965d-ed2bb9650972';
+ // First try to get Microsoft Base App
+ if NavApp.GetModuleInfo(BaseAppId, thisModule) then begin
+ completeVersion := thisModule.AppVersion;
+ exit(Format(completeVersion.Major));
+ end;
+
+ // Second try to get Application App
+ if GetApplicationModuleInfo(thisModule) then begin
+ completeVersion := thisModule.AppVersion;
+ exit(Format(completeVersion.Major));
+ end;
+ end;
+
+ [NonDebuggable]
+ internal procedure GetTenantMinorApplicationVersion(): Code[50]
+ var
+ thisModule: ModuleInfo;
+ BaseAppId: Text;
+ completeVersion: Version;
+ begin
+ BaseAppId := '437dbf0e-84ff-417a-965d-ed2bb9650972';
+ // First try to get Microsoft Base App
+ if NavApp.GetModuleInfo(BaseAppId, thisModule) then begin
+ completeVersion := thisModule.AppVersion;
+ exit(Format(completeVersion.Minor));
+ end;
+
+ // Second try to get Application App
+ if GetApplicationModuleInfo(thisModule) then begin
+ completeVersion := thisModule.AppVersion;
+ exit(Format(completeVersion.Minor));
+ end;
+ end;
+
+ [NonDebuggable]
+ local procedure GetApplicationModuleInfo(var ApplicationModuleInfo: ModuleInfo): Boolean
+ var
+ AppDependencies: List of [ModuleDependencyInfo];
+ AppDependency: ModuleDependencyInfo;
+ CurrentModule: ModuleInfo;
+ begin
+ NavApp.GetCurrentModuleInfo(CurrentModule);
+ AppDependencies := CurrentModule.Dependencies;
+ foreach AppDependency in AppDependencies do
+ if (AppDependency.Name = 'Application') then
+ if NavApp.GetModuleInfo(AppDependency.Id, ApplicationModuleInfo) then
+ exit(true);
+ end;
+
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/app/src/Subscription and Access/ContiniaSubscriptionStatus.Enum.al b/Apps/W1/EDocumentConnectors/Continia/app/src/Subscription and Access/ContiniaSubscriptionStatus.Enum.al
new file mode 100644
index 0000000000..4868a5ff7d
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/app/src/Subscription and Access/ContiniaSubscriptionStatus.Enum.al
@@ -0,0 +1,24 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Continia;
+
+enum 6395 "Continia Subscription Status"
+{
+ Access = Internal;
+ Extensible = false;
+
+ value(0; NotSubscribed)
+ {
+ Caption = 'Not Subscribed';
+ }
+ value(1; Subscription)
+ {
+ Caption = 'Subscription';
+ }
+ value(2; Unsubscribed)
+ {
+ Caption = 'Unsubscribed';
+ }
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/AcceptCompanyLicense200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/AcceptCompanyLicense200.txt
new file mode 100644
index 0000000000..c21aa73e8f
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/AcceptCompanyLicense200.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/AcceptCompanyLicenseError200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/AcceptCompanyLicenseError200.txt
new file mode 100644
index 0000000000..7c8d89d87b
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/AcceptCompanyLicenseError200.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/BusinessResponse200-multiple-accepted.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/BusinessResponse200-multiple-accepted.txt
new file mode 100644
index 0000000000..87c410411a
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/BusinessResponse200-multiple-accepted.txt
@@ -0,0 +1,22 @@
+
+
+ 53395377-9da3-444d-8ca6-c3fa4a7fd232
+ 2024-10-03T15:26:04.577
+
+ IP
+
+ http://testcompany.com/application-response-IP.xml
+
+
+
+
+ b4c00a73-ec0c-456e-9a4f-f26671dfcf69
+ 2024-10-04T15:30:04.597
+
+ AP
+
+ http://testcompany.com/application-response-AP.xml
+
+
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/BusinessResponse200-multiple-rejected.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/BusinessResponse200-multiple-rejected.txt
new file mode 100644
index 0000000000..d52e26d378
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/BusinessResponse200-multiple-rejected.txt
@@ -0,0 +1,23 @@
+
+
+ 53395377-9da3-444d-8ca6-c3fa4a7fd232
+ 2024-10-03T15:26:04.577
+ PRI
+ Prices incorrect
+ RE
+
+ http://testcompany.com/application-response-RE.xml
+
+
+
+
+ b4c00a73-ec0c-456e-9a4f-f26671dfcf69
+ 2024-10-04T15:30:04.597
+
+ AP
+
+ http://testcompany.com/application-response-AP.xml
+
+
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/BusinessResponse200-multiple-statusinfo.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/BusinessResponse200-multiple-statusinfo.txt
new file mode 100644
index 0000000000..58ea246df2
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/BusinessResponse200-multiple-statusinfo.txt
@@ -0,0 +1,22 @@
+
+
+ 53395377-9da3-444d-8ca6-c3fa4a7fd232
+ 2024-10-03T15:26:04.577
+
+ IP
+
+ http://testcompany.com/application-response-IP.xml
+
+
+
+
+ b4c00a73-ec0c-456e-9a4f-f26671dfcf69
+ 2024-10-04T15:30:04.597
+
+ UQ
+
+ http://testcompany.com/application-response-UQ.xml
+
+
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/BusinessResponse200-noresponse.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/BusinessResponse200-noresponse.txt
new file mode 100644
index 0000000000..195080b43a
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/BusinessResponse200-noresponse.txt
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common400.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common400.txt
new file mode 100644
index 0000000000..90c0bfc1cb
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common400.txt
@@ -0,0 +1,4 @@
+
+ Bad Request
+ Missing parameter
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common401.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common401.txt
new file mode 100644
index 0000000000..3af75f78d4
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common401.txt
@@ -0,0 +1,4 @@
+
+ Not Authenticated
+ Login failed
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common404.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common404.txt
new file mode 100644
index 0000000000..3eb77a1b1a
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common404.txt
@@ -0,0 +1,4 @@
+
+ Not Found
+ Not Found
+
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common409.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common409.txt
new file mode 100644
index 0000000000..0765d99bd4
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common409.txt
@@ -0,0 +1,4 @@
+
+ Conflict
+ Conflict
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common422.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common422.txt
new file mode 100644
index 0000000000..c4d278fa24
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common422.txt
@@ -0,0 +1,5 @@
+
+
+ string
+ string
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common500.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common500.txt
new file mode 100644
index 0000000000..847ec96392
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Common500.txt
@@ -0,0 +1,4 @@
+
+ Internal Server
+ Unhandled system error
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/InitializeClient200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/InitializeClient200.txt
new file mode 100644
index 0000000000..051e87cd93
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/InitializeClient200.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/InitializeClient200Incorrect.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/InitializeClient200Incorrect.txt
new file mode 100644
index 0000000000..9781d1ac6a
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/InitializeClient200Incorrect.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/NemhandelNetworkIdTypes200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/NemhandelNetworkIdTypes200.txt
new file mode 100644
index 0000000000..b24f96b70b
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/NemhandelNetworkIdTypes200.txt
@@ -0,0 +1,53 @@
+
+
+ 0002
+ DK
+ CVR
+ false
+ 01babc72-e56c-4b46-ad7b-cdc020a65951
+ DK:CVR
+ DK
+
+
+ 0003
+ SE
+ false
+ 74d3483a-5781-4a2a-a01e-ec7c85aae8a4
+ DK:SE
+
+
+ 0004
+ VANS
+ false
+ cc377c50-b890-47f5-b365-df6fff8f7b9f
+ DK:VANS
+
+
+ 0005
+ P-nummer
+ false
+ 71a6b9e2-6c16-47d1-a974-5fb4f26e75cc
+ DK:P
+
+
+ 0006
+ IBAN
+ false
+ df7a57ac-c5af-4392-93cf-0b6ae0094fd3
+ IBAN
+
+
+ 0007
+ DUNS
+ false
+ 1918a26f-01ea-4ae8-b57f-bd6a1f709d9f
+ DUNS
+
+
+ 0088
+ EAN/GLN
+ false
+ 727080e3-2c45-4b27-a4ee-df6a70e66912
+ GLN
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/NemhandelNetworkProfiles200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/NemhandelNetworkProfiles200.txt
new file mode 100644
index 0000000000..1392a7c0bd
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/NemhandelNetworkProfiles200.txt
@@ -0,0 +1,180 @@
+
+
+ Simpel Fakturaproces - Procurement-BilSim-1.0
+
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##OIOUBL-2.02::2.0
+ Simpel Fakturaproces
+
+ BILSIM
+ true
+ DK
+ 48c21be4-5e96-4541-a60e-3491c6a06346
+ Procurement-BilSim-1.0
+
+
+ Fakturabekræftelse - Procurement-BilSimR-1.0
+ urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2::ApplicationResponse##OIOUBL-2.02::2.0
+ 3680b59b-3713-4d23-b20d-8512ecde8b88
+ Procurement-BilSimR-1.0
+
+
+ Procurement-BilSimReminderOnly
+
+ a5f1de22-c0f3-4b26-99a5-f46ca57401cb
+ Procurement-BilSimReminderOnly
+
+
+ Procurement-OrdAdv-BilSim-1.0
+
+ 8754c52d-b3d6-47a1-bead-00558935f5af
+ Procurement-OrdAdv-BilSim-1.0
+
+
+ Procurement-OrdAdv-BilSim-1.0
+
+ 020395e4-946e-404e-bfe8-3c0135b71799
+ Procurement-OrdAdv-BilSimR-1.0
+
+
+ Procurement-OrdAdv-BilSim-1.0
+
+ cf1de5f3-b4a8-4b4c-beb4-1523f7f4f0ba
+ Procurement-OrdAdvR-BilSim-1.0
+
+
+ Procurement-OrdAdv-BilSim-1.0
+
+ edd27514-5313-42d8-a9cb-2cc3d40c7d12
+ Procurement-OrdAdvR-BilSimR-1.0
+
+
+ Procurement-OrdRes-1.0
+
+ d7527254-541e-4c50-9525-ee50d5373171
+ Procurement-OrdRes-1.0
+
+
+ Procurement-OrdSel-BilSim-1.0
+
+ 66ccd864-ccc7-4dde-8765-ae0f0aa44596
+ Procurement-OrdSel-BilSim-1.0
+
+
+ Procurement-OrdSel-BilSim-1.0
+
+ 7b45a341-7119-491a-be95-1bc207e88c3b
+ Procurement-OrdSel-BilSimR-1.0
+
+
+ Simpel Ordreproces - Procurement-OrdSim-1.0
+ urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##OIOUBL-2.02::2.0
+ 09436b54-c4fc-4227-bc55-7a359d804d1f
+ Procurement-OrdSim-1.0
+
+
+ Simpel Ordre til Simpel Fakturasproces
+
+ 93267abe-72ef-4cf3-b911-8d2398c2f32d
+ Procurement-OrdSim-BilSim-1.0
+
+
+ Procurement-OrdSim-BilSimR-1.0
+
+ adccf54b-939a-4abb-aea4-2bd6d66b8c41
+ Procurement-OrdSim-BilSimR-1.0
+
+
+ Simpel Ordrebekræftelse - Procurement-OrdSimR-1.0
+ urn:oasis:names:specification:ubl:schema:xsd:OrderResponseSimple-2::OrderResponseSimple##OIOUBL-2.02::2.0
+ 6a7d52f4-1cb8-4817-9ff8-f5dab2ee0deb
+ Procurement-OrdSimR-1.0
+
+
+ Procurement-OrdSimR-BilSim-1.0
+
+ 0ff94e31-7383-41c1-abba-92d11aa2e0d6
+ Procurement-OrdSimR-BilSim-1.0
+
+
+ Procurement-OrdSimR-BilSimR-1.0
+
+ 710a60cf-3081-48b6-8e0e-edd37252aaec
+ Procurement-OrdSimR-BilSimR-1.0
+
+
+ Procurement-PayBas-1.0
+
+ 838ad4c4-1fd0-44bf-b219-ee1ed1646e93
+ Procurement-PayBas-1.0
+
+
+ Procurement-PayBas-1.0
+
+ 00470c20-06f0-4f3f-a888-90d41fa0d7cf
+ Procurement-PayBasR-1.0
+
+
+ Procurement-TecRes-1.0
+
+ 822b5f8a-caf2-4377-aaca-6f6802d144c4
+ Procurement-TecRes-1.0
+
+
+ Reference Utility - OIOUTS
+ urn:oasis:names:specification:ubl:schema:xsd:UtilityStatement-2::UtilityStatement##OIOUBL-2.1::2.1
+ Simpel Fakturaproces
+
+ BILSIM
+ true
+ DK
+ 8cd2c16a-80c0-4ddb-9bfd-86718093cbe0
+ Reference-Utility-1.0
+
+
+ Reference-UtilityR-1.0
+
+ d5240ea0-e195-4dea-8d4c-ea18c2fec974
+ Reference-UtilityR-1.0
+
+
+ urn:www.nesubl.eu:profiles:profile1:ver2.0
+
+ 8d0e8868-499d-4a66-a6ac-87a8225e653b
+ urn:www.nesubl.eu:profiles:profile1:ver2.0
+
+
+ urn:www.nesubl.eu:profiles:profile2:ver2.0
+
+ 6fb3889c-5b4a-45e6-9cc2-a355252709b4
+ urn:www.nesubl.eu:profiles:profile2:ver2.0
+
+
+ urn:www.nesubl.eu:profiles:profile3:ver2.0
+
+ 0013e8f5-ebe6-4103-b6c6-e418209fd1fe
+ urn:www.nesubl.eu:profiles:profile3:ver2.0
+
+
+ NES5
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##OIOUBL-2.02::2.0
+ Simpel Fakturaproces
+
+ BILSIM
+ true
+ DK
+ 9dea826b-8857-4b48-8cc7-e151e10cd427
+ urn:www.nesubl.eu:profiles:profile5:ver2.0
+
+
+ urn:www.nesubl.eu:profiles:profile7:ver2.0
+
+ 5665b6e9-27e3-4525-a3c8-3ecee87667a1
+ urn:www.nesubl.eu:profiles:profile7:ver2.0
+
+
+ urn:www.nesubl.eu:profiles:profile8:ver2.0
+
+ 23233193-06e7-47d3-ae43-5f75edcdecbd
+ urn:www.nesubl.eu:profiles:profile8:ver2.0
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/NotFound.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/NotFound.txt
new file mode 100644
index 0000000000..19ad4031c7
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/NotFound.txt
@@ -0,0 +1,3 @@
+
+ Not Found
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/OauthToken200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/OauthToken200.txt
new file mode 100644
index 0000000000..97d13c60e4
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/OauthToken200.txt
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-Connected.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-Connected.txt
new file mode 100644
index 0000000000..9474b01707
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-Connected.txt
@@ -0,0 +1,23 @@
+
+
+ 568c29e7-c2c8-49bb-b135-9199d5b791d1
+ 111222333
+ London Postmaster
+ 111222333
+ 10 North Lake Avenue
+ N12 5XY
+ string
+ string
+ Carol Philips
+ 004412345678
+ cp@londonpostmaster.com
+ true
+ ConnectedEnum
+ 0de4aedc-f84a-41bc-b511-387aaf96263e
+ 2024-10-23T15:12:21.355Z
+ 2024-10-23T15:12:21.355Z
+ 0
+ true
+ Continia
+ 28266ea9-84eb-49a4-948b-6c8b7790605a
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-Disabled.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-Disabled.txt
new file mode 100644
index 0000000000..c041ee4ad9
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-Disabled.txt
@@ -0,0 +1,23 @@
+
+
+ 568c29e7-c2c8-49bb-b135-9199d5b791d1
+ 111222333
+ London Postmaster
+ 111222333
+ 10 North Lake Avenue
+ N12 5XY
+ string
+ string
+ Carol Philips
+ 004412345678
+ cp@londonpostmaster.com
+ true
+ DisabledEnum
+ 0de4aedc-f84a-41bc-b511-387aaf96263e
+ 2024-10-23T15:12:21.355Z
+ 2024-10-23T15:12:21.355Z
+ 0
+ true
+ Continia
+ 28266ea9-84eb-49a4-948b-6c8b7790605a
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-Draft.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-Draft.txt
new file mode 100644
index 0000000000..3c294de16f
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-Draft.txt
@@ -0,0 +1,23 @@
+
+
+ 568c29e7-c2c8-49bb-b135-9199d5b791d1
+ 111222333
+ London Postmaster
+ 111222333
+ 10 North Lake Avenue
+ N12 5XY
+ string
+ string
+ Carol Philips
+ 004412345678
+ cp@londonpostmaster.com
+ true
+ DraftEnum
+ 0de4aedc-f84a-41bc-b511-387aaf96263e
+ 2024-10-23T15:12:21.355Z
+ 2024-10-23T15:12:21.355Z
+ 0
+ true
+ Continia
+ 28266ea9-84eb-49a4-948b-6c8b7790605a
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-InProcess.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-InProcess.txt
new file mode 100644
index 0000000000..fe93eda759
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-InProcess.txt
@@ -0,0 +1,23 @@
+
+
+ 568c29e7-c2c8-49bb-b135-9199d5b791d1
+ 111222333
+ London Postmaster
+ 111222333
+ 10 North Lake Avenue
+ N12 5XY
+ string
+ string
+ Carol Philips
+ 004412345678
+ cp@londonpostmaster.com
+ true
+ InProcessEnum
+ 0de4aedc-f84a-41bc-b511-387aaf96263e
+ 2024-10-23T15:12:21.355Z
+ 2024-10-23T15:12:21.355Z
+ 0
+ true
+ Continia
+ 28266ea9-84eb-49a4-948b-6c8b7790605a
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-Suspended.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-Suspended.txt
new file mode 100644
index 0000000000..269a220a36
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation200-Suspended.txt
@@ -0,0 +1,23 @@
+
+
+ 568c29e7-c2c8-49bb-b135-9199d5b791d1
+ 111222333
+ London Postmaster
+ 111222333
+ 10 North Lake Avenue
+ N12 5XY
+ string
+ string
+ Carol Philips
+ 004412345678
+ cp@londonpostmaster.com
+ true
+ SuspendedEnum
+ 0de4aedc-f84a-41bc-b511-387aaf96263e
+ 2024-10-23T15:12:21.355Z
+ 2024-10-23T15:12:21.355Z
+ 0
+ true
+ Continia
+ 28266ea9-84eb-49a4-948b-6c8b7790605a
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation201-Draft.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation201-Draft.txt
new file mode 100644
index 0000000000..3c294de16f
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/Participation201-Draft.txt
@@ -0,0 +1,23 @@
+
+
+ 568c29e7-c2c8-49bb-b135-9199d5b791d1
+ 111222333
+ London Postmaster
+ 111222333
+ 10 North Lake Avenue
+ N12 5XY
+ string
+ string
+ Carol Philips
+ 004412345678
+ cp@londonpostmaster.com
+ true
+ DraftEnum
+ 0de4aedc-f84a-41bc-b511-387aaf96263e
+ 2024-10-23T15:12:21.355Z
+ 2024-10-23T15:12:21.355Z
+ 0
+ true
+ Continia
+ 28266ea9-84eb-49a4-948b-6c8b7790605a
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationLookup200-external.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationLookup200-external.txt
new file mode 100644
index 0000000000..131a1db234
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationLookup200-external.txt
@@ -0,0 +1,101 @@
+
+
+ 9930
+
+
+
+ peppol@storecove.com
+ Storecove Document Service TEST
+
+
+ PEPPOL Invoice Response (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2::ApplicationResponse##urn:fdc:peppol.eu:poacc:trns:invoice_response:3::2.1
+ 4f333069-936c-4f2d-af71-0f4d261ad4a4
+ urn:fdc:peppol.eu:poacc:bis:invoice_response:3
+
+
+ PEPPOL Message Level Response (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2::ApplicationResponse##urn:fdc:peppol.eu:poacc:trns:mlr:3::2.1
+ 64bb189a-3f65-4c28-a2e2-a257dba5c04b
+ urn:fdc:peppol.eu:poacc:bis:mlr:3
+
+
+ PEPPOL Credit Note (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1
+ PEPPOL BIS3 (Invoice, Credit Note, CII)
+ PEPPOL BIS3.0
+ dd2af6bc-a05a-4fd4-a577-0216a56bea84
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung UBL CreditNote V3.0
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0::2.1
+ XRechnung v3.0 (Invoice, Credit Note, CII)
+ XRECHNUNG V3.0
+ d5e10b17-3070-437e-9277-c2144d160b1b
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung UBL CreditNote V2.3
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.3::2.1
+ XRechnung v2.3 (Invoice, Credit Note, CII)
+ XRECHNUNG V2.3
+ ee8cd57b-6817-4e6f-8c33-6c83e078b43a
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ PEPPOL Invoice (BIS 3.0)
+ 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
+ PEPPOL BIS3 (Invoice, Credit Note, CII)
+ PEPPOL BIS3.0
+ 8f9ab973-c6f0-4dfb-9936-19b56c5a588b
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung UBL Invoice V3.0
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0::2.1
+ XRechnung v3.0 (Invoice, Credit Note, CII)
+ XRECHNUNG V3.0
+ 09f2bd71-d019-439f-8fff-e68ce01fe105
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung UBL Invoice V2.3
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.3::2.1
+ XRechnung v2.3 (Invoice, Credit Note, CII)
+ XRECHNUNG V2.3
+ 86427376-2b53-4e60-a34c-23fb1c78808e
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ PEPPOL Cross Industry Invoice (BIS 3.0)
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::D16B
+ PEPPOL BIS3 (Invoice, Credit Note, CII)
+ PEPPOL BIS3.0
+ 24498487-81a8-4f46-9104-bb3915a6eee0
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung CII Invoice V3.0
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0::D16B
+ XRechnung v3.0 (Invoice, Credit Note, CII)
+ XRECHNUNG V3.0
+ d80fc971-7a72-48d7-8617-69132f97781f
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung CII Invoice V2.3
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.3::D16B
+ XRechnung v2.3 (Invoice, Credit Note, CII)
+ XRECHNUNG V2.3
+ 410ef408-c418-4e23-9952-b86e32b86d63
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ peppol-transport-as4-v2_0
+ https://www.storecove.com/docs
+
+
+ DE111111111
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationLookup200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationLookup200.txt
new file mode 100644
index 0000000000..21f1306c76
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationLookup200.txt
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationProfile-outgoing.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationProfile-outgoing.txt
new file mode 100644
index 0000000000..18ce6cd47b
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationProfile-outgoing.txt
@@ -0,0 +1,7 @@
+
+ 2024-10-23T12:00:00
+ OutboundEnum
+ dd2af6bc-a05a-4fd4-a577-0216a56bea84
+ {participationProfileId.ToLower}
+ 2024-10-23T13:00:00
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationProfile200-peppolInvoice.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationProfile200-peppolInvoice.txt
new file mode 100644
index 0000000000..01484d7640
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationProfile200-peppolInvoice.txt
@@ -0,0 +1,7 @@
+
+ 2024-10-23T12:00:00
+ BothEnum
+ 8f9ab973-c6f0-4dfb-9936-19b56c5a588b
+ {participationProfileId.ToLower}
+ 2024-10-23T13:00:00
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationProfile200-randomId.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationProfile200-randomId.txt
new file mode 100644
index 0000000000..e51b6c5fa6
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationProfile200-randomId.txt
@@ -0,0 +1,7 @@
+
+ 2024-10-23T12:00:00
+ BothEnum
+ dd2af6bc-a05a-4fd4-a577-0216a56bea84
+ {random.guid}
+ 2024-10-23T13:00:00
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationProfile200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationProfile200.txt
new file mode 100644
index 0000000000..15875ceb5f
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ParticipationProfile200.txt
@@ -0,0 +1,7 @@
+
+ 2024-10-23T12:00:00
+ BothEnum
+ dd2af6bc-a05a-4fd4-a577-0216a56bea84
+ {participationProfileId.ToLower}
+ 2024-10-23T13:00:00
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/PartnerZoneConnect200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/PartnerZoneConnect200.txt
new file mode 100644
index 0000000000..65bb7d826f
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/PartnerZoneConnect200.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/PartnerZoneLogin200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/PartnerZoneLogin200.txt
new file mode 100644
index 0000000000..9e1fafed7d
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/PartnerZoneLogin200.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/PartnerZoneLogin200Incorrect.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/PartnerZoneLogin200Incorrect.txt
new file mode 100644
index 0000000000..be1a4aefcf
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/PartnerZoneLogin200Incorrect.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/PeppolNetworkIdTypes200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/PeppolNetworkIdTypes200.txt
new file mode 100644
index 0000000000..4ec7ead9d1
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/PeppolNetworkIdTypes200.txt
@@ -0,0 +1,756 @@
+
+
+ 0002
+
+ INSEE: National Institute for statistics and Economic studies
+ true
+ b79093d7-cada-415f-a6cd-b3b46b83528a
+ FR:SIRENE
+
+
+
+ 0007
+ SE
+ The Swedish National Tax Board
+ true
+ 780ec397-daaa-4ee8-bfcc-e4711b245b5e
+ SE:ORGNR
+ SE
+
+
+ 0009
+ FR
+ DU PONT DE NEMOURS
+ true
+ d361dfeb-18a8-4c25-a627-f1a06be9cc83
+ FR:SIRET
+
+
+
+ 0037
+ FI
+ Finnish tax board
+ true
+ bf97384d-456c-437c-8d1e-7662c0520fe8
+ FI:OVT
+ FI
+
+
+ 0060
+
+ Dun and Bradstreet Ltd
+ true
+ d868eac3-8622-4c71-827e-9cc614a796fb
+ DUNS
+
+
+
+ 0088
+ NZ
+ GS1
+ true
+ 8419e851-11be-4f85-967d-9aa717856b49
+ GLN
+ NZ
+
+
+ 0096
+
+ The Danish Commerce and Companies Agency
+ true
+ a4afdd8e-b55a-4ace-9d32-1d59c5af9c90
+ DK:P
+
+
+
+ 0097
+
+ Ediforum Italia
+ true
+ 052693c4-089a-4604-89ef-ca4a3597c1a0
+ IT:FTI
+
+
+
+ 0106
+
+ Vereniging van Kamers van Koophandel en Fabrieken in Nederland
+ true
+ b9915287-5a79-4fc9-b909-72d65aa3de84
+ NL:KVK
+
+
+
+ 0130
+
+ Directorates of the European Commission
+ true
+ 46ed3758-4660-4b1d-bd5c-160843b84616
+ EU:NAL
+
+
+
+ 0135
+
+ Società Interbancaria per l Automazione
+ true
+ 37d8adca-4ffb-4f7b-a6f7-e55caeb6060e
+ IT:SIA
+
+
+
+ 0142
+
+ Servizi Centralizzati SECETI
+ true
+ b5430f75-2bd4-4f1b-897a-79f486e187d2
+ IT:SECETI
+
+
+
+ 0151
+ AU
+ Australian Business Number (ABN) Scheme
+ true
+ c31c91fd-d8c4-4333-b207-de91bedbcac8
+ AU:ABN
+ AU
+
+
+ 0183
+ CH
+ Swiss Unique Business Identification Number
+ true
+ 2a385d10-9cd9-4eb3-bc4f-39f033c8e57a
+ CH:UIDB
+ CH
+
+
+ 0184
+ DK
+ DIGSTORG
+ true
+ 71e79c72-e470-4f32-90c2-dff4095b8632
+ DK:DIGST
+ DK
+
+
+ 0190
+
+ Organisatie Indentificatie Nummer
+ true
+ de8b2bc7-2e35-48ee-bfff-1535f18546e5
+ NL:OINO
+
+
+
+ 0191
+
+ Estonia company code
+ true
+ 9229c644-b25f-4ac5-ad1a-36e086b93e00
+ EE:CC
+
+
+
+ 0192
+ NO
+ The Brønnøysund Register Centre
+ true
+ eafbc3d8-0e6c-46d9-9398-06728a6e045a
+ NO:ORG
+ NO
+
+
+ 0193
+
+ UBL.BE
+ true
+ 5559bc3d-fc35-4d26-8225-b68d979c6e5a
+ UBLBE
+
+
+
+ 0195
+ SG
+ Singapore Nationwide elnvoice Framework
+ true
+ de823404-5df4-48a9-a7fb-91d47daf5a91
+ SG:UEN
+
+
+
+ 0196
+ IS
+ Icelandic National Registry
+ true
+ 43377426-aa8e-41a2-867f-4fdbddc3b60f
+ IS:KTNR
+ IS
+
+
+ 0198
+
+ The Danish Business Authority
+ true
+ 423efc62-b6f6-43c7-abf0-4f109f7397e5
+ DK:ERST
+
+
+
+ 0199
+
+ Legal Entity Identifier
+ true
+ 35cc83fa-ba61-4400-93f9-affdda6f0c3e
+ LEI
+
+
+
+ 0200
+
+ State Enterprise Centre of Registers
+ true
+ 619523ad-544e-4257-a1b8-4e74049e4667
+ LT:LEC
+
+
+
+ 0201
+
+ Codice Univoco Unità Organizzativa iPA
+ true
+ 42f4a083-59a3-4127-a7f2-9bf33af53cd3
+ IT:CUUO
+
+
+
+ 0204
+
+ Koordinierungsstelle für IT-Standards (KoSIT)
+ true
+ 172d13f3-8b2c-4428-b149-b9dd182c3773
+ DE:LWID
+
+
+
+ 0208
+ BE
+ Numero entreprise / ondernemingsnummer / Unternehmensnummer
+ true
+ c7cd4c68-2cc7-488f-b718-368f9e517a68
+ BE:EN
+ BE
+
+
+ 0216
+ Finnish OVT code
+ true
+ 88701712-0852-4538-9347-57f1f1a34245
+ FI:OVT2
+
+
+ 9901
+
+ Danish Ministry of the Interior and Health
+ false
+ 3f51d306-65de-4596-89cc-933543b0cb43
+ DK:CPR
+
+
+
+ 9902
+
+ The Danish Commerce and Companies Agency
+ false
+ 43057922-16b4-4c11-b865-192717504d53
+ DK:CVR
+
+
+
+ 9904
+
+ Danish Ministry of Taxation, Central Customs and Tax Administration
+ false
+ a2a3fc90-6aa2-4154-91dc-5ae96a0d40a4
+ DK:SE
+
+
+
+ 9905
+
+ Danish VANS providers
+ false
+ 226fb9db-4304-4b1d-8cbc-dac765d0f5ae
+ DK:VANS
+
+
+
+ 9906
+ IT
+ Ufficio responsabile gestione partite IVA
+ false
+ c50e16a8-f170-4c4d-85eb-a4c3c4b4df6f
+ IT:VAT
+ IT
+
+
+ 9907
+
+ TAX Authority
+ false
+ 85a0ab8e-538f-4b63-aef4-80e7530fd6b3
+ IT:CF
+
+
+
+ 9908
+
+ Enhetsregisteret ved Brønnøysundregistrene
+ false
+ bdda76fd-0d59-488f-a953-a651f4560005
+ NO:ORGNR
+
+
+
+ 9909
+
+ Enhetsregisteret ved Brønnøysundregistrene
+ false
+ 82bfd4dc-3964-4bcc-8f2f-d734bb461f5d
+ NO:VAT
+
+
+
+ 9910
+ HU
+ Hungarian Tax Board
+ false
+ 14529f9c-fed4-4207-acdd-259394545eb6
+ HU:VAT
+ HU
+
+
+ 9912
+
+ National ministries of Economy
+ false
+ 215639e8-5f88-49fc-bd1e-05e0b6ab91be
+ EU:VAT
+
+
+
+ 9913
+
+ Business Registers Network
+ false
+ ef0febfa-154d-49ae-9b65-7c259ad831d8
+ EU:REID
+
+
+
+ 9914
+ AT
+ Österreichische Umsatzsteuer-Identifikationsnummer
+ false
+ 6aff0db7-4bda-4758-8457-f2f577de97d7
+ AT:VAT
+ AT
+
+
+ 9915
+
+ Österreichisches Verwaltungs bzw. Organisationskennzeichen
+ false
+ fd2bb7cf-bd41-45ed-8f43-e80343d0a32a
+ AT:GOV
+
+
+
+ 9917
+
+ Icelandic National Registry
+ false
+ 796b2288-b9cf-4fc9-a269-1e7efb8b744e
+ IS:KT
+
+
+
+ 9918
+
+ S.W.I.F.T. Society for Worldwide Interbank Financial Telecommunications s.c.
+ false
+ 9fd493dc-2dd0-414f-a2e4-c8211d37971c
+ IBAN
+
+
+
+ 9919
+
+ Kennziffer des Unternehmensregisters
+ false
+ bb0b52f3-d73b-40d4-84c8-4522d745bbb7
+ AT:KUR
+
+
+
+ 9920
+ ES
+ Agencia Española de Administración Tributaria
+ false
+ cb9ace3a-f4ad-4a4a-bb0e-c4ee0dd9f28e
+ ES:VAT
+ ES
+
+
+ 9921
+
+ Indice delle Pubbliche Amministrazioni
+ false
+ 1d3025ef-0dd1-4646-b57e-ac5c33b12b7e
+ IT:IPA
+
+
+
+ 9922
+ AD
+ Andorra VAT number
+ false
+ d3741495-000e-4ca8-8c8f-2a430855942a
+ AD:VAT
+ AD
+
+
+ 9923
+ AL
+ Albania VAT number
+ false
+ 39d021bb-2de2-4b5e-b089-6a8a58410e4d
+ AL:VAT
+ AL
+
+
+ 9924
+ BA
+ Bosnia and Herzegovina VAT number
+ false
+ 65c36225-c262-46a8-991d-56c295391fa2
+ BA:VAT
+ BA
+
+
+ 9925
+
+ Belgium VAT number
+ false
+ e4698d5e-d383-4355-8d9f-c068af7382f7
+ BE:VAT
+
+
+
+ 9926
+ BG
+ Bulgaria VAT number
+ false
+ 55c6f86c-a66b-4183-bac0-9560ffaf96f4
+ BG:VAT
+ BG
+
+
+ 9927
+
+ Switzerland VAT number
+ false
+ 4a75bbc5-b04d-4caa-9a65-6a25ef2e59d6
+ CH:VAT
+
+
+
+ 9928
+ CY
+ Cyprus VAT number
+ false
+ 6320f37d-90f9-446c-bbb7-e6a94b16ec83
+ CY:VAT
+ CY
+
+
+ 9929
+ CZ
+ Czech Republic VAT number
+ false
+ 89c378a7-5a70-44b8-8ff0-3894180adc4b
+ CZ:VAT
+ CZ
+
+
+ 9930
+ DE
+ Germany VAT number
+ false
+ 5649fa22-eec2-46aa-bc5a-c1cdaa545ce8
+ DE:VAT
+ DE
+
+
+ 9931
+ EE
+ Estonia VAT number
+ false
+ 6f456455-868a-424c-98df-27a4d19f11ed
+ EE:VAT
+ EE
+
+
+ 9932
+ GB
+ United Kingdom VAT number
+ false
+ 568c29e7-c2c8-49bb-b135-9199d5b791d1
+ GB:VAT
+ GB
+
+
+ 9933
+ EL
+ Greece VAT number
+ false
+ 8b1a902f-fae9-493b-b819-e4cb76090e08
+ GR:VAT
+ EL
+
+
+ 9934
+ HR
+ Croatia VAT number
+ false
+ d6c04f97-5c99-4df3-b13f-93fe648c21d9
+ HR:VAT
+ HR
+
+
+ 9935
+ IE
+ Ireland VAT number
+ false
+ 28af06c1-1d77-4e37-a6d7-69bade0f9538
+ IE:VAT
+ IE
+
+
+ 9936
+ LI
+ Liechtenstein VAT number
+ false
+ 0f352343-81d1-4cf2-8790-6e840c99ce90
+ LI:VAT
+ LI
+
+
+ 9937
+ LT
+ Lithuania VAT number
+ false
+ 78423983-2d2d-47df-806d-f791e023eac6
+ LT:VAT
+ LT
+
+
+ 9938
+ LU
+ Luxemburg VAT number
+ false
+ f115e641-e450-470c-a297-c6b0fc697578
+ LU:VAT
+ LU
+
+
+ 9939
+ LV
+ Latvia VAT number
+ false
+ 6ca660b7-dd32-4c22-80e0-631645589d2c
+ LV:VAT
+ LV
+
+
+ 9940
+ MC
+ Monaco VAT number
+ false
+ afcb2d07-21f9-4fac-9bce-be0be031e8e0
+ MC:VAT
+ MC
+
+
+ 9941
+ ME
+ Montenegro VAT number
+ false
+ 1a0d34ca-ed0d-4281-b0a0-2596c1223275
+ ME:VAT
+ ME
+
+
+ 9942
+ MK
+ Macedonia, the former Yugoslav Republic of VAT number
+ false
+ 5057f795-caa9-46ad-bc29-819b634ddc79
+ MK:VAT
+ MK
+
+
+ 9943
+ MT
+ Malta VAT number
+ false
+ eb80d76f-9dbb-4968-becd-ae8f0c39a6fe
+ MT:VAT
+ MT
+
+
+ 9944
+ NL
+ Netherlands VAT number
+ false
+ ab776d27-39c5-4862-abc2-72f2207539ba
+ NL:VAT
+ NL
+
+
+ 9945
+ PL
+ Poland VAT number
+ false
+ db6b318d-5ef5-4adb-9db5-35047bb70259
+ PL:VAT
+ PL
+
+
+ 9946
+ PT
+ Portugal VAT number
+ false
+ 325537ca-138f-4f39-8fd3-94248ee907eb
+ PT:VAT
+ PT
+
+
+ 9947
+ RO
+ Romania VAT number
+ false
+ ed5e9ba9-f43b-4a47-8f14-e58b612a80fd
+ RO:VAT
+ RO
+
+
+ 9948
+ RS
+ Serbia VAT number
+ false
+ 01f159b0-af5c-4c9c-88c7-a3862f7e2f7d
+ RS:VAT
+ RS
+
+
+ 9949
+ SI
+ Slovenia VAT number
+ false
+ 3f51c8a4-a751-4a33-b14d-207e29400288
+ SI:VAT
+ SI
+
+
+ 9950
+ SK
+ Slovakia VAT number
+ false
+ f71c7539-c5d8-4cb7-90a5-752820242d25
+ SK:VAT
+ SK
+
+
+ 9951
+ SM
+ San Marino VAT number
+ false
+ e8be5fa5-8660-4b9d-a05b-c3b8ec4db342
+ SM:VAT
+ SM
+
+
+ 9952
+ TR
+ Turkey VAT number
+ false
+ f689b509-b799-47ce-8c46-b4ac4bb849f4
+ TR:VAT
+ TR
+
+
+ 9953
+ VA
+ Holy See (Vatican City State) VAT number
+ false
+ 343fc230-a23c-4030-b71e-6884001dabec
+ VA:VAT
+ VA
+
+
+ 9954
+
+ Dutch Originator's Identification Number
+ false
+ b9f84d6a-55ed-4318-9dc4-964627c28d4a
+ NL:OIN
+
+
+
+ 9954
+
+ Dutch OverheidsIdentificatieNummer
+ false
+ f590b0a1-2495-4e70-bc13-9a4f11f0bb8a
+ NL:OIN
+
+
+
+ 9955
+
+ Swedish VAT number
+ false
+ bed3edf2-5342-4354-bc0e-95a899fe8578
+ SE:VAT
+
+
+
+ 9956
+
+ Belgian Crossroad Bank of Enterprises
+ false
+ 627d455d-34bc-41e3-a773-f0828b8483ee
+ BE:CBE
+
+
+
+ 9957
+
+ France VAT number
+ false
+ 4038e8fa-d334-4e4a-b981-6056ce50bf30
+ FR:VAT
+ FR
+
+
+ 9958
+
+ German Leitweg ID
+ false
+ d3291252-4161-4468-8188-b02125b5b62a
+ DE:LID
+
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/PeppolNetworkProfiles200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/PeppolNetworkProfiles200.txt
new file mode 100644
index 0000000000..5d9c651653
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/PeppolNetworkProfiles200.txt
@@ -0,0 +1,626 @@
+
+
+ EHF Advanced Order Initiation 3.0
+ urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##urn:fdc:peppol.eu:poacc:trns:order:3:extended:urn:fdc:anskaffelser.no:2019:ehf:spec:3.0::2.2
+ 3692d1e1-2c15-4a2a-b097-5d9c6ecc271a
+ urn:fdc:anskaffelser.no:2019:ehf:postaward:g3:02:1.0
+
+
+ EHF Advanced Order Response 3.0
+ urn:oasis:names:specification:ubl:schema:xsd:OrderResponse-2::OrderResponse##urn:fdc:peppol.eu:poacc:trns:order_response:3:extended:urn:fdc:anskaffelser.no:2019:ehf:spec:3.0::2.2
+ 2782a870-a968-43aa-918d-2baafd96bd47
+ urn:fdc:anskaffelser.no:2019:ehf:postaward:g3:02:1.0
+
+
+ Xrechnung 2.2 Invoice (w. extension)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.2#conformant#urn:xoev-de:kosit:extension:xrechnung_2.2::2.1
+ XRechnung v2.2 (Invoice, Credit Note, CII)
+ XRECHNUNG V2.2
+ true
+ DE
+ 72ee5de2-0ed3-4b30-b848-37dd3726bf87
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung UBL Invoice V2.3
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.3::2.1
+ XRechnung v2.3 (Invoice, Credit Note, CII)
+ XRECHNUNG V2.3
+ 86427376-2b53-4e60-a34c-23fb1c78808e
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ PEPPOL Credit Note (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1
+ PEPPOL BIS3 (Invoice, Credit Note, CII)
+ PEPPOL BIS3.0
+ true
+ dd2af6bc-a05a-4fd4-a577-0216a56bea84
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 2.0 Invoice
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0::2.1
+ f533f6d9-815b-4d5b-b55e-1822c60d71ae
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 2.0 CrossIndustryInvoice (w. extension) for Continia (Freshdesk Ticket #7787) - document id version upgraded at 2021-04-23
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0#conformant#urn:xoev-de:kosit:extension:xrechnung_2.0::16B
+ a9fac71d-8024-4509-af9f-18405a39ca74
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 2.0 Invoice (w. extension)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0#conformant#urn:xoev-de:kosit:extension:xrechnung_2.0::2.1
+ XRechnung v2 (Invoice, Credit Note, CII)
+ XRECHNUNG V2
+ true
+ DE
+ 11d205a6-0e77-4aac-a8dc-18fc4bd1eee8
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ PEPPOL Invoice (BIS 3.0)
+ 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
+ PEPPOL BIS3 (Invoice, Credit Note, CII)
+ PEPPOL BIS3.0
+ true
+ 8f9ab973-c6f0-4dfb-9936-19b56c5a588b
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 2.2 CrossIndustryInvoice (w. extension)
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.2#conformant#urn:xoev-de:kosit:extension:xrechnung_2.2::D16B
+ XRechnung v2.2 (Invoice, Credit Note, CII)
+ XRECHNUNG V2.2
+ 80c9993b-27c7-4999-9c51-11ae6b3bd1ea
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 2.2 Invoice
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.2::2.1
+ 668f126f-06d0-44fb-8e37-0bb64a23a3c9
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 1.3 Invoice
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_1.3#conformant#urn:xoev-de:kosit:extension:xrechnung_1.3::2.1
+ 3ba4a204-0c9d-433d-ae0f-0e7aa763eece
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung CII Invoice V3.0 Extension
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0#conformant#urn:xeinkauf.de:kosit:extension:xrechnung_3.0::D16B
+ 8da41879-e1e5-4c94-9200-5fed43cff8f7
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung UBL Invoice V3.0 Extension
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0#conformant#urn:xeinkauf.de:kosit:extension:xrechnung_3.0::2.1
+ f33fe036-73d0-47b9-b5ae-57da988856cf
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ SG PEPPOL Invoice (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#conformant#urn:fdc:peppol.eu:2017:poacc:billing:international:sg:3.0::2.1
+ SG PEPPOL BIS3 (Invoice, Credit Note)
+ SG PEPPOL BIS3
+ ff1c8f4d-f467-48d8-8c6f-46fad815802f
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung Invoice v1.2
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_1.2::2.1
+ XRechnung v1 (Invoice, Credit Note, CII)
+ XRECHNUNG V1
+ 7063e792-d4b0-4654-a5a0-46fd0659bff8
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung UBL CreditNote V3.0 Extension
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0#conformant#urn:xeinkauf.de:kosit:extension:xrechnung_3.0::2.1
+ fff93ede-42cb-4098-8da5-4a70375442d0
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 2.0 CrossIndustryInvoice (w. extension)
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0#conformant#urn:xoev-de:kosit:extension:xrechnung_2.0::D16B
+ XRechnung v2 (Invoice, Credit Note, CII)
+ XRECHNUNG V2
+ 94b2b716-7f62-4266-b103-856231dfec36
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 2.2 CreditNote
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.2::2.1
+ a5abcfce-a6be-4bc1-a7b1-65692166c1b4
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung UBL CreditNote V2.3 Extension
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.3#conformant#urn:xoev-de:kosit:extension:xrechnung_2.3::2.1
+ ec07f4e6-20c1-4d6c-849e-70432571cb83
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ SG PEPPOL Credit Note (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#conformant#urn:fdc:peppol.eu:2017:poacc:billing:international:sg:3.0::2.1
+ SG PEPPOL BIS3 (Invoice, Credit Note)
+ SG PEPPOL BIS3
+ 3ff9a216-0f44-47ab-ac9a-68af8795d9d0
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 1.3 CreditNote
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_1.3#conformant#urn:xoev-de:kosit:extension:xrechnung_1.3::2.1
+ 9825dd2d-94b7-4fcd-ae24-68dc4432c335
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung CII Invoice V3.0
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0::D16B
+ XRechnung v3.0 (Invoice, Credit Note, CII)
+ XRECHNUNG V3.0
+ d80fc971-7a72-48d7-8617-69132f97781f
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung UBL CreditNote V2.3
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.3::2.1
+ XRechnung v2.3 (Invoice, Credit Note, CII)
+ XRECHNUNG V2.3
+ ee8cd57b-6817-4e6f-8c33-6c83e078b43a
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung Cross Industry Invoice v1.2
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_1.2::D16B
+ XRechnung v1 (Invoice, Credit Note, CII)
+ XRECHNUNG V1
+ 48f96989-0367-46c6-89f0-ec31ff0f178d
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung UBL Invoice V3.0
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0::2.1
+ XRechnung v3.0 (Invoice, Credit Note, CII)
+ XRECHNUNG V3.0
+ 09f2bd71-d019-439f-8fff-e68ce01fe105
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung CII Invoice V2.3 Extension
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.3#conformant#urn:xoev-de:kosit:extension:xrechnung_2.3::D16B
+ 23baf699-f30c-4f7e-9b60-e7da553a6e48
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 2.2 CrossIndustryInvoice
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.2::D16B
+ bce0f939-d4b7-47e8-8345-fc363019b875
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 2.2 CreditNote (w. extension)
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.2#conformant#urn:xoev-de:kosit:extension:xrechnung_2.2::2.1
+ XRechnung v2.2 (Invoice, Credit Note, CII)
+ XRECHNUNG V2.2
+ true
+ DE
+ e7f15d5f-35a7-47e3-abbf-ffb7fbb55785
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung UBL CreditNote V3.0
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0::2.1
+ XRechnung v3.0 (Invoice, Credit Note, CII)
+ XRECHNUNG V3.0
+ d5e10b17-3070-437e-9277-c2144d160b1b
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ AU/NZ PEPPOL Credit Note (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#conformant#urn:fdc:peppol.eu:2017:poacc:billing:international:aunz:3.0::2.1
+ AU-NZ PEPPOL BIS3 (Invoice, Credit Note)
+ PEPPOL AU-NZ BIS3
+ f688e5a3-a387-4abf-bf05-c4847820e6fa
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung UBL Invoice V2.3 Extension
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.3#conformant#urn:xoev-de:kosit:extension:xrechnung_2.3::2.1
+ c0ef92e8-0633-4018-a603-c7fbae53503e
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 2.0 CreditNote
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0::2.1
+ 9446a757-8cb3-4ad6-82d6-ca206a09fb16
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ SI-UBL 2.0 Invoice
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:nen.nl:nlcius:v1.0::2.1
+ 2c43d76d-15f4-4e79-a831-daa6868f9b81
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung Credit Note v1.2
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_1.2::2.1
+ XRechnung v1 (Invoice, Credit Note, CII)
+ XRECHNUNG V1
+ 13a2bd12-b46f-4ae5-9316-a60c2a8ebc34
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ AU/NZ PEPPOL Invoice (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#conformant#urn:fdc:peppol.eu:2017:poacc:billing:international:aunz:3.0::2.1
+ AU-NZ PEPPOL BIS3 (Invoice, Credit Note)
+ PEPPOL AU-NZ BIS3
+ 1fcad749-bb5e-432c-8d23-96bcbda4b875
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ SI-UBL 2.0 Credit Note
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:fdc:nen.nl:nlcius:v1.0::2.1
+ 1d292f60-a6b5-419d-a0d0-97acd9cdb5fc
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 1.3 CrossIndustryInvoice
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_1.3#conformant#urn:xoev-de:kosit:extension:xrechnung_1.3::16B
+ f9087999-af28-4897-9eaf-87ed9151d887
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ Xrechnung 2.0 CreditNote (w. extension)
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0#conformant#urn:xoev-de:kosit:extension:xrechnung_2.0::2.1
+ XRechnung v2 (Invoice, Credit Note, CII)
+ XRECHNUNG V2
+ true
+ DE
+ 890ecf6a-d9f1-4c79-9175-ab55e3e193cc
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ XRechnung CII Invoice V2.3
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.3::D16B
+ XRechnung v2.3 (Invoice, Credit Note, CII)
+ XRECHNUNG V2.3
+ 410ef408-c418-4e23-9952-b86e32b86d63
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ PEPPOL Cross Industry Invoice (BIS 3.0)
+ urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::D16B
+ PEPPOL BIS3 (Invoice, Credit Note, CII)
+ PEPPOL BIS3.0
+ 24498487-81a8-4f46-9104-bb3915a6eee0
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+
+
+ AU/NZ PEPPOL Self-Billing Credit Note (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#conformant#urn:fdc:peppol.eu:2017:poacc:selfbilling:international:aunz:3.0::2.1
+ AU-NZ PEPPOL Self-Billing BIS3 (Invoice, Credit Note)
+ PEPPOL AU-NZ SBIS3
+ 43aafd3d-2de0-46c9-bad2-b4e7608f88ca
+ urn:fdc:peppol.eu:2017:poacc:selfbilling:01:1.0
+
+
+ AU/NZ PEPPOL Self-Billing Invoice (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#conformant#urn:fdc:peppol.eu:2017:poacc:selfbilling:international:aunz:3.0::2.1
+ AU-NZ PEPPOL Self-Billing BIS3 (Invoice, Credit Note)
+ PEPPOL AU-NZ SBIS3
+ 34df4209-079c-4d01-b58e-5fe6c42d2008
+ urn:fdc:peppol.eu:2017:poacc:selfbilling:01:1.0
+
+
+ Peppol Advanced Order (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##urn:fdc:peppol.eu:poacc:trns:order:3::2.1
+ 9357d973-e4a3-49e8-a054-9fad3dcdb171
+ urn:fdc:peppol.eu:poacc:bis:advanced_ordering:3
+
+
+ Peppol Order Change (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:OrderChange-2::OrderChange##urn:fdc:peppol.eu:poacc:trns:order_change:3::2.3
+ f6d47008-04c6-47c7-9f31-e21445b204d5
+ urn:fdc:peppol.eu:poacc:bis:advanced_ordering:3
+
+
+ Peppol Order Response Advanced (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:OrderResponse-2::OrderResponse##urn:fdc:peppol.eu:poacc:trns:order_response_advanced:3::2.3
+ 4dd648a6-7cae-4e8b-ba25-c82eb6edf4b6
+ urn:fdc:peppol.eu:poacc:bis:advanced_ordering:3
+
+
+ Peppol Order Cancellation (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:OrderCancellation-2::OrderCancellation##urn:fdc:peppol.eu:poacc:trns:order_cancellation:3::2.3
+ 3592ed68-d63d-4d26-8c9b-22b5be8d6dd9
+ urn:fdc:peppol.eu:poacc:bis:advanced_ordering:3
+
+
+ PEPPOL Despatch Advice (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:DespatchAdvice-2::DespatchAdvice##urn:fdc:peppol.eu:poacc:trns:despatch_advice:3::2.1
+ 88e08943-2863-43e5-b5b4-aca6f411dbfb
+ urn:fdc:peppol.eu:poacc:bis:despatch_advice:3
+
+
+ PEPPOL Invoice Response (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2::ApplicationResponse##urn:fdc:peppol.eu:poacc:trns:invoice_response:3::2.1
+ 4f333069-936c-4f2d-af71-0f4d261ad4a4
+ urn:fdc:peppol.eu:poacc:bis:invoice_response:3
+
+
+ PEPPOL Message Level Response (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2::ApplicationResponse##urn:fdc:peppol.eu:poacc:trns:mlr:3::2.1
+ 64bb189a-3f65-4c28-a2e2-a257dba5c04b
+ urn:fdc:peppol.eu:poacc:bis:mlr:3
+
+
+ PEPPOL Order Agreement (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:OrderResponse-2::OrderResponse##urn:fdc:peppol.eu:poacc:trns:order_agreement:3::2.1
+ 454f32e9-c413-41d6-8ccf-576e76ea6020
+ urn:fdc:peppol.eu:poacc:bis:order_agreement:3
+
+
+ PEPPOL Order Only (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##urn:fdc:peppol.eu:poacc:trns:order:3::2.1
+ 3824b968-c417-4be8-bb09-b6217cbfc50b
+ urn:fdc:peppol.eu:poacc:bis:order_only:3
+
+
+ PEPPOL Order Response (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:OrderResponse-2::OrderResponse##urn:fdc:peppol.eu:poacc:trns:order_response:3::2.1
+ PEPPOL BIS Ordering 3 (Order, Order Response)
+ PEPPOL EORDERING
+ 5784790c-3ee1-4511-bbd2-b34260cad657
+ urn:fdc:peppol.eu:poacc:bis:ordering:3
+
+
+ PEPPOL Order (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##urn:fdc:peppol.eu:poacc:trns:order:3::2.1
+ PEPPOL BIS Ordering 3 (Order, Order Response)
+ PEPPOL EORDERING
+ 8002d670-23e6-4d8a-b813-749abd3aadb0
+ urn:fdc:peppol.eu:poacc:bis:ordering:3
+
+
+ PEPPOL Punch Out (BIS 3.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Catalogue-2::Catalogue##urn:fdc:peppol.eu:poacc:trns:punch_out:3::2.1
+ 8211f941-a7ea-4143-ac10-1c551649369b
+ urn:fdc:peppol.eu:poacc:bis:punch_out:3
+
+
+ JP PINT Invoice 1.0* (wildcard)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:billing-1@jp-1*::2.1
+ 7915c00a-4f28-4255-b108-169a02b29e7d
+ urn:peppol:bis:billing
+
+
+ A-NZ PINT Credit Note v1.0* (wildcard)
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:peppol:pint:billing-1@aunz-1*::2.1
+ 02b22d34-b1a2-44e6-b568-74f07130a8dd
+ urn:peppol:bis:billing
+
+
+ Peppol PINT Invoice v1.0* (wildcard)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:billing-1*::2.1
+ 43306d19-935f-4f1b-bae0-830cb62857d2
+ urn:peppol:bis:billing
+
+
+ JP PINT Invoice 1.0 (busdox)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:billing-1@jp-1::2.1
+ 1d9fd652-cbe9-4665-b4c0-d01461292d65
+ urn:peppol:bis:billing
+
+
+ Peppol PINT CreditNote v1.0* (wildcard)
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:peppol:pint:billing-1*::2.1
+ 3bc1506d-ef9b-4925-9500-f22b74a98f45
+ urn:peppol:bis:billing
+
+
+ A-NZ PINT Invoice v1.0* (wildcard)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:billing-1@aunz-1*::2.1
+ 88bf3985-acdb-4e4c-8778-f3415a3cad1c
+ urn:peppol:bis:billing
+
+
+ A-NZ PINT Self-Billing Credit Note v1.0* (wildcard)
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:peppol:pint:selfbilling-1@aunz-1*::2.1
+ 137f47f9-8a4f-4c58-a00d-f398f224c5cb
+ urn:peppol:bis:selfbilling
+
+
+ A-NZ PINT Self-Billing Invoice v1.0* (wildcard)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:selfbilling-1@aunz-1*::2.1
+ b6aa6023-25be-4d8f-8b7e-a72e82042d96
+ urn:peppol:bis:selfbilling
+
+
+ SFTI Svefaktura v1 w/ attachment
+ urn:sfti:documents:StandardBusinessDocumentHeader::Invoice##urn:sfti:documents:BasicInvoice:1:0:#BasicInvoice_ObjectEnvelope::1.0
+ Svefaktura simple and with attachment
+ SVEFAKTURA V1
+ e7073408-aaee-4706-aa4d-c919e46c5523
+ urn:sfti:services:documentprocessing:BasicInvoice:1:0
+
+
+ SFTI Svefaktura v1
+ urn:sfti:documents:BasicInvoice:1:0::Invoice##urn:sfti:documents:BasicInvoice:1:0::1.0
+ Svefaktura simple and with attachment
+ SVEFAKTURA V1
+ 66f94162-96ad-444d-9278-2a0b208d8df8
+ urn:sfti:services:documentprocessing:BasicInvoice:1:0
+
+
+ EHF Catalogue v2
+ urn:oasis:names:specification:ubl:schema:xsd:Catalogue-2::Catalogue##urn:www.cenbii.eu:transaction:biitrns019:ver2.0:extended:urn:www.peppol.eu:bis:peppol1a:ver2.0:extended:urn:www.difi.no:ehf:katalog:ver1.0::2.1
+ 85ac7894-851e-47fb-ac08-d683d479bbfb
+ urn:www.cenbii.eu:profile:bii01:ver2.0
+
+
+ SFTI Svekatalog (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Catalogue-2::Catalogue##urn:www.cenbii.eu:transaction:biitrns019:ver2.0:extended:urn:www.sfti.se:svekatalog:ver2.0::2.1
+ 241602cd-6ab1-47c1-9c16-465dc8d3825a
+ urn:www.cenbii.eu:profile:bii01:ver2.0#urn:www.sfti.se:svekatalog:ver2.0
+
+
+ SFTI Sveorder v1
+ urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##urn:www.cenbii.eu:transaction:biicoretrdm001:ver1.0::2.0
+ c41e3243-4a2d-4caa-9b94-abd79028e43f
+ urn:www.cenbii.eu:profile:bii03:ver1.0
+
+
+ PEPPOL Order 3a (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##urn:www.cenbii.eu:transaction:biitrns001:ver2.0:extended:urn:www.peppol.eu:bis:peppol3a:ver2.0:extended:urn:www.ubl-italia.org:spec:ordine:ver2.1::2.1
+ eb255817-235d-424d-9678-d591ebf2c69d
+ urn:www.cenbii.eu:profile:bii03:ver2.0
+
+
+ PEPPOL Order (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##urn:www.cenbii.eu:transaction:biitrns001:ver2.0:extended:urn:www.peppol.eu:bis:peppol3a:ver2.0::2.1
+ 9d953397-2a5c-41c5-bf4a-67d3efddb707
+ urn:www.cenbii.eu:profile:bii03:ver2.0
+
+
+ SimplerInvoicing Invoice v1.1
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol4a:ver2.0:extended:urn:www.simplerinvoicing.org:si:si-ubl:ver1.1.x::2.1
+ 2f299842-3d95-4f33-89ef-f7bc8819680c
+ urn:www.cenbii.eu:profile:bii04:ver1.0
+
+
+ PEPPOL Invoice (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol4a:ver2.0::2.1
+ a43e5c64-7766-4afa-93bc-b61743888005
+ urn:www.cenbii.eu:profile:bii04:ver1.0
+
+
+ PEPPOL Invoice (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol4a:ver2.0::2.1
+ 752be514-ada7-4674-8dbd-56d632934f4d
+ urn:www.cenbii.eu:profile:bii04:ver2.0
+
+
+ EHF Invoice v2
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol4a:ver2.0:extended:urn:www.difi.no:ehf:faktura:ver2.0::2.1
+ EHF v2
+ EHF V2
+ eaf45a75-f04a-4d09-a360-56f2a98c8b02
+ urn:www.cenbii.eu:profile:bii04:ver2.0
+
+
+ ATGOV Invoice 5a (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol4a:ver2.0:extended:urn:www.erechnung.gv.at:ver1.0::2.1
+ 2ea82b29-73fc-4a07-b7f6-3ed775695b80
+ urn:www.cenbii.eu:profile:bii04:ver2.0
+
+
+ PEPPOL Invoice (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol5a:ver2.0::2.1
+ b1b72cf1-78b5-4678-a688-507e4de9b17c
+ urn:www.cenbii.eu:profile:bii05:ver2.0
+
+
+ ATGOV Credit Note 5a (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:www.cenbii.eu:transaction:biitrns014:ver2.0:extended:urn:www.peppol.eu:bis:peppol5a:ver2.0:extended:urn:www.erechnung.gv.at:ver1.0::2.1
+ aa1b11de-58d3-4b3c-b7ce-24bdc651bf17
+ urn:www.cenbii.eu:profile:bii05:ver2.0
+
+
+ UBL Italia Fattura (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol5a:ver2.0:extended:urn:www.ubl-italia.org:spec:fatturapa:ver2.0::2.1
+ UBL Italia (Fattura,Nota Di Credito)
+ UBL ITALIA BIS2
+ 2b324310-9be5-4b5a-91e1-2ccf38908469
+ urn:www.cenbii.eu:profile:bii05:ver2.0
+
+
+ EHF Credit Note v2
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:www.cenbii.eu:transaction:biitrns014:ver2.0:extended:urn:www.peppol.eu:bis:peppol5a:ver2.0:extended:urn:www.difi.no:ehf:kreditnota:ver2.0::2.1
+ EHF v2
+ EHF V2
+ 7ebf777b-2443-49cd-b63f-14f27a2520f1
+ urn:www.cenbii.eu:profile:bii05:ver2.0
+
+
+ ATGOV Invoice 4a (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol5a:ver2.0:extended:urn:www.erechnung.gv.at:ver1.0::2.1
+ 76e3b177-b402-471c-a021-00cea16e0054
+ urn:www.cenbii.eu:profile:bii05:ver2.0
+
+
+ PEPPOL Credit Note (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:www.cenbii.eu:transaction:biitrns014:ver2.0:extended:urn:www.peppol.eu:bis:peppol5a:ver2.0::2.1
+ 6ad21574-b81e-4b99-a6ab-c1586e9da727
+ urn:www.cenbii.eu:profile:bii05:ver2.0
+
+
+ UBL Italia Nota Di Credito (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:www.cenbii.eu:transaction:biitrns014:ver2.0:extended:urn:www.peppol.eu:bis:peppol5a:ver2.0:extended:urn:www.ubl-italia.org:spec:fatturapa:ver2.0::2.1
+ UBL Italia (Fattura,Nota Di Credito)
+ UBL ITALIA BIS2
+ 49cca1f6-46ee-49b1-a06a-a235c2fe9292
+ urn:www.cenbii.eu:profile:bii05:ver2.0
+
+
+ PEPPOL Order Response (BIS 1.0)
+ urn:oasis:names:specification:ubl:schema:xsd:OrderResponse-2::OrderResponse##urn:www.cenbii.eu:transaction:biitrns076:ver2.0:extended:urn:www.peppol.eu:bis:peppol28a:ver1.0::2.1
+ 82fe8d10-79f1-465a-8d95-c1cbde43a4bd
+ urn:www.cenbii.eu:profile:bii28:ver2.0
+
+
+ PEPPOL Order 28a (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##urn:www.cenbii.eu:transaction:biitrns001:ver2.0:extended:urn:www.peppol.eu:bis:peppol28a:ver1.0::2.1
+ 60b08aa7-5021-40a9-b02d-c2105e554218
+ urn:www.cenbii.eu:profile:bii28:ver2.0
+
+
+ EHF Order Response v2
+ urn:oasis:names:specification:ubl:schema:xsd:OrderResponse-2::OrderResponse##urn:www.cenbii.eu:transaction:biitrns076:ver2.0:extended:urn:www.peppol.eu:bis:peppol28a:ver1.0:extended:urn:www.difi.no:ehf:ordrebekreftelse:ver1.0::2.1
+ b4d86c60-7eb6-4fd4-9abf-b59a83141b4d
+ urn:www.cenbii.eu:profile:bii28:ver2.0
+
+
+ PEPPOL Despatch Advice 30a (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:DespatchAdvice-2::DespatchAdvice##urn:www.cenbii.eu:transaction:biitrns016:ver1.0:extended:urn:www.peppol.eu:bis:peppol30a:ver1.0::2.1
+ 6002dbc9-4c0a-411c-977b-d6aa60eaabe9
+ urn:www.cenbii.eu:profile:bii30:ver2.0
+
+
+ UBL Italia Despatch Advice (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:DespatchAdvice-2::DespatchAdvice##urn:www.cenbii.eu:transaction:biitrns016:ver1.0:extended:urn:www.peppol.eu:bis:peppol30a:ver1.0:extended:urn:www.ubl-italia.org:spec:ddt:ver2.1::2.1
+ dc0f7dfc-446f-4f85-93be-24a0f6d61ae2
+ urn:www.cenbii.eu:profile:bii30:ver2.0
+
+
+ PEPPOL Order Agreement (BIS 2.0)
+ urn:oasis:names:specification:ubl:schema:xsd:OrderResponse-2::OrderResponse##urn:www.cenbii.eu:transaction:biitrns110:ver1.0:extended:urn:www.peppol.eu:bis:peppol42a:ver1.0::2.1
+ a0c3063c-a4cc-4d76-91ac-11a07b46dc9d
+ urn:www.cenbii.eu:profile:bii42:ver1.0
+
+
+ EHF Credit Note v2
+ urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:www.cenbii.eu:transaction:biitrns014:ver2.0:extended:urn:www.cenbii.eu:profile:biixx:ver2.0:extended:urn:www.difi.no:ehf:kreditnota:ver2.0::2.1
+ EHF v2
+ EHF V2
+ 0ebb2ea6-cfc6-46e8-a322-57d4d6c9f6d1
+ urn:www.cenbii.eu:profile:biixx:ver2.0
+
+
+ NES UBL Invoice
+ urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##NESUBL-2.0::2.0
+ NESUBL
+ NESUBL V2
+ 710fec3d-a170-4b5d-a28f-8860c5d9851f
+ urn:www.nesubl.eu:profiles:profile4:ver2.0
+
+
+ PPPOL Invoice Response v1.0
+ urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2::ApplicationResponse##urn:www.peppol.eu:transaction:biitrns111:ver1.0::2.1
+ 6dd1ab70-bf54-4bc3-92a8-298191a3f893
+ urn:www.peppol.eu:profile:bis63a:ver1.0
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/ReceiveDocuments-multiple-services.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ReceiveDocuments-multiple-services.txt
new file mode 100644
index 0000000000..cc0cfe29ed
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ReceiveDocuments-multiple-services.txt
@@ -0,0 +1,42 @@
+
+
+ 2024-10-05T09:11:23.223
+ IncomingEnum
+ 65dd7456-7a49-4382-9f76-1211fa8ad0bf
+ bef5048c-985e-4674-8b95-66e1e05fc91b
+ 1f4111a0-cd49-45e1-9f1e-ed14e71e3438
+ 568c29e7-c2c8-49bb-b135-9199d5b791d1
+ 452845225
+ 568c29e7-c2c8-49bb-b135-9199d5b791d1
+ 855475824
+ CreatedEnum
+ 467014
+ 2024-10-05T09:11:23.223
+
+ {fileDownloadUrl}/peppol
+
+
+ {envelopeDownloadUrl}
+
+
+
+ 2024-10-05T09:11:23.223
+ IncomingEnum
+ bb88c953-4cdd-4e77-bf8e-24c7594e4c8a
+ bb3dc544-e227-4894-8d5d-89eb7e473c40
+ 0c383d92-a04d-47af-a8e9-f50d2cb813f3
+ 01babc72-e56c-4b46-ad7b-cdc020a65951
+ DK45284522
+ 01babc72-e56c-4b46-ad7b-cdc020a65951
+ DK85622541
+ CreatedEnum
+ 467014
+ 2024-10-05T09:11:23.223
+
+ {fileDownloadUrl}/oioubl
+
+
+ {envelopeDownloadUrl}
+
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/ReceiveDocuments.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ReceiveDocuments.txt
new file mode 100644
index 0000000000..21d594dbbf
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ReceiveDocuments.txt
@@ -0,0 +1,22 @@
+
+
+ 2024-10-05T09:11:23.223
+ IncomingEnum
+ 65dd7456-7a49-4382-9f76-1211fa8ad0bf
+ bef5048c-985e-4674-8b95-66e1e05fc91b
+ 1f4111a0-cd49-45e1-9f1e-ed14e71e3438
+ 568c29e7-c2c8-49bb-b135-9199d5b791d1
+ 452845225
+ 568c29e7-c2c8-49bb-b135-9199d5b791d1
+ 855475824
+ CreatedEnum
+ 467014
+ 2024-10-05T09:11:23.223
+
+ {fileDownloadUrl}/peppol
+
+
+ {envelopeDownloadUrl}
+
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/ReceiveOioublInvoiceDocument200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ReceiveOioublInvoiceDocument200.txt
new file mode 100644
index 0000000000..7e757cc674
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ReceiveOioublInvoiceDocument200.txt
@@ -0,0 +1,188 @@
+
+
+ 2.0
+ OIOUBL-2.02
+ Procurement-OrdSimR-BilSim-1.0
+ 683f9400-0cc3-4a0d-9da1-27a1edc60c42
+ true
+ 2024-04-08
+ 380
+ DKK
+
+
+ VWERAFS
+ 102231
+ 2024-04-08
+
+
+
+
+ DK85622541
+
+ DK85622541
+
+
+ eVendor
+
+
+ StructuredLax
+ Ringen 5
+ Westminster
+ Kugleby
+ 9900
+
+ DK
+
+
+
+ DK85622541
+
+ 63
+ Moms
+
+
+
+ eVendor
+ DK85622541
+
+
+ LB
+ Lasse Bertramsen
+
+
+ LB@contoso.com
+
+
+
+
+
+ 5798009811639
+
+ DK45284522
+
+
+ demo
+
+
+ StructuredLax
+ Parkvej 44
+
+ Atlanta
+ 4300
+
+ DK
+
+
+
+ Helen Ray
+ Helen Ray
+
+
+ helen.ray@contoso.com
+
+
+
+
+ 2024-04-08
+
+
+ StructuredLax
+ Parkvej 44
+
+ Atlanta
+ 4300
+
+ DK
+
+
+
+
+
+ 1
+ 42
+ 2024-04-22
+ DK:BANK
+
+ 9999888
+
+ 9999
+
+ TEST
+ Konto Banken
+
+
+
+
+
+ 1
+ 1
+ 14 dage netto
+ 0.00
+ 352091.25
+
+ 2024-04-08
+
+
+ 2024-04-22
+
+
+
+ 70418.25
+
+ 281673.00
+ 70418.25
+
+ StandardRated
+ 25.00
+
+ 63
+ Moms
+
+
+
+
+
+ 281673.00
+ 70418.25
+ 352091.25
+ 352091.25
+
+
+ 10000
+ 263.00
+ 281673.00
+
+
+ 10000
+
+ VWERAFS
+
+
+
+ 70418.25
+
+ 281673.00
+ 70418.25
+
+ StandardRated
+ 25.00
+
+ 63
+ Moms
+
+
+
+
+
+ SEOUL Gestestol, rod
+ SEOUL Gestestol, rod
+
+ 1988-S
+
+
+
+ 1071.00
+ 1
+
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/ReceivePeppolInvoiceDocument200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ReceivePeppolInvoiceDocument200.txt
new file mode 100644
index 0000000000..fc83b138ca
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/ReceivePeppolInvoiceDocument200.txt
@@ -0,0 +1,149 @@
+
+
+ urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+ b06b6945-e198-420a-817b-ce06c7fca294
+ 2024-04-08
+ 2024-05-08
+ 380
+ GBP
+ swergfrew
+
+ SDRDFEW
+
+
+ 103215
+
+
+
+ 777777772
+
+ eVendor
+
+
+ 7122 South Ashford Street
+ Westminster
+ London
+ W2 8HG
+
+ GB
+
+
+
+ GB777777772
+
+ VAT
+
+
+
+ eVendor
+ 777777772
+
+
+ Jim Olive
+ JO@contoso.com
+
+
+
+
+
+ 777777771
+
+ eCustomer
+
+
+ Station Road, 21
+ Cambridge
+ CB1 2FB
+
+ GB
+
+
+
+ GB777777771
+
+ VAT
+
+
+
+ eCustomer
+ 777777771
+
+
+ Robert Townes
+ robert.townes@contoso.com
+
+
+
+
+ 2024-04-08
+
+
+ Station Road, 21
+ Cambridge
+ CB1 2FB
+
+ GB
+
+
+
+
+
+ 31
+
+ GB12CPBK08929965044991
+
+ BG99999
+
+
+
+
+ 1 Month/2% 8 days
+
+
+ 1183.68
+
+ 5918.4
+ 1183.68
+
+ S
+ 20
+
+ VAT
+
+
+
+
+
+ 5918.4
+ 5918.4
+ 7102.08
+ 0
+ 0.00
+ 0
+ 7102.08
+
+
+ 10000
+ Item
+ 48
+ 5918.4
+
+ LONDON Swivel Chair, blue
+
+ 1908-S
+
+
+ S
+ 20
+
+ VAT
+
+
+
+
+ 123.30
+ 1
+
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/SubmitDocument200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/SubmitDocument200.txt
new file mode 100644
index 0000000000..3abc36c97b
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/SubmitDocument200.txt
@@ -0,0 +1,4 @@
+
+
+ 3fa85f64-5717-4562-b3fc-2c963f66afa6
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/SubmitDocument201.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/SubmitDocument201.txt
new file mode 100644
index 0000000000..3abc36c97b
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/SubmitDocument201.txt
@@ -0,0 +1,4 @@
+
+
+ 3fa85f64-5717-4562-b3fc-2c963f66afa6
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/TechnicalResponse200-Error.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/TechnicalResponse200-Error.txt
new file mode 100644
index 0000000000..352a80187d
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/TechnicalResponse200-Error.txt
@@ -0,0 +1,5 @@
+
+ ErrorEnum
+ ReceiverNotRegistered
+ The recipient of the document is not registered to receive this type of document.
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/TechnicalResponse200-Pending.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/TechnicalResponse200-Pending.txt
new file mode 100644
index 0000000000..0ab7acbbeb
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/TechnicalResponse200-Pending.txt
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/TechnicalResponse200-Success.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/TechnicalResponse200-Success.txt
new file mode 100644
index 0000000000..54d276cbda
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/TechnicalResponse200-Success.txt
@@ -0,0 +1,5 @@
+
+
+ 1842e99d-5f91-4479-aa18-8c73c52fbef0
+ SuccessEnum
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/UpdateSubscription200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/UpdateSubscription200.txt
new file mode 100644
index 0000000000..c21aa73e8f
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/UpdateSubscription200.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/Resources/UpdateSubscriptionError200.txt b/Apps/W1/EDocumentConnectors/Continia/test/Resources/UpdateSubscriptionError200.txt
new file mode 100644
index 0000000000..7c8d89d87b
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/Resources/UpdateSubscriptionError200.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/app.json b/Apps/W1/EDocumentConnectors/Continia/test/app.json
new file mode 100644
index 0000000000..446ecb9ba1
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/app.json
@@ -0,0 +1,71 @@
+{
+ "id": "769158cc-9498-42cf-b3a3-e5be4333f8b7",
+ "name": "E-Document Connector - Continia Tests",
+ "publisher": "Microsoft",
+ "brief": "E-Document Connector - Continia Tests",
+ "description": "E-Document Connector - Continia 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",
+ "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": "31ef535a-1182-4354-98e8-e0e66a587055",
+ "name": "E-Document Connector - Continia",
+ "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": "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": "40860557-a18d-42ad-aecb-22b7dd80dc80",
+ "name": "Permissions Mock",
+ "publisher": "Microsoft",
+ "version": "26.0.0.0"
+ }
+ ],
+ "screenshots": [
+
+ ],
+ "platform": "26.0.0.0",
+ "idRanges": [
+ {
+ "from": 148200,
+ "to": 148205
+ }
+ ],
+ "resourceExposurePolicy": {
+ "allowDebugging": true,
+ "allowDownloadingSource": true,
+ "includeSourceInSymbolFile": true
+ },
+ "application": "26.0.0.0",
+ "resourceFolders": [
+ "Resources"
+ ],
+ "target": "OnPrem"
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaApiCommUnitTests.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaApiCommUnitTests.Codeunit.al
new file mode 100644
index 0000000000..7c0e83effd
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaApiCommUnitTests.Codeunit.al
@@ -0,0 +1,980 @@
+namespace Microsoft.EServices.EDocumentConnector.Continia;
+
+using System.Utilities;
+
+codeunit 148200 "Continia Api Comm. Unit Tests"
+{
+ Subtype = Test;
+ TestHttpRequestPolicy = AllowOutboundFromHandler;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure GetParticipation200()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(200, GetMockResponseContent('Participation200-InProcess.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Get Participation
+ ApiRequests.GetParticipation(Participation);
+
+ // [Then] Make sure Participation values returned correct
+ Assert.AreEqual(ConnectorLibrary.ParticipationId(true), Participation.Id, IncorrectValueErr);
+ Assert.AreEqual(Enum::"Continia Registration Status"::InProcess, Participation."Registration Status", IncorrectValueErr);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure GetParticipation400()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(400, GetMockResponseContent('Common400.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Get Participation
+ asserterror ApiRequests.GetParticipation(Participation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response400ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure GetParticipation401()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(401, GetMockResponseContent('Common401.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Get Participation
+ asserterror ApiRequests.GetParticipation(Participation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response401ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure GetParticipation404()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(404, GetMockResponseContent('Common404.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Get Participation
+ asserterror ApiRequests.GetParticipation(Participation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response404ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure GetParticipation500()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(500, GetMockResponseContent('Common500.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Get Participation
+ asserterror ApiRequests.GetParticipation(Participation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response500ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PostParticipation200()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(200, GetMockResponseContent('Participation200-Draft.txt'));
+
+ // [Given] Filled in Participation info
+ ConnectorLibrary.PrepareParticipation(TempParticipation);
+
+ // [When] Post Participation
+ ApiRequests.PostParticipation(TempParticipation);
+
+ // [Then] Make sure Participation values returned correct
+ ConnectorLibrary.GetParticipation(Participation);
+ Assert.AreEqual(ConnectorLibrary.ParticipationId(true), Participation.Id, IncorrectValueErr);
+ Assert.AreEqual(Enum::"Continia Registration Status"::Draft, Participation."Registration Status", IncorrectValueErr);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PostParticipation201()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(201, GetMockResponseContent('Participation201-Draft.txt'));
+
+ // [Given] Filled in Participation info
+ ConnectorLibrary.PrepareParticipation(TempParticipation);
+
+ // [When] Post Participation
+ ApiRequests.PostParticipation(TempParticipation);
+
+ // [Then] Make sure Participation values returned correct
+ ConnectorLibrary.GetParticipation(Participation);
+ Assert.AreEqual(ConnectorLibrary.ParticipationId(true), Participation.Id, IncorrectValueErr);
+ Assert.AreEqual(Enum::"Continia Registration Status"::Draft, Participation."Registration Status", IncorrectValueErr);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PostParticipation400()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(400, GetMockResponseContent('Common400.txt'));
+
+ // [Given] Filled in Participation info
+ ConnectorLibrary.PrepareParticipation(TempParticipation);
+
+ // [When] Post Participation
+ asserterror ApiRequests.PostParticipation(TempParticipation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response400ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PostParticipation401()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(401, GetMockResponseContent('Common401.txt'));
+
+ // [Given] Filled in Participation info
+ ConnectorLibrary.PrepareParticipation(TempParticipation);
+
+ // [When] Post Participation
+ asserterror ApiRequests.PostParticipation(TempParticipation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response401ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PostParticipation404()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(404, GetMockResponseContent('Common404.txt'));
+
+ // [Given] Filled in Participation info
+ ConnectorLibrary.PrepareParticipation(TempParticipation);
+
+ // [When] Post Participation
+ asserterror ApiRequests.PostParticipation(TempParticipation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response404ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PostParticipation422()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(422, GetMockResponseContent('Common422.txt'));
+
+ // [Given] Filled in Participation info
+ ConnectorLibrary.PrepareParticipation(TempParticipation);
+
+ // [When] Post Participation
+ asserterror ApiRequests.PostParticipation(TempParticipation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response422ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PostParticipation500()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(500, GetMockResponseContent('Common500.txt'));
+
+ // [Given] Filled in Participation info
+ ConnectorLibrary.PrepareParticipation(TempParticipation);
+
+ // [When] Post Participation
+ asserterror ApiRequests.PostParticipation(TempParticipation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response500ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PatchParticipation200()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(200, GetMockResponseContent('Participation200-InProcess.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Patch Participation
+ TempParticipation := Participation;
+ ApiRequests.PatchParticipation(TempParticipation);
+
+ // [Then] Make sure Participation values returned correct
+ ConnectorLibrary.GetParticipation(Participation);
+ Assert.AreEqual(ConnectorLibrary.ParticipationId(true), Participation.Id, IncorrectValueErr);
+ Assert.AreEqual(Enum::"Continia Registration Status"::InProcess, Participation."Registration Status", IncorrectValueErr);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PatchParticipation400()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(400, GetMockResponseContent('Common400.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Patch Participation
+ TempParticipation := Participation;
+ asserterror ApiRequests.PatchParticipation(TempParticipation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response400ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PatchParticipation401()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(401, GetMockResponseContent('Common401.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Patch Participation
+ TempParticipation := Participation;
+ asserterror ApiRequests.PatchParticipation(TempParticipation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response401ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PatchParticipation404()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(404, GetMockResponseContent('Common404.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Patch Participation
+ TempParticipation := Participation;
+ asserterror ApiRequests.PatchParticipation(TempParticipation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response404ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PatchParticipation409()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(409, GetMockResponseContent('Common409.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Patch Participation
+ TempParticipation := Participation;
+ asserterror ApiRequests.PatchParticipation(TempParticipation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response409ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PatchParticipation422()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(422, GetMockResponseContent('Common422.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Patch Participation
+ TempParticipation := Participation;
+ asserterror ApiRequests.PatchParticipation(TempParticipation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response422ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PatchParticipation500()
+ var
+ TempParticipation: Record "Continia Participation" temporary;
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(500, GetMockResponseContent('Common500.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Patch Participation
+ TempParticipation := Participation;
+ asserterror ApiRequests.PatchParticipation(TempParticipation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response500ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure DeleteParticipation200()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(200, '');
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Delete Participation
+ ApiRequests.DeleteParticipation(Participation);
+
+ // [Then] Make sure Participation does not exist
+ Assert.AreEqual(true, Participation.IsEmpty, 'Participation should not exist');
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure DeleteParticipation202()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(202, '');
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Delete Participation
+ ApiRequests.DeleteParticipation(Participation);
+
+ // [Then] Make sure Participation does not exist
+ ConnectorLibrary.GetParticipation(Participation);
+ Assert.AreEqual(ConnectorLibrary.ParticipationId(true), Participation.Id, IncorrectValueErr);
+ Assert.AreEqual(Enum::"Continia Registration Status"::Disabled, Participation."Registration Status", IncorrectValueErr);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure DeleteParticipation400()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(400, GetMockResponseContent('Common400.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Delete Participation
+ asserterror ApiRequests.DeleteParticipation(Participation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response400ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure DeleteParticipation401()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(401, GetMockResponseContent('Common401.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Delete Participation
+ asserterror ApiRequests.DeleteParticipation(Participation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response401ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure DeleteParticipation404()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(404, GetMockResponseContent('Common404.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Delete Participation
+ asserterror ApiRequests.DeleteParticipation(Participation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response404ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure DeleteParticipation422()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(422, GetMockResponseContent('Common422.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Delete Participation
+ asserterror ApiRequests.DeleteParticipation(Participation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response422ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure DeleteParticipation500()
+ var
+ Participation: Record "Continia Participation";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(500, GetMockResponseContent('Common500.txt'));
+
+ // [Given] a Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [When] Delete Participation
+ asserterror ApiRequests.DeleteParticipation(Participation);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response500ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PostParticipationProfile200()
+ var
+ Participation: Record "Continia Participation";
+ TempActivatedNetProf: Record "Continia Activated Net. Prof." temporary;
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(200, GetMockResponseContent('ParticipationProfile200-randomId.txt'));
+
+ // [Given] a Connected Participation without Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, TempActivatedNetProf);
+
+ // [When] Post Participation Profile
+ ApiRequests.PostParticipationProfile(TempActivatedNetProf, Participation.Id);
+
+ // [Then] Make sure Activated Network Profile exists
+ Assert.AreEqual(true, ConnectorLibrary.GetActivatedNetworkProfile(ActivatedNetProf), 'Activated Network Profile must exist');
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PostParticipationProfile400()
+ var
+ Participation: Record "Continia Participation";
+ TempActivatedNetProf: Record "Continia Activated Net. Prof." temporary;
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(400, GetMockResponseContent('Common400.txt'));
+
+ // [Given] a Connected Participation without Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, TempActivatedNetProf);
+
+ // [When] Post Participation Profile
+ asserterror ApiRequests.PostParticipationProfile(TempActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response400ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PostParticipationProfile401()
+ var
+ Participation: Record "Continia Participation";
+ TempActivatedNetProf: Record "Continia Activated Net. Prof." temporary;
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(401, GetMockResponseContent('Common401.txt'));
+
+ // [Given] a Connected Participation without Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, TempActivatedNetProf);
+
+ // [When] Post Participation Profile
+ asserterror ApiRequests.PostParticipationProfile(TempActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response401ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PostParticipationProfile404()
+ var
+ Participation: Record "Continia Participation";
+ TempActivatedNetProf: Record "Continia Activated Net. Prof." temporary;
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(404, GetMockResponseContent('Common404.txt'));
+
+ // [Given] a Connected Participation without Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, TempActivatedNetProf);
+
+ // [When] Post Participation Profile
+ asserterror ApiRequests.PostParticipationProfile(TempActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response404ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PostParticipationProfile422()
+ var
+ Participation: Record "Continia Participation";
+ TempActivatedNetProf: Record "Continia Activated Net. Prof." temporary;
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(422, GetMockResponseContent('Common422.txt'));
+
+ // [Given] a Connected Participation without Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, TempActivatedNetProf);
+
+ // [When] Post Participation Profile
+ asserterror ApiRequests.PostParticipationProfile(TempActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response422ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PostParticipationProfile500()
+ var
+ Participation: Record "Continia Participation";
+ TempActivatedNetProf: Record "Continia Activated Net. Prof." temporary;
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(500, GetMockResponseContent('Common500.txt'));
+
+ // [Given] a Connected Participation without Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, TempActivatedNetProf);
+
+ // [When] Post Participation Profile
+ asserterror ApiRequests.PostParticipationProfile(TempActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response500ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PatchParticipationProfile200()
+ var
+ Participation: Record "Continia Participation";
+ TempActivatedNetProf: Record "Continia Activated Net. Prof." temporary;
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ // [Given] a Connected Participation with Outbound Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf);
+ ActivatedNetProf."Profile Direction" := ActivatedNetProf."Profile Direction"::Outbound;
+ ActivatedNetProf.Modify();
+
+ ContiniaMockHttpHandler.AddResponse(200, GetMockResponseContent('ParticipationProfile200.txt'));
+
+ // [When] Patch Participation Profile
+ TempActivatedNetProf := ActivatedNetProf;
+ ApiRequests.PatchParticipationProfile(TempActivatedNetProf, Participation.Id);
+
+ // [Then] Make sure Activated Network Profile values returned correct
+ ConnectorLibrary.GetActivatedNetworkProfile(ActivatedNetProf);
+ Assert.AreEqual(ConnectorLibrary.ActiveNetworkProfileId(true), ActivatedNetProf.Id, IncorrectValueErr);
+ Assert.AreEqual(Enum::"Continia Profile Direction"::Both, ActivatedNetProf."Profile Direction", IncorrectValueErr);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PatchParticipationProfile400()
+ var
+ Participation: Record "Continia Participation";
+ TempActivatedNetProf: Record "Continia Activated Net. Prof." temporary;
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(400, GetMockResponseContent('Common400.txt'));
+
+ // [Given] a Connected Participation with Outbound Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf);
+ ActivatedNetProf."Profile Direction" := ActivatedNetProf."Profile Direction"::Outbound;
+ ActivatedNetProf.Modify();
+
+ // [When] Patch Participation Profile
+ TempActivatedNetProf := ActivatedNetProf;
+ asserterror ApiRequests.PatchParticipationProfile(TempActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response400ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PatchParticipationProfile401()
+ var
+ Participation: Record "Continia Participation";
+ TempActivatedNetProf: Record "Continia Activated Net. Prof." temporary;
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(401, GetMockResponseContent('Common401.txt'));
+
+ // [Given] a Connected Participation with Outbound Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf);
+ ActivatedNetProf."Profile Direction" := ActivatedNetProf."Profile Direction"::Outbound;
+ ActivatedNetProf.Modify();
+
+ // [When] Patch Participation Profile
+ TempActivatedNetProf := ActivatedNetProf;
+ asserterror ApiRequests.PatchParticipationProfile(TempActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response401ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PatchParticipationProfile404()
+ var
+ Participation: Record "Continia Participation";
+ TempActivatedNetProf: Record "Continia Activated Net. Prof." temporary;
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(404, GetMockResponseContent('Common404.txt'));
+
+ // [Given] a Connected Participation with Outbound Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf);
+ ActivatedNetProf."Profile Direction" := ActivatedNetProf."Profile Direction"::Outbound;
+ ActivatedNetProf.Modify();
+
+ // [When] Patch Participation Profile
+ TempActivatedNetProf := ActivatedNetProf;
+ asserterror ApiRequests.PatchParticipationProfile(TempActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response404ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PatchParticipationProfile422()
+ var
+ Participation: Record "Continia Participation";
+ TempActivatedNetProf: Record "Continia Activated Net. Prof." temporary;
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(422, GetMockResponseContent('Common422.txt'));
+
+ // [Given] a Connected Participation with Outbound Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf);
+ ActivatedNetProf."Profile Direction" := ActivatedNetProf."Profile Direction"::Outbound;
+ ActivatedNetProf.Modify();
+
+ // [When] Patch Participation Profile
+ TempActivatedNetProf := ActivatedNetProf;
+ asserterror ApiRequests.PatchParticipationProfile(TempActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response422ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure PatchParticipationProfile500()
+ var
+ Participation: Record "Continia Participation";
+ TempActivatedNetProf: Record "Continia Activated Net. Prof." temporary;
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(500, GetMockResponseContent('Common500.txt'));
+
+ // [Given] a Connected Participation with Outbound Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf);
+ ActivatedNetProf."Profile Direction" := ActivatedNetProf."Profile Direction"::Outbound;
+ ActivatedNetProf.Modify();
+
+ // [When] Patch Participation Profile
+ TempActivatedNetProf := ActivatedNetProf;
+ asserterror ApiRequests.PatchParticipationProfile(TempActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response500ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure DeleteParticipationProfile200()
+ var
+ Participation: Record "Continia Participation";
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(200, '');
+
+ // [Given] a Connected Participation with Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf);
+
+ // [When] Delete Participation Profile
+ ApiRequests.DeleteParticipationProfile(ActivatedNetProf, Participation.Id);
+
+ // [Then] Make sure Activated Network Profile values returned correct
+ ConnectorLibrary.GetActivatedNetworkProfile(ActivatedNetProf);
+ Assert.AreEqual(ConnectorLibrary.ActiveNetworkProfileId(true), ActivatedNetProf.Id, IncorrectValueErr);
+ Assert.AreNotEqual(0DT, ActivatedNetProf.Disabled, 'Network Profile should be disabled');
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure DeleteParticipationProfile400()
+ var
+ Participation: Record "Continia Participation";
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(400, GetMockResponseContent('Common400.txt'));
+
+ // [Given] a Connected Participation with Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf);
+
+ // [When] Delete Participation Profile
+ asserterror ApiRequests.DeleteParticipationProfile(ActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response400ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure DeleteParticipationProfile401()
+ var
+ Participation: Record "Continia Participation";
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(401, GetMockResponseContent('Common401.txt'));
+
+ // [Given] a Connected Participation with Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf);
+
+ // [When] Delete Participation Profile
+ asserterror ApiRequests.DeleteParticipationProfile(ActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response401ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure DeleteParticipationProfile404()
+ var
+ Participation: Record "Continia Participation";
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(404, GetMockResponseContent('Common404.txt'));
+
+ // [Given] a Connected Participation with Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf);
+
+ // [When] Delete Participation Profile
+ asserterror ApiRequests.DeleteParticipationProfile(ActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response404ErrorMessageLbl);
+ end;
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure DeleteParticipationProfile500()
+ var
+ Participation: Record "Continia Participation";
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ ApiRequests: Codeunit "Continia Api Requests";
+ begin
+ Initialize();
+ ContiniaMockHttpHandler.AddResponse(500, GetMockResponseContent('Common500.txt'));
+
+ // [Given] a Connected Participation with Activated Network Profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf);
+
+ // [When] Delete Participation Profile
+ asserterror ApiRequests.DeleteParticipationProfile(ActivatedNetProf, Participation.Id);
+
+ // [Then] make sure error is correct
+ Assert.ExpectedError(Response500ErrorMessageLbl);
+ end;
+
+ local procedure Initialize()
+ begin
+ LibraryPermission.SetOutsideO365Scope();
+ ConnectorLibrary.CleanParticipations();
+ ContiniaMockHttpHandler.ClearHandler();
+
+ if IsInitialized then
+ exit;
+
+ IsInitialized := true;
+ end;
+
+ local procedure GetMockResponseContent(FileName: Text) ContentText: Text
+ begin
+ ContentText := NavApp.GetResourceAsText(FileName, TextEncoding::UTF8);
+ end;
+
+ [HttpClientHandler]
+ internal procedure HttpClientHandler(Request: TestHttpRequestMessage; var Response: TestHttpResponseMessage): Boolean
+ begin
+ if ContiniaMockHttpHandler.HandleAuthorization(Request, Response) then
+ exit;
+
+ Response := ContiniaMockHttpHandler.GetResponse(Request);
+ end;
+
+ var
+ LibraryPermission: Codeunit "Library - Lower Permissions";
+ Assert: Codeunit Assert;
+ ConnectorLibrary: Codeunit "Continia Connector Library";
+ ContiniaMockHttpHandler: Codeunit "Continia Mock Http Handler";
+ IsInitialized: Boolean;
+ IncorrectValueErr: Label 'Wrong value';
+ Response400ErrorMessageLbl: Label 'The Continia Delivery Network API returned the following error: Error Code Bad Request - Missing parameter';
+ Response401ErrorMessageLbl: Label 'The Continia Delivery Network API returned the following error: Error Code Not Authenticated - Login failed';
+ Response404ErrorMessageLbl: Label 'The Continia Delivery Network API returned the following error: Error Code Not Found - Not Found';
+ Response409ErrorMessageLbl: Label 'The Continia Delivery Network API returned the following error: Error Code Conflict - Conflict';
+ Response422ErrorMessageLbl: Label 'The Continia Delivery Network API returned the following error: Error Code string - string';
+ Response500ErrorMessageLbl: Label 'The Continia Delivery Network API returned the following system error: Error Code Internal Server - Unhandled system error';
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaConnectorLibrary.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaConnectorLibrary.Codeunit.al
new file mode 100644
index 0000000000..7009832738
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaConnectorLibrary.Codeunit.al
@@ -0,0 +1,210 @@
+namespace Microsoft.EServices.EDocumentConnector.Continia;
+
+using Microsoft.eServices.EDocument;
+using Microsoft.eServices.EDocument.Integration;
+using System.Environment.Configuration;
+
+codeunit 148202 "Continia Connector Library"
+{
+ internal procedure ParticipationId(): Text
+ begin
+ exit(ParticipationIdLbl);
+ end;
+
+ internal procedure ParticipationId(AsGuid: Boolean): Guid
+ begin
+ exit(ConvertToGuid(ParticipationId()));
+ end;
+
+ internal procedure ActiveNetworkProfileId(): Text
+ begin
+ exit(ActivatedNetworkProfileIdLbl);
+ end;
+
+ internal procedure ActiveNetworkProfileId(AsGuid: Boolean): Guid
+ begin
+ exit(ConvertToGuid(ActiveNetworkProfileId()));
+ end;
+
+ internal procedure DefaultNetworkProfileId(): Text
+ begin
+ exit(DefaultNetworkProfileIdLbl);
+ end;
+
+ internal procedure DefaultNetworkProfileId(AsGuid: Boolean): Guid
+ begin
+ exit(ConvertToGuid(DefaultNetworkProfileId()));
+ end;
+
+ internal procedure NetworkProfileIdPeppolBis3Invoice(): Text
+ begin
+ exit(NetworkProfileIdPeppolBis3InvoiceLbl);
+ end;
+
+ internal procedure NetworkProfileIdPeppolBis3Invoice(AsGuid: Boolean): Guid
+ begin
+ exit(ConvertToGuid(NetworkProfileIdPeppolBis3Invoice()));
+ end;
+
+ local procedure ConvertToGuid(GuidText: Text) GuidValue: Guid
+ begin
+ Evaluate(GuidValue, GuidText);
+ end;
+
+ internal procedure InitiateClientCredentials()
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ begin
+ if not ConnectionSetup.Get() then
+ ConnectionSetup.Insert();
+
+ ConnectionSetup.SetClientId(LibraryRandom.RandText(20));
+ ConnectionSetup.SetClientSecret(LibraryRandom.RandText(20));
+ ConnectionSetup."Local Client Identifier" := CopyStr(LibraryRandom.RandText(MaxStrLen(ConnectionSetup."Local Client Identifier")), 1, MaxStrLen(ConnectionSetup."Local Client Identifier"));
+ ConnectionSetup."Subscription Status" := ConnectionSetup."Subscription Status"::Subscription;
+ ConnectionSetup.Modify();
+ end;
+
+ internal procedure ClearClientCredentials()
+ var
+ ConnectionSetup: Record "Continia Connection Setup";
+ begin
+ if ConnectionSetup.Get() then
+ ConnectionSetup.Delete();
+ end;
+
+ internal procedure PrepareParticipation(EDocumentService: Record "E-Document Service")
+ var
+ Participation: Record "Continia Participation";
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ begin
+ // Create a participation with profile
+ PrepareParticipation(Participation, ActivatedNetProf, EDocumentService)
+ end;
+
+ internal procedure PrepareParticipation(var Participation: Record "Continia Participation")
+ var
+ NetworkIdentifier: Record "Continia Network Identifier";
+ begin
+ NetworkIdentifier.Init();
+ NetworkIdentifier.Id := IdentifierTypeIdLbl;
+ NetworkIdentifier.Insert();
+
+ // Create a participation without profile
+ Participation.Init();
+ Participation.Network := Participation.Network::Peppol;
+ Participation."Identifier Type Id" := IdentifierTypeIdLbl;
+ Participation."Identifier Value" := IdentifierValueLbl;
+ if Participation.IsTemporary then begin
+ Participation.Insert();
+ exit;
+ end;
+ Participation.Id := ParticipationIdLbl;
+ Participation."Registration Status" := Participation."Registration Status"::Connected;
+ Participation.Insert();
+ end;
+
+ internal procedure PrepareParticipation(var Participation: Record "Continia Participation"; var ActivatedNetProf: Record "Continia Activated Net. Prof.")
+ var
+ LibraryEDocument: Codeunit "Library - E-Document";
+ EDocServiceCode: Code[20];
+ begin
+ // Create a participation with profile
+ PrepareParticipation(Participation);
+
+ CreateNetworkProfiles();
+
+ EDocServiceCode := LibraryEDocument.CreateService(Enum::"Service Integration"::Continia);
+ AddActivatedNetworkProfile(Participation, ActivatedNetProf, EDocServiceCode);
+ end;
+
+ internal procedure PrepareParticipation(var Participation: Record "Continia Participation"; var ActivatedNetProf: Record "Continia Activated Net. Prof."; EDocumentService: Record "E-Document Service")
+ begin
+ // Create a participation with profile
+ PrepareParticipation(Participation);
+
+ CreateNetworkProfiles();
+
+ AddActivatedNetworkProfile(Participation, ActivatedNetProf, EDocumentService.Code);
+ end;
+
+ internal procedure AddActivatedNetworkProfile(var Participation: Record "Continia Participation"; var ActivatedNetProf: Record "Continia Activated Net. Prof."; EDocServiceCode: Code[20])
+ begin
+ AddActivatedNetworkProfile(Participation, DefaultNetworkProfileIdLbl, ActivatedNetworkProfileIdLbl, ActivatedNetProf, EDocServiceCode);
+ end;
+
+ internal procedure AddActivatedNetworkProfile(var Participation: Record "Continia Participation"; NetworkPrifileId: Guid; ActivatedNetworkPrifileId: Guid; var ActivatedNetProf: Record "Continia Activated Net. Prof."; EDocServiceCode: Code[20])
+ begin
+ ActivatedNetProf.Init();
+ ActivatedNetProf.Network := Participation.Network;
+ ActivatedNetProf."Identifier Type Id" := Participation."Identifier Type Id";
+ ActivatedNetProf."Identifier Value" := Participation."Identifier Value";
+ ActivatedNetProf."Network Profile Id" := NetworkPrifileId;
+ ActivatedNetProf."Profile Direction" := ActivatedNetProf."Profile Direction"::Both;
+ ActivatedNetProf."E-Document Service Code" := EDocServiceCode;
+ if ActivatedNetProf.IsTemporary then begin
+ ActivatedNetProf.Insert();
+ exit;
+ end;
+ ActivatedNetProf.Id := ActivatedNetworkPrifileId;
+ ActivatedNetProf.Insert();
+ end;
+
+ local procedure CreateNetworkProfiles()
+ var
+ NetworkProfile: Record "Continia Network Profile";
+ begin
+ NetworkProfile.Init();
+ NetworkProfile.Id := DefaultNetworkProfileIdLbl;
+ NetworkProfile.Insert();
+
+ NetworkProfile.Init();
+ NetworkProfile.Id := NetworkProfileIdPeppolBis3InvoiceLbl;
+ NetworkProfile.Insert();
+ end;
+
+ [TryFunction]
+ internal procedure GetParticipation(var Participation: Record "Continia Participation")
+ begin
+ Participation.Get(Participation.Network::Peppol, IdentifierTypeIdLbl, IdentifierValueLbl);
+ end;
+
+ [TryFunction]
+ internal procedure GetActivatedNetworkProfile(var ActivatedNetProf: Record "Continia Activated Net. Prof.")
+ begin
+ ActivatedNetProf.Get(ActivatedNetProf.Network::Peppol, IdentifierTypeIdLbl, IdentifierValueLbl, DefaultNetworkProfileIdLbl);
+ end;
+
+ [TryFunction]
+ internal procedure GetActivatedNetworkProfile(NetworkProfileId: Guid; var ActivatedNetProf: Record "Continia Activated Net. Prof.")
+ begin
+ ActivatedNetProf.Get(ActivatedNetProf.Network::Peppol, IdentifierTypeIdLbl, IdentifierValueLbl, NetworkProfileId);
+ end;
+
+ internal procedure CleanParticipations()
+ var
+ Participation: Record "Continia Participation";
+ NetworkIdentifier: Record "Continia Network Identifier";
+ NetworkProfile: Record "Continia Network Profile";
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ begin
+ if not Participation.IsEmpty then
+ Participation.DeleteAll();
+ if not NetworkIdentifier.IsEmpty then
+ NetworkIdentifier.DeleteAll();
+ if not NetworkProfile.IsEmpty then
+ NetworkProfile.DeleteAll();
+ if not ActivatedNetProf.IsEmpty then
+ ActivatedNetProf.DeleteAll();
+ end;
+
+ var
+ LibraryRandom: Codeunit "Library - Random";
+ ParticipationIdLbl: Label '0de4aedc-f84a-41bc-b511-387aaf96263e', Locked = true;
+ ActivatedNetworkProfileIdLbl: Label '1f4111a0-cd49-45e1-9f1e-ed14e71e3438', Locked = true;
+ DefaultNetworkProfileIdLbl: Label 'dd2af6bc-a05a-4fd4-a577-0216a56bea84', Locked = true; //Peppol Credit Note profile used as default
+ NetworkProfileIdPeppolBis3InvoiceLbl: Label '8f9ab973-c6f0-4dfb-9936-19b56c5a588b', Locked = true;
+ IdentifierTypeIdLbl: Label '568c29e7-c2c8-49bb-b135-9199d5b791d1', Locked = true;
+ IdentifierValueLbl: Label '111222333', Locked = true;
+
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaDocIntegrTests.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaDocIntegrTests.Codeunit.al
new file mode 100644
index 0000000000..41aec63303
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaDocIntegrTests.Codeunit.al
@@ -0,0 +1,1216 @@
+namespace Microsoft.EServices.EDocumentConnector.Continia;
+using Microsoft.EServices.EDocumentConnector.Continia;
+using Microsoft.eServices.EDocument;
+using Microsoft.Sales.Customer;
+using Microsoft.Inventory.Item;
+using Microsoft.Foundation.UOM;
+using Microsoft.Inventory.Item.Catalog;
+using Microsoft.Purchases.Vendor;
+using Microsoft.Foundation.Company;
+using System.TestLibraries.Environment;
+using Microsoft.Purchases.Document;
+using System.Threading;
+using Microsoft.eServices.EDocument.Integration;
+codeunit 148203 "Continia Doc. Integr. Tests"
+{
+ Subtype = Test;
+ TestHttpRequestPolicy = AllowOutboundFromHandler;
+
+ ///
+ /// SubmitDocument - Tests successful document submission.
+ /// This test verifies that a document is created, assigned a valid Document ID, and transitions through
+ /// the expected statuses ("In Progress" -> "Processed") as the Continia API processes it. Additionally,
+ /// it validates that the e-Document logs contain the correct status entries.
+ ///
+
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure SubmitDocument()
+ var
+ EDocument: Record "E-Document";
+ EDocLogList: List of [Enum "E-Document Service Status"];
+ begin
+ // Steps:
+ // Pending response -> Sent
+ Initialize();
+
+ // [Given] Team Member
+ LibraryPermission.SetTeamMember();
+
+ // [When] Posting invoice and EDocument is created
+ LibraryEDocument.PostInvoice(Customer);
+ EDocument.FindLast();
+
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ StrSubstNo(DocumentUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('SubmitDocument200.txt'));
+ LibraryEDocument.RunEDocumentJobQueue(EDocument);
+
+ // [When] EDocument is fetched after running Continia SubmitDocument
+ EDocument.FindLast();
+
+ // [Then] Document Id has been correctly set on E-Document, parsed from Integration response
+ Assert.AreEqual(MockDocumentId(), EDocument."Continia Document Id", 'Continia integration failed to set Document Id on E-Document');
+ // [Then] E-Document is "In Progress"
+ Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress');
+
+ // [Then] eDocument Service Status has "Pending Response" and has correct logs
+ Clear(EDocLogList);
+ EDocLogList.Add(Enum::"E-Document Service Status"::Exported);
+ EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::"In Progress", Enum::"E-Document Service Status"::"Pending Response", EDocLogList, '', '');
+
+ // [WHEN] Executing Get Response successfully
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.TechnicalResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('TechnicalResponse200-Success.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.DocumentActionUrl(MockDocumentId()),
+ 200);
+ RunGetResponseJob();
+
+ // [When] EDocument is fetched after running Continia GetResponse
+ EDocument.FindLast();
+
+ // [Then] E-Document is considered processed
+ Assert.AreEqual(Enum::"E-Document Status"::Processed, EDocument.Status, 'E-Document should be set to processed');
+
+ // [Then] eDocument Service Status has Sent and has correct logs
+ 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"::Sent);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Sent, EDocLogList, '', '');
+ end;
+
+ ///
+ /// SubmitDocumentCdnServiceDown - Tests error handling when the Continia service is down.
+ /// This test ensures that when the Continia API returns a 500 error, the document moves to an "Error"
+ /// status. It verifies that the Document ID is not set and that the error is logged correctly.
+ ///
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure SubmitDocumentCdnServiceDown()
+ var
+ EDocument: Record "E-Document";
+ EDocLogList: List of [Enum "E-Document Service Status"];
+ begin
+ Initialize();
+
+ // [Given] Team member
+ LibraryPermission.SetTeamMember();
+
+ // [When] Posting invoice and EDocument is created
+ LibraryEDocument.PostInvoice(Customer);
+ EDocument.FindLast();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ StrSubstNo(DocumentUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 500,
+ GetMockResponseContent('Common500.txt'));
+ LibraryEDocument.RunEDocumentJobQueue(EDocument);
+
+ // [When] EDocument is fetched after running Continia SubmitDocument
+ EDocument.FindLast();
+
+ // [Then] E-Document is in Error
+ Assert.AreEqual(Enum::"E-Document Status"::Error, EDocument.Status, 'E-Document should be set to error state when service is down.');
+ // [Then] Document Id has not been set
+ Assert.IsTrue(IsNullGuid(EDocument."Continia Document Id"), 'Document Id on E-Document should not be set.');
+
+ // [Then] eDocument Service Status has "Sending Error" and has correct logs
+ Clear(EDocLogList);
+ EDocLogList.Add(Enum::"E-Document Service Status"::Exported);
+ EDocLogList.Add(Enum::"E-Document Service Status"::"Sending Error");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Error, Enum::"E-Document Service Status"::"Sending Error", EDocLogList, 'Error', 'The Continia Delivery Network API returned the following system error: Error Code Internal Server - Unhandled system error');
+ end;
+
+ ///
+ /// SubmitDocument_ResponseServerDown_Sent - Tests response retrieval during server down scenario.
+ /// This test simulates a scenario where the Continia API is temporarily down while retrieving responses.
+ /// It verifies that the document status remains "In Progress" and is successfully updated to "Sent" once
+ /// the service is back online.
+ ///
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure SubmitDocument_ResponseServerDown_Sent()
+ var
+ EDocument: Record "E-Document";
+ EDocLogList: List of [Enum "E-Document Service Status"];
+ begin
+ // Steps:
+ // Pending response -> Pending response -> Pending Response (ResponseServerDown) -> Sent
+ Initialize();
+
+ // [Given] Team Member
+ LibraryPermission.SetTeamMember();
+
+ // [When] Posting invoice and EDocument is created
+ LibraryEDocument.PostInvoice(Customer);
+ EDocument.FindLast();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ StrSubstNo(DocumentUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('SubmitDocument200.txt'));
+ LibraryEDocument.RunEDocumentJobQueue(EDocument);
+
+ // [When] EDocument is fetched after running Continia SubmitDocument
+ EDocument.FindLast();
+
+ // [Then] Document Id has been correctly set on E-Document, parsed from Integration response
+ Assert.AreEqual(MockDocumentId(), EDocument."Continia Document Id", 'Continia integration failed to set Document Id on E-Document');
+
+ // [Then] E-Document is "In Progress"
+ Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress');
+
+ // [Then] eDocument Service Status has "Pending Response" and has correct logs
+ Clear(EDocLogList);
+ EDocLogList.Add(Enum::"E-Document Service Status"::Exported);
+ EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::"In Progress", Enum::"E-Document Service Status"::"Pending Response", EDocLogList, '', '');
+
+ // [When] Service is down
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.TechnicalResponseUrl(MockDocumentId()),
+ 500,
+ GetMockResponseContent('Common500.txt'));
+ RunGetResponseJob();
+
+ // [When] EDocument is fetched after running Continia GetResponse
+ EDocument.FindLast();
+
+ // [Then] E-Document is "In Progress"
+ Assert.AreEqual(EDocument.Status::"In Progress", EDocument.Status, 'Continia integration failed to set Document Status on E-Document');
+
+ // [Then] eDocument Service Status has "Pending Response" and has correct logs
+ 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");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::"In Progress", Enum::"E-Document Service Status"::"Pending Response", EDocLogList, '', '');
+
+ // [When] Service is up again
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.TechnicalResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('TechnicalResponse200-Success.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.DocumentActionUrl(MockDocumentId()),
+ 200);
+ RunGetResponseJob();
+
+ // [When] EDocument is fetched after running Continia GetResponse
+ EDocument.FindLast();
+
+ // [Then] E-Document is Processed
+ Assert.AreEqual(EDocument.Status::Processed, EDocument.Status, 'Continia integration failed to set Document Status on E-Document');
+
+ // [Then] eDocument Service Status has Sent and has correct logs
+ 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"::Sent);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Sent, EDocLogList, '', '');
+ end;
+
+ ///
+ /// SubmitDocument_Pending_Sent - Tests handling of pending responses before successful document sending.
+ /// This test checks that the document moves to "In Progress" and remains in this status until the API
+ /// confirms it is processed, transitioning it to "Sent."
+ ///
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure SubmitDocument_Pending_Sent()
+ var
+ EDocument: Record "E-Document";
+ EDocLogList: List of [Enum "E-Document Service Status"];
+ begin
+ // Steps:
+ // Pending response -> Pending response -> Sent
+ Initialize();
+
+ // [Given] Team Member
+ LibraryPermission.SetTeamMember();
+
+ // [When] Posting invoice and EDocument is created
+ LibraryEDocument.PostInvoice(Customer);
+ EDocument.FindLast();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ StrSubstNo(DocumentUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('SubmitDocument200.txt'));
+ LibraryEDocument.RunEDocumentJobQueue(EDocument);
+
+ // [When] EDocument is fetched after running Continia SubmitDocument
+ EDocument.FindLast();
+
+ // [Then] Document Id has been correctly set on E-Document, parsed from Integration response
+ Assert.AreEqual(MockDocumentId(), EDocument."Continia Document Id", 'Continia integration failed to set Document Id on E-Document');
+
+ // [Then] E-Document is "In Progress"
+ Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress');
+
+ // [Then] eDocument Service Status has "Pending Response" and has correct logs
+ Clear(EDocLogList);
+ EDocLogList.Add(Enum::"E-Document Service Status"::Exported);
+ EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::"In Progress", Enum::"E-Document Service Status"::"Pending Response", EDocLogList, '', '');
+
+ // [When] Executing Get Response successfully (pending)
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.TechnicalResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('TechnicalResponse200-Pending.txt'));
+ RunGetResponseJob();
+
+ // [When] EDocument is fetched after running Continia GetResponse
+ EDocument.FindLast();
+
+ // [Then] E-Document is "In Progress"
+ Assert.AreEqual(EDocument.Status::"In Progress", EDocument.Status, 'Continia integration failed to set Document Status on E-Document');
+
+ // [Then] eDocument Service Status has "Pending Response" and has correct logs
+ 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");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::"In Progress", Enum::"E-Document Service Status"::"Pending Response", EDocLogList, '', '');
+
+ // [When] Executing Get Response successfully (Success)
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.TechnicalResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('TechnicalResponse200-Success.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.DocumentActionUrl(MockDocumentId()),
+ 200);
+ RunGetResponseJob();
+
+ // [When] EDocument is fetched after running Continia GetResponse
+ EDocument.FindLast();
+
+ // [Then] E-Document is Processed
+ Assert.AreEqual(EDocument.Status::Processed, EDocument.Status, 'Continia integration failed to set Document Status on E-Document');
+
+ // [Then] eDocument Service Status has Sent and has correct logs
+ 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"::Sent);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Sent, EDocLogList, '', '');
+ end;
+
+ ///
+ /// SubmitDocument_Error_Sent - Tests handling of submission errors, like unregistered recipients.
+ /// This test ensures that when the API response indicates an error (e.g., recipient not registered), the
+ /// document moves to "Error" status, and the error is properly logged. It also verifies successful resubmission
+ /// after the issue is resolved.
+ ///
+ [Test]
+ [HandlerFunctions('EDocServicesPageHandler,HttpClientHandler')]
+ procedure SubmitDocument_Error_Sent()
+ var
+ EDocument: Record "E-Document";
+ EDocumentPage: TestPage "E-Document";
+ EDocLogList: List of [Enum "E-Document Service Status"];
+ begin
+ // Steps:
+ // Pending response -> Error -> Pending response -> Sent
+ Initialize();
+
+ // [Given] Team Member
+ LibraryPermission.SetTeamMember();
+
+ // [When] Posting invoice and EDocument is created
+ LibraryEDocument.PostInvoice(Customer);
+ EDocument.FindLast();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ StrSubstNo(DocumentUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('SubmitDocument200.txt'));
+ LibraryEDocument.RunEDocumentJobQueue(EDocument);
+
+ // [When] EDocument is fetched after running Continia SubmitDocument
+ EDocument.FindLast();
+
+ // [Then] Document Id has been correctly set on E-Document, parsed from Integration response
+ Assert.AreEqual(MockDocumentId(), EDocument."Continia Document Id", 'Continia integration failed to set Document Id on E-Document');
+
+ // [Then] E-Document is "In Progress"
+ Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress');
+
+ // [Then] eDocument Service Status has "Pending Response" and has correct logs
+ Clear(EDocLogList);
+ EDocLogList.Add(Enum::"E-Document Service Status"::Exported);
+ EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::"In Progress", Enum::"E-Document Service Status"::"Pending Response", EDocLogList, '', '');
+
+ // [When] Executing Get Response successfully (error)
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.TechnicalResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('TechnicalResponse200-Error.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.DocumentActionUrl(MockDocumentId()),
+ 200);
+ RunGetResponseJob();
+
+ // [When] EDocument is fetched after running Continia GetResponse
+ EDocument.FindLast();
+
+ // [Then] E-Document is Error
+ Assert.AreEqual(EDocument.Status::Error, EDocument.Status, 'Continia integration failed to set Document Status on E-Document');
+
+ // [Then] eDocument Service Status has "Sending Error" and has correct logs
+ 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");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Error, Enum::"E-Document Service Status"::"Sending Error", EDocLogList, 'Error', 'ReceiverNotRegistered - The recipient of the document is not registered to receive this type of document.');
+
+ // Then user manually send
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ StrSubstNo(DocumentUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('SubmitDocument200.txt'));
+ EDocument.FindLast();
+
+ // [THEN] Open E-Document page and resend
+ EDocumentPage.OpenView();
+ EDocumentPage.GoToRecord(EDocument);
+ EDocumentPage.Send_Promoted.Invoke();
+ // EDocServicesPageHandler
+ EDocumentPage.Close();
+
+ // [When] EDocument is fetched after running Continia Send Document
+ EDocument.FindLast();
+
+ // [Then] E-Document is "In Progress"
+ Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress');
+
+ // [Then] eDocument Service Status has "Pending Response" and has correct logs
+ 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");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::"In Progress", Enum::"E-Document Service Status"::"Pending Response", EDocLogList, '', '');
+
+ // [When] Executing Get Response successfully (Success)
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.TechnicalResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('TechnicalResponse200-Success.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.DocumentActionUrl(MockDocumentId()),
+ 200);
+ RunGetResponseJob();
+
+ // [When] EDocument is fetched after running Continia GetResponse
+ EDocument.FindLast();
+
+ // [Then] E-Document is Processed
+ Assert.AreEqual(EDocument.Status::Processed, EDocument.Status, 'Continia integration failed to set Document Status on E-Document');
+
+ // [Then] eDocument Service Status has Sent and has correct logs
+ 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"::Sent);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Sent, EDocLogList, '', '');
+ end;
+
+ ///
+ /// SubmitDocument_NoApproval - Tests handling when no approval is returned for document processing.
+ /// This test ensures that if no approval is returned, the document remains in the "Sent" state
+ /// without transitioning to "Approved" or other statuses. It validates that the document stays
+ /// in "Sent" when approval is not received.
+ ///
+ [Test]
+ [HandlerFunctions('EDocServicesPageHandler,HttpClientHandler')]
+ procedure SubmitDocument_NoApproval()
+ var
+ EDocument: Record "E-Document";
+ EDocumentPage: TestPage "E-Document";
+ EDocLogList: List of [Enum "E-Document Service Status"];
+ begin
+ // Steps:
+ // Pending response -> Sent -> Sent (No Approval)
+ Initialize();
+
+ // [Given] Team Member
+ LibraryPermission.SetTeamMember();
+
+ // [When] Posting invoice and EDocument is created
+ LibraryEDocument.PostInvoice(Customer);
+ EDocument.FindLast();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ StrSubstNo(DocumentUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('SubmitDocument200.txt'));
+ LibraryEDocument.RunEDocumentJobQueue(EDocument);
+
+ // [When] EDocument is fetched after running Continia SubmitDocument
+ EDocument.FindLast();
+
+ // [Then] Document Id has been correctly set on E-Document, parsed from Integration response
+ Assert.AreEqual(MockDocumentId(), EDocument."Continia Document Id", 'Continia integration failed to set Document Id on E-Document');
+ // [Then] E-Document is "In Progress"
+ Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress');
+
+ // [Then] eDocument Service Status has "Pending Response" and has correct logs
+ Clear(EDocLogList);
+ EDocLogList.Add(Enum::"E-Document Service Status"::Exported);
+ EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::"In Progress", Enum::"E-Document Service Status"::"Pending Response", EDocLogList, '', '');
+
+ // [WHEN] Executing Get Response successfully
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.TechnicalResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('TechnicalResponse200-Success.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.DocumentActionUrl(MockDocumentId()),
+ 200);
+ RunGetResponseJob();
+
+ // [When] EDocument is fetched after running Continia GetResponse
+ EDocument.FindLast();
+
+ // [Then] E-Document is considered processed
+ Assert.AreEqual(Enum::"E-Document Status"::Processed, EDocument.Status, 'E-Document should be set to processed');
+
+ // [Then] eDocument Service Status has Sent and has correct logs
+ 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"::Sent);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Sent, EDocLogList, '', '');
+
+
+ // [Then] Open E-Document page and Get Approval
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.BusinessResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('BusinessResponse200-noresponse.txt'));
+ EDocumentPage.OpenView();
+ EDocumentPage.GoToRecord(EDocument);
+ EDocumentPage.GetApproval.Invoke();
+ // EDocServicesPageHandler
+ EDocumentPage.Close();
+
+ // [When] EDocument is fetched after running Continia Send Document
+ EDocument.FindLast();
+
+ // [Then] E-Document is considered processed
+ Assert.AreEqual(Enum::"E-Document Status"::Processed, EDocument.Status, 'E-Document should be set to processed');
+
+ // [Then] eDocument Service Status has Sent and has correct logs
+ 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"::Sent);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Sent, EDocLogList, '', '');
+ end;
+
+ ///
+ /// SubmitDocument_StatusInfo - Tests handling of responses without approval.
+ /// This test ensures that if responses are received without any approval indication,
+ /// the document is treated as though no approval has been received and remains in the "Sent" state.
+ /// It validates that the system does not move the document to an "Approved" status
+ /// without an explicit approval response.
+ ///
+ [Test]
+ [HandlerFunctions('EDocServicesPageHandler,HttpClientHandler')]
+ procedure SubmitDocument_StatusInfo()
+ var
+ EDocument: Record "E-Document";
+ EDocumentPage: TestPage "E-Document";
+ EDocLogList: List of [Enum "E-Document Service Status"];
+ begin
+ // Steps:
+ // Pending response -> Sent -> Sent (StatusInfo)
+ Initialize();
+
+ // [Given] Team Member
+ LibraryPermission.SetTeamMember();
+
+ // [When] Posting invoice and EDocument is created
+ LibraryEDocument.PostInvoice(Customer);
+ EDocument.FindLast();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ StrSubstNo(DocumentUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('SubmitDocument200.txt'));
+ LibraryEDocument.RunEDocumentJobQueue(EDocument);
+
+ // [When] EDocument is fetched after running Continia SubmitDocument
+ EDocument.FindLast();
+
+ // [Then] Document Id has been correctly set on E-Document, parsed from Integration response
+ Assert.AreEqual(MockDocumentId(), EDocument."Continia Document Id", 'Continia integration failed to set Document Id on E-Document');
+ // [Then] E-Document is "In Progress"
+ Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress');
+
+ // [Then] eDocument Service Status has "Pending Response" and has correct logs
+ Clear(EDocLogList);
+ EDocLogList.Add(Enum::"E-Document Service Status"::Exported);
+ EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::"In Progress", Enum::"E-Document Service Status"::"Pending Response", EDocLogList, '', '');
+
+ // [WHEN] Executing Get Response successfully
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.TechnicalResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('TechnicalResponse200-Success.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.DocumentActionUrl(MockDocumentId()),
+ 200);
+ RunGetResponseJob();
+
+ // [When] EDocument is fetched after running Continia GetResponse
+ EDocument.FindLast();
+
+ // [Then] E-Document is considered processed
+ Assert.AreEqual(Enum::"E-Document Status"::Processed, EDocument.Status, 'E-Document should be set to processed');
+
+ // [Then] eDocument Service Status has Sent and has correct logs
+ 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"::Sent);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Sent, EDocLogList, '', '');
+
+
+ // [Then] Open E-Document page and Get Approval
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.BusinessResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('BusinessResponse200-multiple-statusinfo.txt'));
+ EDocumentPage.OpenView();
+ EDocumentPage.GoToRecord(EDocument);
+ EDocumentPage.GetApproval.Invoke();
+ // EDocServicesPageHandler
+ EDocumentPage.Close();
+
+ // [When] EDocument is fetched after running Continia Send Document
+ EDocument.FindLast();
+
+ // [Then] E-Document is considered processed
+ Assert.AreEqual(Enum::"E-Document Status"::Processed, EDocument.Status, 'E-Document should be set to processed');
+
+ // [Then] eDocument Service Status has Sent and has correct logs
+ 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"::Sent);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Sent, EDocLogList, '', '');
+ end;
+
+ ///
+ /// SubmitDocument_Approved - Tests document status update upon approval.
+ /// This test ensures that when an approved response is received, the document status is updated
+ /// from "Sent" to "Approved," validating proper handling and logging of approvals.
+ ///
+ [Test]
+ [HandlerFunctions('EDocServicesPageHandler,HttpClientHandler')]
+ procedure SubmitDocument_Approved()
+ var
+ EDocument: Record "E-Document";
+ EDocumentPage: TestPage "E-Document";
+ EDocLogList: List of [Enum "E-Document Service Status"];
+ begin
+ // Steps:
+ // Pending response -> Sent -> Approved
+ Initialize();
+
+ // [Given] Team Member
+ LibraryPermission.SetTeamMember();
+
+ // [When] Posting invoice and EDocument is created
+ LibraryEDocument.PostInvoice(Customer);
+ EDocument.FindLast();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ StrSubstNo(DocumentUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('SubmitDocument200.txt'));
+ LibraryEDocument.RunEDocumentJobQueue(EDocument);
+
+ // [When] EDocument is fetched after running Continia SubmitDocument
+ EDocument.FindLast();
+
+ // [Then] Document Id has been correctly set on E-Document, parsed from Integration response
+ Assert.AreEqual(MockDocumentId(), EDocument."Continia Document Id", 'Continia integration failed to set Document Id on E-Document');
+ // [Then] E-Document is "In Progress"
+ Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress');
+
+ // [Then] eDocument Service Status has "Pending Response" and has correct logs
+ Clear(EDocLogList);
+ EDocLogList.Add(Enum::"E-Document Service Status"::Exported);
+ EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::"In Progress", Enum::"E-Document Service Status"::"Pending Response", EDocLogList, '', '');
+
+ // [WHEN] Executing Get Response successfully
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.TechnicalResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('TechnicalResponse200-Success.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.DocumentActionUrl(MockDocumentId()),
+ 200);
+ RunGetResponseJob();
+
+ // [When] EDocument is fetched after running Continia GetResponse
+ EDocument.FindLast();
+
+ // [Then] E-Document is considered processed
+ Assert.AreEqual(Enum::"E-Document Status"::Processed, EDocument.Status, 'E-Document should be set to processed');
+
+ // [Then] eDocument Service Status has Sent and has correct logs
+ 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"::Sent);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Sent, EDocLogList, '', '');
+
+ // [Then] Open E-Document page and Get Approval
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.BusinessResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('BusinessResponse200-multiple-accepted.txt'));
+ EDocumentPage.OpenView();
+ EDocumentPage.GoToRecord(EDocument);
+ EDocumentPage.GetApproval.Invoke();
+ // EDocServicesPageHandler
+ EDocumentPage.Close();
+
+ // [When] EDocument is fetched after running Continia Send Document
+ EDocument.FindLast();
+
+ // [Then] E-Document is considered processed
+ Assert.AreEqual(Enum::"E-Document Status"::Processed, EDocument.Status, 'E-Document should be set to processed');
+
+ // [Then] eDocument Service Status has Approved and has correct logs
+ 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"::Sent);
+ EDocLogList.Add(Enum::"E-Document Service Status"::Approved);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Approved, EDocLogList, '', '');
+ end;
+
+ ///
+ /// SubmitDocument_Rejected - Tests error handling for rejected documents with rejection reasons.
+ /// This test validates that when the document is rejected by the API, it moves to an "Error" status
+ /// with the rejection reason logged, ensuring accurate status updates for failed submissions.
+ ///
+ [Test]
+ [HandlerFunctions('EDocServicesPageHandler,HttpClientHandler')]
+ procedure SubmitDocument_Rejected()
+ var
+ EDocument: Record "E-Document";
+ EDocumentPage: TestPage "E-Document";
+ EDocLogList: List of [Enum "E-Document Service Status"];
+ begin
+ // Steps:
+ // Pending response -> Sent -> Error (Rejected)
+ Initialize();
+
+ // [Given] Team Member
+ LibraryPermission.SetTeamMember();
+
+ // [When] Posting invoice and EDocument is created
+ LibraryEDocument.PostInvoice(Customer);
+ EDocument.FindLast();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ StrSubstNo(DocumentUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('SubmitDocument200.txt'));
+ LibraryEDocument.RunEDocumentJobQueue(EDocument);
+
+ // [When] EDocument is fetched after running Continia SubmitDocument
+ EDocument.FindLast();
+
+ // [Then] Document Id has been correctly set on E-Document, parsed from Integration response
+ Assert.AreEqual(MockDocumentId(), EDocument."Continia Document Id", 'Continia integration failed to set Document Id on E-Document');
+ // [Then] E-Document is "In Progress"
+ Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress');
+
+ // [Then] eDocument Service Status has "Pending Response" and has correct logs
+ Clear(EDocLogList);
+ EDocLogList.Add(Enum::"E-Document Service Status"::Exported);
+ EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::"In Progress", Enum::"E-Document Service Status"::"Pending Response", EDocLogList, '', '');
+
+ // [WHEN] Executing Get Response successfully
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.TechnicalResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('TechnicalResponse200-Success.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.DocumentActionUrl(MockDocumentId()),
+ 200);
+ RunGetResponseJob();
+
+ // [When] EDocument is fetched after running Continia GetResponse
+ EDocument.FindLast();
+
+ // [Then] E-Document is considered processed
+ Assert.AreEqual(Enum::"E-Document Status"::Processed, EDocument.Status, 'E-Document should be set to processed');
+
+ // [Then] eDocument Service Status has Sent and has correct logs
+ 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"::Sent);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Sent, EDocLogList, '', '');
+
+
+ // [Then] Open E-Document page and Get Approval
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.BusinessResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('BusinessResponse200-multiple-rejected.txt'));
+ EDocumentPage.OpenView();
+ EDocumentPage.GoToRecord(EDocument);
+ EDocumentPage.GetApproval.Invoke();
+ // EDocServicesPageHandler
+ EDocumentPage.Close();
+
+ // [When] EDocument is fetched after running Continia Send Document
+ EDocument.FindLast();
+
+ // [Then] E-Document is considered processed
+ Assert.AreEqual(Enum::"E-Document Status"::Processed, EDocument.Status, 'E-Document should be set to processed');
+
+ // [Then] eDocument Service Status is Processed and has correct logs
+ 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"::Sent);
+ EDocLogList.Add(Enum::"E-Document Service Status"::Rejected);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Rejected, EDocLogList, 'Warning', 'Reason: PRI - Prices incorrect');
+ end;
+
+ ///
+ /// SubmitDocument_GetApprovalServiceDown - Tests handling of approval retrieval when the service is down.
+ /// This test simulates a scenario where the approval API is temporarily down, verifying that the document
+ /// can be processed as "Sent" and retries approval retrieval once the service is available.
+ ///
+ [Test]
+ [HandlerFunctions('EDocServicesPageHandler,HttpClientHandler')]
+ procedure SubmitDocument_GetApprovalServiceDown()
+ var
+ EDocument: Record "E-Document";
+ EDocumentPage: TestPage "E-Document";
+ EDocLogList: List of [Enum "E-Document Service Status"];
+ begin
+ // Steps:
+ // Pending response -> Sent -> Sent (Service Down)
+ Initialize();
+
+ // [Given] Team Member
+ LibraryPermission.SetTeamMember();
+
+ // [When] Posting invoice and EDocument is created
+ LibraryEDocument.PostInvoice(Customer);
+ EDocument.FindLast();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ StrSubstNo(DocumentUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('SubmitDocument200.txt'));
+ LibraryEDocument.RunEDocumentJobQueue(EDocument);
+
+ // [When] EDocument is fetched after running Continia SubmitDocument
+ EDocument.FindLast();
+
+ // [Then] Document Id has been correctly set on E-Document, parsed from Integration response
+ Assert.AreEqual(MockDocumentId(), EDocument."Continia Document Id", 'Continia integration failed to set Document Id on E-Document');
+ // [Then] E-Document is "In Progress"
+ Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress');
+
+ // [Then] eDocument Service Status has "Pending Response" and has correct logs
+ Clear(EDocLogList);
+ EDocLogList.Add(Enum::"E-Document Service Status"::Exported);
+ EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response");
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::"In Progress", Enum::"E-Document Service Status"::"Pending Response", EDocLogList, '', '');
+
+ // [WHEN] Executing Get Response successfully
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.TechnicalResponseUrl(MockDocumentId()),
+ 200,
+ GetMockResponseContent('TechnicalResponse200-Success.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.DocumentActionUrl(MockDocumentId()),
+ 200);
+ RunGetResponseJob();
+
+ // [When] EDocument is fetched after running Continia GetResponse
+ EDocument.FindLast();
+
+ // [Then] E-Document is considered processed
+ Assert.AreEqual(Enum::"E-Document Status"::Processed, EDocument.Status, 'E-Document should be set to processed');
+
+ // [Then] eDocument Service Status has Sent and has correct logs
+ 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"::Sent);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Sent, EDocLogList, '', '');
+
+
+ // [Then] Open E-Document page and Get Approval
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.BusinessResponseUrl(MockDocumentId()),
+ 500,
+ GetMockResponseContent('Common500.txt'));
+ EDocumentPage.OpenView();
+ EDocumentPage.GoToRecord(EDocument);
+ EDocumentPage.GetApproval.Invoke();
+ // EDocServicesPageHandler
+ EDocumentPage.Close();
+
+ // [When] EDocument is fetched after running Continia Send Document
+ EDocument.FindLast();
+
+ // [Then] E-Document is considered Processed
+ Assert.AreEqual(Enum::"E-Document Status"::Processed, EDocument.Status, 'E-Document should be set to processed');
+
+ // [Then] eDocument Service Status has Sent and has correct logs
+ 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"::Sent);
+ TestEDocumentPage(EDocument, Enum::"E-Document Status"::Processed, Enum::"E-Document Service Status"::Sent, EDocLogList, '', '');
+ end;
+
+ ///
+ /// ReceiveDocuments_SingleDocument - Tests receiving a single document and creating a Purchase Invoice.
+ /// This test verifies that a single document is correctly received from the API and that a Purchase
+ /// Invoice is created, linking the document to the correct vendor.
+ ///
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure ReceiveDocuments_SingleDocument()
+ var
+ EDocument: Record "E-Document";
+ PurchaseHeader: Record "Purchase Header";
+ EDocServicePage: TestPage "E-Document Service";
+ begin
+ Initialize();
+ // [Given] Empty E-Document table
+ EDocument.DeleteAll();
+
+ // [Given] Auto import job. Open and close E-Doc page creates auto import job due to setting
+ EDocServicePage.OpenView();
+ EDocServicePage.GoToRecord(EDocumentService);
+ EDocServicePage."Resolve Unit Of Measure".SetValue(true);
+ EDocServicePage."Lookup Item Reference".SetValue(true);
+ EDocServicePage."Lookup Item GTIN".SetValue(false);
+ EDocServicePage."Lookup Account Mapping".SetValue(false);
+ EDocServicePage."Validate Line Discount".SetValue(false);
+ EDocServicePage.Close();
+
+ // [When] Manually fire job queue job to import Documents
+ if EDocument.FindLast() then
+ EDocument.SetFilter("Entry No", '>%1', EDocument."Entry No");
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ StrSubstNo(DocumentUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('ReceiveDocuments.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ StrSubstNo(DownloadUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('ReceivePeppolInvoiceDocument200.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.DocumentActionUrl('65DD7456-7A49-4382-9F76-1211FA8AD0BF'),
+ 200);
+
+ LibraryEDocument.RunImportJob();
+
+ // Assert that we have Purchase Invoice created
+#pragma warning disable AA0210
+ EDocument.SetRange("Document Type", EDocument."Document Type"::"Purchase Invoice");
+ EDocument.SetRange("Bill-to/Pay-to No.", Vendor."No.");
+#pragma warning restore AA0210
+ EDocument.FindLast();
+ PurchaseHeader.Get(EDocument."Document Record ID");
+ Assert.AreEqual(Vendor."No.", PurchaseHeader."Buy-from Vendor No.", 'Wrong Vendor');
+ end;
+
+ ///
+ /// ReceiveDocuments_Peppol_MultipleEdocServices - Tests handling documents from multiple e-Document services.
+ /// This test ensures that only documents associated with the specified e-Document service are imported,
+ /// even when multiple documents from various services are present in the API response.
+ ///
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure ReceiveDocuments_Peppol_MultipleEdocServices()
+ var
+ EDocument: Record "E-Document";
+ EDocServicePage: TestPage "E-Document Service";
+ begin
+ // Receive only 1 E-Document service related documents when there are Documents from multiple E-Document services
+ Initialize();
+ // [Given] Empty E-Document table
+ EDocument.DeleteAll();
+
+ // [Given] Auto import job. Open and close E-Doc page creates auto import job due to setting
+ EDocServicePage.OpenView();
+ EDocServicePage.GoToRecord(EDocumentService);
+ EDocServicePage."Resolve Unit Of Measure".SetValue(true);
+ EDocServicePage."Lookup Item Reference".SetValue(true);
+ EDocServicePage."Lookup Item GTIN".SetValue(false);
+ EDocServicePage."Lookup Account Mapping".SetValue(false);
+ EDocServicePage."Validate Line Discount".SetValue(false);
+ EDocServicePage.Close();
+
+ // [When] Manually fire job queue job to import Documents
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ StrSubstNo(DocumentUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('ReceiveDocuments-multiple-services.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ StrSubstNo(DownloadUriPatternTok, ContiniaApiUrlMgt.CdnBaseUrl()),
+ 200,
+ GetMockResponseContent('ReceivePeppolInvoiceDocument200.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.DocumentActionUrl('65DD7456-7A49-4382-9F76-1211FA8AD0BF'),
+ 200);
+ LibraryEDocument.RunImportJob();
+
+ // Assert that we have only 1 document imported
+ EDocument.FindLast();
+ Assert.AreEqual(1, EDocument.Count, 'Wrong number of documents imported');
+ end;
+
+ local procedure Initialize()
+ var
+ CompanyInformation: Record "Company Information";
+ ContiniaConnectionSetup: Record "Continia Connection Setup";
+ PurchaseHeader: Record "Purchase Header";
+ EnvironmentInfoTestLibrary: Codeunit "Environment Info Test Library";
+ begin
+ LibraryPermission.SetOutsideO365Scope();
+ EnvironmentInfoTestLibrary.SetTestabilitySoftwareAsAService(true);
+
+ ContiniaConnectionSetup.DeleteAll();
+ ContiniaConnectionSetup.Init();
+ ContiniaConnectionSetup.Insert(true);
+
+ PurchaseHeader.DeleteAll();
+
+ if IsInitialized then
+ exit;
+ LibraryEDocument.SetupStandardVAT();
+ LibraryEDocument.SetupStandardSalesScenario(Customer, EDocumentService, Enum::"E-Document Format"::"PEPPOL BIS 3.0", Enum::"Service Integration"::Continia);
+
+ LibraryEDocument.SetupStandardPurchaseScenario(Vendor, EDocumentService, Enum::"E-Document Format"::"PEPPOL BIS 3.0", Enum::"Service Integration"::Continia);
+ EDocumentService.Validate("Auto Import", true);
+ EDocumentService."Import Minutes between runs" := 10;
+ EDocumentService."Import Start Time" := Time();
+ EDocumentService.Modify();
+
+ CompanyInformation.Get();
+ CompanyInformation."VAT Registration No." := 'GB777777771';
+ CompanyInformation.Modify();
+
+ Vendor."VAT Registration No." := 'GB777777772';
+ Vendor."Receive E-Document To" := Enum::"E-Document Type"::"Purchase Invoice";
+ Vendor.Modify();
+
+ CreateTestItem();
+
+ ConnectorLibrary.PrepareParticipation(EDocumentService);
+
+ IsInitialized := true;
+ end;
+
+ local procedure CreateTestItem()
+ var
+ Item: Record Item;
+ ItemReference: Record "Item Reference";
+ UnitofMeasure: Record "Unit of Measure";
+ begin
+ // Create a test item
+ LibraryInventory.CreateItem(Item);
+#pragma warning disable AA0210
+ UnitofMeasure.SetRange("International Standard Code", TestItemIsoUomTok);
+#pragma warning restore AA0210
+ UnitofMeasure.FindFirst();
+ Item.Validate("Base Unit of Measure", UnitofMeasure.Code);
+ Item.Modify(true);
+ LibraryItemReference.CreateItemReferenceWithNo(ItemReference, TestVendorItemNoTok, Item."No.", Enum::"Item Reference Type"::Vendor, Vendor."No.");
+ end;
+
+ local procedure TestEDocumentPage(EDocument: Record "E-Document"; EDocumentStatus: Enum "E-Document Status"; EDocServiceStatus: Enum "E-Document Service Status"; EDocLogList: List of [Enum "E-Document Service Status"]; ErrorMessageType: Text; ErrorMessage: Text)
+ var
+ EDocumentPage: TestPage "E-Document";
+ begin
+ // [Then] Open E-Document page
+ EDocumentPage.OpenView();
+ EDocumentPage.GoToRecord(EDocument);
+ Assert.AreEqual(Format(EDocumentStatus), EDocumentPage."Electronic Document Status".Value(), IncorrectValueErr);
+ Assert.AreEqual(Format(EDocument.Direction::Outgoing), EDocumentPage.Direction.Value(), IncorrectValueErr);
+ Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), IncorrectValueErr);
+
+ // [Then] E-Document Service Status is correct
+ Assert.AreEqual(EDocumentService.Code, EDocumentPage."Outbound E-Doc. Factbox"."E-Document Service Code".Value(), IncorrectValueErr);
+ Assert.AreEqual(Format(EDocServiceStatus), EDocumentPage."Outbound E-Doc. Factbox".Status.Value(), IncorrectValueErr);
+ Assert.AreEqual(Format(EDocLogList.Count), EDocumentPage."Outbound E-Doc. Factbox".Log.Value(), IncorrectValueErr);
+
+ LibraryEDocument.AssertEDocumentLogs(EDocument, EDocumentService, EDocLogList);
+
+ if (ErrorMessageType = '') and (ErrorMessage = '') then
+ // [Then] E-Document Has no Errors or Warnings
+ Assert.AreEqual(0, GetEDocumentErrorOrWarningsCount(EDocument), IncorrectValueErr)
+ else begin
+ // [Then] E-Document Errors and Warnings has correct status
+ Assert.AreEqual(ErrorMessageType, EDocumentPage.ErrorMessagesPart."Message Type".Value(), IncorrectValueErr);
+ Assert.AreEqual(ErrorMessage, EDocumentPage.ErrorMessagesPart.Description.Value(), IncorrectValueErr);
+ end;
+ EDocumentPage.Close();
+ end;
+
+ local procedure GetEDocumentErrorOrWarningsCount(EDocument: Record "E-Document"): Integer
+ var
+ EDocumentErrorHelper: Codeunit "E-Document Error Helper";
+ begin
+ exit(EDocumentErrorHelper.ErrorMessageCount(EDocument) + EDocumentErrorHelper.WarningMessageCount(EDocument))
+ end;
+
+ local procedure RunGetResponseJob()
+ var
+ JobQueueEntry: Record "Job Queue Entry";
+ begin
+ JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response");
+ Codeunit.Run(Codeunit::"Job Queue Dispatcher", JobQueueEntry);
+ LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry);
+ end;
+
+ local procedure MockDocumentId() DocumentId: Guid
+ begin
+ Evaluate(DocumentId, '{3fa85f64-5717-4562-b3fc-2c963f66afa6}');
+ end;
+
+ [ModalPageHandler]
+ internal procedure EDocServicesPageHandler(var EDocServicesPage: TestPage "E-Document Services")
+ begin
+ EDocServicesPage.Filter.SetFilter(Code, EDocumentService.Code);
+ EDocServicesPage.OK().Invoke();
+ end;
+
+ local procedure GetMockResponseContent(ResourceFileName: Text): Text
+ begin
+ exit(NavApp.GetResourceAsText(ResourceFileName, TextEncoding::UTF8));
+ end;
+
+ [HttpClientHandler]
+ internal procedure HttpClientHandler(Request: TestHttpRequestMessage; var Response: TestHttpResponseMessage): Boolean
+ begin
+ if ContiniaMockHttpHandler.HandleAuthorization(Request, Response) then
+ exit;
+
+ Response := ContiniaMockHttpHandler.GetResponse(Request);
+ end;
+
+ var
+ Customer: Record Customer;
+ Vendor: Record Vendor;
+ EDocumentService: Record "E-Document Service";
+ LibraryEDocument: Codeunit "Library - E-Document";
+ LibraryPermission: Codeunit "Library - Lower Permissions";
+ LibraryJobQueue: Codeunit "Library - Job Queue";
+ Assert: Codeunit Assert;
+ LibraryInventory: Codeunit "Library - Inventory";
+ LibraryItemReference: Codeunit "Library - Item Reference";
+ ConnectorLibrary: Codeunit "Continia Connector Library";
+ ContiniaMockHttpHandler: Codeunit "Continia Mock Http Handler";
+ ContiniaApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+
+ IsInitialized: Boolean;
+ IncorrectValueErr: Label 'Wrong value';
+ TestVendorItemNoTok: Label '1908-S', Locked = true;
+ TestItemIsoUomTok: Label 'EA', Locked = true;
+ DocumentUriPatternTok: Label '%1/documents.xml', Comment = '%1 - Base URL', Locked = true;
+ DownloadUriPatternTok: Label '%1/documents.xml/download/peppol', Comment = '%1 - Base URL', Locked = true;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaMockHttpHandler.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaMockHttpHandler.Codeunit.al
new file mode 100644
index 0000000000..4be0e8c0c7
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaMockHttpHandler.Codeunit.al
@@ -0,0 +1,95 @@
+codeunit 148201 "Continia Mock Http Handler"
+{
+ var
+ ResponseStatusCodes: Dictionary of [Text, Integer];
+ ResponseContents: Dictionary of [Text, Text];
+ DefaultRequest: Boolean;
+
+ internal procedure AddResponse(Method: HttpRequestType; RequestPath: Text; StatusCode: Integer; ResponseContent: Text)
+ var
+ DictionaryKey: Text;
+
+ begin
+ if StrPos(RequestPath, '?') > 0 then
+ RequestPath := CopyStr(RequestPath, 1, StrPos(RequestPath, '?') - 1);
+
+ if (Method = Method::Unknown) and (RequestPath = '') then begin
+ DefaultRequest := true;
+ DictionaryKey := '';
+ end else
+ DictionaryKey := GetDictionaryKey(RequestPath, Method);
+
+ ResponseStatusCodes.Add(DictionaryKey, StatusCode);
+ ResponseContents.Add(DictionaryKey, ResponseContent);
+ end;
+
+ internal procedure AddResponse(Method: HttpRequestType; RequestPath: Text; StatusCode: Integer)
+ begin
+ AddResponse(Method, RequestPath, StatusCode, '');
+ end;
+
+ internal procedure AddResponse(StatusCode: Integer; ResponseContent: Text)
+ begin
+ AddResponse(HttpRequestType::Unknown, '', StatusCode, ResponseContent);
+ end;
+
+ internal procedure GetResponse(Request: TestHttpRequestMessage) HttpResponseMessage: TestHttpResponseMessage
+ var
+ DictionaryKey: Text;
+ begin
+ if DefaultRequest then
+ DictionaryKey := ''
+ else
+ DictionaryKey := GetDictionaryKey(Request.Path, Request.RequestType);
+ HttpResponseMessage.HttpStatusCode := ResponseStatusCodes.Get(DictionaryKey);
+ HttpResponseMessage.Content().WriteFrom(ReplaceContentPlaceholders(ResponseContents.Get(DictionaryKey), Request.Path));
+ Clear(DefaultRequest);
+ end;
+
+ internal procedure HandleAuthorization(Request: TestHttpRequestMessage; var HttpResponseMessage: TestHttpResponseMessage): Boolean
+ var
+ ContiniaApiUrlMgt: Codeunit "Continia Api Url Mgt.";
+ begin
+ if Request.Path = ContiniaApiUrlMgt.ClientAccessTokenUrl() then begin
+ HttpResponseMessage.HttpStatusCode := 200;
+ HttpResponseMessage.Content.WriteFrom(NavApp.GetResourceAsText('OauthToken200.txt', TextEncoding::UTF8));
+ exit(true);
+ end;
+ end;
+
+ internal procedure ClearHandler();
+ begin
+ Clear(ResponseStatusCodes);
+ Clear(ResponseContents);
+ end;
+
+ local procedure ReplaceContentPlaceholders(OriginalContent: Text; Uri: Text): Text
+ var
+ Regex: Codeunit Regex;
+ UriSegments: List of [Text];
+ ParticipationProfileId: Text;
+ DownloadUriPatternTok: Label '%1/download', Comment = '%1 = Uri', Locked = true;
+ begin
+ if OriginalContent.Contains('{random.guid}') then
+ OriginalContent := Regex.Replace(OriginalContent, '{random.guid}', Format(CreateGuid(), 0, 9));
+
+ if OriginalContent.Contains('{fileDownloadUrl}') then
+ OriginalContent := Regex.Replace(OriginalContent, '{fileDownloadUrl}', StrSubstNo(DownloadUriPatternTok, Uri));
+
+ if OriginalContent.Contains('{participationProfileId.ToLower}') then begin
+ UriSegments := Uri.Split('/');
+ ParticipationProfileId := UriSegments.Get(UriSegments.Count());
+ if ParticipationProfileId.EndsWith('.xml') then
+ ParticipationProfileId := ParticipationProfileId.Substring(1, StrLen(ParticipationProfileId) - 4);
+ OriginalContent := Regex.Replace(OriginalContent, '{participationProfileId.ToLower}', ParticipationProfileId.ToLower());
+ end;
+ exit(OriginalContent);
+ end;
+
+ local procedure GetDictionaryKey(RequestPath: Text; Method: HttpRequestType) returnValue: Text
+ var
+ KeyPatternTok: Label '%1;%2', Comment = '%1 = Method, %2 = RequestPath', Locked = true;
+ begin
+ returnValue := StrSubstNo(KeyPatternTok, Format(Method), RequestPath);
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaProfileSelection.PageExt.al b/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaProfileSelection.PageExt.al
new file mode 100644
index 0000000000..c119431fe5
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaProfileSelection.PageExt.al
@@ -0,0 +1,21 @@
+namespace Microsoft.EServices.EDocumentConnector.Continia;
+
+pageextension 148200 "Continia Profile Selection" extends "Continia Profile Selection"
+{
+
+ actions
+ {
+ addlast(Processing)
+ {
+ action(DeleteProfile)
+ {
+ Image = Delete;
+ ToolTip = 'Delete Profile. Used for automated testing only';
+ trigger OnAction()
+ begin
+ Rec.Delete();
+ end;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaRegIntegrTests.Codeunit.al b/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaRegIntegrTests.Codeunit.al
new file mode 100644
index 0000000000..2f5c67da7b
--- /dev/null
+++ b/Apps/W1/EDocumentConnectors/Continia/test/src/ContiniaRegIntegrTests.Codeunit.al
@@ -0,0 +1,1076 @@
+namespace Microsoft.EServices.EDocumentConnector.Continia;
+using Microsoft.EServices.EDocumentConnector.Continia;
+using Microsoft.eServices.EDocument;
+using System.TestLibraries.Environment;
+using Microsoft.Sales.Customer;
+using Microsoft.eServices.EDocument.Integration;
+using Microsoft.Foundation.Company;
+codeunit 148204 "Continia Reg. Integr. Tests"
+{
+ Subtype = Test;
+ TestHttpRequestPolicy = AllowOutboundFromHandler;
+
+ ///
+ /// Scenario: This test verifies the complete advanced registration flow in the e-Document service.
+ /// It ensures that the onboarding wizard navigates through all steps, validates mandatory fields,
+ /// handles invalid credentials, and successfully registers a new participation with various document types.
+ /// Additionally, it checks for the correct handling of external errors such as duplicate registrations in
+ /// the Peppol network.
+ ///
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure Registration_AdvancedFlow()
+ var
+ EDocServicePage: TestPage "E-Document Service";
+ OnboardingWizard: TestPage "Continia Onboarding Wizard";
+ ExtConnectionSetup: TestPage "Continia Ext. Connection Setup";
+ Participations: TestPage "Continia Participations";
+ ParticipationAlreadyRegisteredPeppolErr: Label 'There is already a registration in Peppol network with the identifier type';
+ begin
+ Initialize();
+
+ // [Given] Team Member + 'E-Doc. Core - Edit' permissions
+ LibraryPermission.SetTeamMember();
+ LibraryPermission.AddPermissionSet('E-Doc. Core - Edit');
+
+ // [When] Open eDocument Service
+ EDocServicePage.OpenView();
+ EDocServicePage.GoToRecord(EDocumentService);
+
+ // [When] Open Setup Service Integration
+ ExtConnectionSetup.Trap();
+ EDocServicePage.SetupServiceIntegration.Invoke();
+
+ // [Then] Validate No Of Participations is 0
+ Assert.AreEqual('0', ExtConnectionSetup.NoOfParticipations.Value, IncorrectValueErr);
+
+ // [When] Click on Register New Participation and on CDN Onboarding Click Next
+ OnboardingWizard.Trap();
+ ExtConnectionSetup.RegisterNewParticipation.Invoke();
+ OnboardingWizard.ActionNext.Invoke();
+ Commit();
+
+ // [Then] not set credentials and try click Next
+ asserterror OnboardingWizard.ActionNext.Invoke();
+ Assert.ExpectedError('Partner credentials for Continia PartnerZone are invalid or missing.');
+
+ // [When] set Credential Click Next and expect Credentials are not correct
+ OnboardingWizard.PartnerUserName.SetValue('PartnerUserName@contoso.com');
+ OnboardingWizard.PartnerPassword.SetValue('PartnerPassword');
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.PartnerAccessTokenUrl(),
+ 200,
+ GetMockResponseContent('PartnerZoneLogin200Incorrect.txt')
+ );
+ asserterror OnboardingWizard.ActionNext.Invoke();
+
+ // [Then] check the error exists
+ Assert.ExpectedError('Partner credentials for Continia PartnerZone are invalid or missing.');
+
+ // [When] Click Next and expect Credentials are correct
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.PartnerAccessTokenUrl(),
+ 200,
+ GetMockResponseContent('PartnerZoneLogin200.txt')
+ );
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.ClientEnvironmentInitializeUrl(),
+ 200,
+ GetMockResponseContent('InitializeClient200.txt')
+ );
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.PartnerZoneUrl(),
+ 200,
+ GetMockResponseContent('PartnerZoneConnect200.txt')
+ );
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.NetworkIdentifiersUrl(Enum::"Continia E-Delivery Network"::Peppol, 1, 100),
+ 200,
+ GetMockResponseContent('PeppolNetworkIdTypes200.txt')
+ );
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.NetworkIdentifiersUrl(Enum::"Continia E-Delivery Network"::Nemhandel, 1, 100),
+ 200,
+ GetMockResponseContent('NemhandelNetworkIdTypes200.txt')
+ );
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.NetworkProfilesUrl(Enum::"Continia E-Delivery Network"::Peppol, 1, 100),
+ 200,
+ GetMockResponseContent('PeppolNetworkProfiles200.txt')
+ );
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.NetworkProfilesUrl(Enum::"Continia E-Delivery Network"::Nemhandel, 1, 100),
+ 200,
+ GetMockResponseContent('NemhandelNetworkProfiles200.txt')
+ );
+
+ OnboardingWizard.ActionNext.Invoke();
+ Commit();
+
+ // [Then] Legal company information step opens and values are filled in correctly
+ Assert.AreEqual(true, OnboardingWizard."Company Name".Visible(), 'Legal company information should be visible');
+ Assert.AreEqual(CompanyInformation.Name, OnboardingWizard."Company Name".Value, IncorrectValueErr);
+ Assert.AreEqual(CompanyInformation."VAT Registration No.", OnboardingWizard."VAT Registration No.".Value, IncorrectValueErr);
+ Assert.AreEqual(CompanyInformation.Address, OnboardingWizard.Address.Value, IncorrectValueErr);
+ Assert.AreEqual(CompanyInformation."Post Code", OnboardingWizard."Post Code".Value, IncorrectValueErr);
+ Assert.AreEqual(CompanyInformation."Country/Region Code", OnboardingWizard."Country/Region Code".Value, IncorrectValueErr);
+ Assert.AreEqual(false, OnboardingWizard.ActionNext.Enabled(), 'Next should be disabled');
+
+ // [When] fill mandatory information
+ OnboardingWizard."Signatory Name".SetValue('Signatory Name');
+ OnboardingWizard."Signatory Email".SetValue('signatory@email.address');
+ OnboardingWizard.LicenseTerms.SetValue(true);
+
+ // [Then] Next is enabled
+ Assert.AreEqual(true, OnboardingWizard.ActionNext.Enabled(), 'Next should be enabled');
+
+ // [When] click Next
+ OnboardingWizard.ActionNext.Invoke();
+ Commit();
+
+ // [Then] Company contact information step opens and Next is disabled
+ Assert.AreEqual(false, OnboardingWizard."Company Name".Visible(), 'Legal company information should not be visible');
+ Assert.AreEqual(true, OnboardingWizard.CompanyContactName.Visible(), 'Company company information should be visible');
+ Assert.AreEqual(false, OnboardingWizard.ActionNext.Enabled(), 'Next should be disabled');
+
+ // [When] fill mandatory information
+ OnboardingWizard.CompanyContactName.SetValue('Company Contact Name');
+ OnboardingWizard.CompanyContactVAT.SetValue('123456789');
+ OnboardingWizard.CompanyContactAddress.SetValue('CompanyContact Address');
+ OnboardingWizard.CompanyContactPostCode.SetValue('111222');
+ OnboardingWizard.CompanyContactCounty.SetValue('Company Contact County');
+ OnboardingWizard.CompanyContactCountryRegion.SetValue(CompanyInformation."Country/Region Code");
+ OnboardingWizard.CompanyContactPersonName.SetValue('Contact Name');
+ OnboardingWizard.CompanyContactPersonEmail.SetValue('contact@email.address');
+ OnboardingWizard.CompanyContactPersonPhoneNo.SetValue('999888777');
+
+ // [Then] Next is enabled
+ Assert.AreEqual(true, OnboardingWizard.ActionNext.Enabled(), 'Next should be enabled');
+
+ // [When] click Next
+ OnboardingWizard.ActionNext.Invoke();
+ Commit();
+
+ // [Then] Participation Network registration details step opens
+ Assert.AreEqual(false, OnboardingWizard.CompanyContactName.Visible(), 'Company company information should not be visible');
+ Assert.AreEqual(true, OnboardingWizard.Network.Visible(), 'Participation Network registration details should be visible');
+
+ // [When] click Next
+ OnboardingWizard.ActionNext.Invoke();
+ Commit();
+
+ // [Then] Document Types selection step opens
+ Assert.AreEqual(false, OnboardingWizard.Network.Visible(), 'Participation Network registration details should not be visible');
+ Assert.AreEqual(true, OnboardingWizard.SendInvoiceCreditMemo.Visible(), 'Document Types selection should be visible');
+
+ // [When] Select Document Types and Expect Participation registered externally and click Next
+ OnboardingWizard.SendInvoiceCreditMemo.SetValue(true);
+ OnboardingWizard.ReceiveInvoiceResponse.SetValue(true);
+ OnboardingWizard.ReceiveOrder.SetValue(true);
+ OnboardingWizard.SendOrderResponse.SetValue(true);
+ OnboardingWizard.ReceiveInvoiceCreditMemo.SetValue(true);
+ OnboardingWizard.SendInvoiceResponse.SetValue(true);
+ OnboardingWizard.SendOrder.SetValue(true);
+ OnboardingWizard.ReceiveOrderResponse.SetValue(true);
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationLookupUrl(
+ Enum::"Continia E-Delivery Network"::Peppol,
+ CopyStr(OnboardingWizard.IdentifierTypeDesc.Value, 1, 4),
+ CopyStr(OnboardingWizard.CompanyIdentifierValue.Value, 1, 50)),
+ 200,
+ GetMockResponseContent('ParticipationLookup200-external.txt'));
+
+ asserterror OnboardingWizard.ActionNext.Invoke();
+
+ // [Then] check the error thrown
+ Assert.ExpectedError(ParticipationAlreadyRegisteredPeppolErr);
+
+ // [When] click Advanced Setup
+ OnboardingWizard.ActionAdvancedSetup.Invoke();
+ Commit();
+
+ // [Then] Advanced Setup step opens
+ Assert.AreEqual(false, OnboardingWizard.SendInvoiceCreditMemo.Visible(), 'Document Types selection should not be visible');
+ Assert.AreEqual(true, OnboardingWizard.SelectProfilesPeppol."Profile Name".Visible(), 'Advanced Setup should be visible');
+
+ // [When] assign E-Document Service Code on each record
+ OnboardingWizard.SelectProfilesPeppol.First();
+ repeat
+ if OnboardingWizard.SelectProfilesPeppol."Profile Name".Value <> '' then
+ OnboardingWizard.SelectProfilesPeppol."E-Document Service Code".SetValue(EDocumentService.Code);
+ until not OnboardingWizard.SelectProfilesPeppol.Next();
+
+ // [When] Participation registered externally and click Next
+ asserterror OnboardingWizard.ActionNext.Invoke();
+
+ // [Then] check the error thrown
+ Assert.ExpectedError(ParticipationAlreadyRegisteredPeppolErr);
+
+ // [When] Participation is not registered externally and click Next
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationLookupUrl(
+ Enum::"Continia E-Delivery Network"::Peppol,
+ CopyStr(OnboardingWizard.IdentifierTypeDesc.Value, 1, 4),
+ CopyStr(OnboardingWizard.CompanyIdentifierValue.Value, 1, 50)),
+ 200,
+ GetMockResponseContent('ParticipationLookup200.txt'));
+ OnboardingWizard.ActionNext.Invoke();
+
+ // [Then] Last step opens
+ Assert.AreEqual(false, OnboardingWizard.SelectProfilesPeppol."Profile Name".Visible(), 'Advanced Setup should not be visible');
+ Assert.AreEqual(false, OnboardingWizard.ActionNext.Enabled(), 'Next must be disabled');
+ Assert.AreEqual(true, OnboardingWizard.ActionFinish.Enabled(), 'Finish must be enabled');
+
+ // [When] click Finish
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.UpdateSubscriptionUrl(),
+ 200,
+ GetMockResponseContent('UpdateSubscription200.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.GetAcceptCompanyLicenseUrl(),
+ 200,
+ GetMockResponseContent('AcceptCompanyLicense200.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.ParticipationUrl(Enum::"Continia E-Delivery Network"::Peppol),
+ 200,
+ GetMockResponseContent('Participation200-Draft.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.ParticipationProfilesUrl(Enum::"Continia E-Delivery Network"::Peppol, ConnectorLibrary.ParticipationId(true)),
+ 200,
+ GetMockResponseContent('ParticipationProfile200-randomId.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Patch,
+ ContiniaApiUrlMgt.SingleParticipationUrl(Enum::"Continia E-Delivery Network"::Peppol, ConnectorLibrary.ParticipationId(true)),
+ 200,
+ GetMockResponseContent('Participation200-InProcess.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.SingleParticipationUrl(Enum::"Continia E-Delivery Network"::Peppol, ConnectorLibrary.ParticipationId(true)),
+ 200,
+ GetMockResponseContent('Participation200-InProcess.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationProfilesUrl(Enum::"Continia E-Delivery Network"::Peppol, ConnectorLibrary.ParticipationId(true), 1, 100),
+ 200,
+ GetMockResponseContent('ParticipationProfile200-randomId.txt'));
+ OnboardingWizard.ActionFinish.Invoke();
+ Commit();
+
+ // [Then] Participation is created in pending state
+ Assert.AreEqual('1', ExtConnectionSetup.NoOfParticipations.Value, IncorrectValueErr);
+ Participations.Trap();
+ ExtConnectionSetup.NoOfParticipations.Drilldown();
+ Participations.First();
+ Assert.AreEqual(Format(ConnectorLibrary.ParticipationId(true)).ToLower(), Participations.Id.Value, IncorrectValueErr);
+ Assert.AreEqual(Format(Enum::"Continia Registration Status"::InProcess), Participations.RegistrationStatus.Value, IncorrectValueErr);
+
+ // [Then] Activated network profiles created
+ ValidateActivatedNetworkProfiles();
+
+ ExtConnectionSetup.Close();
+ EDocServicePage.Close();
+ end;
+
+ ///
+ /// Scenario: This test confirms the correct process for unregistering a connected participation.
+ /// It starts with a configured, connected participation and verifies the status change to "Disabled"
+ /// upon successful unregistration, ensuring that the process is completed without errors.
+ ///
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure Unregister_Connected()
+ var
+ Participation: Record "Continia Participation";
+ EDocServicePage: TestPage "E-Document Service";
+ ExtConnectionSetup: TestPage "Continia Ext. Connection Setup";
+ Participations: TestPage "Continia Participations";
+ begin
+ Initialize();
+
+ // [Given] Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+ // [Given] Team Member + 'E-Doc. Core - Edit' permissions
+ LibraryPermission.SetTeamMember();
+ LibraryPermission.AddPermissionSet('E-Doc. Core - Edit');
+
+ // [When] Open eDocument Service
+ EDocServicePage.OpenView();
+ EDocServicePage.GoToRecord(EDocumentService);
+
+ // [When] Open Setup Service Integration
+ ExtConnectionSetup.Trap();
+ EDocServicePage.SetupServiceIntegration.Invoke();
+ Commit();
+
+ // [Then] Validate No Of Participations is 1
+ Assert.AreEqual('1', ExtConnectionSetup.NoOfParticipations.Value, IncorrectValueErr);
+
+ // [When] DrillDown on No of Participations
+ Participations.Trap();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.SingleParticipationUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id),
+ 200,
+ GetMockResponseContent('Participation200-Connected.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationProfilesUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id, 1, 100),
+ 200,
+ GetMockResponseContent('ParticipationProfile200-randomId.txt'));
+ ExtConnectionSetup.NoOfParticipations.Drilldown();
+ Commit();
+
+ // [Then] Participations Page opens with Connected participation
+ Participations.First();
+ Assert.AreEqual(Format(Enum::"Continia Registration Status"::Connected), Participations.RegistrationStatus.Value, IncorrectValueErr);
+
+ // [When] click Unregister
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Delete,
+ ContiniaApiUrlMgt.SingleParticipationUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id),
+ 202);
+ Participations.DeleteParticipation.Invoke();
+
+ // [Then] Participation status is Disabled
+ Participations.First();
+ Assert.AreEqual(Format(Enum::"Continia Registration Status"::Disabled), Participations.RegistrationStatus.Value, IncorrectValueErr);
+
+ Participations.Close();
+ ExtConnectionSetup.Close();
+ EDocServicePage.Close();
+ end;
+
+ ///
+ /// Scenario: This test case validates the behavior of unregistering a participation with the status "InProcess."
+ /// The test confirms that the participation is properly deleted upon completion of the unregistering action,
+ /// verifying that no residual records are left in the system.
+ ///
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure Unregister_InProcess()
+ var
+ Participation: Record "Continia Participation";
+ EDocServicePage: TestPage "E-Document Service";
+ ExtConnectionSetup: TestPage "Continia Ext. Connection Setup";
+ Participations: TestPage "Continia Participations";
+ begin
+ Initialize();
+
+ // [Given] Connected Participation
+ ConnectorLibrary.PrepareParticipation(Participation);
+
+ // [Given] Team Member + 'E-Doc. Core - Edit' permissions
+ LibraryPermission.SetTeamMember();
+ LibraryPermission.AddPermissionSet('E-Doc. Core - Edit');
+
+ // [When] Open eDocument Service
+ EDocServicePage.OpenView();
+ EDocServicePage.GoToRecord(EDocumentService);
+
+ // [When] Open Setup Service Integration
+ ExtConnectionSetup.Trap();
+ EDocServicePage.SetupServiceIntegration.Invoke();
+ Commit();
+
+ // [Then] Validate No Of Participations is 1
+ Assert.AreEqual('1', ExtConnectionSetup.NoOfParticipations.Value, IncorrectValueErr);
+
+ // [When] DrillDown on No of Participations
+ Participations.Trap();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.SingleParticipationUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id),
+ 200,
+ GetMockResponseContent('Participation200-InProcess.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationProfilesUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id, 1, 100),
+ 200,
+ GetMockResponseContent('ParticipationProfile200-randomId.txt'));
+ ExtConnectionSetup.NoOfParticipations.Drilldown();
+ Commit();
+
+ // [Then] Participations Page opens with InProcess participation
+ Participations.First();
+ Assert.AreEqual(Format(Enum::"Continia Registration Status"::InProcess), Participations.RegistrationStatus.Value, IncorrectValueErr);
+
+ // [When] click Unregister
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Delete,
+ ContiniaApiUrlMgt.SingleParticipationUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id),
+ 200);
+ Participations.DeleteParticipation.Invoke();
+
+ // [Then] Participation must be deleted
+ Assert.AreEqual(false, Participations.First(), 'Participation must not be found');
+
+ Participations.Close();
+ ExtConnectionSetup.Close();
+ EDocServicePage.Close();
+ end;
+
+ ///
+ /// Scenario: This test evaluates the process of editing an existing participation to modify its profile direction.
+ /// It ensures that changes are successfully applied and that the onboarding wizard navigates through the necessary steps,
+ /// ending with a status verification of the updated profile direction.
+ ///
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure EditParticipation_ChangeProfileDirection()
+ var
+ Participation: Record "Continia Participation";
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ EDocServicePage: TestPage "E-Document Service";
+ ExtConnectionSetup: TestPage "Continia Ext. Connection Setup";
+ Participations: TestPage "Continia Participations";
+ OnboardingWizard: TestPage "Continia Onboarding Wizard";
+ begin
+ Initialize();
+
+ // [Given] Connected Participation with a profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf, EDocumentService);
+
+ // [Given] Configured Client Credentials
+ ConnectorLibrary.InitiateClientCredentials();
+
+ // [Given] Team Member + 'E-Doc. Core - Edit' permissions
+ LibraryPermission.SetTeamMember();
+ LibraryPermission.AddPermissionSet('E-Doc. Core - Edit');
+
+ // [When] Open eDocument Service
+ EDocServicePage.OpenView();
+ EDocServicePage.GoToRecord(EDocumentService);
+
+ // [When] Open Setup Service Integration
+ ExtConnectionSetup.Trap();
+ EDocServicePage.SetupServiceIntegration.Invoke();
+ Commit();
+
+ // [Then] Validate No Of Participations is 1
+ Assert.AreEqual('1', ExtConnectionSetup.NoOfParticipations.Value, IncorrectValueErr);
+
+ // [When] DrillDown on No of Participations
+ Participations.Trap();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.SingleParticipationUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id),
+ 200,
+ GetMockResponseContent('Participation200-Connected.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationProfilesUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id, 1, 100),
+ 200,
+ GetMockResponseContent('ParticipationProfile200-randomId.txt'));
+ ExtConnectionSetup.NoOfParticipations.Drilldown();
+ Commit();
+
+ // [Then] Participations Page opens with Connected participation
+ Participations.First();
+ Assert.AreEqual(Format(Enum::"Continia Registration Status"::Connected), Participations.RegistrationStatus.Value, IncorrectValueErr);
+
+ // [When] click Edit Participation
+ OnboardingWizard.Trap();
+ Participations.EditParticipation.Invoke();
+
+ // [Then] Onboarding Wizard Legal company information step opens and values are filled in correctly
+ Assert.AreEqual(true, OnboardingWizard."Company Name".Visible(), 'Legal company information should be visible');
+ Assert.AreNotEqual('', OnboardingWizard."Company Name".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."VAT Registration No.".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard.Address.Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Post Code".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Country/Region Code".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Signatory Name".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Signatory Email".Value, IncorrectValueErr);
+ Assert.AreEqual(false, OnboardingWizard.ActionNext.Enabled(), 'Next should be disabled');
+
+ // [When] fill mandatory information
+ OnboardingWizard.LicenseTerms.SetValue(true);
+
+ // [Then] Next is enabled
+ Assert.AreEqual(true, OnboardingWizard.ActionNext.Enabled(), 'Next should be enabled');
+
+ // [When] click Next
+ OnboardingWizard.ActionNext.Invoke();
+ Commit();
+
+ // [Then] Onboarding Wizard Advanced Setup step opens
+ Assert.AreEqual(false, OnboardingWizard.PartnerUserName.Visible(), 'Partner Details should not be visible');
+ Assert.AreEqual(true, OnboardingWizard.SelectProfilesPeppol."Profile Name".Visible(), 'Advanced Setup should be visible');
+
+ // [When] Set participation profile direction to Outgoing and click Next
+ OnboardingWizard.SelectProfilesPeppol.First();
+ OnboardingWizard.SelectProfilesPeppol."Profile Direction".SetValue(Enum::"Continia Profile Direction"::Outbound);
+
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationLookupUrl(
+ Enum::"Continia E-Delivery Network"::Peppol,
+ CopyStr(OnboardingWizard.IdentifierTypeDesc.Value, 1, 4),
+ CopyStr(OnboardingWizard.CompanyIdentifierValue.Value, 1, 50)),
+ 200,
+ GetMockResponseContent('ParticipationLookup200.txt'));
+ OnboardingWizard.ActionNext.Invoke();
+ Commit();
+
+ // [Then] Last step opens
+ Assert.AreEqual(false, OnboardingWizard.SelectProfilesPeppol."Profile Name".Visible(), 'Advanced Setup should not be visible');
+ Assert.AreEqual(false, OnboardingWizard.ActionNext.Enabled(), 'Next must be disabled');
+ Assert.AreEqual(true, OnboardingWizard.ActionFinish.Enabled(), 'Finish must be enabled');
+
+ // [When] click Finish
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Patch,
+ ContiniaApiUrlMgt.UpdateSubscriptionUrl(),
+ 200,
+ GetMockResponseContent('Participation200-InProcess.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Patch,
+ ContiniaApiUrlMgt.SingleParticipationProfileUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id, ActivatedNetProf.Id),
+ 200,
+ GetMockResponseContent('ParticipationProfile-outgoing.txt'));
+ OnboardingWizard.ActionFinish.Invoke();
+ Commit();
+
+ // [Then] Profile Direction is Outgoing
+ ConnectorLibrary.GetActivatedNetworkProfile(ActivatedNetProf);
+ Assert.AreEqual(Enum::"Continia Profile Direction"::Outbound, ActivatedNetProf."Profile Direction", IncorrectValueErr);
+
+ Participations.Close();
+ ExtConnectionSetup.Close();
+ EDocServicePage.Close();
+ end;
+
+ ///
+ /// Scenario: This test checks the functionality of adding an additional network profile to an existing participation.
+ /// It confirms that the onboarding wizard proceeds through each step and that the newly added profile is correctly
+ /// registered in the system, verifying that both activated and required profiles are present after completion.
+ ///
+ [Test]
+ [HandlerFunctions('HandlePeppolInvoiceProfileSelection,HttpClientHandler')]
+ procedure EditParticipation_AddProfile()
+ var
+ Participation: Record "Continia Participation";
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ EDocServicePage: TestPage "E-Document Service";
+ ExtConnectionSetup: TestPage "Continia Ext. Connection Setup";
+ Participations: TestPage "Continia Participations";
+ OnboardingWizard: TestPage "Continia Onboarding Wizard";
+ NetworkProfileIds: List of [Guid];
+ begin
+ Initialize();
+
+ // [Given] Connected Participation with a profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf, EDocumentService);
+
+ // [Given] Configured Client Credentials
+ ConnectorLibrary.InitiateClientCredentials();
+
+ // [Given] Team Member + 'E-Doc. Core - Edit' permissions
+ LibraryPermission.SetTeamMember();
+ LibraryPermission.AddPermissionSet('E-Doc. Core - Edit');
+
+ // [When] Open eDocument Service
+ EDocServicePage.OpenView();
+ EDocServicePage.GoToRecord(EDocumentService);
+
+ // [When] Open Setup Service Integration
+ ExtConnectionSetup.Trap();
+ EDocServicePage.SetupServiceIntegration.Invoke();
+ Commit();
+
+ // [Then] Validate No Of Participations is 1
+ Assert.AreEqual('1', ExtConnectionSetup.NoOfParticipations.Value, IncorrectValueErr);
+
+ // [When] DrillDown on No of Participations
+ Participations.Trap();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.SingleParticipationUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id),
+ 200,
+ GetMockResponseContent('Participation200-Connected.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationProfilesUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id, 1, 100),
+ 200,
+ GetMockResponseContent('ParticipationProfile200-randomId.txt'));
+ ExtConnectionSetup.NoOfParticipations.Drilldown();
+ Commit();
+
+ // [Then] Participations Page opens with Connected participation
+ Participations.First();
+ Assert.AreEqual(Format(Enum::"Continia Registration Status"::Connected), Participations.RegistrationStatus.Value, IncorrectValueErr);
+
+ // [When] click Edit Participation
+ OnboardingWizard.Trap();
+ Participations.EditParticipation.Invoke();
+
+ // [Then] Onboarding Wizard Legal company information step opens and values are filled in correctly
+ Assert.AreEqual(true, OnboardingWizard."Company Name".Visible(), 'Legal company information should be visible');
+ Assert.AreNotEqual('', OnboardingWizard."Company Name".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."VAT Registration No.".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard.Address.Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Post Code".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Country/Region Code".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Signatory Name".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Signatory Email".Value, IncorrectValueErr);
+ Assert.AreEqual(false, OnboardingWizard.ActionNext.Enabled(), 'Next should be disabled');
+
+ // [When] fill mandatory information
+ OnboardingWizard.LicenseTerms.SetValue(true);
+
+ // [Then] Next is enabled
+ Assert.AreEqual(true, OnboardingWizard.ActionNext.Enabled(), 'Next should be enabled');
+
+ // [When] click Next
+ OnboardingWizard.ActionNext.Invoke();
+ Commit();
+
+ // [Then] Onboarding Wizard Advanced Setup step opens
+ Assert.AreEqual(false, OnboardingWizard.PartnerUserName.Visible(), 'Partner Details should not be visible');
+ Assert.AreEqual(true, OnboardingWizard.SelectProfilesPeppol."Profile Name".Visible(), 'Advanced Setup should be visible');
+
+ // [When] Add participation profile and click Next
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationLookupUrl(
+ Enum::"Continia E-Delivery Network"::Peppol,
+ CopyStr(OnboardingWizard.IdentifierTypeDesc.Value, 1, 4),
+ CopyStr(OnboardingWizard.CompanyIdentifierValue.Value, 1, 50)),
+ 200,
+ GetMockResponseContent('ParticipationLookup200.txt'));
+ OnboardingWizard.SelectProfilesPeppol.New();
+ OnboardingWizard.SelectProfilesPeppol."Profile Name".Lookup();
+ // HandlePeppolInvoiceProfileSelection()
+ OnboardingWizard.SelectProfilesPeppol."Profile Direction".SetValue(Enum::"Continia Profile Direction"::Both);
+ OnboardingWizard.SelectProfilesPeppol."E-Document Service Code".SetValue(EDocumentService.Code);
+ OnboardingWizard.ActionNext.Invoke();
+ Commit();
+
+ // [Then] Last step opens
+ Assert.AreEqual(false, OnboardingWizard.SelectProfilesPeppol."Profile Name".Visible(), 'Advanced Setup should not be visible');
+ Assert.AreEqual(false, OnboardingWizard.ActionNext.Enabled(), 'Next must be disabled');
+ Assert.AreEqual(true, OnboardingWizard.ActionFinish.Enabled(), 'Finish must be enabled');
+
+ // [When] click Finish
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Post,
+ ContiniaApiUrlMgt.ParticipationProfilesUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id),
+ 200,
+ GetMockResponseContent('ParticipationProfile200-randomId.txt'));
+ OnboardingWizard.ActionFinish.Invoke();
+ Commit();
+
+ // [Then] Make sure all needed activated profiles exist
+ NetworkProfileIds.Add(ConnectorLibrary.DefaultNetworkProfileId(true));
+ NetworkProfileIds.Add(ConnectorLibrary.NetworkProfileIdPeppolBis3Invoice(true));
+ TestActivatedNetworkProfiles(Participation, NetworkProfileIds, false);
+
+ Participations.Close();
+ ExtConnectionSetup.Close();
+ EDocServicePage.Close();
+ end;
+
+ ///
+ /// Scenario: This test verifies the process of removing a network profile from a participation.
+ /// It checks that the onboarding wizard accurately reflects the deletion of the profile and that remaining
+ /// active and required profiles are correctly identified, with no errors upon completion.
+ ///
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure EditParticipation_RemoveProfile()
+ var
+ Participation: Record "Continia Participation";
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ EDocServicePage: TestPage "E-Document Service";
+ ExtConnectionSetup: TestPage "Continia Ext. Connection Setup";
+ Participations: TestPage "Continia Participations";
+ OnboardingWizard: TestPage "Continia Onboarding Wizard";
+ NetworkProfileIds: List of [Guid];
+ begin
+ Initialize();
+
+ // [Given] Connected Participation with 2 network profiles
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf, EDocumentService);
+ ConnectorLibrary.AddActivatedNetworkProfile(Participation, ConnectorLibrary.NetworkProfileIdPeppolBis3Invoice(), CreateGuid(), ActivatedNetProf, EDocumentService.Code);
+
+ // [Given] Configured Client Credentials
+ ConnectorLibrary.InitiateClientCredentials();
+
+ // [Given] Team Member + 'E-Doc. Core - Edit' permissions
+ LibraryPermission.SetTeamMember();
+ LibraryPermission.AddPermissionSet('E-Doc. Core - Edit');
+
+ // [When] Open eDocument Service
+ EDocServicePage.OpenView();
+ EDocServicePage.GoToRecord(EDocumentService);
+
+ // [When] Open Setup Service Integration
+ ExtConnectionSetup.Trap();
+ EDocServicePage.SetupServiceIntegration.Invoke();
+ Commit();
+
+ // [Then] Validate No Of Participations is 1
+ Assert.AreEqual('1', ExtConnectionSetup.NoOfParticipations.Value, IncorrectValueErr);
+
+ // [When] DrillDown on No of Participations
+ Participations.Trap();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.SingleParticipationUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id),
+ 200,
+ GetMockResponseContent('Participation200-Connected.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationProfilesUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id, 1, 100),
+ 200,
+ GetMockResponseContent('ParticipationProfile200-randomId.txt'));
+ ExtConnectionSetup.NoOfParticipations.Drilldown();
+ Commit();
+
+ // [Then] Participations Page opens with Connected participation
+ Participations.First();
+ Assert.AreEqual(Format(Enum::"Continia Registration Status"::Connected), Participations.RegistrationStatus.Value, IncorrectValueErr);
+
+ // [When] click Edit Participation
+ OnboardingWizard.Trap();
+ Participations.EditParticipation.Invoke();
+
+ // [Then] Onboarding Wizard Legal company information step opens and values are filled in correctly
+ Assert.AreEqual(true, OnboardingWizard."Company Name".Visible(), 'Legal company information should be visible');
+ Assert.AreNotEqual('', OnboardingWizard."Company Name".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."VAT Registration No.".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard.Address.Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Post Code".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Country/Region Code".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Signatory Name".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Signatory Email".Value, IncorrectValueErr);
+ Assert.AreEqual(false, OnboardingWizard.ActionNext.Enabled(), 'Next should be disabled');
+
+ // [When] fill mandatory information
+ OnboardingWizard.LicenseTerms.SetValue(true);
+
+ // [Then] Next is enabled
+ Assert.AreEqual(true, OnboardingWizard.ActionNext.Enabled(), 'Next should be enabled');
+
+ // [When] click Next
+ OnboardingWizard.ActionNext.Invoke();
+ Commit();
+
+ // [Then] Onboarding Wizard Advanced Setup step opens
+ Assert.AreEqual(false, OnboardingWizard.PartnerUserName.Visible(), 'Partner Details should not be visible');
+ Assert.AreEqual(true, OnboardingWizard.SelectProfilesPeppol."Profile Name".Visible(), 'Advanced Setup should be visible');
+
+ // [When] Delete invoice participation profile and click Next
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationLookupUrl(
+ Enum::"Continia E-Delivery Network"::Peppol,
+ CopyStr(OnboardingWizard.IdentifierTypeDesc.Value, 1, 4),
+ CopyStr(OnboardingWizard.CompanyIdentifierValue.Value, 1, 50)),
+ 200,
+ GetMockResponseContent('ParticipationLookup200.txt'));
+ ConnectorLibrary.GetActivatedNetworkProfile(ConnectorLibrary.NetworkProfileIdPeppolBis3Invoice(), ActivatedNetProf);
+ OnboardingWizard.SelectProfilesPeppol.GoToRecord(ActivatedNetProf);
+ OnboardingWizard.SelectProfilesPeppol.DeleteProfile.Invoke();
+ OnboardingWizard.ActionNext.Invoke();
+ Commit();
+
+ // [Then] Last step opens
+ Assert.AreEqual(false, OnboardingWizard.SelectProfilesPeppol."Profile Name".Visible(), 'Advanced Setup should not be visible');
+ Assert.AreEqual(false, OnboardingWizard.ActionNext.Enabled(), 'Next must be disabled');
+ Assert.AreEqual(true, OnboardingWizard.ActionFinish.Enabled(), 'Finish must be enabled');
+
+ // [When] click Finish
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Delete,
+ ContiniaApiUrlMgt.SingleParticipationProfileUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id, ActivatedNetProf.Id),
+ 200);
+ OnboardingWizard.ActionFinish.Invoke();
+ Commit();
+
+ // [Then] Make sure activated and disabled profiles exist
+ NetworkProfileIds.Add(ConnectorLibrary.DefaultNetworkProfileId(true));
+ TestActivatedNetworkProfiles(Participation, NetworkProfileIds, false);
+ Clear(NetworkProfileIds);
+ NetworkProfileIds.Add(ConnectorLibrary.NetworkProfileIdPeppolBis3Invoice(true));
+ TestActivatedNetworkProfiles(Participation, NetworkProfileIds, true);
+
+ Participations.Close();
+ ExtConnectionSetup.Close();
+ EDocServicePage.Close();
+ end;
+
+ ///
+ /// Scenario: This test assesses the process of updating the VAT number for a registered participation.
+ /// It verifies that the VAT change triggers the correct flow through the onboarding wizard and that the
+ /// participation status is accurately updated to "In Process." Additionally, it checks for error handling
+ /// when a participation is suspended.
+ ///
+ [Test]
+ [HandlerFunctions('HttpClientHandler')]
+ procedure EditParticipation_ChangeVat()
+ var
+ Participation: Record "Continia Participation";
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ EDocServicePage: TestPage "E-Document Service";
+ ExtConnectionSetup: TestPage "Continia Ext. Connection Setup";
+ Participations: TestPage "Continia Participations";
+ OnboardingWizard: TestPage "Continia Onboarding Wizard";
+ begin
+ Initialize();
+
+ // [Given] Connected Participation with a profile
+ ConnectorLibrary.PrepareParticipation(Participation, ActivatedNetProf, EDocumentService);
+
+ // [Given] Configured Client Credentials
+ ConnectorLibrary.InitiateClientCredentials();
+
+ // [Given] Team Member + 'E-Doc. Core - Edit' permissions
+ LibraryPermission.SetTeamMember();
+ LibraryPermission.AddPermissionSet('E-Doc. Core - Edit');
+
+ // [When] Open eDocument Service
+ EDocServicePage.OpenView();
+ EDocServicePage.GoToRecord(EDocumentService);
+
+ // [When] Open Setup Service Integration
+ ExtConnectionSetup.Trap();
+ EDocServicePage.SetupServiceIntegration.Invoke();
+ Commit();
+
+ // [Then] Validate No Of Participations is 1
+ Assert.AreEqual('1', ExtConnectionSetup.NoOfParticipations.Value, IncorrectValueErr);
+
+ // [When] DrillDown on No of Participations
+ Participations.Trap();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.SingleParticipationUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id),
+ 200,
+ GetMockResponseContent('Participation200-Connected.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationProfilesUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id, 1, 100),
+ 200,
+ GetMockResponseContent('ParticipationProfile200-randomId.txt'));
+ ExtConnectionSetup.NoOfParticipations.Drilldown();
+ Commit();
+
+ // [Then] Participations Page opens with Connected participation
+ Participations.First();
+ Assert.AreEqual(Format(Enum::"Continia Registration Status"::Connected), Participations.RegistrationStatus.Value, IncorrectValueErr);
+
+ // [When] click Edit Participation
+ OnboardingWizard.Trap();
+ Participations.EditParticipation.Invoke();
+
+ // [Then] Onboarding Wizard Legal company information step opens and values are filled in correctly
+ Assert.AreEqual(true, OnboardingWizard."Company Name".Visible(), 'Legal company information should be visible');
+ Assert.AreNotEqual('', OnboardingWizard."Company Name".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."VAT Registration No.".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard.Address.Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Post Code".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Country/Region Code".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Signatory Name".Value, IncorrectValueErr);
+ Assert.AreNotEqual('', OnboardingWizard."Signatory Email".Value, IncorrectValueErr);
+ Assert.AreEqual(false, OnboardingWizard.ActionNext.Enabled(), 'Next should be disabled');
+
+ // [When] Change VAT number and Accept License terms
+ OnboardingWizard."VAT Registration No.".SetValue('111222334');
+ OnboardingWizard.LicenseTerms.SetValue(true);
+
+ // [Then] Next is enabled
+ Assert.AreEqual(true, OnboardingWizard.ActionNext.Enabled(), 'Next should be enabled');
+
+ // [When] click Next
+ OnboardingWizard.ActionNext.Invoke();
+ Commit();
+
+ // [Then] Onboarding Wizard Advanced Setup step opens
+ Assert.AreEqual(false, OnboardingWizard.PartnerUserName.Visible(), 'Partner Details should not be visible');
+ Assert.AreEqual(true, OnboardingWizard.SelectProfilesPeppol."Profile Name".Visible(), 'Advanced Setup should be visible');
+
+ // [When] click Next
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationLookupUrl(
+ Enum::"Continia E-Delivery Network"::Peppol,
+ CopyStr(OnboardingWizard.IdentifierTypeDesc.Value, 1, 4),
+ CopyStr(OnboardingWizard.CompanyIdentifierValue.Value, 1, 50)),
+ 200,
+ GetMockResponseContent('ParticipationLookup200.txt'));
+ OnboardingWizard.ActionNext.Invoke();
+ Commit();
+
+ // [Then] Last step opens
+ Assert.AreEqual(false, OnboardingWizard.SelectProfilesPeppol."Profile Name".Visible(), 'Advanced Setup should not be visible');
+ Assert.AreEqual(false, OnboardingWizard.ActionNext.Enabled(), 'Next must be disabled');
+ Assert.AreEqual(true, OnboardingWizard.ActionFinish.Enabled(), 'Finish must be enabled');
+
+ // [When] click Finish
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Patch,
+ ContiniaApiUrlMgt.SingleParticipationUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id),
+ 200,
+ GetMockResponseContent('Participation200-Suspended.txt'));
+ OnboardingWizard.ActionFinish.Invoke();
+ Commit();
+
+ // [Then] Participation registration status is In Process
+ ConnectorLibrary.GetParticipation(Participation);
+ Assert.AreEqual(Enum::"Continia Registration Status"::InProcess, Participation."Registration Status", IncorrectValueErr);
+
+ // [When] Participations Page close and open again
+ Participations.Close();
+ ContiniaMockHttpHandler.ClearHandler();
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.SingleParticipationUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id),
+ 200,
+ GetMockResponseContent('Participation200-Suspended.txt'));
+ ContiniaMockHttpHandler.AddResponse(
+ HttpRequestType::Get,
+ ContiniaApiUrlMgt.ParticipationProfilesUrl(Enum::"Continia E-Delivery Network"::Peppol, Participation.Id, 1, 100),
+ 404,
+ GetMockResponseContent('Common404.txt'));
+ asserterror ExtConnectionSetup.NoOfParticipations.Drilldown();
+
+ // [Then] Error appears, since Participation is not found
+ Assert.ExpectedError(Response404ErrorMessageLbl);
+
+ ExtConnectionSetup.Close();
+ EDocServicePage.Close();
+ end;
+
+ local procedure TestActivatedNetworkProfiles(Participation: Record "Continia Participation"; NetworkProfileIds: List of [Guid]; Disabled: Boolean)
+ var
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ UnexpectedProfileFoundErr: Label 'Unexpected Activated Network Profile %1 was found', Comment = '%1 - Network Profile Id';
+ begin
+ ActivatedNetProf.SetRange(Network, Participation.Network);
+ ActivatedNetProf.SetRange("Identifier Type Id", Participation."Identifier Type Id");
+ ActivatedNetProf.SetRange("Identifier Value", Participation."Identifier Value");
+ if Disabled then
+ ActivatedNetProf.SetFilter(Disabled, '<>%1', 0DT)
+ else
+ ActivatedNetProf.SetRange(Disabled, 0DT);
+ Assert.AreEqual(NetworkProfileIds.Count, ActivatedNetProf.Count, IncorrectValueErr);
+ if ActivatedNetProf.IsEmpty then
+ exit;
+ ActivatedNetProf.FindSet();
+ repeat
+ Assert.AreEqual(true, NetworkProfileIds.Contains(ActivatedNetProf."Network Profile Id"), StrSubstNo(UnexpectedProfileFoundErr, ActivatedNetProf."Network Profile Id"));
+ until ActivatedNetProf.Next() = 0;
+ end;
+
+ [ModalPageHandler]
+ internal procedure HandlePeppolInvoiceProfileSelection(var NetworkProfileList: TestPage "Continia Network Profile List")
+ var
+ NetworkProfile: Record "Continia Network Profile";
+ begin
+ NetworkProfile.Get(ConnectorLibrary.NetworkProfileIdPeppolBis3Invoice());
+ NetworkProfileList.GoToRecord(NetworkProfile);
+ NetworkProfileList.OK().Invoke();
+ end;
+
+ local procedure Initialize()
+ begin
+ LibraryPermission.SetOutsideO365Scope();
+
+ ConnectorLibrary.ClearClientCredentials();
+ ConnectorLibrary.CleanParticipations();
+
+ if IsInitialized then
+ exit;
+ EnvironmentInfoTestLibrary.SetTestabilitySoftwareAsAService(true);
+
+ LibraryEDocument.SetupStandardVAT();
+ LibraryEDocument.SetupStandardSalesScenario(Customer, EDocumentService, Enum::"E-Document Format"::"PEPPOL BIS 3.0", Enum::"Service Integration"::Continia);
+ CompanyInformation.Get();
+ CompanyInformation."Country/Region Code" := 'GB';
+ CompanyInformation.Modify(false);
+
+ IsInitialized := true;
+ end;
+
+ local procedure ValidateActivatedNetworkProfiles()
+ var
+ Participation: Record "Continia Participation";
+ ActivatedNetProf: Record "Continia Activated Net. Prof.";
+ NetworkProfile: Record "Continia Network Profile";
+ begin
+ Participation.FindFirst();
+ ActivatedNetProf.FindSet();
+ repeat
+ Assert.AreEqual(Participation.Network, ActivatedNetProf.Network, 'Activated Network Profile Network field value is incorrect');
+ Assert.AreEqual(Participation."Identifier Type Id", ActivatedNetProf."Identifier Type Id", 'Activated Network Profile "Identifier Type Id" field value is incorrect');
+ Assert.AreEqual(Participation."Identifier Value", ActivatedNetProf."Identifier Value", 'Activated Network Profile "Identifier Value" field value is incorrect');
+ Assert.AreEqual(Enum::"Continia Profile Direction"::Both, ActivatedNetProf."Profile Direction", 'Activated Network Profile "Profile Direction" field value is incorrect');
+ ActivatedNetProf.TestField(Created);
+ ActivatedNetProf.TestField(Updated);
+ NetworkProfile.Get(ActivatedNetProf."Network Profile Id");
+ until ActivatedNetProf.Next() = 0;
+ end;
+
+ local procedure GetMockResponseContent(ResourceFileName: Text): Text
+ begin
+ exit(NavApp.GetResourceAsText(ResourceFileName, TextEncoding::UTF8));
+ end;
+
+ [HttpClientHandler]
+ internal procedure HttpClientHandler(Request: TestHttpRequestMessage; var Response: TestHttpResponseMessage): Boolean
+ begin
+ if ContiniaMockHttpHandler.HandleAuthorization(Request, Response) then
+ exit;
+
+ Response := ContiniaMockHttpHandler.GetResponse(Request);
+ end;
+
+ var
+ CompanyInformation: Record "Company Information";
+ Customer: Record Customer;
+ EDocumentService: Record "E-Document Service";
+ LibraryEDocument: Codeunit "Library - E-Document";
+ LibraryPermission: Codeunit "Library - Lower Permissions";
+ Assert: Codeunit Assert;
+ ContiniaMockHttpHandler: Codeunit "Continia Mock Http Handler";
+ ContiniaApiUrlMgt: Codeunit "Continia API URL Mgt.";
+ EnvironmentInfoTestLibrary: Codeunit "Environment Info Test Library";
+ ConnectorLibrary: Codeunit "Continia Connector Library";
+ IsInitialized: Boolean;
+ IncorrectValueErr: Label 'Wrong value';
+ Response404ErrorMessageLbl: Label 'The Continia Delivery Network API returned the following error: Error Code Not Found - Not Found';
+}
\ No newline at end of file