Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

#27057 EDocument Connector for Tietoevry #27233 #27626

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2395fb4
app checkin
Roglar01 Oct 29, 2024
e08a53c
Updated for tests
Roglar01 Oct 29, 2024
2ff1977
Tietoevry tests based on Avalara tests
Roglar01 Oct 29, 2024
974aa28
Merge branch 'microsoft:main' into main
Roglar01 Nov 13, 2024
211ab74
Updated app id
Roglar01 Nov 20, 2024
509dc9c
Merge branch 'microsoft:main' into main
Roglar01 Nov 20, 2024
53a81f6
Updated for new namespace
Roglar01 Nov 20, 2024
e214a39
Updated to new E-Doc Core
Roglar01 Nov 26, 2024
5d265de
correction after review
Roglar01 Nov 26, 2024
218a37b
Acknowledge Received
Roglar01 Nov 27, 2024
1112145
Merge branch 'microsoft:main' into main
Roglar01 Nov 28, 2024
e337674
"Uptake latest master of E-Doc Core. Remove dependency on E-Documents…
Dec 1, 2024
202399a
Merge branch 'microsoft:main' into main
Roglar01 Dec 2, 2024
f89a9f5
Syncing with version 26.0.27457.0
Roglar01 Dec 2, 2024
555c2e9
Syncing with version 26.0.27457.0
Roglar01 Dec 2, 2024
e58b5f1
uptake
Roglar01 Dec 2, 2024
1828d9c
Removed dependency to "Document Id"-field
Roglar01 Dec 2, 2024
ab0ea6f
update
Roglar01 Dec 2, 2024
95a42ed
resolved issues
Roglar01 Dec 2, 2024
4620cf6
workflow
Roglar01 Dec 2, 2024
25c524d
moved tooltips to table
Roglar01 Dec 2, 2024
9588622
Fixes
Dec 2, 2024
c55f8f4
Merge branch 'microsoft:main' into main
Roglar01 Dec 2, 2024
71a7b2d
Fix tests
Dec 2, 2024
f9a1f30
Merge branch 'main' of https://github.com/Roglar01/ALAppExtensions in…
Dec 2, 2024
9ae3e59
Merge branch 'microsoft:main' into main
Roglar01 Dec 5, 2024
8d7db5b
Merge branch 'microsoft:main' into main
Roglar01 Dec 11, 2024
456c1e5
Removed unused directives
Roglar01 Dec 11, 2024
135f4e5
Merge branch 'microsoft:main' into main
mjohans8 Dec 23, 2024
ac9597f
Fixed DocumentDownload
mjohans8 Dec 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 55 additions & 0 deletions Apps/W1/EDocumentConnectors/Tietoevry/app/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"id": "3b3c094c-ae7f-43f2-9246-22111b688d2e",
"name": "E-Document Connector - Tietoevry",
"publisher": "Microsoft",
"brief": "E-Document Connector - Tietoevry",
"description": "E-Document Connector - Tietoevry",
"version": "26.0.0.0",
"privacyStatement": "https://go.microsoft.com/fwlink/?LinkId=724009",
"EULA": "https://go.microsoft.com/fwlink/?linkid=2009120",
"help": "https://go.microsoft.com/fwlink/?linkid=2204541",
"url": "https://go.microsoft.com/fwlink/?LinkId=724011",
"logo": "ExtensionLogo.png",
"contextSensitiveHelpUrl": "https://go.microsoft.com/fwlink/?linkid=2206603",
"dependencies": [
{
"id": "e1d97edc-c239-46b4-8d84-6368bdf67c8b",
"name": "E-Document Core",
"publisher": "Microsoft",
"version": "26.0.0.0"
},
{
"id": "d852a468-263e-49e5-bfda-f09e33342b89",
"name": "E-Documents Connector with External Endpoints",
"publisher": "Microsoft",
"version": "26.0.0.0"
}
],
"internalsVisibleTo": [
{
"id": "985549ff-145a-4b5c-acd1-db6d425f6cbc",
"name": "E-Document Connector - Tietoevry Tests",
"publisher": "Microsoft"
}
],
"screenshots": [

],
"platform": "26.0.0.0",
"idRanges": [
{
"from": 6380,
"to": 6389
}
],
"resourceExposurePolicy": {
"allowDebugging": true,
"allowDownloadingSource": true,
"includeSourceInSymbolFile": true
},
"application": "26.0.0.0",
"target": "OnPrem",
"features": [
"TranslationFile"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// ------------------------------------------------------------------------------------------------
// 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.Tietoevry;

using Microsoft.Sales.Peppol;
using Microsoft.Sales.Document;
using Microsoft.Foundation.Company;
using Microsoft.Sales.Customer;
using Microsoft.eServices.EDocument;
using System.Utilities;
using Microsoft.eServices.EDocument.Service.Participant;

codeunit 6380 "Connection Events"
{
SingleInstance = true;
EventSubscriberInstance = StaticAutomatic;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"PEPPOL Validation", OnCheckSalesDocumentOnBeforeCheckCompanyVATRegNo, '', false, false)]
local procedure "PEPPOL Validation_OnCheckSalesDocumentOnBeforeCheckCompanyVATRegNo"(SalesHeader: Record "Sales Header"; CompanyInformation: Record "Company Information"; var IsHandled: Boolean)
var
ExternalConnectionSetup: Record "Connection Setup";
begin
if not ExternalConnectionSetup.Get() then
exit;

IsHandled := true;
if CompanyInformation."VAT Registration No." = '' then
Error(MissingCompInfVATRegNoErr, CompanyInformation.TableCaption());
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"PEPPOL Validation", OnCheckSalesDocumentOnBeforeCheckCustomerVATRegNo, '', false, false)]
local procedure "PEPPOL Validation_OnCheckSalesDocumentOnBeforeCheckCustomerVATRegNo"(SalesHeader: Record "Sales Header"; Customer: Record Customer; var IsHandled: Boolean)
var
ServiceParticipant: Record "Service Participant";
EDocumentService: Record "E-Document Service";
EDocExtConnectionSetup: Record "Connection Setup";
begin
if not EDocExtConnectionSetup.Get() then
exit;
EDocumentService.SetRange("Service Integration", EDocumentService."Service Integration"::Tietoevry);
if not EDocumentService.FindFirst() then
exit;

IsHandled := true;
if (SalesHeader."Document Type" in [SalesHeader."Document Type"::Invoice, SalesHeader."Document Type"::Order, SalesHeader."Document Type"::"Credit Memo"]) and
Customer.Get(SalesHeader."Bill-to Customer No.")
then
if Customer."VAT Registration No." = '' then
Error(MissingCustInfoErr, Customer.FieldCaption("VAT Registration No."), Customer."No.");

if not ServiceParticipant.Get(EDocumentService.Code, ServiceParticipant."Participant Type"::Customer, SalesHeader."Bill-to Customer No.") then
ServiceParticipant.Init();

if ServiceParticipant."Participant Identifier" = '' then
Error(MissingCustInfoErr, ServiceParticipant.FieldCaption("Participant Identifier"), Customer."No.");
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc. Import", 'OnAfterInsertImportedEdocument', '', false, false)]
local procedure OnAfterInsertEdocument(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; var TempBlob: Codeunit "Temp Blob"; EDocCount: Integer; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage)
var
LocalHttpRequest: HttpRequestMessage;
LocalHttpResponse: HttpResponseMessage;
DocumentOutStream: OutStream;
ContentData, MessageId : Text;
begin
if EDocumentService."Service Integration" <> EDocumentService."Service Integration"::Tietoevry then
exit;

HttpResponse.Content.ReadAs(ContentData);
if not TietoevryProcessing.ParseReceivedDocument(ContentData, EDocument."Index In Batch", MessageId) then begin
EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, DocumentIdNotFoundErr);
exit;
end;

TietoevryConnection.HandleGetTargetDocumentRequest(MessageId, LocalHttpRequest, LocalHttpResponse, false);
EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, LocalHttpRequest, LocalHttpResponse);

LocalHttpResponse.Content.ReadAs(ContentData);
if ContentData = '' then
EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(CouldNotRetrieveDocumentErr, MessageId));

Clear(TempBlob);
TempBlob.CreateOutStream(DocumentOutStream, TextEncoding::UTF8);
DocumentOutStream.WriteText(ContentData);

TietoevryProcessing.AcknowledgeEDocument(EDocument, EDocumentService, MessageId);

EDocument."Message Id" := CopyStr(MessageId, 1, MaxStrLen(EDocument."Message Id"));

EDocumentLogHelper.InsertLog(EDocument, EDocumentService, TempBlob, "E-Document Service Status"::Imported);
end;

[EventSubscriber(ObjectType::Table, Database::"E-Document Service", 'OnAfterValidateEvent', 'Document Format', false, false)]
local procedure OnAfterValidateDocumentFormat(var Rec: Record "E-Document Service"; var xRec: Record "E-Document Service"; CurrFieldNo: Integer)
var
EDocServiceSupportedType: Record "E-Doc. Service Supported Type";
begin
if Rec."Document Format" <> Rec."Document Format"::"TE PEPPOL BIS 3.0" then
exit;

EDocServiceSupportedType.SetRange("E-Document Service Code", Rec.Code);
if EDocServiceSupportedType.IsEmpty() then begin
EDocServiceSupportedType.Init();
EDocServiceSupportedType."E-Document Service Code" := Rec.Code;
EDocServiceSupportedType."Source Document Type" := EDocServiceSupportedType."Source Document Type"::"Sales Invoice";
EDocServiceSupportedType.Insert();

EDocServiceSupportedType."Source Document Type" := EDocServiceSupportedType."Source Document Type"::"Sales Credit Memo";
EDocServiceSupportedType.Insert();

EDocServiceSupportedType."Source Document Type" := EDocServiceSupportedType."Source Document Type"::"Service Invoice";
EDocServiceSupportedType.Insert();

EDocServiceSupportedType."Source Document Type" := EDocServiceSupportedType."Source Document Type"::"Service Credit Memo";
EDocServiceSupportedType.Insert();
end;
end;

[EventSubscriber(ObjectType::Table, Database::"Service Participant", 'OnAfterValidateEvent', 'Participant Identifier', false, false)]
local procedure OnAfterValidateServiceParticipant(var Rec: Record "Service Participant"; var xRec: Record "Service Participant"; CurrFieldNo: Integer)
var
EDocumentService: Record "E-Document Service";
begin
if not EDocumentService.Get(Rec.Service) then
exit;
if EDocumentService."Service Integration" <> EDocumentService."Service Integration"::Tietoevry then
exit;
if Rec."Participant Identifier" <> '' then
if not TietoevryProcessing.IsValidSchemeId(Rec."Participant Identifier") then
Rec.FieldError(Rec."Participant Identifier");
end;

var
TietoevryConnection: Codeunit "Connection";
TietoevryProcessing: Codeunit "Processing";
EDocumentLogHelper: Codeunit "E-Document Log Helper";
EDocumentErrorHelper: Codeunit "E-Document Error Helper";
#pragma warning disable AA0470
MissingCompInfVATRegNoErr: Label 'You must specify VAT Registration No. in %1.', Comment = '%1=Company Information';
#pragma warning restore AA0470
#pragma warning disable AA0470
MissingCustInfoErr: Label 'You must specify %1 for Customer %2.', Comment = '%1=Fieldcaption %2=Customer No.';
#pragma warning restore AA0470
CouldNotRetrieveDocumentErr: Label 'Could not retrieve document with id: %1 from the service', Comment = '%1 - Document ID';
DocumentIdNotFoundErr: Label 'Document ID not found in response';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// ------------------------------------------------------------------------------------------------
// 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.Tietoevry;

using Microsoft.EServices.EDocument;
using System.Utilities;
using Microsoft.Purchases.Posting;
using Microsoft.Purchases.Document;

codeunit 6381 "Connection"
{
Access = Internal;
Permissions = tabledata "E-Document" = m;

procedure HandleSendDocumentRequest(var TempBlob: Codeunit "Temp Blob"; var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean
begin
if not TietoevryAPIRequests.SendDocumentRequest(TempBlob, EDocument, HttpRequest, HttpResponse) then
if Retry then
TietoevryAPIRequests.SendDocumentRequest(TempBlob, EDocument, HttpRequest, HttpResponse);

exit(CheckIfSuccessfulRequest(EDocument, HttpResponse));
end;

procedure CheckDocumentStatus(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean
begin
if not TietoevryAPIRequests.GetDocumentStatusRequest(EDocument, HttpRequest, HttpResponse) then
if Retry then
TietoevryAPIRequests.GetDocumentStatusRequest(EDocument, HttpRequest, HttpResponse);

exit(CheckIfSuccessfulRequest(EDocument, HttpResponse));
end;

procedure GetReceivedDocuments(var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean
var
InputTxt: Text;
begin
if not TietoevryAPIRequests.GetReceivedDocumentsRequest(HttpRequest, HttpResponse) then
if Retry then
TietoevryAPIRequests.GetReceivedDocumentsRequest(HttpRequest, HttpResponse);

if not HttpResponse.IsSuccessStatusCode then
exit(false);

InputTxt := ParseAsJsonArray(HttpResponse.Content);
if InputTxt <> '' then
exit(true);
end;

procedure HandleGetTargetDocumentRequest(DocumentId: Text; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean
begin
if not TietoevryAPIRequests.GetTargetDocumentRequest(DocumentId, HttpRequest, HttpResponse) then
if Retry then
TietoevryAPIRequests.GetTargetDocumentRequest(DocumentId, HttpRequest, HttpResponse);

if HttpResponse.IsSuccessStatusCode then
exit(true);
end;

procedure HandleSendFetchDocumentRequest(DocumentId: Text; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean
begin
if not TietoevryAPIRequests.SendAcknowledgeDocumentRequest(DocumentId, HttpRequest, HttpResponse) then
if Retry then
TietoevryAPIRequests.SendAcknowledgeDocumentRequest(DocumentId, HttpRequest, HttpResponse);

if HttpResponse.IsSuccessStatusCode then
exit(true);
end;

procedure ParseAsJsonArray(HttpContentResponse: HttpContent): Text
var
ResponseJArray: JsonArray;
ResponseJson: Text;
Result: Text;
IsJsonResponse: Boolean;
begin
HttpContentResponse.ReadAs(Result);
IsJsonResponse := ResponseJArray.ReadFrom(Result);
if IsJsonResponse then
ResponseJArray.WriteTo(ResponseJson)
else
exit('');

exit(Result);
end;

local procedure CheckIfSuccessfulRequest(EDocument: Record "E-Document"; HttpResponse: HttpResponseMessage): Boolean
var
EDocumentErrorHelper: Codeunit "E-Document Error Helper";
begin
if HttpResponse.IsSuccessStatusCode then
exit(true);

if HttpResponse.IsBlockedByEnvironment then
EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, EnvironmentBlocksErr)
else
EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(UnsuccessfulResponseErr, HttpResponse.HttpStatusCode, HttpResponse.ReasonPhrase));
end;


[EventSubscriber(ObjectType::Codeunit, Codeunit::"Purch.-Post", 'OnAfterCheckAndUpdate', '', false, false)]
local procedure CheckOnPosting(var PurchaseHeader: Record "Purchase Header"; CommitIsSuppressed: Boolean; PreviewMode: Boolean)
var
EDocument: Record "E-Document";
EDocumentService: Record "E-Document Service";
EDocumentServiceStatus: Record "E-Document Service Status";
begin
EDocument.SetRange("Document Record ID", PurchaseHeader.RecordId);
if not EDocument.FindFirst() then
exit;

EDocumentService.SetRange("Service Integration", EDocumentService."Service Integration"::Tietoevry);
if EDocumentService.FindFirst() then;
EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No");
EDocumentServiceStatus.SetRange("E-Document Service Code", EDocumentService.Code);
if EDocumentServiceStatus.FindSet() then
repeat
EDocumentServiceStatus.TestField(EDocumentServiceStatus.Status, EDocumentServiceStatus.Status::Approved);
until EDocumentServiceStatus.Next() = 0;
end;

var
TietoevryAPIRequests: Codeunit "API Requests";
UnsuccessfulResponseErr: Label 'There was an error sending the request. Response code: %1 and error message: %2', Comment = '%1 - http response status code, e.g. 400, %2- error message';
EnvironmentBlocksErr: Label 'The request to send documents has been blocked. To resolve the problem, enable outgoing HTTP requests for the E-Document apps on the Extension Management page.';
}
Original file line number Diff line number Diff line change
@@ -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.Tietoevry;

using System.Utilities;
using Microsoft.EServices.EDocument;

codeunit 6382 "Integration Impl." implements "E-Document Integration"
{
Access = Internal;

procedure Send(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage)
var
begin
TietoevryProcessing.SendEDocument(EDocument, TempBlob, IsAsync, HttpRequest, HttpResponse);
end;

procedure SendBatch(var EDocuments: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage)
begin
IsAsync := false;
Error('Batch sending is not supported in this version');
end;

procedure GetResponse(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean
begin
exit(TietoevryProcessing.GetDocumentResponse(EDocument, HttpRequest, HttpResponse));
end;

procedure GetApproval(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean
begin
Error('Get Approval is not supported in this version');
end;

procedure Cancel(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean
begin
exit(TietoevryProcessing.CancelEDocument(EDocument, HttpRequest, HttpResponse));
end;

procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage)
begin
TietoevryProcessing.ReceiveDocument(TempBlob, HttpRequest, HttpResponse);
end;

procedure GetDocumentCountInBatch(var TempBlob: Codeunit "Temp Blob"): Integer
begin
exit(TietoevryProcessing.GetDocumentCountInBatch(TempBlob));
end;

procedure GetIntegrationSetup(var SetupPage: Integer; var SetupTable: Integer)
begin
SetupPage := page::"Connection Setup Card";
SetupTable := Database::"Connection Setup";
end;

var
TietoevryProcessing: Codeunit "Processing";
}
Loading
Loading