Codeunit 5854 Invt. Doc. Line-Reserve
- App
- Base Application
- Namespace
- Microsoft.Inventory.Document
- Versions
- 18-28
Versions171819202122232425262728
Source29
Source in 29
src/Layers/W1/BaseApp/Inventory/Document/InvtDocLineReserve.Codeunit.al827 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.Inventory.Document;
using Microsoft.Foundation.Enums;
using Microsoft.Foundation.UOM;
using Microsoft.Inventory.Journal;
using Microsoft.Inventory.Ledger;
using Microsoft.Inventory.Location;
using Microsoft.Inventory.Planning;
using Microsoft.Inventory.Setup;
using Microsoft.Inventory.Tracking;
using Microsoft.Warehouse.Activity;
codeunit 5854 "Invt. Doc. Line-Reserve"
{
Permissions = TableData "Reservation Entry" = rimd;
trigger OnRun()
begin
end;
var
FromTrackingSpecification: Record "Tracking Specification";
InventorySetup: Record "Inventory Setup";
ReservationManagement: Codeunit "Reservation Management";
CreateReservEntry: Codeunit "Create Reserv. Entry";
ReservationEngineMgt: Codeunit "Reservation Engine Mgt.";
UOMMgt: Codeunit "Unit of Measure Management";
Blocked: Boolean;
DeleteItemTracking: Boolean;
InvtSetupRead: Boolean;
CodeunitIsNotInitializedErr: Label 'Codeunit is not initialized correctly.';
CannotBeGreaterErr: Label 'Reserved quantity cannot be greater than %1.', Comment = '%1 - quantity';
MustBeFilledErr: Label 'must be filled in when a quantity is reserved';
MustNotBeChangedErr: Label 'must not be changed when a quantity is reserved';
DirectionTxt: Label 'Outbound,Inbound';
InventoryTxt: Label 'Inventory';
SummaryTypeTxt: Label '%1, %2', Locked = true;
SourceDoc3Txt: Label '%1 %2 %3', Locked = true;
procedure CreateReservation(var InvtDocumentLine: Record "Invt. Document Line"; Description: Text[100]; ExpectedReceiptDate: Date; Quantity: Decimal; QuantityBase: Decimal; ForReservationEntry: Record "Reservation Entry")
var
ShipmentDate: Date;
begin
if FromTrackingSpecification."Source Type" = 0 then
Error(CodeunitIsNotInitializedErr);
InvtDocumentLine.TestField("Item No.");
InvtDocumentLine.TestField("Variant Code", FromTrackingSpecification."Variant Code");
case InvtDocumentLine."Document Type" of
"Invt. Doc. Document Type"::Shipment:
begin
InvtDocumentLine.TestField("Document Date");
InvtDocumentLine.TestField("Location Code", FromTrackingSpecification."Location Code");
InvtDocumentLine.CalcFields("Reserved Qty. Outbnd. (Base)");
if Abs(InvtDocumentLine."Quantity (Base)") <
Abs(InvtDocumentLine."Reserved Qty. Outbnd. (Base)") + Quantity
then
Error(
CannotBeGreaterErr,
Abs(InvtDocumentLine."Quantity (Base)") - Abs(InvtDocumentLine."Reserved Qty. Outbnd. (Base)"));
ShipmentDate := InvtDocumentLine."Document Date";
end;
"Invt. Doc. Document Type"::Receipt:
begin
InvtDocumentLine.TestField("Document Date");
InvtDocumentLine.TestField("Location Code", FromTrackingSpecification."Location Code");
InvtDocumentLine.CalcFields("Reserved Qty. Inbnd. (Base)");
if Abs(InvtDocumentLine."Quantity (Base)") <
Abs(InvtDocumentLine."Reserved Qty. Inbnd. (Base)") + Quantity
then
Error(
CannotBeGreaterErr,
Abs(InvtDocumentLine."Quantity (Base)") - Abs(InvtDocumentLine."Reserved Qty. Inbnd. (Base)"));
ExpectedReceiptDate := InvtDocumentLine."Document Date";
end;
end;
CreateReservEntry.CreateReservEntryFor(
Database::"Invt. Document Line",
InvtDocumentLine."Document Type".AsInteger(), InvtDocumentLine."Document No.", '',
0, InvtDocumentLine."Line No.", InvtDocumentLine."Qty. per Unit of Measure",
Quantity, QuantityBase, ForReservationEntry);
CreateReservEntry.CreateReservEntryFrom(FromTrackingSpecification);
CreateReservEntry.CreateReservEntry(
InvtDocumentLine."Item No.", InvtDocumentLine."Variant Code", FromTrackingSpecification."Location Code",
Description, ExpectedReceiptDate, ShipmentDate, 0);
FromTrackingSpecification."Source Type" := 0;
end;
procedure CreateReservationSetFrom(TrackingSpecification: Record "Tracking Specification")
begin
FromTrackingSpecification := TrackingSpecification;
end;
procedure FilterReservFor(var FilterReservationEntry: Record "Reservation Entry"; InvtDocumentLine: Record "Invt. Document Line")
begin
InvtDocumentLine.SetReservationFilters(FilterReservationEntry);
end;
procedure Caption(InvtDocumentLine: Record "Invt. Document Line"): Text
begin
exit(InvtDocumentLine.GetSourceCaption());
end;
procedure FindReservEntry(InvtDocumentLine: Record "Invt. Document Line"; var ReservationEntry: Record "Reservation Entry"): Boolean
begin
ReservationEntry.InitSortingAndFilters(false);
InvtDocumentLine.SetReservationFilters(ReservationEntry);
exit(ReservationEntry.Find('+'));
end;
procedure VerifyChange(var NewInvtDocumentLine: Record "Invt. Document Line"; var OldInvtDocumentLine: Record "Invt. Document Line")
var
InvtDocumentLine: Record "Invt. Document Line";
ShowErrorInbnd: Boolean;
ShowErrorOutbnd: Boolean;
HasErrorInbnd: Boolean;
HasErrorOutbnd: Boolean;
IsHandled: Boolean;
begin
if Blocked then
exit;
if NewInvtDocumentLine."Line No." = 0 then
if not InvtDocumentLine.Get(NewInvtDocumentLine."Document Type", NewInvtDocumentLine."Document No.", NewInvtDocumentLine."Line No.") then
exit;
IsHandled := false;
OnBeforeVerifyChange(NewInvtDocumentLine, OldInvtDocumentLine, IsHandled);
if IsHandled then
exit;
NewInvtDocumentLine.CalcFields("Reserved Qty. Inbnd. (Base)");
NewInvtDocumentLine.CalcFields("Reserved Qty. Outbnd. (Base)");
ShowErrorInbnd := (NewInvtDocumentLine."Reserved Qty. Inbnd. (Base)" <> 0);
ShowErrorOutbnd := (NewInvtDocumentLine."Reserved Qty. Outbnd. (Base)" <> 0);
if NewInvtDocumentLine."Document Type" = NewInvtDocumentLine."Document Type"::Receipt then
if NewInvtDocumentLine."Document Date" = 0D then begin
if ShowErrorOutbnd then
NewInvtDocumentLine.FieldError("Document Date", MustBeFilledErr);
HasErrorOutbnd := true;
end;
if NewInvtDocumentLine."Document Type" = NewInvtDocumentLine."Document Type"::Shipment then
if NewInvtDocumentLine."Document Date" = 0D then begin
if ShowErrorOutbnd then
NewInvtDocumentLine.FieldError("Document Date", MustBeFilledErr);
HasErrorOutbnd := true;
end;
if NewInvtDocumentLine."Item No." <> OldInvtDocumentLine."Item No." then begin
if ShowErrorInbnd or ShowErrorOutbnd then
NewInvtDocumentLine.FieldError("Item No.", MustNotBeChangedErr);
HasErrorInbnd := true;
HasErrorOutbnd := true;
end;
if NewInvtDocumentLine."Location Code" <> OldInvtDocumentLine."Location Code" then begin
if ShowErrorOutbnd then
NewInvtDocumentLine.FieldError("Location Code", MustNotBeChangedErr);
HasErrorOutbnd := true;
end;
if NewInvtDocumentLine."Bin Code" <> OldInvtDocumentLine."Bin Code" then begin
if ShowErrorOutbnd then
NewInvtDocumentLine.FieldError("Bin Code", MustNotBeChangedErr);
HasErrorOutbnd := true;
end;
if NewInvtDocumentLine."Variant Code" <> OldInvtDocumentLine."Variant Code" then begin
if ShowErrorInbnd or ShowErrorOutbnd then
NewInvtDocumentLine.FieldError("Variant Code", MustNotBeChangedErr);
HasErrorInbnd := true;
HasErrorOutbnd := true;
end;
if NewInvtDocumentLine."Line No." <> OldInvtDocumentLine."Line No." then begin
HasErrorInbnd := true;
HasErrorOutbnd := true;
end;
if HasErrorOutbnd then begin
if (NewInvtDocumentLine."Item No." <> OldInvtDocumentLine."Item No.") or NewInvtDocumentLine.ReservEntryExist() then begin
if NewInvtDocumentLine."Item No." <> OldInvtDocumentLine."Item No." then begin
ReservationManagement.SetReservSource(OldInvtDocumentLine);
ReservationManagement.DeleteReservEntries(true, 0);
ReservationManagement.SetReservSource(NewInvtDocumentLine);
end else begin
ReservationManagement.SetReservSource(NewInvtDocumentLine);
ReservationManagement.DeleteReservEntries(true, 0);
end;
ReservationManagement.AutoTrack(NewInvtDocumentLine."Quantity (Base)");
end;
AssignForPlanning(NewInvtDocumentLine);
if (NewInvtDocumentLine."Item No." <> OldInvtDocumentLine."Item No.") or
(NewInvtDocumentLine."Variant Code" <> OldInvtDocumentLine."Variant Code")
then
AssignForPlanning(OldInvtDocumentLine);
end;
if HasErrorInbnd then begin
if (NewInvtDocumentLine."Item No." <> OldInvtDocumentLine."Item No.") or NewInvtDocumentLine.ReservEntryExist() then begin
if NewInvtDocumentLine."Item No." <> OldInvtDocumentLine."Item No." then begin
ReservationManagement.SetReservSource(OldInvtDocumentLine);
ReservationManagement.DeleteReservEntries(true, 0);
ReservationManagement.SetReservSource(NewInvtDocumentLine);
end else begin
ReservationManagement.SetReservSource(NewInvtDocumentLine);
ReservationManagement.DeleteReservEntries(true, 0);
end;
ReservationManagement.AutoTrack(NewInvtDocumentLine."Quantity (Base)");
end;
AssignForPlanning(NewInvtDocumentLine);
if (NewInvtDocumentLine."Item No." <> OldInvtDocumentLine."Item No.") or
(NewInvtDocumentLine."Variant Code" <> OldInvtDocumentLine."Variant Code") or
(NewInvtDocumentLine."Location Code" <> OldInvtDocumentLine."Location Code")
then
AssignForPlanning(OldInvtDocumentLine);
end;
end;
procedure VerifyQuantity(var NewInvtDocumentLine: Record "Invt. Document Line"; var OldInvtDocumentLine: Record "Invt. Document Line")
var
InvtDocumentLine: Record "Invt. Document Line";
begin
if Blocked then
exit;
if NewInvtDocumentLine."Line No." = OldInvtDocumentLine."Line No." then
if NewInvtDocumentLine."Quantity (Base)" = OldInvtDocumentLine."Quantity (Base)" then
exit;
if NewInvtDocumentLine."Line No." = 0 then
if not InvtDocumentLine.Get(NewInvtDocumentLine."Document Type", NewInvtDocumentLine."Document No.", NewInvtDocumentLine."Line No.") then
exit;
ReservationManagement.SetReservSource(NewInvtDocumentLine);
if NewInvtDocumentLine."Qty. per Unit of Measure" <> OldInvtDocumentLine."Qty. per Unit of Measure" then
ReservationManagement.ModifyUnitOfMeasure();
ReservationManagement.DeleteReservEntries(false, NewInvtDocumentLine."Quantity (Base)");
ReservationManagement.ClearSurplus();
ReservationManagement.AutoTrack(NewInvtDocumentLine."Quantity (Base)");
AssignForPlanning(NewInvtDocumentLine);
end;
procedure TransferInvtDocToItemJnlLine(var InvtDocumentLine: Record "Invt. Document Line"; var ItemJournalLine: Record "Item Journal Line"; ReceiptQty: Decimal)
var
OldReservationEntry: Record "Reservation Entry";
RemainingReceiptQtyBase: Decimal;
begin
if not FindReservEntry(InvtDocumentLine, OldReservationEntry) then
exit;
OldReservationEntry.LockTable();
OldReservationEntry.FindLast();
ItemJournalLine.TestField("Location Code", InvtDocumentLine."Location Code");
ItemJournalLine.TestField("Item No.", InvtDocumentLine."Item No.");
ItemJournalLine.TestField("Variant Code", InvtDocumentLine."Variant Code");
if ReceiptQty = 0 then
exit;
RemainingReceiptQtyBase := ReceiptQty * ItemJournalLine."Qty. per Unit of Measure";
if ReservationEngineMgt.InitRecordSet(OldReservationEntry) then
repeat
OldReservationEntry.TestField("Item No.", InvtDocumentLine."Item No.");
OldReservationEntry.TestField("Variant Code", InvtDocumentLine."Variant Code");
OldReservationEntry.TestField("Location Code", InvtDocumentLine."Location Code");
RemainingReceiptQtyBase :=
CreateReservEntry.TransferReservEntry(
Database::"Item Journal Line",
ItemJournalLine."Entry Type".AsInteger(), ItemJournalLine."Journal Template Name",
ItemJournalLine."Journal Batch Name", 0, ItemJournalLine."Line No.",
ItemJournalLine."Qty. per Unit of Measure", OldReservationEntry,
RemainingReceiptQtyBase); // qty base
until (ReservationEngineMgt.NEXTRecord(OldReservationEntry) = 0) or (RemainingReceiptQtyBase = 0);
end;
procedure RenameLine(var NewInvtDocumentLine: Record "Invt. Document Line"; var OldInvtDocumentLine: Record "Invt. Document Line")
begin
ReservationEngineMgt.RenamePointer(
Database::"Invt. Document Line",
0, OldInvtDocumentLine."Document No.", '', 0, OldInvtDocumentLine."Line No.",
0, NewInvtDocumentLine."Document No.", '', 0, NewInvtDocumentLine."Line No.");
end;
procedure DeleteLine(var InvtDocumentLine: Record "Invt. Document Line")
var
InvtDocumentHeader: Record "Invt. Document Header";
RedStorno: Boolean;
IsHandled: Boolean;
begin
OnBeforeDeleteLine(InvtDocumentLine, DeleteItemTracking, Blocked, IsHandled);
if IsHandled then
exit;
if Blocked then
exit;
InvtDocumentHeader.Get(InvtDocumentLine."Document Type", InvtDocumentLine."Document No.");
RedStorno := InvtDocumentHeader.Correction;
case InvtDocumentLine."Document Type" of
InvtDocumentLine."Document Type"::Receipt:
begin
ReservationManagement.SetReservSource(InvtDocumentLine);
if RedStorno or DeleteItemTracking then
ReservationManagement.SetItemTrackingHandling(1);
// Allow Deletion
ReservationManagement.DeleteReservEntries(true, 0);
InvtDocumentLine.CalcFields("Reserved Qty. Outbnd. (Base)");
end;
InvtDocumentLine."Document Type"::Shipment:
begin
ReservationManagement.SetReservSource(InvtDocumentLine);
if RedStorno or DeleteItemTracking then
ReservationManagement.SetItemTrackingHandling(1);
// Allow Deletion
ReservationManagement.DeleteReservEntries(true, 0);
InvtDocumentLine.CalcFields("Reserved Qty. Inbnd. (Base)");
end;
end;
end;
procedure AssignForPlanning(var InvtDocumentLine: Record "Invt. Document Line")
var
PlanningAssignment: Record "Planning Assignment";
begin
if InvtDocumentLine."Item No." <> '' then
PlanningAssignment.ChkAssignOne(
InvtDocumentLine."Item No.",
InvtDocumentLine."Variant Code",
InvtDocumentLine."Location Code",
InvtDocumentLine."Document Date");
end;
procedure Block(SetBlocked: Boolean)
begin
Blocked := SetBlocked;
end;
procedure CallItemTracking(var InvtDocumentLine: Record "Invt. Document Line")
var
TrackingSpecification: Record "Tracking Specification";
ItemTrackingLines: Page "Item Tracking Lines";
IsInbound: Boolean;
begin
IsInbound :=
((InvtDocumentLine."Document Type" = InvtDocumentLine."Document Type"::Receipt) and not InvtDocumentLine.IsCorrection()) or
((InvtDocumentLine."Document Type" = InvtDocumentLine."Document Type"::Shipment) and InvtDocumentLine.IsCorrection());
InitFromInvtDocLine(TrackingSpecification, InvtDocumentLine);
ItemTrackingLines.SetIsInvtDocumentCorrection(InvtDocumentLine.IsCorrection());
ItemTrackingLines.SetSourceSpec(TrackingSpecification, InvtDocumentLine."Document Date");
ItemTrackingLines.SetInbound(IsInbound);
ItemTrackingLines.RunModal();
end;
procedure CallItemTracking2(var InvtDocumentLine: Record "Invt. Document Line"; var SecondSourceQuantityArray: array[3] of Decimal)
var
TrackingSpecification: Record "Tracking Specification";
ItemTrackingLines: Page "Item Tracking Lines";
begin
InitFromInvtDocLine(TrackingSpecification, InvtDocumentLine);
ItemTrackingLines.SetSourceSpec(TrackingSpecification, InvtDocumentLine."Document Date");
ItemTrackingLines.SetSecondSourceQuantity(SecondSourceQuantityArray);
ItemTrackingLines.RunModal();
end;
[EventSubscriber(ObjectType::Page, Page::Reservation, 'OnGetQtyPerUOMFromSourceRecRef', '', false, false)]
local procedure OnGetQtyPerUOMFromSourceRecRef(SourceRecRef: RecordRef; var QtyPerUOM: Decimal; var QtyReserved: Decimal; var QtyReservedBase: Decimal; var QtyToReserve: Decimal; var QtyToReserveBase: Decimal; ReservEntry: Record "Reservation Entry")
var
InvtDocumentLine: Record "Invt. Document Line";
begin
if MatchThisTable(SourceRecRef.Number) then begin
SourceRecRef.SetTable(InvtDocumentLine);
InvtDocumentLine.Find();
QtyPerUOM := InvtDocumentLine.GetReservationQty(QtyReserved, QtyReservedBase, QtyToReserve, QtyToReserveBase, ReservEntry."Source Subtype");
end;
end;
local procedure SetReservSourceFor(SourceRecordRef: RecordRef; var ReservationEntry: Record "Reservation Entry"; var CaptionText: Text)
var
InvtDocumentLine: Record "Invt. Document Line";
begin
SourceRecordRef.SetTable(InvtDocumentLine);
ReservationEntry.SetSource(
Database::"Invt. Document Line", InvtDocumentLine."Document Type".AsInteger(), InvtDocumentLine."Document No.", InvtDocumentLine."Line No.", '', 0);
ReservationEntry."Item No." := InvtDocumentLine."Item No.";
ReservationEntry."Variant Code" := InvtDocumentLine."Variant Code";
ReservationEntry."Location Code" := InvtDocumentLine."Location Code";
if ReservationEntry."Source Subtype" = 0 then
ReservationEntry."Expected Receipt Date" := InvtDocumentLine."Document Date"
else
ReservationEntry."Shipment Date" := InvtDocumentLine."Document Date";
CaptionText := InvtDocumentLine.GetSourceCaption();
end;
local procedure EntryStartNo(): Integer
begin
exit("Reservation Summary Type"::"Inventory Receipt".AsInteger());
end;
local procedure MatchThisEntry(EntryNo: Integer): Boolean
begin
if not (EntryNo in ["Reservation Summary Type"::"Inventory Receipt".AsInteger(),
"Reservation Summary Type"::"Inventory Shipment".AsInteger()])
then
exit(false);
GetInvtSetup();
exit(InventorySetup."Allow Invt. Doc. Reservation");
end;
local procedure MatchThisTable(TableID: Integer): Boolean
begin
if TableID <> Database::"Invt. Document Line" then
exit(false);
GetInvtSetup();
exit(InventorySetup."Allow Invt. Doc. Reservation");
end;
local procedure GetInvtSetup()
begin
if InvtSetupRead then
exit;
InventorySetup.Get();
InvtSetupRead := true;
end;
procedure DeleteLineConfirm(var InvtDocumentLine: Record "Invt. Document Line"): Boolean
begin
if not InvtDocumentLine.ReservEntryExist() then
exit(true);
ReservationManagement.SetReservSource(InvtDocumentLine);
if ReservationManagement.DeleteItemTrackingConfirm() then
DeleteItemTracking := true;
exit(DeleteItemTracking);
end;
[EventSubscriber(ObjectType::Page, Page::Reservation, 'OnSetReservSource', '', false, false)]
local procedure OnSetReservSource(SourceRecRef: RecordRef; var ReservEntry: Record "Reservation Entry"; var CaptionText: Text)
begin
if MatchThisTable(SourceRecRef.Number) then
SetReservSourceFor(SourceRecRef, ReservEntry, CaptionText);
end;
[EventSubscriber(ObjectType::Page, Page::Reservation, 'OnDrillDownTotalQuantity', '', false, false)]
local procedure OnDrillDownTotalQuantity(SourceRecRef: RecordRef; ReservEntry: Record "Reservation Entry"; EntrySummary: Record "Entry Summary"; Location: Record Location; MaxQtyToReserve: Decimal)
var
AvailableInvtDocumentLines: page "Available - Invt. Doc. Lines";
begin
if MatchThisEntry(EntrySummary."Entry No.") then begin
Clear(AvailableInvtDocumentLines);
AvailableInvtDocumentLines.SetSource(SourceRecRef, ReservEntry, ReservEntry.GetTransferDirection());
AvailableInvtDocumentLines.RunModal();
end;
end;
[EventSubscriber(ObjectType::Page, Page::Reservation, 'OnFilterReservEntry', '', false, false)]
local procedure OnFilterReservEntry(var FilterReservEntry: Record "Reservation Entry"; ReservEntrySummary: Record "Entry Summary")
begin
if MatchThisEntry(ReservEntrySummary."Entry No.") then begin
FilterReservEntry.SetRange("Source Type", Database::"Invt. Document Line");
FilterReservEntry.SetRange("Source Subtype", ReservEntrySummary."Entry No." - EntryStartNo());
end;
end;
[EventSubscriber(ObjectType::Page, Page::Reservation, 'OnAfterRelatesToSummEntry', '', false, false)]
local procedure OnRelatesToEntrySummary(var FilterReservEntry: Record "Reservation Entry"; FromEntrySummary: Record "Entry Summary"; var IsHandled: Boolean)
begin
if MatchThisEntry(FromEntrySummary."Entry No.") then
IsHandled :=
(FilterReservEntry."Source Type" = Database::"Invt. Document Line") and
(FilterReservEntry."Source Subtype" = FromEntrySummary."Entry No." - EntryStartNo());
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Item Ledger Entry-Reserve", 'OnDrillDownTotalQuantityElseCase', '', false, false)]
local procedure OnDrillDownTotalQuantityElseCase(SourceRecRef: RecordRef; EntrySummary: Record "Entry Summary"; ReservEntry: Record "Reservation Entry"; Location: Record Location; MaxQtyToReserve: Decimal)
var
CreatePick: Codeunit "Create Pick";
AvailableItemLedgEntries: page "Available - Item Ledg. Entries";
begin
if MatchThisTable(ReservEntry."Source Type") then begin
AvailableItemLedgEntries.SetSource(SourceRecRef, ReservEntry, Enum::"Transfer Direction".FromInteger(ReservEntry."Source Subtype"));
if Location."Bin Mandatory" or Location."Require Pick" then
AvailableItemLedgEntries.SetTotalAvailQty(
EntrySummary."Total Available Quantity" +
CreatePick.CheckOutBound(
ReservEntry."Source Type", ReservEntry."Source Subtype",
ReservEntry."Source ID", ReservEntry."Source Ref. No.",
ReservEntry."Source Prod. Order Line"))
else
AvailableItemLedgEntries.SetTotalAvailQty(EntrySummary."Total Available Quantity");
AvailableItemLedgEntries.SetMaxQtyToReserve(MaxQtyToReserve);
AvailableItemLedgEntries.RunModal();
end;
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Reservation Management", 'OnCreateReservation', '', false, false)]
local procedure OnCreateReservation(SourceRecRef: RecordRef; TrackingSpecification: Record "Tracking Specification"; ForReservEntry: Record "Reservation Entry"; Description: Text[100]; ExpectedDate: Date; Quantity: Decimal; QuantityBase: Decimal)
var
InvtDocumentLine: Record "Invt. Document Line";
begin
if MatchThisTable(ForReservEntry."Source Type") then begin
CreateReservationSetFrom(TrackingSpecification);
SourceRecRef.SetTable(InvtDocumentLine);
CreateReservation(InvtDocumentLine, Description, ExpectedDate, Quantity, QuantityBase, ForReservEntry);
end;
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Reservation Management", 'OnLookupDocument', '', false, false)]
local procedure OnLookupDocument(SourceType: Integer; SourceSubtype: Integer; SourceID: Code[20])
var
InvtDocHeader: Record "Invt. Document Header";
begin
if MatchThisTable(SourceType) then begin
InvtDocHeader.Reset();
InvtDocHeader.SetRange("Document Type", SourceSubtype);
InvtDocHeader.SetRange("No.", SourceID);
case SourceSubtype of
0:
PAGE.RunModal(PAGE::"Invt. Receipt", InvtDocHeader);
1:
PAGE.RunModal(PAGE::"Invt. Shipment", InvtDocHeader);
end;
end;
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Reservation Management", 'OnLookupLine', '', false, false)]
local procedure OnLookupLine(SourceType: Integer; SourceSubtype: Integer; SourceID: Code[20]; SourceRefNo: Integer)
var
InvtDocumentLine: Record "Invt. Document Line";
begin
if MatchThisTable(SourceType) then begin
InvtDocumentLine.Reset();
InvtDocumentLine.SetRange("Document Type", SourceSubtype);
InvtDocumentLine.SetRange("Document No.", SourceID);
InvtDocumentLine.SetRange("Line No.", SourceRefNo);
PAGE.Run(0, InvtDocumentLine);
end;
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Reservation Management", 'OnFilterReservFor', '', false, false)]
local procedure OnFilterReservFor(SourceRecRef: RecordRef; var ReservEntry: Record "Reservation Entry"; var CaptionText: Text)
var
InvtDocumentLine: Record "Invt. Document Line";
begin
if MatchThisTable(SourceRecRef.Number) then begin
SourceRecRef.SetTable(InvtDocumentLine);
InvtDocumentLine.SetReservationFilters(ReservEntry);
CaptionText := InvtDocumentLine.GetSourceCaption();
end;
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Reservation Management", 'OnCalculateRemainingQty', '', false, false)]
local procedure OnCalculateRemainingQty(SourceRecRef: RecordRef; var ReservEntry: Record "Reservation Entry"; var RemainingQty: Decimal; var RemainingQtyBase: Decimal)
var
InvtDocumentLine: Record "Invt. Document Line";
begin
if MatchThisTable(ReservEntry."Source Type") then begin
SourceRecRef.SetTable(InvtDocumentLine);
InvtDocumentLine.GetRemainingQty(RemainingQty, RemainingQtyBase, ReservEntry."Source Subtype");
end;
end;
local procedure GetSourceValue(ReservationEntry: Record "Reservation Entry"; var SourceRecordRef: RecordRef; ReturnOption: Option "Net Qty. (Base)","Gross Qty. (Base)"): Decimal
var
InvtDocumentLine: Record "Invt. Document Line";
begin
InvtDocumentLine.Get(ReservationEntry."Source Subtype", ReservationEntry."Source ID", ReservationEntry."Source Ref. No.");
SourceRecordRef.GetTable(InvtDocumentLine);
case ReturnOption of
ReturnOption::"Net Qty. (Base)":
exit(InvtDocumentLine."Quantity (Base)");
ReturnOption::"Gross Qty. (Base)":
exit(InvtDocumentLine."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;
local procedure UpdateStatistics(ReservationEntry: Record "Reservation Entry"; var TempEntrySummary: Record "Entry Summary" temporary; AvailabilityDate: Date; DocumentType: Integer; Positive: Boolean; var TotalQuantity: Decimal)
var
InvtDocumentLine: Record "Invt. Document Line";
AvailabilityFilter: Text;
begin
if not InvtDocumentLine.ReadPermission() then
exit;
AvailabilityFilter := ReservationEntry.GetAvailabilityFilter(AvailabilityDate, Positive);
case DocumentType of
0:
InvtDocumentLine.FilterShipmentLinesForReservation(ReservationEntry, AvailabilityFilter, Positive);
1:
InvtDocumentLine.FilterReceiptLinesForReservation(ReservationEntry, AvailabilityFilter, Positive);
end;
if InvtDocumentLine.FindSet() then
repeat
case DocumentType of
0:
begin
InvtDocumentLine.CalcFields("Reserved Qty. Outbnd. (Base)");
TempEntrySummary."Total Reserved Quantity" -= InvtDocumentLine."Reserved Qty. Outbnd. (Base)";
TotalQuantity -= InvtDocumentLine."Quantity (Base)";
end;
1:
begin
InvtDocumentLine.CalcFields("Reserved Qty. Inbnd. (Base)");
TempEntrySummary."Total Reserved Quantity" += InvtDocumentLine."Reserved Qty. Inbnd. (Base)";
TotalQuantity += InvtDocumentLine."Quantity (Base)";
end;
end;
until InvtDocumentLine.Next() = 0;
if TotalQuantity = 0 then
exit;
if (TotalQuantity > 0) = Positive then begin
TempEntrySummary."Table ID" := Database::"Invt. Document Line";
TempEntrySummary."Summary Type" :=
CopyStr(
StrSubstNo(SummaryTypeTxt, InvtDocumentLine.TableCaption(), SelectStr(DocumentType + 1, DirectionTxt)),
1, MaxStrLen(TempEntrySummary."Summary Type"));
TempEntrySummary."Total Quantity" := TotalQuantity;
TempEntrySummary."Total Available Quantity" :=
TempEntrySummary."Total Quantity" - TempEntrySummary."Total Reserved Quantity";
if not TempEntrySummary.Insert() then
TempEntrySummary.Modify();
end;
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Reservation Management", 'OnUpdateStatistics', '', false, false)]
local procedure OnUpdateStatistics(CalcReservEntry: Record "Reservation Entry"; var ReservSummEntry: Record "Entry Summary"; AvailabilityDate: Date; Positive: Boolean; var TotalQuantity: Decimal)
begin
if MatchThisEntry(ReservSummEntry."Entry No.") then
UpdateStatistics(
CalcReservEntry, ReservSummEntry, AvailabilityDate, ReservSummEntry."Entry No." - EntryStartNo(), Positive, TotalQuantity);
end;
[EventSubscriber(ObjectType::Page, Page::"Reservation Entries", 'OnLookupReserved', '', false, false)]
local procedure OnLookupReserved(var ReservationEntry: Record "Reservation Entry")
begin
if ReservationEntry."Source Type" = Database::"Invt. Document Line" then
ShowSourceLines(ReservationEntry);
end;
local procedure ShowSourceLines(var ReservationEntry: Record "Reservation Entry")
var
InvtDocumentLine: Record "Invt. Document Line";
begin
InvtDocumentLine.SetRange("Document Type", ReservationEntry."Source Subtype");
InvtDocumentLine.SetRange("Document No.", ReservationEntry."Source ID");
InvtDocumentLine.SetRange("Line No.", ReservationEntry."Source Ref. No.");
PAGE.RunModal(Page::"Invt. Document Lines", InvtDocumentLine);
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Reservation Management", 'OnAfterAutoReserveOneLine', '', false, false)]
local procedure OnAfterAutoReserveOneLine(ReservSummEntryNo: Integer; var RemainingQtyToReserve: Decimal; var RemainingQtyToReserveBase: Decimal; Description: Text[100]; AvailabilityDate: Date; Search: Text[1]; NextStep: Integer; CalcReservEntry: Record "Reservation Entry"; CalcReservEntry2: Record "Reservation Entry"; Positive: Boolean; var sender: Codeunit "Reservation Management")
begin
if MatchThisEntry(ReservSummEntryNo) then
AutoInvtDocLineReserve(
CalcReservEntry, sender, ReservSummEntryNo, RemainingQtyToReserve, RemainingQtyToReserveBase,
Description, AvailabilityDate, Search, NextStep, Positive);
end;
local procedure AutoInvtDocLineReserve(var CalcReservEntry: Record "Reservation Entry"; var sender: Codeunit "Reservation Management"; ReservSummEntryNo: Integer; var RemainingQtyToReserve: Decimal; var RemainingQtyToReserveBase: Decimal; Description: Text[100]; AvailabilityDate: Date; Search: Text[1]; NextStep: Integer; Positive: Boolean)
var
CallTrackingSpecification: Record "Tracking Specification";
InvtDocLine: Record "Invt. Document Line";
QtyThisLine: Decimal;
QtyThisLineBase: Decimal;
ReservQty: Decimal;
begin
case ReservSummEntryNo of
Enum::"Reservation Summary Type"::"Inventory Receipt".AsInteger():
InvtDocLine.FilterReceiptLinesForReservation(CalcReservEntry, sender.GetAvailabilityFilter(AvailabilityDate), Positive);
Enum::"Reservation Summary Type"::"Inventory Shipment".AsInteger():
InvtDocLine.FilterShipmentLinesForReservation(CalcReservEntry, sender.GetAvailabilityFilter(AvailabilityDate), Positive);
end;
if InvtDocLine.Find(Search) then
repeat
case ReservSummEntryNo of
Enum::"Reservation Summary Type"::"Inventory Shipment".AsInteger():
begin
InvtDocLine.CalcFields("Reserved Qty. Outbnd. (Base)");
QtyThisLine := -InvtDocLine.Quantity;
QtyThisLineBase := -InvtDocLine."Quantity (Base)";
ReservQty := -InvtDocLine."Reserved Qty. Outbnd. (Base)";
if Positive = (QtyThisLine < 0) then begin
QtyThisLine := 0;
QtyThisLineBase := 0;
end;
end;
Enum::"Reservation Summary Type"::"Inventory Receipt".AsInteger():
begin
InvtDocLine.CalcFields("Reserved Qty. Inbnd. (Base)");
QtyThisLine := InvtDocLine.Quantity;
QtyThisLineBase := InvtDocLine."Quantity (Base)";
ReservQty := InvtDocLine."Reserved Qty. Inbnd. (Base)";
if Positive = (QtyThisLine < 0) then begin
QtyThisLine := 0;
QtyThisLineBase := 0;
end;
end;
end;
if QtyThisLine <> 0 then
if Abs(QtyThisLine - ReservQty) > 0 then begin
if Abs(QtyThisLine - ReservQty) > Abs(RemainingQtyToReserve) then begin
QtyThisLine := RemainingQtyToReserve;
QtyThisLineBase := RemainingQtyToReserveBase;
end else begin
QtyThisLineBase := QtyThisLineBase - ReservQty;
QtyThisLine := Round(RemainingQtyToReserve / RemainingQtyToReserveBase * QtyThisLineBase, UOMMgt.QtyRndPrecision());
end;
sender.CopySign(RemainingQtyToReserve, QtyThisLine);
sender.CopySign(RemainingQtyToReserveBase, QtyThisLineBase);
CallTrackingSpecification.InitTrackingSpecification(
Database::"Invt. Document Line", ReservSummEntryNo - Enum::"Reservation Summary Type"::"Inventory Receipt".AsInteger(),
InvtDocLine."Document No.", '', 0, InvtDocLine."Line No.", InvtDocLine."Variant Code", InvtDocLine."Location Code", InvtDocLine."Qty. per Unit of Measure");
CallTrackingSpecification.CopyTrackingFromReservEntry(CalcReservEntry);
sender.CreateReservation(Description, InvtDocLine."Posting Date", QtyThisLine, QtyThisLineBase, CallTrackingSpecification);
RemainingQtyToReserve := RemainingQtyToReserve - QtyThisLine;
RemainingQtyToReserveBase := RemainingQtyToReserveBase - QtyThisLineBase;
end;
until (InvtDocLine.Next(NextStep) = 0) or (RemainingQtyToReserve = 0);
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::"Invt. Document Line" then begin
PointerFieldIsActive[1] := true; // Type
PointerFieldIsActive[2] := true; // SubType
PointerFieldIsActive[3] := true; // ID
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)
begin
if ReservationEntry."Source Type" = Database::"Invt. Document Line" then
Description :=
StrSubstNo(
SourceDoc3Txt, InventoryTxt,
Enum::"Invt. Doc. Document Type".FromInteger(ReservationEntry."Source Subtype"), ReservationEntry."Source ID");
end;
procedure InitFromInvtDocLine(var TrackingSpecification: Record "Tracking Specification"; var InvtDocLine: Record "Invt. Document Line")
var
QtySignFactor: Integer;
begin
TrackingSpecification.Init();
TrackingSpecification.SetItemData(
InvtDocLine."Item No.", InvtDocLine.Description, InvtDocLine."Location Code", InvtDocLine."Variant Code",
InvtDocLine."Bin Code", InvtDocLine."Qty. per Unit of Measure", InvtDocLine."Qty. Rounding Precision (Base)");
TrackingSpecification.SetSource(
Database::"Invt. Document Line", InvtDocLine."Document Type".AsInteger(), InvtDocLine."Document No.", InvtDocLine."Line No.", '', 0);
QtySignFactor := 1;
if InvtDocLine.IsCorrection() then
QtySignFactor := -1;
TrackingSpecification.SetQuantities(
InvtDocLine."Quantity (Base)" * QtySignFactor, InvtDocLine.Quantity * QtySignFactor, InvtDocLine."Quantity (Base)" * QtySignFactor,
InvtDocLine.Quantity * QtySignFactor, InvtDocLine."Quantity (Base)" * QtySignFactor, 0, 0);
end;
[EventSubscriber(ObjectType::Table, Database::"Tracking Specification", 'OnBeforeCheckApplyFromItemEntrySourceType', '', false, false)]
local procedure OnBeforeCheckApplyFromItemEntrySourceType(var TrackingSpecification: Record "Tracking Specification"; var IsHandled: Boolean)
begin
if not MatchThisTable(TrackingSpecification."Source Type") then
exit;
if ((TrackingSpecification."Source Subtype" in [1, 3, 4, 5]) and (TrackingSpecification."Quantity (Base)" > 0)) or
((TrackingSpecification."Source Subtype" in [0, 2, 6]) and (TrackingSpecification."Quantity (Base)" < 0))
then
TrackingSpecification.FieldError("Quantity (Base)");
IsHandled := true;
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeVerifyChange(var NewInvtDocumentLine: Record "Invt. Document Line"; var OldInvtDocumentLine: Record "Invt. Document Line"; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeDeleteLine(var InvtDocumentLine: Record "Invt. Document Line"; DeleteItemTracking: Boolean; Blocked: Boolean; var IsHandled: Boolean)
begin
end;
}