Codeunit 99000844 Job Jnl. Line-Reserve, source in 29
Source29
src/Layers/W1/BaseApp/Projects/Project/Journal/JobJnlLineReserve.Codeunit.al338 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.Journal;
using Microsoft.Inventory.Journal;
using Microsoft.Inventory.Tracking;
codeunit 99000844 "Job Jnl. Line-Reserve"
{
Permissions = TableData "Reservation Entry" = rimd;
trigger OnRun()
begin
end;
var
ReservMgt: Codeunit "Reservation Management";
CreateReservEntry: Codeunit "Create Reserv. Entry";
ReservEngineMgt: Codeunit "Reservation Engine Mgt.";
DeleteItemTracking: Boolean;
CalledFromInvtPutawayPick: Boolean;
#pragma warning disable AA0074
Text002: Label 'must be filled in when a quantity is reserved.';
Text004: Label 'must not be changed when a quantity is reserved.';
#pragma warning restore AA0074
JobJournalTxt: Label 'Project Journal';
SourceDoc4Txt: Label '%1 %2 %3 %4', Locked = true;
local procedure FindReservEntry(JobJnlLine: Record "Job Journal Line"; var ReservEntry: Record "Reservation Entry"): Boolean
begin
ReservEntry.InitSortingAndFilters(false);
JobJnlLine.SetReservationFilters(ReservEntry);
exit(ReservEntry.Find('+'));
end;
procedure VerifyChange(var NewJobJnlLine: Record "Job Journal Line"; var OldJobJnlLine: Record "Job Journal Line")
var
JobJnlLine: Record "Job Journal Line";
TempReservEntry: Record "Reservation Entry";
ShowError: Boolean;
HasError: Boolean;
PointerChanged: Boolean;
begin
if NewJobJnlLine."Line No." = 0 then
if not JobJnlLine.Get(
NewJobJnlLine."Journal Template Name",
NewJobJnlLine."Journal Batch Name",
NewJobJnlLine."Line No.")
then
exit;
NewJobJnlLine.CalcFields("Reserved Qty. (Base)");
ShowError := NewJobJnlLine."Reserved Qty. (Base)" <> 0;
if NewJobJnlLine."Posting Date" = 0D then
if not ShowError then
HasError := true
else
NewJobJnlLine.FieldError("Posting Date", Text002);
if NewJobJnlLine."Job No." <> OldJobJnlLine."Job No." then
if not ShowError then
HasError := true
else
NewJobJnlLine.FieldError("Job No.", Text004);
if NewJobJnlLine."Entry Type" <> OldJobJnlLine."Entry Type" then
if not ShowError then
HasError := true
else
NewJobJnlLine.FieldError("Entry Type", Text004);
if NewJobJnlLine."Location Code" <> OldJobJnlLine."Location Code" then
if not ShowError then
HasError := true
else
NewJobJnlLine.FieldError("Location Code", Text004);
if (NewJobJnlLine.Type = NewJobJnlLine.Type::Item) and (OldJobJnlLine.Type = OldJobJnlLine.Type::Item) then
if (NewJobJnlLine."Bin Code" <> OldJobJnlLine."Bin Code") and
(not ReservMgt.CalcIsAvailTrackedQtyInBin(
NewJobJnlLine."No.", NewJobJnlLine."Bin Code",
NewJobJnlLine."Location Code", NewJobJnlLine."Variant Code",
DATABASE::"Job Journal Line", NewJobJnlLine."Entry Type".AsInteger(),
NewJobJnlLine."Journal Template Name", NewJobJnlLine."Journal Batch Name", 0, NewJobJnlLine."Line No."))
then begin
if ShowError then
NewJobJnlLine.FieldError("Bin Code", Text004);
HasError := true;
end;
if NewJobJnlLine."Variant Code" <> OldJobJnlLine."Variant Code" then
if not ShowError then
HasError := true
else
NewJobJnlLine.FieldError("Variant Code", Text004);
if NewJobJnlLine."Line No." <> OldJobJnlLine."Line No." then
HasError := true;
if NewJobJnlLine."No." <> OldJobJnlLine."No." then
HasError := true;
OnVerifyChangeOnBeforeHasError(NewJobJnlLine, OldJobJnlLine, HasError, ShowError);
if HasError then begin
FindReservEntry(NewJobJnlLine, TempReservEntry);
TempReservEntry.ClearTrackingFilter();
PointerChanged := (NewJobJnlLine."Job No." <> OldJobJnlLine."Job No.") or
(NewJobJnlLine."Entry Type" <> OldJobJnlLine."Entry Type") or
(NewJobJnlLine."No." <> OldJobJnlLine."No.");
if PointerChanged or
(not TempReservEntry.IsEmpty)
then begin
if PointerChanged then begin
ReservMgt.SetReservSource(OldJobJnlLine);
ReservMgt.DeleteReservEntries(true, 0);
ReservMgt.SetReservSource(NewJobJnlLine);
end else begin
ReservMgt.SetReservSource(NewJobJnlLine);
ReservMgt.DeleteReservEntries(true, 0);
end;
ReservMgt.AutoTrack(NewJobJnlLine."Quantity (Base)");
end;
end;
end;
procedure VerifyQuantity(var NewJobJnlLine: Record "Job Journal Line"; var OldJobJnlLine: Record "Job Journal Line")
var
JobJnlLine: Record "Job Journal Line";
begin
if NewJobJnlLine."Line No." = OldJobJnlLine."Line No." then
if NewJobJnlLine."Quantity (Base)" = OldJobJnlLine."Quantity (Base)" then
exit;
if NewJobJnlLine."Line No." = 0 then
if not JobJnlLine.Get(NewJobJnlLine."Journal Template Name", NewJobJnlLine."Journal Batch Name", NewJobJnlLine."Line No.") then
exit;
ReservMgt.SetReservSource(NewJobJnlLine);
if NewJobJnlLine."Qty. per Unit of Measure" <> OldJobJnlLine."Qty. per Unit of Measure" then
ReservMgt.ModifyUnitOfMeasure();
if NewJobJnlLine."Quantity (Base)" * OldJobJnlLine."Quantity (Base)" < 0 then
ReservMgt.DeleteReservEntries(true, 0)
else
ReservMgt.DeleteReservEntries(false, NewJobJnlLine."Quantity (Base)");
end;
procedure RenameLine(var NewJobJnlLine: Record "Job Journal Line"; var OldJobJnlLine: Record "Job Journal Line")
begin
ReservEngineMgt.RenamePointer(DATABASE::"Job Journal Line",
OldJobJnlLine."Entry Type".AsInteger(),
OldJobJnlLine."Journal Template Name",
OldJobJnlLine."Journal Batch Name",
0,
OldJobJnlLine."Line No.",
NewJobJnlLine."Entry Type".AsInteger(),
NewJobJnlLine."Journal Template Name",
NewJobJnlLine."Journal Batch Name",
0,
NewJobJnlLine."Line No.");
end;
procedure DeleteLineConfirm(var JobJnlLine: Record "Job Journal Line"): Boolean
begin
if not JobJnlLine.ReservEntryExist() then
exit(true);
ReservMgt.SetReservSource(JobJnlLine);
if ReservMgt.DeleteItemTrackingConfirm() then
DeleteItemTracking := true;
exit(DeleteItemTracking);
end;
procedure DeleteLine(var JobJnlLine: Record "Job Journal Line")
begin
if JobJnlLine.Type = JobJnlLine.Type::Item then begin
ReservMgt.SetReservSource(JobJnlLine);
if DeleteItemTracking then
ReservMgt.SetItemTrackingHandling(1); // Allow Deletion
ReservMgt.DeleteReservEntries(true, 0);
end;
end;
procedure CallItemTracking(var JobJnlLine: Record "Job Journal Line"; IsReclass: Boolean)
var
TrackingSpecification: Record "Tracking Specification";
ItemTrackingLines: Page "Item Tracking Lines";
begin
InitFromJobJnlLine(TrackingSpecification, JobJnlLine);
if IsReclass then
ItemTrackingLines.SetRunMode(Enum::"Item Tracking Run Mode"::Reclass);
ItemTrackingLines.SetSourceSpec(TrackingSpecification, JobJnlLine."Posting Date");
ItemTrackingLines.SetInbound(JobJnlLine.IsInbound());
ItemTrackingLines.RunModal();
end;
internal procedure TransJobJnlLineToItemJnlLine(var JobJnlLine: Record "Job Journal Line"; var ItemJnlLine: Record "Item Journal Line"; TransferQty: Decimal; CalledFromInvtPutawayPickVal: Boolean): Decimal
begin
CalledFromInvtPutawayPick := CalledFromInvtPutawayPickVal;
exit(TransJobJnlLineToItemJnlLine(JobJnlLine, ItemJnlLine, TransferQty));
end;
procedure TransJobJnlLineToItemJnlLine(var JobJnlLine: Record "Job Journal Line"; var ItemJnlLine: Record "Item Journal Line"; TransferQty: Decimal): Decimal
var
OldReservEntry: Record "Reservation Entry";
begin
if not FindReservEntry(JobJnlLine, OldReservEntry) then
exit(TransferQty);
OldReservEntry.Lock();
// Handle Item Tracking on drop shipment:
Clear(CreateReservEntry);
ItemJnlLine.TestItemFields(JobJnlLine."No.", JobJnlLine."Variant Code", JobJnlLine."Location Code");
if TransferQty = 0 then
exit;
//Do not transfer remaining quantity when posting from Inventory Pick as the entry is created during posting process of Item through Item Jnl Line.
CreateReservEntry.SetCalledFromInvtPutawayPick(CalledFromInvtPutawayPick);
if ReservEngineMgt.InitRecordSet(OldReservEntry) then
repeat
OldReservEntry.TestItemFields(JobJnlLine."No.", JobJnlLine."Variant Code", JobJnlLine."Location Code");
TransferQty := CreateReservEntry.TransferReservEntry(DATABASE::"Item Journal Line",
ItemJnlLine."Entry Type".AsInteger(), ItemJnlLine."Journal Template Name",
ItemJnlLine."Journal Batch Name", 0, ItemJnlLine."Line No.",
ItemJnlLine."Qty. per Unit of Measure", OldReservEntry, TransferQty);
until (ReservEngineMgt.NEXTRecord(OldReservEntry) = 0) or (TransferQty = 0);
exit(TransferQty);
end;
local procedure MatchThisTable(TableID: Integer): Boolean
begin
exit(TableID = DATABASE::"Job Journal Line");
end;
local procedure GetSourceValue(ReservEntry: Record "Reservation Entry"; var SourceRecRef: RecordRef; ReturnOption: Option "Net Qty. (Base)","Gross Qty. (Base)"): Decimal
var
JobJnlLine: Record "Job Journal Line";
begin
JobJnlLine.Get(ReservEntry."Source ID", ReservEntry."Source Batch Name", ReservEntry."Source Ref. No.");
SourceRecRef.GetTable(JobJnlLine);
case ReturnOption of
ReturnOption::"Net Qty. (Base)":
exit(JobJnlLine."Quantity (Base)");
ReturnOption::"Gross Qty. (Base)":
exit(JobJnlLine."Quantity (Base)");
end;
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Reservation Management", 'OnGetSourceRecordValue', '', false, false)]
local procedure OnGetSourceRecordValue(var ReservEntry: Record "Reservation Entry"; ReturnOption: Option; var ReturnQty: Decimal; var SourceRecRef: RecordRef)
begin
if MatchThisTable(ReservEntry."Source Type") then
ReturnQty := GetSourceValue(ReservEntry, SourceRecRef, ReturnOption);
end;
[IntegrationEvent(false, false)]
local procedure OnVerifyChangeOnBeforeHasError(NewJobJnlLine: Record "Job Journal Line"; OldJobJnlLine: Record "Job Journal Line"; var HasError: Boolean; var ShowError: Boolean)
begin
end;
#if not CLEAN27
[Obsolete('This event is never raised.', '27.0')]
[IntegrationEvent(false, false)]
local procedure OnSetSourceForReservationOnBeforeUpdateReservation(var ReservEntry: Record "Reservation Entry"; JobJnlLine: Record "Job Journal Line")
begin
end;
#endif
// codeunit Create Reserv. Entry
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Create Reserv. Entry", 'OnCheckSourceTypeSubtype', '', false, false)]
local procedure CheckSourceTypeSubtype(var ReservationEntry: Record "Reservation Entry"; var IsError: Boolean)
begin
if MatchThisTable(ReservationEntry."Source Type") then
IsError := ReservationEntry.Binding = ReservationEntry.Binding::"Order-to-Order";
end;
// codeunit Reservation Engine Mgt. subscribers
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Reservation Engine Mgt.", 'OnGetActivePointerFieldsOnBeforeAssignArrayValues', '', false, false)]
local procedure OnGetActivePointerFieldsOnBeforeAssignArrayValues(TableID: Integer; var PointerFieldIsActive: array[6] of Boolean; var IsHandled: Boolean)
begin
if TableID = Database::"Job Journal Line" then begin
PointerFieldIsActive[1] := true; // Type
PointerFieldIsActive[2] := true; // SubType
PointerFieldIsActive[3] := true; // ID
PointerFieldIsActive[4] := true; // BatchName
PointerFieldIsActive[6] := true; // RefNo
end;
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Reservation Engine Mgt.", 'OnCreateText', '', false, false)]
local procedure OnAfterCreateText(ReservationEntry: Record "Reservation Entry"; var Description: Text[80])
begin
if MatchThisTable(ReservationEntry."Source Type") then
Description :=
StrSubstNo(
SourceDoc4Txt, JobJournalTxt, Enum::"Job Journal Line Entry Type".FromInteger(ReservationEntry."Source Subtype"),
ReservationEntry."Source ID", ReservationEntry."Source Batch Name");
end;
procedure InitFromJobJnlLine(var TrackingSpecification: Record "Tracking Specification"; var JobJnlLine: Record "Job Journal Line")
begin
TrackingSpecification.Init();
TrackingSpecification.SetItemData(
JobJnlLine."No.", JobJnlLine.Description, JobJnlLine."Location Code", JobJnlLine."Variant Code", JobJnlLine."Bin Code",
JobJnlLine."Qty. per Unit of Measure", JobJnlLine."Qty. Rounding Precision (Base)");
TrackingSpecification.SetSource(
Database::"Job Journal Line", JobJnlLine."Entry Type".AsInteger(), JobJnlLine."Journal Template Name", JobJnlLine."Line No.",
JobJnlLine."Journal Batch Name", 0);
TrackingSpecification.SetQuantities(
JobJnlLine."Quantity (Base)", JobJnlLine.Quantity, JobJnlLine."Quantity (Base)", JobJnlLine.Quantity,
JobJnlLine."Quantity (Base)", 0, 0);
OnAfterInitFromJobJnlLine(TrackingSpecification, JobJnlLine);
end;
[IntegrationEvent(false, false)]
local procedure OnAfterInitFromJobJnlLine(var TrackingSpecification: Record "Tracking Specification"; JobJournalLine: Record "Job Journal Line")
begin
end;
[EventSubscriber(ObjectType::Table, Database::"Reservation Entry", 'OnAfterSummEntryNo', '', false, false)]
local procedure OnBeforeSummEntryNo(ReservationEntry: Record "Reservation Entry"; var ReturnValue: Integer)
begin
if MatchThisTable(ReservationEntry."Source Type") then
ReturnValue := Enum::"Reservation Summary Type"::"Job Journal Usage".AsInteger() + ReservationEntry."Source Subtype";
end;
}