Skip to content

[Event Request] codeunit 99000773 "Calculate Prod. Order" #30207

Description

@Simon110394

Why do you need this change?

We need a couple of new event in codeunit "Calculate Prod. Order".
The first one is supposed to be exploited to perform a custom procedure TransferBOM, instead of the standard one.
At the moment there are no other available events useful in order to manage a custom procedure instead of TransferBOM if a particular custom codition is fulfilled.

The second one will be useful in order to set other filters on variable CapLedgEntry.

Describe the request

In procedure TransferBOM of codeunit 99000773 "Calculate Prod. Order" we need an event:

[IntegrationEvent(false, false)]
local procedure OnTransferBOMOnBeforeProcessProdBOM2(var Ishandled: Boolean; ProdBOMLine: Record "Production BOM Line"; LineQtyPerUOM: Decimal; ItemQtyPerUOM: Decimal; var ReqQty: Decimal; var ProdOrderLine: Record "Prod. Order Line")
begin
end;

Changes between **:

procedure TransferBOM(ProdBOMNo: Code[20]; Level: Integer; LineQtyPerUOM: Decimal; ItemQtyPerUOM: Decimal): Boolean
    var
        BOMHeader: Record "Production BOM Header";
        ProductionBOMVersion: Record "Production BOM Version";
        ReqQty: Decimal;
        ErrorOccured: Boolean;
        VersionCode: Code[20];
        IsHandled: Boolean;
        SkipTransfer: Boolean;
    begin
        IsHandled := false;
        OnBeforeTransferBOM(ProdOrder, ProdOrderLine, ProdBOMNo, Level, LineQtyPerUOM, ItemQtyPerUOM, Blocked, ErrorOccured, IsHandled);
        if IsHandled then
            exit(not ErrorOccured);

        if ProdBOMNo = '' then
            exit;

        ProdOrderComp.LockTable();

        if Level > 50 then
            Error(
              Text000,
              ProdBOMNo);

        BOMHeader.Get(ProdBOMNo);

        if Level > 1 then
            VersionCode := VersionMgt.GetBOMVersion(ProdBOMNo, ProdOrderLine."Starting Date", true)
        else
            VersionCode := ProdOrderLine."Production BOM Version Code";

        if VersionCode <> '' then begin
            ProductionBOMVersion.Get(ProdBOMNo, VersionCode);
            ProductionBOMVersion.TestField(Status, ProductionBOMVersion.Status::Certified);
        end else
            BOMHeader.TestField(Status, BOMHeader.Status::Certified);

        ProdBOMLine[Level].SetRange("Production BOM No.", ProdBOMNo);
        ProdBOMLine[Level].SetRange("Version Code", VersionCode);
        ProdBOMLine[Level].SetFilter("Starting Date", '%1|..%2', 0D, ProdOrderLine."Starting Date");
        ProdBOMLine[Level].SetFilter("Ending Date", '%1|%2..', 0D, ProdOrderLine."Starting Date");
        OnTransferBOMOnAfterSetFiltersProdBOMLine(ProdBOMLine[Level], ProdOrderLine);
        if ProdBOMLine[Level].Find('-') then
            repeat
                IsHandled := false;
                OnBeforeTransferBOMComponent(ProdOrder, ProdOrderLine, ProdBOMLine[Level], ErrorOccured, IsHandled, Level);
                if not IsHandled then begin
                    if ProdBOMLine[Level]."Routing Link Code" <> '' then begin
                        IsHandled := false;
                        OnBeforeFindProdOrderRoutingLine(ProdOrderLine, ProdBOMLine[Level], IsHandled, ReqQty);
                        if not IsHandled then begin
                            ProdOrderRoutingLine2.SetRange(Status, ProdOrderLine.Status);
                            ProdOrderRoutingLine2.SetRange("Prod. Order No.", ProdOrderLine."Prod. Order No.");
                            ProdOrderRoutingLine2.SetRange("Routing Link Code", ProdBOMLine[Level]."Routing Link Code");
                            ProdOrderRoutingLine2.FindFirst();
                            ReqQty :=
                              ProdBOMLine[Level].Quantity * (1 + ProdBOMLine[Level]."Scrap %" / 100) *
                              (1 + ProdOrderRoutingLine2."Scrap Factor % (Accumulated)") * LineQtyPerUOM / ItemQtyPerUOM +
                              ProdOrderRoutingLine2."Fixed Scrap Qty. (Accum.)";
                        end;
                    end else
                        ReqQty :=
                          ProdBOMLine[Level].Quantity * (1 + ProdBOMLine[Level]."Scrap %" / 100) * LineQtyPerUOM / ItemQtyPerUOM;

                    OnTransferBOMOnAfterCalcReqQty(
                      ProdBOMLine[Level], ProdOrderRoutingLine2, ProdOrderLine, ReqQty, LineQtyPerUOM, ItemQtyPerUOM);

                    case ProdBOMLine[Level].Type of
                        ProdBOMLine[Level].Type::Item:
                            begin
                                SkipTransfer := false;
                                OnTransferBOMOnBeforeProcessItem(ProdBOMLine[Level], ReqQty, SkipTransfer);
                                if not SkipTransfer then
                                    TransferBOMProcessItem(Level, LineQtyPerUOM, ItemQtyPerUOM, ErrorOccured);
                            end;
                        ProdBOMLine[Level].Type::"Production BOM":
                            begin
                                OnTransferBOMOnBeforeProcessProdBOM(ProdBOMLine[Level], LineQtyPerUOM, ItemQtyPerUOM, ReqQty, ProdOrderLine);
								**IsHandled := false;
								OnTransferBOMOnBeforeProcessProdBOM2(IsHandled, ProdBOMLine[Level], LineQtyPerUOM, ItemQtyPerUOM, ReqQty, ProdOrderLine);
								if not IsHandled then**
									TransferBOM(ProdBOMLine[Level]."No.", Level + 1, ReqQty, 1);
                                ProdBOMLine[Level].SetRange("Production BOM No.", ProdBOMNo);
                                if Level > 1 then
                                    ProdBOMLine[Level].SetRange("Version Code", VersionMgt.GetBOMVersion(ProdBOMNo, ProdOrderLine."Starting Date", true))
                                else
                                    ProdBOMLine[Level].SetRange("Version Code", ProdOrderLine."Production BOM Version Code");
                                ProdBOMLine[Level].SetFilter("Starting Date", '%1|..%2', 0D, ProdOrderLine."Starting Date");
                                ProdBOMLine[Level].SetFilter("Ending Date", '%1|%2..', 0D, ProdOrderLine."Starting Date");
                            end;
                    end;
                end;
            until ProdBOMLine[Level].Next() = 0;

        OnAfterTransferBOM(ProdOrder, ProdOrderLine, ProdBOMNo, Level, LineQtyPerUOM, ItemQtyPerUOM, Blocked, ErrorOccured);

        exit(not ErrorOccured);
    end;

In procedure Calculate of codeunit 99000773 "Calculate Prod. Order" we need an event:

[IntegrationEvent(false, false)]
local procedure OnCalculateOnAfterCapLedgEntrySetFilters(ProdOrderLine: Record "Prod. Order Line"; var CapLedgEntry: Record "Capacity Ledger Entry")
begin
end;

Changes between **:

procedure Calculate(ProdOrderLine2: Record "Prod. Order Line"; Direction: Option Forward,Backward; CalcRouting: Boolean; CalcComponents: Boolean; DeleteRelations: Boolean; LetDueDateDecrease: Boolean): Boolean
    var
        CapLedgEntry: Record "Capacity Ledger Entry";
        ItemLedgEntry: Record "Item Ledger Entry";
        ProdOrderRoutingLine3: Record "Prod. Order Routing Line";
        ProdOrderRoutingLine4: Record "Prod. Order Routing Line";
        RoutingHeader: Record "Routing Header";
        ProdOrderRoutingLine: Record "Prod. Order Routing Line";
        ErrorOccured: Boolean;
        IsHandled: Boolean;
        ShouldCheckIfEntriesExist: Boolean;
        SkipCalcComponents: Boolean;
    begin
        ProdOrderLine := ProdOrderLine2;

        IsHandled := false;
        OnBeforeCalculate(ItemLedgEntry, CapLedgEntry, Direction, CalcRouting, CalcComponents, DeleteRelations, LetDueDateDecrease, IsHandled, ProdOrderLine, ErrorOccured);
        if IsHandled then
            exit(not ErrorOccured);

        ShouldCheckIfEntriesExist := ProdOrderLine.Status = ProdOrderLine.Status::Released;
        OnCalculateOnAfterCalcShouldCheckIfEntriesExist(ProdOrderLine, CalcRouting, ShouldCheckIfEntriesExist);
        if ShouldCheckIfEntriesExist then begin
            ItemLedgEntry.SetCurrentKey("Order Type", "Order No.");
            ItemLedgEntry.SetRange("Order Type", ItemLedgEntry."Order Type"::Production);
            ItemLedgEntry.SetRange("Order No.", ProdOrderLine."Prod. Order No.");
            OnCalculateOnAfterItemLedgEntrySetFilters(ProdOrderLine, ItemLedgEntry);
            if not ItemLedgEntry.IsEmpty() then
                Error(
                  Text001,
                  ProdOrderLine.Status, ProdOrderLine.TableCaption(), ProdOrderLine."Prod. Order No.",
                  ItemLedgEntry.TableCaption());

            CapLedgEntry.SetCurrentKey("Order Type", "Order No.");
            CapLedgEntry.SetRange("Order Type", CapLedgEntry."Order Type"::Production);
            CapLedgEntry.SetRange("Order No.", ProdOrderLine."Prod. Order No.");
			***OnCalculateOnAfterCapLedgEntrySetFilters(ProdOrderLine, CapLedgEntry);**
            if not CapLedgEntry.IsEmpty() then
                Error(
                  Text001,
                  ProdOrderLine.Status, ProdOrderLine.TableCaption(), ProdOrderLine."Prod. Order No.",
                  CapLedgEntry.TableCaption());
        end;

        CheckProdOrderLineQuantity(ProdOrderLine);
        if Direction = Direction::Backward then
            ProdOrderLine.TestField("Ending Date")
        else
            ProdOrderLine.TestField("Starting Date");

        if DeleteRelations then
            ProdOrderLine.DeleteRelations();

        if CalcRouting then begin
            TransferRouting();
            if not CalcComponents then begin // components will not be calculated later- update bin code
                ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);
                ProdOrderRoutingLine.SetRange("Prod. Order No.", ProdOrderLine."Prod. Order No.");
                ProdOrderRoutingLine.SetRange("Routing Reference No.", ProdOrderLine."Routing Reference No.");
                ProdOrderRoutingLine.SetRange("Routing No.", ProdOrderLine."Routing No.");
                if not ProdOrderRouteMgt.UpdateComponentsBin(ProdOrderRoutingLine, true) then
                    ErrorOccured := true;
            end;
        end else
            if RoutingHeader.Get(ProdOrderLine2."Routing No.") or (ProdOrderLine2."Routing No." = '') then
                if RoutingHeader.Type <> RoutingHeader.Type::Parallel then begin
                    ProdOrderRoutingLine3.SetRange(Status, ProdOrderLine2.Status);
                    ProdOrderRoutingLine3.SetRange("Prod. Order No.", ProdOrderLine2."Prod. Order No.");
                    ProdOrderRoutingLine3.SetRange("Routing Reference No.", ProdOrderLine2."Routing Reference No.");
                    ProdOrderRoutingLine3.SetRange("Routing No.", ProdOrderLine2."Routing No.");
                    ProdOrderRoutingLine3.SetFilter("Routing Status", '<>%1', ProdOrderRoutingLine3."Routing Status"::Finished);
                    ProdOrderRoutingLine4.CopyFilters(ProdOrderRoutingLine3);
                    if ProdOrderRoutingLine3.Find('-') then
                        repeat
                            if ProdOrderRoutingLine3."Next Operation No." <> '' then begin
                                ProdOrderRoutingLine4.SetRange("Operation No.", ProdOrderRoutingLine3."Next Operation No.");
                                if ProdOrderRoutingLine4.IsEmpty() then begin
                                    IsHandled := false;
                                    OnCalculateOnBeforeCheckNextOperation(ProdOrder, ProdOrderLine2, ProdOrderRoutingLine3, IsHandled);
                                    if not IsHandled then
                                        Error(OperationCannotFollowErr, ProdOrderRoutingLine3."Next Operation No.");
                                end;
                            end;
                            if ProdOrderRoutingLine3."Previous Operation No." <> '' then begin
                                ProdOrderRoutingLine4.SetRange("Operation No.", ProdOrderRoutingLine3."Previous Operation No.");
                                if ProdOrderRoutingLine4.IsEmpty() then begin
                                    IsHandled := false;
                                    OnCalculateOnBeforeCheckPrevOperation(ProdOrder, ProdOrderLine2, ProdOrderRoutingLine3, IsHandled);
                                    if not IsHandled then
                                        Error(OperationCannotPrecedeErr, ProdOrderRoutingLine3."Previous Operation No.");
                                end;
                            end;
                        until ProdOrderRoutingLine3.Next() = 0;
                end;

        SkipCalcComponents := false;
        OnCalculateOnBeforeCalcComponents(ProdOrderLine, CalcComponents, SkipCalcComponents);
        if CalcComponents and not SkipCalcComponents then
            if ProdOrderLine."Production BOM No." <> '' then begin
                Item.Get(ProdOrderLine."Item No.");
                GetPlanningParameters.AtSKU(
                  SKU,
                  ProdOrderLine."Item No.",
                  ProdOrderLine."Variant Code",
                  ProdOrderLine."Location Code");
                OnCalculateOnAfterGetpLanningParameterAtSKUCalcComponents(ProdOrderLine, SKU);

                CalculateLeadTime(ProdOrderLine, Direction, LetDueDateDecrease);
                CalculateRouting(Direction, LetDueDateDecrease);
                if not TransferBOM(
                     ProdOrderLine."Production BOM No.",
                     1,
                     ProdOrderLine."Qty. per Unit of Measure",
                     UOMMgt.GetQtyPerUnitOfMeasure(
                       Item,
                       VersionMgt.GetBOMUnitOfMeasure(
                         ProdOrderLine."Production BOM No.",
                         ProdOrderLine."Production BOM Version Code")))
                then
                    ErrorOccured := true;
            end;
        Recalculate(ProdOrderLine, Direction, LetDueDateDecrease, CalcRouting, CalcComponents);

        OnAfterCalculate(ProdOrderLine, ErrorOccured);

        exit(not ErrorOccured);
    end;

Metadata

Metadata

Assignees

No one assigned

    Labels

    missing-infoThe issue misses information that prevents it from completion.

    Type

    No fields configured for Task.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions