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-Document Core] - Allow to recreate unposted purchase documents from an incoming e-document #27973

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3e81f6a
add EDocument app workspace
petemchlk Dec 11, 2024
f4c11e2
add code analyzers settings to code workspace
petemchlk Dec 12, 2024
26753b9
Merge pull request #1 from GMatuleviciute/dev/pmi/EDocumentWorkspace
GMatuleviciute Dec 12, 2024
8370437
allow to recreate unposted purchase documents from an incoming e-docu…
AdeleStankeviciute Jan 14, 2025
508be12
change status modifying, add automated tests
AdeleStankeviciute Jan 16, 2025
59a9663
refactor automated test
AdeleStankeviciute Jan 16, 2025
4648160
clear document no after deletion
AdeleStankeviciute Jan 17, 2025
1687dcd
insert log after deleting document
AdeleStankeviciute Jan 20, 2025
5b89c53
fix
AdeleStankeviciute Jan 20, 2025
60bb62b
fix
AdeleStankeviciute Jan 20, 2025
a19432d
refactor status modification
AdeleStankeviciute Jan 20, 2025
629fe29
fixes
AdeleStankeviciute Jan 21, 2025
08f04de
clear order no when order is deleted
AdeleStankeviciute Jan 22, 2025
d8293d2
fix service status after posting purchase document
AdeleStankeviciute Jan 24, 2025
0d1cc5f
use clear procedure
AdeleStankeviciute Feb 3, 2025
4008028
test fix
AdeleStankeviciute Feb 3, 2025
5c52ac8
clear document record id after deleting purchase document
AdeleStankeviciute Feb 11, 2025
4bb541c
restructure afterdelete event
AdeleStankeviciute Feb 11, 2025
8b9b4cd
Merge branch 'main' into dev/asm/RecreateDeletedPurchaseDocument
AdeleStankeviciute Feb 13, 2025
705b1a0
fixes
AdeleStankeviciute Feb 14, 2025
4a54f57
fix automated test
AdeleStankeviciute Feb 17, 2025
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
15 changes: 14 additions & 1 deletion Apps/W1/EDocument/app/src/Document/EDocument.Page.al
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,19 @@ page 6121 "E-Document"
EDocOrderMatch.RunMatching(Rec);
end;
}
action(DeleteRelatedDocument)
{
Caption = 'Delete Related Document';
ToolTip = 'Delete the related purchase document.';
Image = Delete;
Visible = IsIncomingDoc and IsProcessed;

trigger OnAction()
begin
if Confirm(StrSubstNo(this.ConfirmDeleteRelatedDocQst, this.RecordLinkTxt)) then
this.EDocumentHelper.DeleteRelatedRecord(Rec);
end;
}
}
group(Troubleshoot)
{
Expand Down Expand Up @@ -462,7 +475,6 @@ page 6121 "E-Document"
actionref(Cancel_promoteed; Cancel) { }
actionref(Approval_promoteed; GetApproval) { }
actionref(Preview_promoteed; ViewFile) { }

}
group(Category_Troubleshoot)
{
Expand Down Expand Up @@ -651,5 +663,6 @@ page 6121 "E-Document"
ShowRelink, ShowMapToOrder, HasErrorsOrWarnings, HasErrors, IsIncomingDoc, IsProcessed, CopilotVisible : Boolean;
EDocHasErrorOrWarningMsg: Label 'Errors or warnings found for E-Document. Please review below in "Error Messages" section.';
DocNotCreatedMsg: Label 'Failed to create new %1 from E-Document. Please review errors below.', Comment = '%1 - E-Document Document Type';
ConfirmDeleteRelatedDocQst: Label 'Do you want to delete the related document %1?', Comment = '%1 - related record ID';

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ enum 6106 "E-Document Service Status"
value(17; "Order Linked") { Caption = 'Order linked'; }
value(18; "Pending") { Caption = 'Pending Document Link'; }
value(19; "Approval Error") { Caption = 'Approval error'; }
value(21; "Imported Document Deleted") { Caption = 'Imported document deleted'; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,21 @@ codeunit 6108 "E-Document Processing"
exit(GetPostedRecord(EDocument, RelatedRecord));
end;

/// <summary>
/// Deletes related record if it is not posted.
/// </summary>
/// <param name="EDocument">E-Document record</param>
procedure DeleteRelatedRecord(EDocument: Record "E-Document")
var
RecRef: RecordRef;
begin
if this.GetRelatedRecord(EDocument, RecRef) then
if RecRef.Number = Database::"Purchase Header" then
Copy link
Contributor

Choose a reason for hiding this comment

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

This model is insufficient.
Assumption should be that any document type can be deleted.
In case that document is posted it cannot.
How do you know document is posted? E-Doc state Completed should indicate that.

RecRef.Delete(true)
else
Error(this.CannotDeletePostedRecordErr);
end;

procedure GetTelemetryDimensions(EDocService: Record "E-Document Service"; var EDocument: Record "E-Document"; var Dimensions: Dictionary of [Text, Text])
var
EDocument2: Record "E-Document";
Expand Down Expand Up @@ -454,4 +469,5 @@ codeunit 6108 "E-Document Processing"
EDocTelemetryCategoryLbl: Label 'E-Document', Locked = true;
EDocTelemetryIdLbl: Label 'E-Doc %1', Locked = true;
EDocTok: Label 'W1 E-Document', Locked = true;
CannotDeletePostedRecordErr: Label 'Cannot delete related record because it is already posted.';
}
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,37 @@ codeunit 6103 "E-Document Subscription"
local procedure OnBeforeOnDeletePurchaseHeader(var PurchaseHeader: Record "Purchase Header"; var IsHandled: Boolean)
begin
if not IsNullGuid(PurchaseHeader."E-Document Link") then
Error(DeleteNotAllowedErr);
if GuiAllowed() then
if not Confirm(this.ConfirmDeleteQst) then
Error('');
end;

[EventSubscriber(ObjectType::Table, Database::"Purchase Header", 'OnAfterDeleteEvent', '', false, false)]
local procedure OnAfterDeletePurchaseHeader(var Rec: Record "Purchase Header"; RunTrigger: Boolean)
var
EDocument: Record "E-Document";
EDocumentService: Record "E-Document Service";
EDocumentLog: Codeunit "E-Document Log";
EDocumentProcessing: Codeunit "E-Document Processing";
EDocServiceStatusDeleted: Enum "E-Document Service Status";
begin
if IsNullGuid(Rec."E-Document Link") then
exit;

if not EDocument.GetBySystemId(Rec."E-Document Link") then
exit;

EDocServiceStatusDeleted := Enum::"E-Document Service Status"::"Imported Document Deleted";
EDocumentService := EDocumentLog.GetLastServiceFromLog(EDocument);

Clear(EDocument."Document No.");
Clear(EDocument."Document Record ID");
if Rec."Document Type" = Rec."Document Type"::Order then
Clear(EDocument."Order No.");

EDocumentLog.InsertLog(EDocument, EDocumentService, EDocServiceStatusDeleted);
EDocumentProcessing.ModifyServiceStatus(EDocument, EDocumentService, EDocServiceStatusDeleted);
EDocumentProcessing.ModifyEDocumentStatus(EDocument, EDocServiceStatusDeleted);
Copy link
Contributor

Choose a reason for hiding this comment

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

Not handled properly. This new status is not taken into account inside the function.

Choose a reason for hiding this comment

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

The new status translates to "In Progress" E-Document status so it will be handled in this procedure

end;

local procedure RunEDocumentCheck(Record: Variant; EDocumentProcPhase: Enum "E-Document Processing Phase")
Expand Down Expand Up @@ -270,6 +300,7 @@ codeunit 6103 "E-Document Subscription"
EDocService: Record "E-Document Service";
EDocumentLog: Codeunit "E-Document Log";
EDocLogHelper: Codeunit "E-Document Log Helper";
EDocumentProcessing: Codeunit "E-Document Processing";
PostedSourceDocumentHeader: RecordRef;
begin
PostedSourceDocumentHeader.GetTable(PostedRecord);
Expand All @@ -281,6 +312,7 @@ codeunit 6103 "E-Document Subscription"

EDocService := EDocumentLog.GetLastServiceFromLog(EDocument);
EDocLogHelper.InsertLog(EDocument, EDocService, Enum::"E-Document Service Status"::"Imported Document Created");
EDocumentProcessing.ModifyServiceStatus(EDocument, EDocService, Enum::"E-Document Service Status"::"Imported Document Created");
end;

local procedure CreateEDocumentFromPosedDocument(PostedRecord: Variant)
Expand Down Expand Up @@ -308,5 +340,5 @@ codeunit 6103 "E-Document Subscription"
EDocumentHelper: Codeunit "E-Document Helper";
EDocumentProcessingPhase: Enum "E-Document Processing Phase";
WrongAmountErr: Label 'Purchase Document cannot be released as Amount Incl. VAT: %1, is different from E-Document Amount Incl. VAT: %2', Comment = '%1 - Purchase document amount, %2 - E-document amount';
DeleteNotAllowedErr: Label 'Deletion of Purchase Header linked to E-Document is not allowed.';
ConfirmDeleteQst: Label 'This purchase document is created from an E-Document. Do you want to proceed with deletion?';
}
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"
}
]
}
16 changes: 12 additions & 4 deletions Apps/W1/EDocument/test/src/Processing/EDocE2ETest.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,7 @@ codeunit 139624 "E-Doc E2E Test"
end;

[Test]
[HandlerFunctions('DeleteConfirmationHandler')]
procedure DeleteLinkedPurchaseHeaderNoAllowedSuccess()
var
PurchaseHeader: Record "Purchase Header";
Expand All @@ -1445,9 +1446,8 @@ codeunit 139624 "E-Doc E2E Test"
PurchaseHeader.Modify();
Commit();

// [THEN] Fails to delete
// [THEN] Show confirmation message and throw error if cancelled
asserterror PurchaseHeader.Delete(true);
Assert.ExpectedError(DeleteNotAllowedErr);

// [GIVEN] Reset link
PurchaseHeader."E-Document Link" := NullGuid;
Expand Down Expand Up @@ -2233,6 +2233,7 @@ codeunit 139624 "E-Doc E2E Test"
end;

[Test]
[HandlerFunctions('DeleteConfirmationHandler')]
internal procedure DeleteLinkedPurchaseHeaderNoAllowedSuccess26()
var
PurchaseHeader: Record "Purchase Header";
Expand All @@ -2248,9 +2249,8 @@ codeunit 139624 "E-Doc E2E Test"
PurchaseHeader.Modify();
Commit();

// [THEN] Fails to delete
// [THEN] Show confirmation message and throw error if cancelled
asserterror PurchaseHeader.Delete(true);
Assert.ExpectedError(DeleteNotAllowedErr);

