Skip to content

[Event Request]Codeunit 99000854 “Inventory Profile Offsetting”: Add extensibility event to split/create multiple Demand Inventory Profile lines in MaintainPlanningLine method(for transfer orders) #29643

@Sriram-innovites

Description

@Sriram-innovites

Why do you need this change?

Business scenario

Cable distribution / cutting industry scenario where planning must respect length buckets / cut lengths, not only total quantity.

Business configuration
SKU configuration for the item

Main warehouse replenishment system = Purchase

Other locations replenishment system = Transfer

Transfer-from location = Main warehouse

Demand pattern (length-based)

We operate in a cable distribution scenario where demand is naturally split into length lots (cut lengths), and those length lots must be preserved through planning and purchasing.

Example demand at a location (3 demand lots):

150 m

250 m

350 m

Total demand = 750 m, but the split is critical (150/250/350 must remain separate).

What happens today (standard behavior)
Step 1: Master Planning creates transfer suggestion

When Master Planning runs:

A planned transfer order (Requisition Line) is created for 750 m

The system still retains the breakdown of 150/250/350 at the planning calculation level because these originate from separate demand profiles.

Step 2: The Demand Inventory Profile is created for the transfer

After creating the transfer Requisition Line, the planning engine creates a Demand Inventory Profile entry for the transfer demand.

Current outcome (problem):

Standard logic creates one Demand Inventory Profile line with 750 m (aggregated)

Step 3: Purchase suggestion gets aggregated

Because the Demand Inventory Profile is aggregated into a single 750 m line, the downstream netting/supply creation results in:

One planned purchase order for 750 m

Why this is a problem

Because there is now only one Demand Inventory Profile (750 m):

The planning engine creates one Planned Purchase Order

Quantity = 750 m

The original length requirements (150 m, 250 m, 350 m) are no longer represented in planning suggestions.

If BC creates 3 Demand Inventory Profile lines instead of one:

Demand Inv. Profile 1 → 150 m

Demand Inv. Profile 2 → 250 m

Demand Inv. Profile 3 → 350 m

Then:

Reservations can be created per demand profile

Planning suggestions can stay separated

Result would be multiple planned purchase suggestions/orders aligned with the length lots (instead of a single 750 m PO)

Requirement:

Planning must split demand into multiple buckets by length and create multiple Demand Inventory Profile lines so that the planning engine produces multiple planned purchase suggestions / planned purchase orders (rather than one aggregated suggestion).

Problem / extensibility gap

In MaintainPlanningLine, the standard logic creates/updates inventory profiles, but extensibility is currently only provided for SupplyInvtProfile insert via OnMaintainPlanningLineOnBeforeSupplyInvtProfileInsert.

We need to create multiple DemandInvtProfile records (one per length bucket). There is no supported hook to:

Override demand profile creation, and

Insert multiple Demand Inventory Profile lines safely (requires unique "Line No." values; standard line numbering is internal)

As a result, we cannot implement length-based demand splitting without unsupported base code changes.

Requested change

Add or update the existing Event in== OnMaintainPlanningLineOnBeforeSupplyInvtProfileInsert in Codeunit 99000854 "Inventory Profile Offsetting" that allows extensions to take over DemandInvtProfile creation for a planning line and insert multiple demand profiles.

procedure MaintainPlanningLine(var SupplyInvtProfile: Record "Inventory Profile"; DemandInvtProfile: Record "Inventory Profile"; NewPhase: Option " ","Line Created","Routing Created",Exploded,Obsolete; Direction: Option Forward,Backward)
    var
        PurchaseLine: Record "Purchase Line";
        TransLine: Record "Transfer Line";
        CurrentSupplyInvtProfile: Record "Inventory Profile";
        PlanLineNo: Integer;
        RecalculationRequired: Boolean;
        IsHandled: Boolean;
    begin
       // showing main issue code

            if (ReqLine."Ref. Order Type" = ReqLine."Ref. Order Type"::Transfer) and
               not ((ReqLine.Quantity = 0) and (ReqLine."Action Message" = ReqLine."Action Message"::New))
            then begin
                AdjustTransferDates(ReqLine);
                if ReqLine."Action Message" = ReqLine."Action Message"::New then begin
                    CurrentSupplyInvtProfile.Copy(SupplyInvtProfile);

                    SupplyInvtProfile.Reset();
                    SupplyInvtProfile.SetSourceFilter(
                      Database::"Requisition Line", 1, ReqLine."Worksheet Template Name", ReqLine."Line No.", ReqLine."Journal Batch Name", 0);
                    SupplyInvtProfile.SetTrackingFilter(CurrentSupplyInvtProfile);
                    if not SupplyInvtProfile.FindFirst() then begin
                        SupplyInvtProfile.Init();
                        SupplyInvtProfile."Line No." := GetNextLineNo();
                        SupplyInvtProfile."Item No." := ReqLine."No.";
                        SupplyInvtProfile.TransferFromOutboundTransfPlan(ReqLine, TempItemTrkgEntry);
                        SupplyInvtProfile.CopyTrackingFromInvtProfile(CurrentSupplyInvtProfile);
                        if SupplyInvtProfile.IsSupply then
                            SupplyInvtProfile.ChangeSign();
                        **OnMaintainPlanningLineOnBeforeSupplyInvtProfileInsert(SupplyInvtProfile, CurrentSupplyInvtProfile);**
                        SupplyInvtProfile.Insert();
                    end else begin
                        SupplyInvtProfile.TransferFromOutboundTransfPlan(ReqLine, TempItemTrkgEntry);
                        SupplyInvtProfile.Modify();
                    end;

                    SupplyInvtProfile.Copy(CurrentSupplyInvtProfile);
                end else
                    SynchronizeTransferProfiles(SupplyInvtProfile, ReqLine);
            end;
        end;

       


Acceptance criteria

Subscriber can create multiple Demand Inventory Profile records for a single planning demand line (split by length bucket/cut length).

These separate demand profiles drive separate planning suggestions, resulting in multiple planned purchase orders (or separate planned purchase suggestions).

Standard behavior remains unchanged if there is no subscriber (IsHandled = false).

No breaking change to existing extensions (new event preferred over modifying existing event signatures).

Business value

Enables attribute/length-driven planning for industries like cable distribution, metals, textiles, etc., where demand must be planned by cut lengths rather than only total quantityΓÇöwithout requiring unsupported base code modifications.```

### Describe the request

[IntegrationEvent(false, false)]
local procedure OnBeforeCreateDemandInvtProfileForPlanningLine(
var ReqLine: Record "Requisition Line";
var DemandInvtProfile: Record "Inventory Profile";
var TempTrkgReservEntry: Record "Reservation Entry" temporary;
var NextInvtProfileLineNo: Integer;
var IsHandled: Boolean)
begin
end;


TempTrkgReservEntry(temporary): reservation entries are required to identify the length buckets / cut lengths (in our solution, reservations are created per length via custom logic).

NextInvtProfileLineNo (var Integer): required to safely insert multiple Inventory Profile lines; the line numbering logic is internal, so extensions need an allocator to avoid collisions.
Internal work item: [AB#620193](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/620193)

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