Skip to content

[EVENT REQUEST] [DE][Codeunit][6500][Item Tracking Management] #30380

Description

@SarkeSrb

Why do you need this change?

We need an additional event in codeunit 6500 "Item Tracking Management". The event placement and logic should be the same as within the procedure SplitInternalPutAwayLine ΓÇö specifically, the event OnSplitInternalPutAwayLineOnNotFindWhseItemTrackingLine.

We need this event to perform custom splitting.

This was already requested in #20070, but the whole request was declined because of the event inside the loop. We agree that custom splitting can be handled before the loop, but we still need the new event in case Warehouse Item Entry Relation is not found.

Performance Considerations:
The proposed event OnSplitPostedWhseReceiptLineOnNotFindWhseItemEntryRelation is located outside the repeat...until loop, in the else branch that executes only when WhseItemEntryRelation.FindSet() returns no records for the given posted warehouse receipt line. It fires at most once per call to SplitPostedWhseRcptLine, not once per iteration. SplitPostedWhseRcptLine itself is called once per posted warehouse receipt line during put-away/cross-dock processing, so the added overhead is negligible ΓÇö a single conditional check and, if no subscriber is attached, no additional cost at all.

Data Sensitivity Review:
The event exposes PostedWhseRcptLine and TempPostedWhseRcptLine, which are already parameters of the calling procedure and are standard warehouse receipt line records (item, quantity, location, tracking fields). No new or sensitive data (e.g., pricing, customer, or personal data) is introduced beyond what the procedure already operates on.

Multi-Extension Interaction:
The event follows the standard IsHandled pattern already used elsewhere in this codeunit (e.g., OnBeforeSplitPostedWhseReceiptLine). If multiple extensions subscribe, each subscriber can inspect and set IsHandled; once any subscriber sets it to true, the base logic (TempPostedWhseRcptLine := PostedWhseRcptLine; TempPostedWhseRcptLine.Insert();) is skipped. As with all IsHandled events, subscriber execution order is not guaranteed, so conflicting subscribers should coordinate via subscriber priority ([EventSubscriber(..., '', false, false)] ordering) or check TempPostedWhseRcptLine state before acting. This is the same mitigation pattern already accepted for the analogous event in SplitInternalPutAwayLine.

Describe the request

[Procedure SplitPostedWhseRcptLine]

procedure SplitPostedWhseRcptLine(PostedWhseRcptLine: Record "Posted Whse. Receipt Line"; var TempPostedWhseRcptLine: Record "Posted Whse. Receipt Line" temporary)
    var
        WhseItemEntryRelation: Record "Whse. Item Entry Relation";
        WhseItemTrackingSetup: Record "Item Tracking Setup";
        ItemLedgEntry: Record "Item Ledger Entry";
        LineNo: Integer;
        CrossDockQty: Decimal;
        CrossDockQtyBase: Decimal;
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeSplitPostedWhseReceiptLine(PostedWhseRcptLine, TempPostedWhseRcptLine, IsHandled);
        if IsHandled then
            exit;

        TempPostedWhseRcptLine.Reset();
        TempPostedWhseRcptLine.DeleteAll();

        if not GetWhseItemTrkgSetup(PostedWhseRcptLine."Item No.", WhseItemTrackingSetup) then begin
            TempPostedWhseRcptLine := PostedWhseRcptLine;
            TempPostedWhseRcptLine.Insert();
            OnAfterSplitPostedWhseReceiptLine(PostedWhseRcptLine, TempPostedWhseRcptLine);
            exit;
        end;

        WhseItemEntryRelation.Reset();
        WhseItemEntryRelation.SetSourceFilter(
          Database::"Posted Whse. Receipt Line", 0, PostedWhseRcptLine."No.", PostedWhseRcptLine."Line No.", true);
        if WhseItemEntryRelation.FindSet() then
            repeat
                ItemLedgEntry.Get(WhseItemEntryRelation."Item Entry No.");
                TempPostedWhseRcptLine.SetTrackingFilterFromItemLedgEntry(ItemLedgEntry);
                TempPostedWhseRcptLine.SetRange("Warranty Date", ItemLedgEntry."Warranty Date");
                TempPostedWhseRcptLine.SetRange("Expiration Date", ItemLedgEntry."Expiration Date");
                OnTempPostedWhseRcptLineSetFilters(TempPostedWhseRcptLine, ItemLedgEntry, WhseItemEntryRelation);
                if TempPostedWhseRcptLine.FindFirst() then begin
                    TempPostedWhseRcptLine."Qty. (Base)" += ItemLedgEntry.Quantity;
                    TempPostedWhseRcptLine.Quantity :=
                      Round(
                        TempPostedWhseRcptLine."Qty. (Base)" / TempPostedWhseRcptLine."Qty. per Unit of Measure",
                        UOMMgt.QtyRndPrecision());
                    OnBeforeModifySplitPostedWhseRcptLine(
                      TempPostedWhseRcptLine, PostedWhseRcptLine, WhseItemEntryRelation, ItemLedgEntry);
                    TempPostedWhseRcptLine.Modify();

                    CrossDockQty := CrossDockQty - TempPostedWhseRcptLine."Qty. Cross-Docked";
                    CrossDockQtyBase := CrossDockQtyBase - TempPostedWhseRcptLine."Qty. Cross-Docked (Base)";
                end else begin
                    LineNo += 10000;
                    TempPostedWhseRcptLine.Reset();
                    TempPostedWhseRcptLine := PostedWhseRcptLine;
                    TempPostedWhseRcptLine."Line No." := LineNo;
                    TempPostedWhseRcptLine.CopyTrackingFromWhseItemEntryRelation(WhseItemEntryRelation);
                    TempPostedWhseRcptLine."Warranty Date" := ItemLedgEntry."Warranty Date";
                    TempPostedWhseRcptLine."Expiration Date" := ItemLedgEntry."Expiration Date";
                    TempPostedWhseRcptLine."Qty. (Base)" := ItemLedgEntry.Quantity;
                    TempPostedWhseRcptLine.Quantity :=
                      Round(
                        TempPostedWhseRcptLine."Qty. (Base)" / TempPostedWhseRcptLine."Qty. per Unit of Measure",
                        UOMMgt.QtyRndPrecision());
                    OnBeforeInsertSplitPostedWhseRcptLine(
                      TempPostedWhseRcptLine, PostedWhseRcptLine, WhseItemEntryRelation, ItemLedgEntry);
                    TempPostedWhseRcptLine.Insert();
                end;

                if WhseItemTrackingSetup."Serial No. Required" then begin
                    if CrossDockQty < PostedWhseRcptLine."Qty. Cross-Docked" then begin
                        TempPostedWhseRcptLine."Qty. Cross-Docked" := TempPostedWhseRcptLine.Quantity;
                        TempPostedWhseRcptLine."Qty. Cross-Docked (Base)" := TempPostedWhseRcptLine."Qty. (Base)";
                    end else begin
                        TempPostedWhseRcptLine."Qty. Cross-Docked" := 0;
                        TempPostedWhseRcptLine."Qty. Cross-Docked (Base)" := 0;
                    end;
                    CrossDockQty := CrossDockQty + TempPostedWhseRcptLine.Quantity;
                end else
                    if PostedWhseRcptLine."Qty. Cross-Docked" > 0 then begin
                        if TempPostedWhseRcptLine.Quantity <=
                           PostedWhseRcptLine."Qty. Cross-Docked" - CrossDockQty
                        then begin
                            TempPostedWhseRcptLine."Qty. Cross-Docked" := TempPostedWhseRcptLine.Quantity;
                            TempPostedWhseRcptLine."Qty. Cross-Docked (Base)" := TempPostedWhseRcptLine."Qty. (Base)";
                        end else begin
                            TempPostedWhseRcptLine."Qty. Cross-Docked" := PostedWhseRcptLine."Qty. Cross-Docked" - CrossDockQty;
                            TempPostedWhseRcptLine."Qty. Cross-Docked (Base)" :=
                              PostedWhseRcptLine."Qty. Cross-Docked (Base)" - CrossDockQtyBase;
                        end;
                        CrossDockQty := CrossDockQty + TempPostedWhseRcptLine."Qty. Cross-Docked";
                        CrossDockQtyBase := CrossDockQtyBase + TempPostedWhseRcptLine."Qty. Cross-Docked (Base)";
                        if CrossDockQty >= PostedWhseRcptLine."Qty. Cross-Docked" then begin
                            PostedWhseRcptLine."Qty. Cross-Docked" := 0;
                            PostedWhseRcptLine."Qty. Cross-Docked (Base)" := 0;
                        end;
                    end;
                TempPostedWhseRcptLine.Modify();
            until WhseItemEntryRelation.Next() = 0
        else begin
// START
            OnSplitPostedWhseReceiptLineOnNotFindWhseItemEntryRelation(PostedWhseRcptLine, TempPostedWhseRcptLine, IsHandled);
            if not IsHandled then begin
// END
                TempPostedWhseRcptLine := PostedWhseRcptLine;
                TempPostedWhseRcptLine.Insert();
//  START
            end;
// END
        end;

        OnAfterSplitPostedWhseReceiptLine(PostedWhseRcptLine, TempPostedWhseRcptLine);
    end;

    [IntegrationEvent(false, false)]
    local procedure OnSplitPostedWhseReceiptLineOnNotFindWhseItemEntryRelation(PostedWhseRcptLine: Record "Posted Whse. Receipt Line"; var TempPostedWhseRcptLine: Record "Posted Whse. Receipt Line" temporary; var IsHandled: Boolean)
    begin
    end;

Internal work item: AB#644119

Metadata

Metadata

Assignees

No one assigned

    Labels

    SCMGitHub request for SCM areaevent-requestRequest for adding an event

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions