Codeunit 437 IC Navigation, source in 29
Source29
src/Layers/W1/BaseApp/Finance/Intercompany/ICNavigation.Codeunit.al324 lines, Copyright (c) Microsoft Corporation. MIT
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.Intercompany;
using Microsoft.Intercompany.Inbox;
using Microsoft.Intercompany.Journal;
using Microsoft.Intercompany.Outbox;
using Microsoft.Intercompany.Setup;
using Microsoft.Purchases.Document;
using Microsoft.Purchases.History;
using Microsoft.Purchases.Vendor;
using Microsoft.Sales.Customer;
using Microsoft.Sales.Document;
using Microsoft.Sales.History;
/// <summary>
/// Provides navigation functionality to related documents from intercompany transactions.
/// Enables users to jump to source or resulting documents in sales and purchase modules.
/// </summary>
/// <remarks>
/// Handles navigation between IC transactions and their corresponding sales orders, invoices,
/// credit memos, and purchase documents across incoming and outgoing transaction flows.
/// </remarks>
codeunit 437 "IC Navigation"
{
var
UnableToNavigateToSpecifiedDocumentMsg: Label 'Unable to navigate to the related document.';
/// <summary>
/// Navigates to the related document from a handled IC inbox transaction.
/// Opens the corresponding sales or purchase document based on transaction details.
/// </summary>
/// <param name="HandledICInboxTrans">Handled IC inbox transaction record containing navigation details</param>
procedure NavigateToDocument(HandledICInboxTrans: Record "Handled IC Inbox Trans.")
begin
if HandledICInboxTrans.IsEmpty() then
exit;
NavigateToDocument(HandledICInboxTrans."Document No.", Enum::"IC Direction Type"::Incoming, HandledICInboxTrans."IC Partner Code", HandledICInboxTrans."Document Type", HandledICInboxTrans."IC Source Type");
end;
/// <summary>
/// Navigates to the related document from an IC outbox transaction.
/// Opens the corresponding sales or purchase document that was sent to partner.
/// </summary>
/// <param name="ICOutboxTransaction">IC outbox transaction record containing navigation details</param>
procedure NavigateToDocument(ICOutboxTransaction: Record "IC Outbox Transaction")
begin
if ICOutboxTransaction.IsEmpty() then
exit;
NavigateToDocument(ICOutboxTransaction."Document No.", Enum::"IC Direction Type"::Outgoing, ICOutboxTransaction."IC Partner Code", ICOutboxTransaction."Document Type", ICOutboxTransaction."IC Source Type");
end;
/// <summary>
/// Navigates to the related document from a handled IC outbox transaction.
/// Opens the corresponding sales or purchase document that was previously sent.
/// </summary>
/// <param name="HandledICOutboxTrans">Handled IC outbox transaction record containing navigation details</param>
procedure NavigateToDocument(HandledICOutboxTrans: Record "Handled IC Outbox Trans.")
begin
if HandledICOutboxTrans.IsEmpty() then
exit;
NavigateToDocument(HandledICOutboxTrans."Document No.", Enum::"IC Direction Type"::Outgoing, HandledICOutboxTrans."IC Partner Code", HandledICOutboxTrans."Document Type", HandledICOutboxTrans."IC Source Type");
end;
local procedure NavigateToSalesInvoice(DocumentNo: Code[20]): Boolean
var
SalesInvoiceHeader: Record "Sales Invoice Header";
PostedSalesInvoice: Page "Posted Sales Invoice";
begin
// An IC Transaction of type Sales Invoice can only be sent when posted, not received.
if not SalesInvoiceHeader.Get(DocumentNo) then
exit(false);
// The related document is a Posted Sales Invoice.
PostedSalesInvoice.SetRecord(SalesInvoiceHeader);
PostedSalesInvoice.Run();
exit(true);
end;
local procedure NavigateToSalesCreditMemo(DocumentNo: Code[20]): Boolean
var
SalesCrMemoHeader: Record "Sales Cr.Memo Header";
PostedSalesCreditMemo: Page "Posted Sales Credit Memo";
begin
// An IC Transaction of type Sales Credit Memo can only be sent when posted.
if not SalesCrMemoHeader.Get(DocumentNo) then
exit(false);
// The related document is a Posted Sales Credit Memo.
PostedSalesCreditMemo.SetRecord(SalesCrMemoHeader);
PostedSalesCreditMemo.Run();
exit(true);
end;
local procedure NavigateToSalesInvoice(DocumentNo: Code[20]; ICPartnerCode: Code[20]): Boolean
var
Customer: Record Customer;
SalesInvoiceHeader: Record "Sales Invoice Header";
PostedSalesInvoice: Page "Posted Sales Invoice";
begin
// This is called when we couldn't find a related sales order,
// so we attempt to find a Posted Sales Invoice
Customer.SetRange("IC Partner Code", ICPartnerCode);
if not Customer.FindSet() then
exit(false);
repeat
SalesInvoiceHeader.Reset();
SalesInvoiceHeader.SetRange("Order No.", DocumentNo);
SalesInvoiceHeader.SetRange("Sell-to Customer No.", Customer."No.");
if SalesInvoiceHeader.FindFirst() then begin
PostedSalesInvoice.SetRecord(SalesInvoiceHeader);
PostedSalesInvoice.Run();
exit(true);
end;
until Customer.Next() = 0;
exit(false);
end;
local procedure NavigateToSalesOrderDocument(DocumentNo: Code[20]; ICDirectionType: Enum "IC Direction Type"; ICPartnerCode: Code[20]): Boolean
var
SalesHeader: Record "Sales Header";
SalesOrder: Page "Sales Order";
begin
// An IC transaction line of type sales order, could navigate to either
// the sales order, or the invoice if it was posted after received
// We first attempt to find the Sales Order
case ICDirectionType of
ICDirectionType::Outgoing:
begin
SalesHeader.SetRange("Document Type", SalesHeader."Document Type"::Order);
SalesHeader.SetRange("No.", DocumentNo);
end;
ICDirectionType::Incoming:
begin
SalesHeader.SetRange("External Document No.", DocumentNo);
SalesHeader.SetRange("IC Direction", ICDirectionType);
SalesHeader.SetRange("Sell-to IC Partner Code", ICPartnerCode);
end;
end;
if SalesHeader.FindFirst() then begin
SalesOrder.SetRecord(SalesHeader);
SalesOrder.Run();
exit(true);
end;
// If we can't find it, we attempt to find the corresponding Sales Invoice
exit(NavigateToSalesInvoice(DocumentNo, ICPartnerCode));
end;
local procedure NavigateToSalesDocument(DocumentNo: Code[20]; ICDirectionType: Enum "IC Direction Type"; ICPartnerCode: Code[20]; DocumentType: Enum "IC Transaction Document Type"): Boolean
var
ShouldNavigateToDoc: Boolean;
begin
case DocumentType of
DocumentType::Order:
exit(NavigateToSalesOrderDocument(DocumentNo, ICDirectionType, ICPartnerCode));
DocumentType::Invoice:
exit(NavigateToSalesInvoice(DocumentNo));
DocumentType::"Credit Memo":
exit(NavigateToSalesCreditMemo(DocumentNo));
else begin
ShouldNavigateToDoc := false;
OnNavigateToSalesDocumentOnAfterCheckDocumentType(DocumentNo, ICDirectionType, ICPartnerCode, DocumentType, ShouldNavigateToDoc);
exit(ShouldNavigateToDoc);
end;
end;
end;
local procedure NavigateToPurchaseInvoice(DocumentNo: Code[20]; ICPartnerCode: Code[20]): Boolean
var
Vendor: Record Vendor;
PurchInvHeader: Record "Purch. Inv. Header";
PostedPurchaseInvoice: Page "Posted Purchase Invoice";
begin
// When this is called, we tried to find a purchase order, but we couldn't find it
// so we attempt to navigate to the Posted Purchase Invoice instead
Vendor.SetRange("IC Partner Code", ICPartnerCode);
if not Vendor.FindSet() then
exit(false);
repeat
PurchInvHeader.Reset();
PurchInvHeader.SetRange("Vendor Order No.", DocumentNo);
PurchInvHeader.SetRange("Buy-from Vendor No.", Vendor."No.");
if PurchInvHeader.FindFirst() then begin
PostedPurchaseInvoice.SetRecord(PurchInvHeader);
PostedPurchaseInvoice.Run();
exit(true);
end;
until Vendor.Next() = 0;
exit(false);
end;
local procedure NavigateToPostedPurchaseInvoice(DocumentNo: Code[20]; VendorNo: Code[20]): Boolean
var
PurchInvHeader: Record "Purch. Inv. Header";
PostedPurchaseInvoice: Page "Posted Purchase Invoice";
begin
PurchInvHeader.SetRange("Buy-from Vendor No.", VendorNo);
PurchInvHeader.SetRange("Vendor Invoice No.", DocumentNo);
if not PurchInvHeader.FindFirst() then
exit(false);
PostedPurchaseInvoice.SetRecord(PurchInvHeader);
PostedPurchaseInvoice.Run();
exit(true);
end;
local procedure NavigateToPurchaseInvoiceDocument(DocumentNo: Code[20]; ICPartnerCode: Code[20]): Boolean
var
Vendor: Record Vendor;
PurchaseHeader: Record "Purchase Header";
PurchaseInvoice: Page "Purchase Invoice";
begin
// An IC Transaction of type purchase invoice, could navigate to either
// the purchase invoice, or the posted purchase invoice if it was posted after received.
Vendor.SetRange("IC Partner Code", ICPartnerCode);
if not Vendor.FindSet() then
exit(false);
repeat
PurchaseHeader.SetRange("IC Direction", PurchaseHeader."IC Direction"::Incoming);
PurchaseHeader.SetRange("Buy-from Vendor No.", Vendor."No.");
PurchaseHeader.SetRange("Vendor Invoice No.", DocumentNo);
if PurchaseHeader.FindFirst() then begin
PurchaseInvoice.SetRecord(PurchaseHeader);
PurchaseInvoice.Run();
exit(true);
end;
if NavigateToPostedPurchaseInvoice(DocumentNo, Vendor."No.") then
exit(true);
until Vendor.Next() = 0;
exit(false);
end;
local procedure NavigateToPurchaseOrderDocument(DocumentNo: Code[20]; ICDirectionType: Enum "IC Direction Type"; ICPartnerCode: Code[20]): Boolean
var
PurchaseHeader: Record "Purchase Header";
PurchaseOrder: Page "Purchase Order";
begin
// An IC transaction line of type sales order, could navigate to either
// the sales order, or the invoice if it was posted after received
// We first attempt to find the Sales Order
case ICDirectionType of
ICDirectionType::Outgoing:
begin
PurchaseHeader.SetRange("Document Type", PurchaseHeader."Document Type"::Order);
PurchaseHeader.SetRange("No.", DocumentNo);
end;
ICDirectionType::Incoming:
begin
PurchaseHeader.SetRange("Vendor Order No.", DocumentNo);
PurchaseHeader.SetRange("IC Direction", ICDirectionType);
PurchaseHeader.SetRange("Buy-from IC Partner Code", ICPartnerCode);
end;
end;
if PurchaseHeader.FindFirst() then begin
PurchaseOrder.SetRecord(PurchaseHeader);
PurchaseOrder.Run();
exit(true);
end;
// If we can't find it, we attempt to find the corresponding Sales Invoice
exit(NavigateToPurchaseInvoice(DocumentNo, ICPartnerCode));
end;
local procedure NavigateToPurchaseDocument(DocumentNo: Code[20]; ICDirectionType: Enum "IC Direction Type"; ICPartnerCode: Code[20]; DocumentType: Enum "IC Transaction Document Type"): Boolean
var
OpenDoc: Boolean;
begin
case DocumentType of
DocumentType::Order:
exit(NavigateToPurchaseOrderDocument(DocumentNo, ICDirectionType, ICPartnerCode));
DocumentType::Invoice:
exit(NavigateToPurchaseInvoiceDocument(DocumentNo, ICPartnerCode));
else begin
OnNavigateToPurchaseDocumentOnDocumentTypeCaseElse(DocumentNo, ICDirectionType, ICPartnerCode, DocumentType, OpenDoc);
exit(OpenDoc);
end;
end;
exit(false);
end;
local procedure NavigateToDocument(DocumentNo: Code[20]; ICDirectionType: Enum "IC Direction Type"; ICPartnerCode: Code[20]; DocumentType: Enum "IC Transaction Document Type"; SourceType: enum "IC Transaction Source Type")
var
Succeeded: Boolean;
begin
case SourceType of
SourceType::"Sales Document":
Succeeded := NavigateToSalesDocument(DocumentNo, ICDirectionType, ICPartnerCode, DocumentType);
SourceType::"Purchase Document":
Succeeded := NavigateToPurchaseDocument(DocumentNo, ICDirectionType, ICPartnerCode, DocumentType);
end;
if not Succeeded then
Error(UnableToNavigateToSpecifiedDocumentMsg);
end;
/// <summary>
/// Integration event raised when navigating to purchase documents for custom document types.
/// Enables custom navigation logic for extended IC transaction document types.
/// </summary>
/// <param name="DocumentNo">Document number to navigate to</param>
/// <param name="ICDirectionType">Direction of the IC transaction (incoming/outgoing)</param>
/// <param name="ICPartnerCode">Code of the IC partner</param>
/// <param name="DocumentType">IC transaction document type</param>
/// <param name="OpenDoc">Set to true if navigation was handled successfully</param>
[IntegrationEvent(false, false)]
local procedure OnNavigateToPurchaseDocumentOnDocumentTypeCaseElse(DocumentNo: Code[20]; ICDirectionType: Enum "IC Direction Type"; ICPartnerCode: Code[20]; DocumentType: Enum "IC Transaction Document Type"; var OpenDoc: Boolean)
begin
end;
/// <summary>
/// Integration event raised when navigating to sales documents after document type validation.
/// Enables custom navigation logic for extended IC transaction document types.
/// </summary>
/// <param name="DocumentNo">Document number to navigate to</param>
/// <param name="ICDirectionType">Direction of the IC transaction (incoming/outgoing)</param>
/// <param name="ICPartnerCode">Code of the IC partner</param>
/// <param name="ICTransactionDocumentType">IC transaction document type</param>
/// <param name="ShouldNavigateToDoc">Set to true if navigation should proceed</param>
[IntegrationEvent(false, false)]
local procedure OnNavigateToSalesDocumentOnAfterCheckDocumentType(DocumentNo: Code[20]; ICDirectionType: Enum "IC Direction Type"; ICPartnerCode: Code[20]; ICTransactionDocumentType: Enum "IC Transaction Document Type"; var ShouldNavigateToDoc: Boolean)
begin
end;
}