// [GIVEN] Reset link
PurchaseHeader."E-Document Link" := NullGuid;
Expand All @@ -2261,4 +2261,12 @@ codeunit 139624 "E-Doc E2E Test"
end;

#endif
[ConfirmHandler]
procedure DeleteConfirmationHandler(Message: Text[1024]; var Reply: Boolean)
var
ExpectedConfirmLbl: Label 'This purchase document is created from E-Document. Do you want to proceed with deletion?';
begin
Assert.ExpectedConfirm(ExpectedConfirmLbl, Message);
Reply := false;
end;
}
124 changes: 123 additions & 1 deletion Apps/W1/EDocument/test/src/Receive/EDocReceiveTest.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -1340,6 +1340,59 @@ codeunit 139628 "E-Doc. Receive Test"
PurchaseHeader.Delete(true);
end;

[Test]
[HandlerFunctions('ConfirmHandlerYes')]
procedure RecreateReceivedPurchaseInvoice()
var
EDocService: Record "E-Document Service";
EDocServicePage: TestPage "E-Document Service";
EDocumentPage: TestPage "E-Document";
CreatedInvoiceNo: Text[20];
begin
// [FEATURE] [E-Document] [Receive]
// [SCENARIO] Delete and recreate purchase invoice from E-Document page
Initialize();

// [GIVEN] e-Document service to receive one single purchase invoice
LibraryEDoc.CreateTestReceiveServiceForEDoc(EDocService, Enum::"Service Integration"::"Mock");
BindSubscription(this.EDocImplState);

SetDefaultEDocServiceValues(EDocService);

// [GIVEN] Purchase invoice
CreatePurchaseInvoiceWithLines(this.PurchaseHeader, this.PurchaseLine, this.Vendor);

PurchOrderTestBuffer.ClearTempVariables();
PurchOrderTestBuffer.AddPurchaseDocToTemp(this.PurchaseHeader);

// [WHEN] Running Receive
EDocServicePage.OpenView();
EDocServicePage.Filter.SetFilter(Code, EDocService.Code);
EDocServicePage.Receive.Invoke();

// [THEN] Purchase invoice is created with corresponding values
EDocumentPage.OpenView();
EDocumentPage.Last();
CreatedInvoiceNo := EDocumentPage."Document No.".Value;

CheckPurchaseInvoiceCreatedWithCorrectValues(this.PurchaseHeader, this.CreatedPurchaseHeader, this.PurchaseLine, this.CreatedPurchaseLine, CreatedInvoiceNo);

// [WHEN] Delete created purchase invoice from E-Document page
EDocumentPage.DeleteRelatedDocument.Invoke();

// [THEN] Check that purchase invoice is deleted
this.Assert.AreEqual('', EDocumentPage."Document No.".Value, '');
CheckPurchaseInvoiceDeleted(this.CreatedPurchaseHeader, CreatedInvoiceNo);

// [WHEN] Recreate purchase invoice
EDocumentPage.CreateDocument.Invoke();

// [THEN] Check that purchase invoice is created again with corresponding values
CheckPurchaseInvoiceCreatedWithCorrectValues(this.PurchaseHeader, this.CreatedPurchaseHeader, this.PurchaseLine, this.CreatedPurchaseLine, EDocumentPage."Document No.".Value);

DeletePurchaseHeaders(this.PurchaseHeader, this.CreatedPurchaseHeader);
end;

[ModalPageHandler]
procedure SelectPOHandler(var POList: TestPage "Purchase Order List")
var
Expand Down Expand Up @@ -1397,6 +1450,36 @@ codeunit 139628 "E-Doc. Receive Test"
EDocument.DeleteAll();
end;

local procedure SetDefaultEDocServiceValues(var EDocService: Record "E-Document Service")
begin
EDocService."Lookup Account Mapping" := false;
EDocService."Lookup Item GTIN" := false;
EDocService."Lookup Item Reference" := false;
EDocService."Resolve Unit Of Measure" := false;
EDocService."Validate Line Discount" := false;
EDocService."Verify Totals" := false;
EDocService."Use Batch Processing" := false;
EDocService."Validate Receiving Company" := false;
EDocService."Create Journal Lines" := false;
EDocService.Modify(false);
end;

local procedure CreatePurchaseInvoiceWithLines(var PurchHeader: Record "Purchase Header"; var PurchLine: Record "Purchase Line"; var Vendor: Record Vendor)
var
i: Integer;
begin
this.LibraryPurchase.CreateVendorWithAddress(this.Vendor);
this.Vendor."Receive E-Document To" := this.Vendor."Receive E-Document To"::"Purchase Invoice";
this.Vendor.Modify(false);
this.LibraryPurchase.CreatePurchHeader(PurchHeader, PurchHeader."Document Type"::Invoice, this.Vendor."No.");

for i := 1 to 3 do begin
this.LibraryPurchase.CreatePurchaseLine(PurchLine, PurchHeader, PurchLine.Type::Item, this.LibraryInventory.CreateItemNo(), this.LibraryRandom.RandInt(100));
PurchLine.Validate("Direct Unit Cost", this.LibraryRandom.RandDecInRange(1, 100, 2));
PurchLine.Modify(true);
end;
end;

local procedure CheckPurchaseHeadersAreEqual(var PurchHeader1: Record "Purchase Header"; var PurchHeader2: Record "Purchase Header")
begin
Assert.AreEqual(PurchHeader1."Pay-to Vendor No.", PurchHeader2."Pay-to Vendor No.", '');
Expand Down Expand Up @@ -1435,6 +1518,46 @@ codeunit 139628 "E-Doc. Receive Test"
Assert.AreEqual(PurchHeader."Amount Including VAT", Abs(GenJnlLine.Amount), '');
end;

local procedure CheckPurchaseInvoiceCreatedWithCorrectValues(PurchHeader: Record "Purchase Header"; var CreatedPurchHeader: Record "Purchase Header"; PurchLine: Record "Purchase Line"; CreatedPurchLine: Record "Purchase Line"; DocumentNo: Code[20])
begin
CreatedPurchHeader.Reset();
CreatedPurchHeader.SetRange("Document Type", CreatedPurchHeader."Document Type"::Invoice);
CreatedPurchHeader.SetRange("No.", DocumentNo);
CreatedPurchHeader.FindFirst();

CheckPurchaseHeadersAreEqual(PurchHeader, CreatedPurchHeader);

CreatedPurchLine.SetRange("Document Type", CreatedPurchHeader."Document Type");
CreatedPurchLine.SetRange("Document No.", CreatedPurchHeader."No.");
if CreatedPurchLine.FindSet() then
repeat
PurchLine.SetRange("Document Type", PurchHeader."Document Type");
PurchLine.SetRange("Document No.", PurchHeader."No.");
PurchLine.SetRange("Line No.", CreatedPurchLine."Line No.");
PurchLine.FindFirst();
CheckPurchaseLinesAreEqual(PurchLine, CreatedPurchLine);
until CreatedPurchLine.Next() = 0;
end;

local procedure CheckPurchaseInvoiceDeleted(var CreatedPurchHeader: Record "Purchase Header"; DocumentNo: Code[20])
begin
CreatedPurchHeader.Reset();
CreatedPurchHeader.SetRange("Document Type", CreatedPurchHeader."Document Type"::Invoice);
CreatedPurchHeader.SetRange("No.", DocumentNo);
Assert.RecordIsEmpty(CreatedPurchHeader);
end;

local procedure DeletePurchaseHeaders(var PurchHeader: Record "Purchase Header"; var CreatedPurchHeader: Record "Purchase Header")
begin
PurchHeader.SetHideValidationDialog(true);
PurchHeader."E-Document Link" := NullGuid;
PurchHeader.Delete(true);

CreatedPurchHeader.SetHideValidationDialog(true);
CreatedPurchHeader."E-Document Link" := NullGuid;
CreatedPurchHeader.Delete(true);
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Document Create Purch. Doc.", 'OnBeforeProcessHeaderFieldsAssignment', '', false, false)]
local procedure OnBeforeProcessHeaderFieldsAssignment(var DocumentHeader: RecordRef; var PurchaseField: Record Field);
begin
Expand Down Expand Up @@ -2761,5 +2884,4 @@ codeunit 139628 "E-Doc. Receive Test"


#endif

}
Loading