Codeunit 1019 Job-Explode BOM, source in 29
Source29
src/Layers/W1/BaseApp/Projects/Project/Planning/JobExplodeBOM.Codeunit.al264 lines, Copyright (c) Microsoft Corporation. MIT
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.Projects.Project.Planning;
using Microsoft.Assembly.Document;
using Microsoft.Foundation.ExtendedText;
using Microsoft.Foundation.UOM;
using Microsoft.Inventory.BOM;
using Microsoft.Inventory.Item;
using Microsoft.Inventory.Tracking;
using Microsoft.Projects.Project.Job;
using Microsoft.Projects.Resources.Resource;
codeunit 1019 "Job-Explode BOM"
{
TableNo = "Job Planning Line";
trigger OnRun()
var
AssembleToOrderLink: Record "Assemble-to-Order Link";
HideDialog: Boolean;
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeOnRun(Rec, IsHandled);
if IsHandled then
exit;
Job.Get(Rec."Job No.");
CheckJobPlanningLine(Rec);
DeleteReservEntries(Rec);
FromBOMComp.SetRange("Parent Item No.", Rec."No.");
NoOfBOMComp := FromBOMComp.Count();
if not HideDialog then
if NoOfBOMComp = 0 then
Error(ItemNotBOMErr, Rec."No.");
ToJobPlanningLine := Rec;
FromBOMComp.SetRange(Type, FromBOMComp.Type::Item);
FromBOMComp.SetFilter("No.", '<>%1', '');
if FromBOMComp.FindSet() then
repeat
FromBOMComp.TestField(Type, FromBOMComp.Type::Item);
Item.Get(FromBOMComp."No.");
AssingJobPlannigLineDataFromBOMComp();
until FromBOMComp.Next() = 0;
if Rec."BOM Item No." = '' then
BOMItemNo := Rec."No."
else
BOMItemNo := Rec."BOM Item No.";
if Rec.Type = Rec.Type::Item then
AssembleToOrderLink.DeleteAsmFromJobPlanningLine(Rec);
InitParentItemLine(Rec);
AddExtText();
ExplodeBOMCompLines(Rec);
end;
var
ToJobPlanningLine: Record "Job Planning Line";
FromBOMComp: Record "BOM Component";
Job: Record Job;
ItemTranslation: Record "Item Translation";
Item: Record Item;
Resource: Record Resource;
UOMMgt: Codeunit "Unit of Measure Management";
TransferExtendedText: Codeunit "Transfer Extended Text";
ReservMgt: Codeunit "Reservation Management";
BOMItemNo: Code[20];
LineSpacing: Integer;
NextLineNo: Integer;
NoOfBOMComp: Integer;
ItemNotBOMErr: Label 'Item %1 is not a BOM.', Comment = '%1 = Item No.';
NotEnoughSpaceMsg: Label 'There is not enough space to explode the BOM.';
procedure CallExplodeBOMCompLines(JobPlanningLine: Record "Job Planning Line")
begin
ExplodeBOMCompLines(JobPlanningLine);
end;
local procedure ExplodeBOMCompLines(JobPlanningLine: Record "Job Planning Line")
var
PreviousJobPlanningLine: Record "Job Planning Line";
InsertLinesBetween: Boolean;
begin
SetFiltersOnJobPlanningLine(JobPlanningLine);
ToJobPlanningLine := JobPlanningLine;
NextLineNo := JobPlanningLine."Line No.";
InsertLinesBetween := false;
if ToJobPlanningLine.Find('>') then
if ToJobPlanningLine.IsExtendedText() and (ToJobPlanningLine."Attached to Line No." = JobPlanningLine."Line No.") then begin
ToJobPlanningLine.SetRange("Attached to Line No.", JobPlanningLine."Line No.");
ToJobPlanningLine.FindLast();
ToJobPlanningLine.SetRange("Attached to Line No.");
NextLineNo := ToJobPlanningLine."Line No.";
InsertLinesBetween := ToJobPlanningLine.Find('>');
end else
InsertLinesBetween := true;
GenerateLineSpacing(InsertLinesBetween);
FromBOMComp.Reset();
FromBOMComp.SetRange("Parent Item No.", JobPlanningLine."No.");
FromBOMComp.FindSet();
repeat
ToJobPlanningLine.Init();
NextLineNo := NextLineNo + LineSpacing;
ToJobPlanningLine."Line No." := NextLineNo;
ToJobPlanningLine.Validate("Line Type", JobPlanningLine."Line Type");
AssignBOMCompType();
if ToJobPlanningLine.Type <> ToJobPlanningLine.Type::Text then begin
FromBOMComp.TestField("No.");
ValidateJobPlanningLineData(JobPlanningLine);
end;
AddDescriptionFromTranslationIfExist();
ToJobPlanningLine."BOM Item No." := BOMItemNo;
ToJobPlanningLine.Insert(true);
if not (ToJobPlanningLine."Line Type" = ToJobPlanningLine."Line Type"::Billable) then
ToJobPlanningLine.Validate("Qty. to Assemble");
if (ToJobPlanningLine.Type = ToJobPlanningLine.Type::Item) and (ToJobPlanningLine.Reserve = ToJobPlanningLine.Reserve::Always) then
ToJobPlanningLine.AutoReserve();
if PreviousJobPlanningLine."Job No." <> '' then
if TransferExtendedText.JobCheckIfAnyExtText(PreviousJobPlanningLine, false) then
TransferExtendedText.InsertJobExtText(PreviousJobPlanningLine);
PreviousJobPlanningLine := ToJobPlanningLine;
until FromBOMComp.Next() = 0;
AddExtText();
end;
local procedure ValidateJobPlanningLineData(JobPlanningLine: Record "Job Planning Line")
begin
ToJobPlanningLine.Validate("Planning Date", JobPlanningLine."Planning Date");
ToJobPlanningLine.Validate("Document No.", JobPlanningLine."Document No.");
ToJobPlanningLine.Validate("No.", FromBOMComp."No.");
ToJobPlanningLine.Validate("Location Code", JobPlanningLine."Location Code");
if FromBOMComp."Variant Code" <> '' then
ToJobPlanningLine.Validate("Variant Code", FromBOMComp."Variant Code");
ValidateQtyAndUoMForDifferentTypes(JobPlanningLine);
end;
local procedure SetFiltersOnJobPlanningLine(JobPlanningLine: Record "Job Planning Line")
begin
ToJobPlanningLine.Reset();
ToJobPlanningLine.SetRange("Job No.", JobPlanningLine."Job No.");
ToJobPlanningLine.SetRange("Job Task No.", JobPlanningLine."Job Task No.");
end;
local procedure AddExtText()
begin
if TransferExtendedText.JobCheckIfAnyExtText(ToJobPlanningLine, false) then
TransferExtendedText.InsertJobExtText(ToJobPlanningLine);
end;
local procedure AssignBOMCompType()
begin
case FromBOMComp.Type of
FromBOMComp.Type::" ":
ToJobPlanningLine.Type := ToJobPlanningLine.Type::Text;
FromBOMComp.Type::Item:
ToJobPlanningLine.Type := ToJobPlanningLine.Type::Item;
FromBOMComp.Type::Resource:
ToJobPlanningLine.Type := ToJobPlanningLine.Type::Resource;
end;
end;
local procedure AssingJobPlannigLineDataFromBOMComp()
begin
ToJobPlanningLine."Line No." := 0;
ToJobPlanningLine."No." := FromBOMComp."No.";
ToJobPlanningLine."Variant Code" := FromBOMComp."Variant Code";
ToJobPlanningLine."Unit of Measure Code" := FromBOMComp."Unit of Measure Code";
ToJobPlanningLine."Qty. per Unit of Measure" := UOMMgt.GetQtyPerUnitOfMeasure(Item, FromBOMComp."Unit of Measure Code");
end;
local procedure CheckJobPlanningLine(JobPlanningLine: Record "Job Planning Line")
begin
JobPlanningLine.TestField(Type, JobPlanningLine.Type::Item);
JobPlanningLine.CalcFields("Reserved Qty. (Base)");
JobPlanningLine.TestField("Reserved Qty. (Base)", 0);
end;
local procedure InitParentItemLine(var FromJobPlanningLine: Record "Job Planning Line")
begin
ToJobPlanningLine := FromJobPlanningLine;
ToJobPlanningLine.Init();
ToJobPlanningLine."Line Type" := FromJobPlanningLine."Line Type";
ToJobPlanningLine.Type := ToJobPlanningLine.Type::Text;
ToJobPlanningLine.Description := FromJobPlanningLine.Description;
ToJobPlanningLine."Description 2" := FromJobPlanningLine."Description 2";
ToJobPlanningLine."BOM Item No." := BOMItemNo;
ToJobPlanningLine.Modify();
end;
local procedure ValidateQtyAndUoMForDifferentTypes(JobPlanningLine: Record "Job Planning Line")
var
QtyRoundingPrecision: Decimal;
begin
case ToJobPlanningLine.Type of
ToJobPlanningLine.Type::Item:
begin
Item.Get(FromBOMComp."No.");
ToJobPlanningLine.Validate("Unit of Measure Code", FromBOMComp."Unit of Measure Code");
ToJobPlanningLine."Qty. per Unit of Measure" := UOMMgt.GetQtyPerUnitOfMeasure(Item, ToJobPlanningLine."Unit of Measure Code");
QtyRoundingPrecision := UOMMgt.GetQtyRoundingPrecision(Item, ToJobPlanningLine."Unit of Measure Code");
if QtyRoundingPrecision = 0 then
QtyRoundingPrecision := UOMMgt.QtyRndPrecision();
ToJobPlanningLine.Validate(Quantity, Round(JobPlanningLine."Quantity (Base)" * FromBOMComp."Quantity per", QtyRoundingPrecision));
end;
ToJobPlanningLine.Type::Resource:
begin
Resource.Get(FromBOMComp."No.");
ToJobPlanningLine.Validate("Unit of Measure Code", FromBOMComp."Unit of Measure Code");
ToJobPlanningLine."Qty. per Unit of Measure" := UOMMgt.GetResQtyPerUnitOfMeasure(Resource, ToJobPlanningLine."Unit of Measure Code");
ToJobPlanningLine.Validate(Quantity, Round(JobPlanningLine."Quantity (Base)" * FromBOMComp."Quantity per", UOMMgt.QtyRndPrecision()));
end;
else
ToJobPlanningLine.Validate(Quantity, JobPlanningLine."Quantity (Base)" * FromBOMComp."Quantity per");
end;
end;
local procedure AddDescriptionFromTranslationIfExist()
begin
if Job."Language Code" = '' then
ToJobPlanningLine.Description := FromBOMComp.Description
else
if not ItemTranslation.Get(FromBOMComp."No.", FromBOMComp."Variant Code", Job."Language Code") then
ToJobPlanningLine.Description := FromBOMComp.Description;
end;
local procedure GenerateLineSpacing(InsertLinesBetween: Boolean)
begin
if InsertLinesBetween then
LineSpacing := (ToJobPlanningLine."Line No." - NextLineNo) div (1 + NoOfBOMComp)
else
LineSpacing := 10000;
if LineSpacing = 0 then
Error(NotEnoughSpaceMsg);
end;
local procedure DeleteReservEntries(JobPlanningLine: Record "Job Planning Line")
begin
ReservMgt.SetReservSource(JobPlanningLine);
ReservMgt.SetItemTrackingHandling(1);
ReservMgt.DeleteReservEntries(true, 0);
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeOnRun(var JobPlanningLine: Record "Job Planning Line"; var IsHandled: Boolean)
begin
end;
}