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
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 eventOnSplitInternalPutAwayLineOnNotFindWhseItemTrackingLine.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
OnSplitPostedWhseReceiptLineOnNotFindWhseItemEntryRelationis located outside therepeat...untilloop, in theelsebranch that executes only whenWhseItemEntryRelation.FindSet()returns no records for the given posted warehouse receipt line. It fires at most once per call toSplitPostedWhseRcptLine, not once per iteration.SplitPostedWhseRcptLineitself 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
PostedWhseRcptLineandTempPostedWhseRcptLine, 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
IsHandledpattern already used elsewhere in this codeunit (e.g.,OnBeforeSplitPostedWhseReceiptLine). If multiple extensions subscribe, each subscriber can inspect and setIsHandled; once any subscriber sets it totrue, the base logic (TempPostedWhseRcptLine := PostedWhseRcptLine; TempPostedWhseRcptLine.Insert();) is skipped. As with allIsHandledevents, subscriber execution order is not guaranteed, so conflicting subscribers should coordinate via subscriber priority ([EventSubscriber(..., '', false, false)]ordering) or checkTempPostedWhseRcptLinestate before acting. This is the same mitigation pattern already accepted for the analogous event inSplitInternalPutAwayLine.Describe the request
[Procedure
SplitPostedWhseRcptLine]Internal work item: AB#644119