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;
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:
Changes between **:
In procedure Calculate of codeunit 99000773 "Calculate Prod. Order" we need an event:
Changes between **: