Skip to content

[Event Requests] - codeunit 6620 "Copy Document Mgt." #30028

@exnihiloo

Description

@exnihiloo

Why do you need this change?

  1. Procedure CopySalesInvLinesToDoc
    Please add a new integration event in the procedure CopySalesInvLinesToDoc, raised at the end of each repeat … until TempSalesLineBuf.Next() = 0 iteration, to expose detailed context of the sales line copy process, including the variable LinesNotCopied.
    This enables extensions to reliably react to skipped posted invoice lines on a perΓÇæline basis, without duplicating base application logic.

    In CopySalesInvLinesToDoc, the variable LinesNotCopied is updated inside the call to CopySalesDocLine. However:

    There is no event raised at the end of each loop iteration
    Existing events do not expose LinesNotCopied
    Extensions cannot detect partial copy results per buffer line

    This makes it impossible to implement validation, logging, or conditional logic based on skipped lines in an upgradeΓÇæsafe way.

    The event should be raised inside the loop
    After CopySalesDocLine has executed
    After LinesNotCopied may have been incremented
    Before the next iteration starts
    Specifically: at the end of the repeat block:

 procedure CopySalesInvLinesToDoc(ToSalesHeader: Record "Sales Header"; var FromSalesInvLine: Record "Sales Invoice Line"; var LinesNotCopied: Integer; var MissingExCostRevLink: Boolean)
 ...
if TempSalesLineBuf.FindSet() then begin
...
if CopySalesDocLine(
      ToSalesHeader, ToSalesLine, FromSalesHeader, FromSalesLine2, NextLineNo, LinesNotCopied, TempSalesLineBuf."Return Receipt No." = '',
      "Sales Document Type From"::"Posted Invoice", CopyPostedDeferral, GetSalesLineNo(TempDocSalesLine, FromSalesLine2."Line No."))
  then begin
      if CopyPostedDeferral then
          CopySalesPostedDeferrals(ToSalesLine, "Deferral Document Type"::Sales,
            DeferralTypeForSalesDoc("Sales Document Type From"::"Posted Invoice".AsInteger()), TempSalesLineBuf."Shipment No.", TempSalesLineBuf."Return Receipt Line No.",
            ToSalesLine."Document Type".AsInteger(), ToSalesLine."Document No.", ToSalesLine."Line No.");
      FromSalesInvLine.Get(TempSalesLineBuf."Shipment No.", TempSalesLineBuf."Return Receipt Line No.");
      OnCopySalesInvLinesToDocOnAfterCopySalesPostedDeferrals(FromSalesInvLine, NextLineNo, ToSalesLine, TempSalesLineBuf);
      // copy item charges
      if TempSalesLineBuf.Type = TempSalesLineBuf.Type::"Charge (Item)" then begin
          FromSalesLine.TransferFields(FromSalesInvLine);
          FromSalesLine."Document Type" := FromSalesLine."Document Type"::Invoice;
          CopyFromSalesLineItemChargeAssign(FromSalesLine, ToSalesLine, FromSalesHeader, ItemChargeAssgntNextLineNo);
      end;

      IsHandled := false;
      OnCopySalesInvLinesToDocOnBeforeCopyItemTracking(TempSalesLineBuf, ToSalesHeader, FromSalesInvLine, TempItemLedgEntryBuf, TempItemTrkgEntry, IsHandled);
      // copy item tracking
      if not IsHandled then
          if (TempSalesLineBuf.Type = TempSalesLineBuf.Type::Item) and (TempSalesLineBuf.Quantity <> 0) and SalesDocCanReceiveTracking(ToSalesHeader) then begin
              FromSalesInvLine."Document No." := OldInvDocNo;
              FromSalesInvLine."Line No." := TempSalesLineBuf."Return Receipt Line No.";
              FromSalesInvLine.GetItemLedgEntries(TempItemLedgEntryBuf, true);
              if IsCopyItemTrkg(TempItemLedgEntryBuf, CopyItemTrkg, FillExactCostRevLink) then begin
                  CopyItemLedgEntryTrackingToSalesLine(
                    TempItemLedgEntryBuf, TempItemTrkgEntry, TempSalesLineBuf, ToSalesLine, ToSalesHeader."Prices Including VAT",
                    FromSalesHeader."Prices Including VAT", FillExactCostRevLink, MissingExCostRevLink);
                  OnCopySalesInvLinesToDocOnAfterCopyItemLedgEntryTrackingToSalesLine(ToSalesLine);
              end;
          end;

      OnAfterCopySalesLineFromSalesLineBuffer(
        ToSalesLine, FromSalesInvLine, IncludeHeader, RecalculateLines, TempDocSalesLine, ToSalesHeader, TempSalesLineBuf,
        FromSalesLine2, FromSalesLine, ExactCostRevMandatory, FromSalesInvHeader);
  end;
  OnCopySalesInvLinesToDocOnAfterCopySalesDocLine(ToSalesLine, FromSalesInvLine);
until TempSalesLineBuf.Next() = 0;                
OnCopySalesInvLinesToDocOnAfterSalesLineIteration(RecalculateLines,ToSalesHeader,ToSalesLine,FromSalesHeader,FromSalesLine,FromSalesLine2,LinesNotCopied) //New event
end;
CloseWindow();
...

This guarantees:
One event execution per processed buffer line
Accurate visibility into skipped lines
Consistent execution order for extensions

Business Scenario:
When copying posted invoice lines, some lines may intentionally be skipped.
Extensions must:
Detect skipped lines immediately
Know how many lines were skipped (LinesNotCopied)
React per line (notifications, validation, telemetry, conditional logic)

Performance Considerations:
Event runs once per processed buffer line
Adds only record references and an integer
No additional database operations

Data Sensitivity Review:
LinesNotCopied is a numeric counter
All records are already in scope
No personal or sensitive data exposed

  1. On procedure CopySalesCrMemoLinesToDoc
    Please extend the integration event
    OnBeforeCopySalesCrMemoLinesToBuffer(FromSalesLine, FromSalesCrMemoLine, ToSalesHeader)
    by adding the parameter RecalculateLines: Boolean.

    Our business logic depends on the Recalculate Lines setting.
    When RecalculateLines = false, we need to copy data directly from FromSalesCrMemoLine into a RecordRef.
    The current event does not expose this flag, making it impossible for extensions to correctly differentiate behavior without duplicating base logic or using unreliable workarounds.

    Impact
    No performance impact (single Boolean parameter)
    No data sensitivity concerns
    Improves extensibility and consistency with other copy events that already expose RecalculateLines

  2. On procedure CopySalesReturnRcptLinesToDoc
    Please extend the integration event
    OnCopySalesReturnRcptLinesToDocOnBeforeFromSalesHeaderTransferFields(FromReturnRcptHeader, FromSalesHeader, ToSalesHeader, FromReturnRcptLine);
    by adding the parameter RecalculateLines: Boolean.

    Our business logic depends on the Recalculate Lines setting.
    When RecalculateLines = false, we need to copy data directly from FromReturnRcptLine into a RecordRef.
    The current event does not expose this flag, making it impossible for extensions to correctly differentiate behavior without duplicating base logic or using unreliable workarounds.

    Impact
    No performance impact (single Boolean parameter)
    No data sensitivity concerns
    Improves extensibility and consistency with other copy events that already expose RecalculateLines

  3. On Procedure CopySalesReturnRcptLinesToDoc
    Please extend the integration event
    OnAfterCopySalesLineFromReturnRcptLineBuffer
    to include the additional parameters FromSalesHeader: Record "Sales Header" and var LinesNotCopied: Integer.

    During the copy process from return receipt lines, LinesNotCopied is updated as part of the underlying CopySalesDocLine logic, but this information is not available to extensions at this stage.
    Additionally, access to the original FromSalesHeader is required to apply documentΓÇælevel business rules when processing copied or skipped lines.
    Without these parameters:

    Extensions cannot detect skipped lines
    Conditional logic based on source header data cannot be implemented
    Partners must rely on nonΓÇæupgradeΓÇæsafe workarounds

    Impact
    No performance impact (record reference + integer)
    No data sensitivity concerns
    Improves extensibility and consistency with other Sales Document copy events

Describe the request

  1. On Procedure CopySalesInvLinesToDoc
    New event:
[IntegrationEvent(false, false)]
local procedure OnCopySalesInvLinesToDocOnAfterSalesLineIteration(RecalculateLines: Boolean; var ToSalesHeader: Record "Sales Header"; var ToSalesLine: Record "Sales Line"; FromSalesHeader: Record "Sales Header"; FromSalesLine: Record "Sales Line"; FromSalesLine2: Record "Sales Line";  var LinesNotCopied: Integer)
begin
end;
  1. On procedure CopySalesCrMemoLinesToDoc
    Existing event
[IntegrationEvent(false, false)]
local procedure OnBeforeCopySalesCrMemoLinesToBuffer(var FromSalesLine: Record "Sales Line"; var FromSalesCrMemoLine: Record "Sales Cr.Memo Line"; var ToSalesHeader: Record "Sales Header")
begin
end;

Modified event (added RacalculateLines parameter)

[IntegrationEvent(false, false)]
local procedure OnBeforeCopySalesCrMemoLinesToBuffer(var FromSalesLine: Record "Sales Line"; var FromSalesCrMemoLine: Record "Sales Cr.Memo Line"; var ToSalesHeader: Record "Sales Header"; RecalculateLines: Boolean)
begin
end;
  1. On procedure CopySalesReturnRcptLinesToDoc
    Existing event
[IntegrationEvent(false, false)]
local procedure OnCopySalesReturnRcptLinesToDocOnBeforeFromSalesHeaderTransferFields(FromReturnRcptHeader: Record "Return Receipt Header"; var FromSalesHeader: Record "Sales Header"; ToSalesHeader: Record "Sales Header"; var FromReturnRcptLine: Record "Return Receipt Line")
begin
end;

Modified event (added RacalculateLines parameter)

[IntegrationEvent(false, false)]
local procedure OnCopySalesReturnRcptLinesToDocOnBeforeFromSalesHeaderTransferFields(FromReturnRcptHeader: Record "Return Receipt Header"; var FromSalesHeader: Record "Sales Header"; ToSalesHeader: Record "Sales Header"; var FromReturnRcptLine: Record "Return Receipt Line", RecalculateLines: Boolean)
begin
end;
  1. On procedure CopySalesReturnRcptLinesToDoc
    Existing event
[IntegrationEvent(false, false)]
    local procedure OnAfterCopySalesLineFromReturnRcptLineBuffer(var ToSalesLine: Record "Sales Line"; FromReturnReceiptLine: Record "Return Receipt Line"; IncludeHeader: Boolean; RecalculateLines: Boolean; var TempDocSalesLine: Record "Sales Line" temporary; ToSalesHeader: Record "Sales Header"; FromSalesLineBuf: Record "Sales Line"; CopyItemTrkg: Boolean)
    begin
    end;

Modified event (added parameters var LinesNotCopied: Integer, FromSalesHeader: Record "Sales Header")

[IntegrationEvent(false, false)]
    local procedure OnAfterCopySalesLineFromReturnRcptLineBuffer(var ToSalesLine: Record "Sales Line"; FromReturnReceiptLine: Record "Return Receipt Line"; IncludeHeader: Boolean; RecalculateLines: Boolean; var TempDocSalesLine: Record "Sales Line" temporary; ToSalesHeader: Record "Sales Header"; FromSalesLineBuf: Record "Sales Line"; CopyItemTrkg: Boolean; var LinesNotCopied: Integer, FromSalesHeader: Record "Sales Header")
    begin
    end;

Internal work item: AB#636313

Metadata

Metadata

Assignees

No one assigned

    Labels

    IntegrationGitHub request for Integration areaevent-requestRequest for adding an event

    Type

    No fields configured for Task.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions