Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[E-Documents Core] - Manual multiple files import #8

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
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
20 changes: 19 additions & 1 deletion Apps/W1/EDocument/app/src/Document/EDocuments.Page.al
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,29 @@ page 6122 "E-Documents"
Caption = 'New From File';
ToolTip = 'Create an electronic document by manually uploading a file.';
Image = Import;
Visible = false;
petemchlk marked this conversation as resolved.
Show resolved Hide resolved

trigger OnAction()
begin
NewFromFile();
end;
}
fileuploadaction(ImportManuallyMultiple)
{
Caption = 'Import Files';
ToolTip = 'Create electronic documents by uploading single or multiple files.';
Image = Import;
AllowedFileExtensions = '.xml';
AllowMultipleFiles = true;
petemchlk marked this conversation as resolved.
Show resolved Hide resolved
trigger OnAction(Files: List of [FileUpload])
var
EDocImport: Codeunit "E-Doc. Import";
begin
EDocImport.UploadDocuments(Files);
CurrPage.Update();
petemchlk marked this conversation as resolved.
Show resolved Hide resolved
end;

petemchlk marked this conversation as resolved.
Show resolved Hide resolved
}
action(EDocumentServices)
{
RunObject = Page "E-Document Services";
Expand All @@ -88,7 +105,8 @@ page 6122 "E-Documents"
}
area(Promoted)
{
actionref(Promoted_ImportManually; ImportManually) { }
actionref(Promoted_ImportManually; ImportManually) { Visible = false; }
petemchlk marked this conversation as resolved.
Show resolved Hide resolved
actionref(Promoted_ImportManuallyMultiple; ImportManuallyMultiple) { }
actionref(Promoted_EDocumentServices; EDocumentServices) { }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ codeunit 6134 "E-Doc. Integration Management"
local procedure ReceiveSingleDocument(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; DocumentMetadata: Codeunit "Temp Blob"; IDocumentReceiver: Interface IDocumentReceiver): Boolean
var
ReceiveContext, FetchContextImpl : Codeunit ReceiveContext;
EDocumentContent: Codeunit "Temp Blob";
ErrorCount: Integer;
Success, IsFetchableType : Boolean;
begin
Expand All @@ -209,19 +210,22 @@ codeunit 6134 "E-Doc. Integration Management"
if not Success then
exit(false);

if not ReceiveContext.GetTempBlob().HasValue() then
EDocumentContent := ReceiveContext.GetTempBlob();
if not EDocumentContent.HasValue() then
exit(false);

IsFetchableType := IDocumentReceiver is IReceivedDocumentMarker;
if IsFetchableType then begin
ErrorCount := EDocumentErrorHelper.ErrorMessageCount(EDocument);
RunMarkFetched(EDocument, EDocumentService, ReceiveContext.GetTempBlob(), IDocumentReceiver, FetchContextImpl);
Success := EDocumentErrorHelper.ErrorMessageCount(EDocument) = ErrorCount;

if not Success then
exit(false);
end;

if HasDuplicate(EDocument, EDocumentContent, EDocumentService."Document Format") then
exit(false);

// Only after sucecssfully downloading and (optionally) marking as fetched, the document is considered imported
// Insert logs for downloading document
InsertLogAndEDocumentStatus(EDocument, EDocumentService, ReceiveContext.GetTempBlob(), ReceiveContext.Status().GetStatus());
Expand All @@ -235,6 +239,24 @@ codeunit 6134 "E-Doc. Integration Management"
end;

petemchlk marked this conversation as resolved.
Show resolved Hide resolved

internal procedure HasDuplicate(var IncomingEDocument: Record "E-Document"; var EDocumentContent: Codeunit "Temp Blob"; IEDocument: Interface "E-Document"): Boolean
petemchlk marked this conversation as resolved.
Show resolved Hide resolved
var
EDocument: Record "E-Document";
EDocGetBasicInfo: Codeunit "E-Doc. Get Basic Info";
begin
// Commit before getting basic info with error handling (if Codeunit.Run then )
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    // Commit before getting basic info with error handling (if Codeunit.Run then)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should remove this? Wouldn't it be better to have comment on why we do the commit? They have the same comment when they call GetBasicInfo with commit before

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No no, just one space symbol need to be removed before the last bracket :D

Commit();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is from another PR, but this commit in here makes me a bit nervous. Because seeing a procedure like HasDuplicates doesn't make you think that the transaction will be commited in here...

You don't have to change anything, because I know you have other fires to fight, and I know MS is quite liberal with their commits as well, but just something to think about...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually tried to avoid this commit, but happened to me while testing manually to get this error. Will keep this in my mind so if there will be some time left will try to handle this :)

EDocGetBasicInfo.SetValues(IEDocument, IncomingEDocument, EDocumentContent);
if not EDocGetBasicInfo.Run() then
exit(false);
EDocGetBasicInfo.GetValues(IEDocument, IncomingEDocument, EDocumentContent);

EDocument.SetFilter("Entry No", '<>%1', IncomingEDocument."Entry No");
EDocument.SetRange("Incoming E-Document No.", IncomingEDocument."Incoming E-Document No.");
EDocument.SetRange("Bill-to/Pay-to No.", IncomingEDocument."Bill-to/Pay-to No.");
EDocument.SetRange("Document Date", IncomingEDocument."Document Date");
exit(not EDocument.IsEmpty());
end;
#endregion

#region Actions
Expand Down Expand Up @@ -564,7 +586,6 @@ codeunit 6134 "E-Doc. Integration Management"
exit(true);
end;


#endregion

var
Expand Down
142 changes: 125 additions & 17 deletions Apps/W1/EDocument/app/src/Processing/EDocImport.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// ------------------------------------------------------------------------------------------------
namespace Microsoft.eServices.EDocument;

using Microsoft.eServices.EDocument;
using Microsoft.Finance.GeneralLedger.Journal;
using Microsoft.Purchases.Vendor;
using Microsoft.Purchases.Document;
Expand All @@ -19,33 +20,38 @@ codeunit 6140 "E-Doc. Import"
internal procedure UploadDocument(var EDocument: Record "E-Document")
var
EDocumentService: Record "E-Document Service";
TempBlob: Codeunit "Temp Blob";
OutStr: OutStream;
InStr: InStream;
FileName: Text;
begin
if Page.RunModal(Page::"E-Document Services", EDocumentService) <> Action::LookupOK then
if not this.ChooseEDocumentService(EDocumentService) then
exit;

if not UploadIntoStream('', '', '', FileName, InStr) then
exit;

TempBlob.CreateOutStream(OutStr);
CopyStream(OutStr, InStr);
this.ImportEDocumentFromStream(EDocument, EDocumentService, InStr);
end;

EDocument.Direction := EDocument.Direction::Incoming;
EDocument."Document Type" := Enum::"E-Document Type"::None;
internal procedure UploadDocument(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; DocumentFile: FileUpload): Boolean
petemchlk marked this conversation as resolved.
Show resolved Hide resolved
var
DocumentInStream: InStream;
begin
DocumentFile.CreateInStream(DocumentInStream);
exit(this.ImportEDocumentFromStream(EDocument, EDocumentService, DocumentInStream));
end;

if EDocument."Entry No" = 0 then begin
EDocument.Insert(true);
EDocumentProcessing.InsertServiceStatus(EDocument, EDocumentService, Enum::"E-Document Service Status"::Imported);
end else begin
EDocument.Modify(true);
EDocumentProcessing.ModifyServiceStatus(EDocument, EDocumentService, Enum::"E-Document Service Status"::Imported);
end;
internal procedure UploadDocuments(Documents: List of [FileUpload])
petemchlk marked this conversation as resolved.
Show resolved Hide resolved
var
EDocument: Record "E-Document";
EDocumentService: Record "E-Document Service";
begin
if Documents.Count = 0 then
petemchlk marked this conversation as resolved.
Show resolved Hide resolved
exit;

EDocumentLog.InsertLog(EDocument, EDocumentService, TempBlob, Enum::"E-Document Service Status"::Imported);
EDocumentProcessing.ModifyEDocumentStatus(EDocument, Enum::"E-Document Service Status"::Imported);
if not this.ChooseEDocumentService(EDocumentService) then
exit;

this.HandleMultipleDocumentUpload(Documents, EDocument, EDocumentService);
end;

internal procedure GetBasicInfo(var EDocument: Record "E-Document")
Expand Down Expand Up @@ -303,7 +309,8 @@ codeunit 6140 "E-Doc. Import"
UpdateEDocumentRecordId(EDocument, EDocument."Document Type", DocNo, RecordId);
end;

local procedure UpdateEDocumentRecordId(var EDocument: Record "E-Document"; EDocType: enum "E-Document Type"; DocNo: Code[20]; RecordId: RecordId)
local procedure UpdateEDocumentRecordId(var EDocument: Record "E-Document"; EDocType: enum "E-Document Type"; DocNo: Code[20];
RecordId: RecordId)
petemchlk marked this conversation as resolved.
Show resolved Hide resolved
begin
EDocument."Document Type" := EDocType;
EDocument."Document No." := DocNo;
Expand Down Expand Up @@ -620,6 +627,39 @@ codeunit 6140 "E-Doc. Import"
until TempEDocImportedLine.Next() = 0;
end;

local procedure ChooseEDocumentService(var EDocumentService: Record "E-Document Service"): Boolean
begin
exit(not (Page.RunModal(Page::"E-Document Services", EDocumentService) <> Action::LookupOK));
petemchlk marked this conversation as resolved.
Show resolved Hide resolved
end;

local procedure ImportEDocumentFromStream(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; var InStr: InStream): Boolean
var
IntegrationManagement: Codeunit "E-Doc. Integration Management";
TempBlob: Codeunit "Temp Blob";
OutStr: OutStream;
petemchlk marked this conversation as resolved.
Show resolved Hide resolved
begin
TempBlob.CreateOutStream(OutStr);
CopyStream(OutStr, InStr);

EDocument.Direction := EDocument.Direction::Incoming;
EDocument."Document Type" := Enum::"E-Document Type"::None;

if IntegrationManagement.HasDuplicate(EDocument, TempBlob, EDocumentService."Document Format") then
exit(false);

if EDocument."Entry No" = 0 then begin
EDocument.Insert(true);
EDocumentProcessing.InsertServiceStatus(EDocument, EDocumentService, Enum::"E-Document Service Status"::Imported);
end else begin
EDocument.Modify(true);
EDocumentProcessing.ModifyServiceStatus(EDocument, EDocumentService, Enum::"E-Document Service Status"::Imported);
end;

EDocumentLog.InsertLog(EDocument, EDocumentService, TempBlob, Enum::"E-Document Service Status"::Imported);
EDocumentProcessing.ModifyEDocumentStatus(EDocument, Enum::"E-Document Service Status"::Imported);
exit(true);
end;

internal procedure SetHideDialogs(Hide: Boolean)
begin
HideDialogs := Hide;
Expand All @@ -637,6 +677,70 @@ codeunit 6140 "E-Doc. Import"
end;
#endif

local procedure HandleMultipleDocumentUpload(var Documents: List of [FileUpload]; var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service")
petemchlk marked this conversation as resolved.
Show resolved Hide resolved
var
Document: FileUpload;
DocumentInstream: InStream;
MultipleDocuments: Boolean;
DuplicateExists: Boolean;
NotProcessedDocuments: Integer;
begin
if Documents.Count > 1 then begin
MultipleDocuments := true;
this.SetHideDialogs(true);
end;

foreach Document in Documents do begin
Clear(EDocument);
Clear(DocumentInstream);
Document.CreateInStream(DocumentInstream);

CreateEDocumentFromStream(
EDocument,
EDocumentService,
DocumentInstream,
MultipleDocuments,
DuplicateExists,
NotProcessedDocuments);
end;

if MultipleDocuments then
if DuplicateExists then
Message(StrSubstNo(DuplicatesMsg, NotProcessedDocuments, Documents.Count()))
else
Message(DocsImportedMsg);
end;

internal procedure CreateEDocumentFromStream(
var EDocument: Record "E-Document";
EDocumentService: Record "E-Document Service";
var DocumentInstream: InStream;
MultipleDocuments: Boolean;
var DuplicateExists: Boolean;
var NotProcessedDocuments: Integer)
begin
if not this.ImportEDocumentFromStream(EDocument, EDocumentService, DocumentInstream) then
if MultipleDocuments then begin
DuplicateExists := true;
NotProcessedDocuments += 1;
end else
Error(
EDocumentAlreadyExistErr,
EDocument.FieldCaption("Incoming E-Document No."),
EDocument."Incoming E-Document No.",
EDocument.FieldCaption("Bill-to/Pay-to No."),
EDocument."Bill-to/Pay-to No.",
EDocument.FieldCaption("Document Date"),
EDocument."Document Date");

if EDocument."Entry No" <> 0 then begin
this.ProcessDocument(EDocument, false);
if not this.HideDialogs and EDocErrorHelper.HasErrors(EDocument) then
if Confirm(DocNotCreatedQst, true, EDocument."Document Type") then
Page.Run(Page::"E-Document", EDocument);
end;
end;

var
EDocumentLog: Codeunit "E-Document Log";
EDocImportHelper: Codeunit "E-Document Import Helper";
Expand All @@ -651,6 +755,10 @@ codeunit 6140 "E-Doc. Import"
DocTypeIsNotSupportedErr: Label 'Document type %1 is not supported.', Comment = '%1 - Document Type';
FailedToFindVendorErr: Label 'No vendor is set for Edocument';
CannotProcessEDocumentMsg: Label 'Cannot process E-Document %1 with Purchase Order %2 before Purchase Order has been matched and posted for E-Document %3.', Comment = '%1 - E-Document entry no, %2 - Purchase Order number, %3 - EDocument entry no.';
DocNotCreatedQst: Label 'Failed to create new %1 from E-Document. Do you want to open E-Document and see the reported errors?', Comment = '%1 - E-Document Document Type';
EDocumentAlreadyExistErr: Label 'E-Document with %1 %2, %3 %4 and %5 %6 already exists.', Comment = '%1 - Incoming E-Document No. fieldcaption, %2 - Incoming E-Document No. value, %3 - Bill-to/Pay-to No. fieldcaption, %4 - Bill-to/Pay-to No. value, %5 - Document Date fieldcaption, %6 - Document Date value.';
petemchlk marked this conversation as resolved.
Show resolved Hide resolved
DuplicatesMsg: Label '%1 of %2 uploaded documents were not imported because they already exist in the system.', Comment = '%1 - Not processed documents, %2 - Total documents';
DocsImportedMsg: Label 'Document(s) imported successfully.';

[IntegrationEvent(false, false)]
local procedure OnAfterProcessImportedDocument(var EDocument: Record "E-Document"; var DocumentHeader: RecordRef)
Expand Down
24 changes: 24 additions & 0 deletions Apps/W1/EDocument/edocument_workspace.code-workspace
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"settings": {
"al.enableCodeAnalysis": true,
"al.codeAnalyzers": [
"${CodeCop}",
"${UICop}",
"${AppSourceCop}"
]
},
"folders": [
{
"name": "app",
"path": "app"
},
{
"name": "test",
"path": "test"
},
{
"name": "demo data",
"path": "demo data"
}
]
}
Loading