Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
49 changes: 47 additions & 2 deletions src/Apps/W1/EDocument/App/src/Processing/EDocExport.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ codeunit 6102 "E-Doc. Export"
EDocumentServiceStatus: Record "E-Document Service Status";
EDocWorkFlowProcessing: Codeunit "E-Document WorkFlow Processing";
EDocumentBackgroundJobs: Codeunit "E-Document Background Jobs";
HasServiceResponses: Boolean;
begin
if not WorkFlow.Get(DocumentSendingProfile."Electronic Service Flow") then
Error(DocumentSendingProfileWithWorkflowErr, DocumentSendingProfile."Electronic Service Flow", Format(DocumentSendingProfile."Electronic Document"::"Extended E-Document Service Flow"), DocumentSendingProfile.Code);
Expand All @@ -73,14 +74,30 @@ codeunit 6102 "E-Doc. Export"
if DocumentSendingProfile."Electronic Document" <> DocumentSendingProfile."Electronic Document"::"Extended E-Document Service Flow" then
exit;

if not EDocWorkFlowProcessing.GetServicesFromEntryPointResponseInWorkflow(WorkFlow, EDocumentService) then
HasServiceResponses := EDocWorkFlowProcessing.GetServicesFromEntryPointResponseInWorkflow(WorkFlow, EDocumentService);

if not HasServiceResponses then begin
if not EDocWorkFlowProcessing.WorkflowHasNonServiceResponses(WorkFlow) then
exit;
// Create E-Document for non-service workflow processing (e.g., email-only)
CreateEDocumentForNonServiceWorkflow(EDocument, DocumentHeader, EDocumentType, WorkFlow.Code, DocumentSendingProfile.Code);
if EDocument."Entry No" <> 0 then
EDocumentBackgroundJobs.StartEDocumentCreatedFlow(EDocument);
exit;
end;

EDocument."Workflow Code" := WorkFlow.Code;
EDocument."Document Sending Profile" := DocumentSendingProfile.Code;

if not CreateEDocument(EDocument, DocumentHeader, EDocumentService, EDocumentType) then
if not CreateEDocument(EDocument, DocumentHeader, EDocumentService, EDocumentType) then begin
// No services support the document type. Check for non-service responses (e.g., email).
if not EDocWorkFlowProcessing.WorkflowHasNonServiceResponses(WorkFlow) then
exit;
CreateEDocumentForNonServiceWorkflow(EDocument, DocumentHeader, EDocumentType, WorkFlow.Code, DocumentSendingProfile.Code);
if EDocument."Entry No" <> 0 then
EDocumentBackgroundJobs.StartEDocumentCreatedFlow(EDocument);
exit;
end;

// For each service supporting the document type, export it before creating E-Document Created Flow
EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No");
Expand Down Expand Up @@ -500,6 +517,34 @@ codeunit 6102 "E-Doc. Export"
exit(IExportEligibilityEvaluator.ShouldExport(EDocumentService, SourceDocumentHeader, DocumentType));
end;

local procedure CreateEDocumentForNonServiceWorkflow(var EDocument: Record "E-Document"; var DocumentHeader: RecordRef; EDocumentType: Enum "E-Document Type"; WorkflowCode: Code[20]; DocSendingProfile: Code[20])
var
EDocumentLog: Codeunit "E-Document Log";
begin
EDocument.SetRange("Document Record ID", DocumentHeader.RecordId);
if not EDocument.IsEmpty() then
exit;

EDocument.Init();
EDocument."Workflow Code" := WorkflowCode;
EDocument."Document Sending Profile" := DocSendingProfile;

OnBeforeCreateEDocument(EDocument, DocumentHeader);

EDocument.Validate("Document Record ID", DocumentHeader.RecordId);
EDocument.Validate("Document Type", EDocumentType);
EDocument.Validate(Status, EDocument.Status::"In Progress");
EDocument.Validate(Direction, EDocument.Direction::Outgoing);
EDocument.Insert();

PopulateEDocument(EDocument, DocumentHeader);
EDocument.Modify();

OnAfterCreateEDocument(EDocument, DocumentHeader);

EDocumentLog.InsertLog(EDocument, Enum::"E-Document Service Status"::Created);
end;

var
EDocumentProcessing: Codeunit "E-Document Processing";
EDocumentErrorHelper: Codeunit "E-Document Error Helper";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,20 @@ codeunit 6135 "E-Document WorkFlow Processing"
WorkflowStepArgument: Record "Workflow Step Argument";
EDocumentService: Record "E-Document Service";
EDocument: Record "E-Document";
EDocExport: Codeunit "E-Doc. Export";
begin
if not GetEDocumentFromRecordRef(RecordRef, EDocument) then
exit;
if not ValidateFlowStep(EDocument, WorkflowStepArgument, WorkflowStepInstance, true) then
exit;
EDocumentService.Get(WorkflowStepArgument."E-Document Service");

// Skip if service does not support the document type, but continue workflow
if not EDocExport.IsDocumentTypeSupported(EDocumentService, EDocument."Document Type") then begin
SkipSendAndContinueWorkflow(EDocument, EDocumentService);
exit;
end;

SendEDocument(EDocument, EDocumentService);
end;

Expand Down Expand Up @@ -481,6 +489,12 @@ codeunit 6135 "E-Document WorkFlow Processing"

EDocumentService.Get(WorkflowStepArgument."E-Document Service");

// Skip if service does not support the document type, but continue workflow
if not EDocExport.IsDocumentTypeSupported(EDocumentService, EDocument."Document Type") then begin
WorkflowManagement.HandleEventOnKnownWorkflowInstance(EDocWorkflowSetup.EventEDocExported(), EDocument, EDocument."Workflow Step Instance ID");
exit;
end;

if EDocExport.ExportEDocument(EDocument, EDocumentService) then
WorkflowManagement.HandleEventOnKnownWorkflowInstance(EDocWorkflowSetup.EventEDocExported(), EDocument, EDocument."Workflow Step Instance ID");
end;
Expand Down Expand Up @@ -554,6 +568,29 @@ codeunit 6135 "E-Document WorkFlow Processing"
CannotFindEDocErr: Label 'Cannot find the E-Document with type %1, document number %2.', Comment = '%1 - E-Document type, %2 - Document number';
NotSupportedEDocTypeErr: Label 'The document type %1 is not supported for sending from email.', Comment = '%1 - E-Document type';

internal procedure WorkflowHasNonServiceResponses(Workflow: Record Workflow): Boolean
var
WorkflowStep: Record "Workflow Step";
EDocWorkflowSetup: Codeunit "E-Document Workflow Setup";
begin
WorkflowStep.SetRange("Workflow Code", Workflow.Code);
WorkflowStep.SetRange(Type, WorkflowStep.Type::Response);
WorkflowStep.SetFilter("Function Name", '%1|%2', EDocWorkflowSetup.ResponseSendEDocByEmail(), EDocWorkflowSetup.ResponseSendEDocAndPDFByEmail());
exit(not WorkflowStep.IsEmpty());
end;

local procedure SkipSendAndContinueWorkflow(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service")
var
EDocumentServiceStatus: Record "E-Document Service Status";
begin
// Insert a service status to enable workflow continuation through HandleNextEvent
if not EDocumentServiceStatus.Get(EDocument."Entry No", EDocumentService.Code) then
EDocumentProcessing.InsertServiceStatus(EDocument, EDocumentService, Enum::"E-Document Service Status"::Sent);

EDocument.SetRecFilter();
HandleNextEvent(EDocument, EDocumentService);
end;

[IntegrationEvent(false, false)]
local procedure OnBatchSendWithCustomBatchMode(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var IsHandled: Boolean)
begin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,13 @@ codeunit 6139 "E-Document Workflow Setup"
end;
ResponseSendEDocByEmail():
begin
WorkflowResponseHandling.AddResponsePredecessor(ResponseSendEDocByEmail(), EDocCreated());
WorkflowResponseHandling.AddResponsePredecessor(ResponseSendEDocByEmail(), EventEDocStatusChanged());
WorkflowResponseHandling.AddResponsePredecessor(ResponseSendEDocByEmail(), EventEDocExported());
end;
ResponseSendEDocAndPDFByEmail():
begin
WorkflowResponseHandling.AddResponsePredecessor(ResponseSendEDocAndPDFByEmail(), EDocCreated());
WorkflowResponseHandling.AddResponsePredecessor(ResponseSendEDocAndPDFByEmail(), EventEDocStatusChanged());
WorkflowResponseHandling.AddResponsePredecessor(ResponseSendEDocAndPDFByEmail(), EventEDocExported());
end;
Expand Down
118 changes: 118 additions & 0 deletions src/Apps/W1/EDocument/Test/src/Flow/EDocFlowTest.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ namespace Microsoft.eServices.EDocument.Test;

using Microsoft.eServices.EDocument;
using Microsoft.eServices.EDocument.Integration;
using Microsoft.Foundation.Reporting;
using Microsoft.Sales.Customer;
using System.Automation;
using System.IO;
using System.TestLibraries.Utilities;
Expand All @@ -23,6 +25,7 @@ codeunit 139631 "E-Doc. Flow Test"
LibrarySales: Codeunit "Library - Sales";
LibraryVariableStorage: Codeunit "Library - Variable Storage";
LibraryEDoc: Codeunit "Library - E-Document";
LibraryJobQueue: Codeunit "Library - Job Queue";
LibraryLowerPermission: Codeunit "Library - Lower Permissions";
WrongValueErr: Label 'Wrong value';
WorkflowEmptyErr: Label 'Must return false for an empty workflow';
Expand Down Expand Up @@ -203,6 +206,121 @@ codeunit 139631 "E-Doc. Flow Test"
#pragma warning restore AL0432
#endif

[Test]
procedure EDocFlowShipmentCreatedWhenServiceDoesNotSupportTypeButEmailExists()
var
EDocument: Record "E-Document";
EDocumentServiceStatus: Record "E-Document Service Status";
Customer: Record Customer;
EDocService: Record "E-Document Service";
DocumentSendingProfile: Record "Document Sending Profile";
CustomerNo, DocSendProfileNo, WorkflowCode, ServiceCode : Code[20];
begin
// [FEATURE] [E-Document] [Flow]
// [SCENARIO] E-Document is created for Sales Shipment when service does not support
// the type, but workflow contains email responses

// [GIVEN] Service that supports Sales Invoice but NOT Sales Shipment, workflow with Send + Email
Initialize();
LibraryEDoc.SetupStandardVAT();

CustomerNo := LibrarySales.CreateCustomerNo();
DocSendProfileNo := LibraryEDoc.CreateDocumentSendingProfileForWorkflow(CustomerNo, '');
ServiceCode := LibraryEDoc.CreateService(Enum::"Service Integration"::"Mock");
// Standard service supports Sales Invoice, not Sales Shipment
WorkflowCode := LibraryEDoc.CreateFlowWithServiceAndEmail(DocSendProfileNo, ServiceCode);
LibraryEDoc.UpdateWorkflowOnDocumentSendingProfile(DocSendProfileNo, WorkflowCode);

// [WHEN] Posting a Sales Shipment (type not supported by service)
EDocService.Get(ServiceCode);
Customer.Get(CustomerNo);
LibraryLowerPermission.SetTeamMember();
LibraryJobQueue.SetDoNotHandleCodeunitJobQueueEnqueueEvent(true);

LibraryEDoc.PostSalesShipment(Customer);

// [THEN] E-Document should be created for Sales Shipment
EDocument.FindLast();
Assert.AreEqual(Enum::"E-Document Type"::"Sales Shipment", EDocument."Document Type", WrongValueErr);
Assert.AreEqual(WorkflowCode, EDocument."Workflow Code", WrongValueErr);

// [THEN] No service status should exist (service does not support type)
EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No");
Assert.IsTrue(EDocumentServiceStatus.IsEmpty(), 'No service status should exist for unsupported document type');
end;

[Test]
procedure EDocFlowSendSkippedForUnsupportedDocType()
var
EDocument: Record "E-Document";
EDocumentServiceStatus: Record "E-Document Service Status";
WorkflowStepArgument: Record "Workflow Step Argument";
WorkflowStepInstance: Record "Workflow Step Instance";
EDocWorkflowProcessing: Codeunit "E-Document WorkFlow Processing";
RecordRef: RecordRef;
CustomerNo, DocSendProfileNo, ServiceCode : Code[20];
begin
// [FEATURE] [E-Document] [Flow]
// [SCENARIO] SendEDocument skips when service does not support the document type and sets Sent status

// [GIVEN] E-Document with type Sales Shipment, service that only supports Sales Invoice
Initialize();

CustomerNo := LibrarySales.CreateCustomerNo();
DocSendProfileNo := LibraryEDoc.CreateDocumentSendingProfileForWorkflow(CustomerNo, '');
ServiceCode := LibraryEDoc.CreateService(Enum::"Service Integration"::"Mock");
LibraryEDoc.CreateFlowWithService(DocSendProfileNo, ServiceCode);

EDocument."Entry No" := 0;
EDocument."Document Type" := Enum::"E-Document Type"::"Sales Shipment";
EDocument.Insert();

// [WHEN] Calling SendEDocument with a service that does not support the type
WorkflowStepArgument.FindLast();
WorkflowStepInstance.Argument := WorkflowStepArgument.ID;

LibraryLowerPermission.SetTeamMember();
RecordRef.GetTable(EDocument);
EDocWorkflowProcessing.SendEDocument(RecordRef, WorkflowStepInstance);

// [THEN] Service status is Sent (skipped sending, but workflow can continue)
EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No");
EDocumentServiceStatus.SetRange("E-Document Service Code", ServiceCode);
Assert.IsTrue(EDocumentServiceStatus.FindFirst(), 'Service status should exist after skip');
Assert.AreEqual(Enum::"E-Document Service Status"::Sent, EDocumentServiceStatus.Status, 'Service status should be Sent when type is not supported');
end;

[Test]
procedure EDocFlowEmailOnlyWorkflowCreatesEDocument()
var
EDocument: Record "E-Document";
Customer: Record Customer;
CustomerNo, DocSendProfileNo, WorkflowCode : Code[20];
begin
// [FEATURE] [E-Document] [Flow]
// [SCENARIO] E-Document created when workflow has only email response and no service responses

// [GIVEN] Workflow with only email response (no service/send response)
Initialize();
LibraryEDoc.SetupStandardVAT();

CustomerNo := LibrarySales.CreateCustomerNo();
DocSendProfileNo := LibraryEDoc.CreateDocumentSendingProfileForWorkflow(CustomerNo, '');
WorkflowCode := LibraryEDoc.CreateFlowWithEmailOnly(DocSendProfileNo);
LibraryEDoc.UpdateWorkflowOnDocumentSendingProfile(DocSendProfileNo, WorkflowCode);

// [WHEN] Posting a Sales Invoice
Customer.Get(CustomerNo);
LibraryLowerPermission.SetTeamMember();
LibraryJobQueue.SetDoNotHandleCodeunitJobQueueEnqueueEvent(true);
LibraryEDoc.PostInvoice(Customer);

// [THEN] E-Document should be created even without any service
EDocument.FindLast();
Assert.AreEqual(Enum::"E-Document Type"::"Sales Invoice", EDocument."Document Type", WrongValueErr);
Assert.AreEqual(WorkflowCode, EDocument."Workflow Code", WrongValueErr);
end;

local procedure Initialize()
var
TransformationRule: Record "Transformation Rule";
Expand Down
44 changes: 44 additions & 0 deletions src/Apps/W1/EDocument/Test/src/LibraryEDocument.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,50 @@ codeunit 139629 "Library - E-Document"
exit(Workflow.Code);
end;

procedure CreateFlowWithServiceAndEmail(DocSendingProfile: Code[20]; ServiceCode: Code[20]): Code[20]
var
Workflow: Record Workflow;
WorkflowStepResponse: Record "Workflow Step";
WorkflowStepArgument: Record "Workflow Step Argument";
EDocWorkflowSetup: Codeunit "E-Document Workflow Setup";
EDocCreatedEventID, SendEDocResponseEventID, EmailResponseEventID : Integer;
EventConditions: Text;
begin
LibraryWorkflow.CreateWorkflow(Workflow);
EventConditions := CreateWorkflowEventConditionDocSendingProfileFilter(DocSendingProfile);

EDocCreatedEventID := LibraryWorkflow.InsertEntryPointEventStep(Workflow, EDocWorkflowSetup.EDocCreated());
LibraryWorkflow.InsertEventArgument(EDocCreatedEventID, EventConditions);
SendEDocResponseEventID := LibraryWorkflow.InsertResponseStep(Workflow, EDocWorkflowSetup.EDocSendEDocResponseCode(), EDocCreatedEventID);
EmailResponseEventID := LibraryWorkflow.InsertResponseStep(Workflow, EDocWorkflowSetup.ResponseSendEDocByEmail(), SendEDocResponseEventID);

WorkflowStepResponse.Get(Workflow.Code, SendEDocResponseEventID);
WorkflowStepArgument.Get(WorkflowStepResponse.Argument);
WorkflowStepArgument.Validate("E-Document Service", ServiceCode);
WorkflowStepArgument.Modify();

LibraryWorkflow.EnableWorkflow(Workflow);
exit(Workflow.Code);
end;

procedure CreateFlowWithEmailOnly(DocSendingProfile: Code[20]): Code[20]
var
Workflow: Record Workflow;
EDocWorkflowSetup: Codeunit "E-Document Workflow Setup";
EDocCreatedEventID: Integer;
EventConditions: Text;
begin
LibraryWorkflow.CreateWorkflow(Workflow);
EventConditions := CreateWorkflowEventConditionDocSendingProfileFilter(DocSendingProfile);

EDocCreatedEventID := LibraryWorkflow.InsertEntryPointEventStep(Workflow, EDocWorkflowSetup.EDocCreated());
LibraryWorkflow.InsertEventArgument(EDocCreatedEventID, EventConditions);
LibraryWorkflow.InsertResponseStep(Workflow, EDocWorkflowSetup.ResponseSendEDocByEmail(), EDocCreatedEventID);

LibraryWorkflow.EnableWorkflow(Workflow);
exit(Workflow.Code);
end;

local procedure DeleteEDocumentRelatedEntities()
var
DynamicRequestPageEntity: Record "Dynamic Request Page Entity";
Expand Down
Loading