Codeunit 7308 Replenishment, source in 29
Source29
src/Layers/W1/BaseApp/Warehouse/Worksheet/Replenishment.Codeunit.al404 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.Warehouse.Worksheet;
using Microsoft.Foundation.UOM;
using Microsoft.Inventory.Item;
using Microsoft.Inventory.Location;
using Microsoft.Inventory.Tracking;
using Microsoft.Warehouse.Structure;
codeunit 7308 Replenishment
{
trigger OnRun()
begin
end;
var
Bin: Record Bin;
BinType: Record "Bin Type";
TempWhseWkshLine: Record "Whse. Worksheet Line" temporary;
ItemUnitOfMeasure: Record "Item Unit of Measure";
Location: Record Location;
UOMMgt: Codeunit "Unit of Measure Management";
WhseWkshTemplateName: Code[10];
WhseWkshName: Code[10];
LocationCode: Code[10];
RemainQtyToReplenishBase: Decimal;
NextLineNo: Integer;
DoNotFillQtytoHandle: Boolean;
MustNotBeErr: Label 'must not be %1.', Comment = '%1 - field value';
procedure ReplenishBin(ToBinContent: Record "Bin Content"; AllowBreakBulk: Boolean)
var
ExcludedQtyBase: Decimal;
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeReplenishBin(ToBinContent, IsHandled, RemainQtyToReplenishBase, AllowBreakBulk);
if IsHandled then
exit;
if not ToBinContent.Fixed then
ToBinContent.FieldError(Fixed, StrSubstNo(MustNotBeErr, ToBinContent.FieldCaption(Fixed)));
if BinBlockedInbound(ToBinContent."Location Code", ToBinContent."Bin Code") then
Bin.FieldError("Block Movement", StrSubstNo(MustNotBeErr, Bin."Block Movement"));
ExcludedQtyBase := 0;
OnReplenishBinOnAfterAssignExcludedQtyBase(ToBinContent, ExcludedQtyBase);
if not ToBinContent.NeedToReplenish(ExcludedQtyBase) then
exit;
RemainQtyToReplenishBase := ToBinContent.CalcQtyToReplenish(ExcludedQtyBase);
if RemainQtyToReplenishBase <= 0 then
exit;
FindReplenishmtBin(ToBinContent, AllowBreakBulk);
end;
procedure FindReplenishmtBin(ToBinContent: Record "Bin Content"; AllowBreakBulk: Boolean)
var
FromBinContent: Record "Bin Content";
WhseWkshLine2: Record "Whse. Worksheet Line";
QtyAvailToTakeBase: Decimal;
MovementQtyBase: Decimal;
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeFindReplenishmtBin(
TempWhseWkshLine, ToBinContent, AllowBreakBulk, NextLineNo,
WhseWkshTemplateName, WhseWkshName, LocationCode, DoNotFillQtytoHandle, RemainQtyToReplenishBase, IsHandled);
if IsHandled then
exit;
FromBinContent.Reset();
FromBinContent.SetCurrentKey(
"Location Code", "Item No.", "Variant Code", "Cross-Dock Bin",
"Qty. per Unit of Measure", "Bin Ranking");
FromBinContent.Ascending(false);
FromBinContent.SetRange("Location Code", ToBinContent."Location Code");
FromBinContent.SetRange("Item No.", ToBinContent."Item No.");
FromBinContent.SetRange("Variant Code", ToBinContent."Variant Code");
FromBinContent.SetRange("Cross-Dock Bin", false);
FromBinContent.SetRange("Qty. per Unit of Measure", ToBinContent."Qty. per Unit of Measure");
FromBinContent.SetFilter("Bin Ranking", '<%1', ToBinContent."Bin Ranking");
OnFindReplenishmtBinOnAfterFromBinContentSetFilters(FromBinContent, ToBinContent);
if FromBinContent.Find('-') then begin
WhseWkshLine2.Copy(TempWhseWkshLine);
TempWhseWkshLine.SetCurrentKey(
"Item No.", "From Bin Code", "Location Code", "Variant Code", "From Unit of Measure Code");
TempWhseWkshLine.SetRange("Item No.", FromBinContent."Item No.");
TempWhseWkshLine.SetRange("Location Code", FromBinContent."Location Code");
TempWhseWkshLine.SetRange("Variant Code", FromBinContent."Variant Code");
repeat
IsHandled := false;
OnFindReplenishmtBinOnBeforeCalcQtyAvailToTakeBase(FromBinContent, IsHandled);
if not IsHandled then
if UseForReplenishment(FromBinContent) then begin
QtyAvailToTakeBase := FromBinContent.CalcQtyAvailToTake(0);
TempWhseWkshLine.SetRange("From Bin Code", FromBinContent."Bin Code");
TempWhseWkshLine.SetRange("From Unit of Measure Code", FromBinContent."Unit of Measure Code");
TempWhseWkshLine.CalcSums("Qty. (Base)");
QtyAvailToTakeBase := QtyAvailToTakeBase - TempWhseWkshLine."Qty. (Base)";
if QtyAvailToTakeBase > 0 then begin
if QtyAvailToTakeBase < RemainQtyToReplenishBase then
MovementQtyBase := QtyAvailToTakeBase
else
MovementQtyBase := RemainQtyToReplenishBase;
CreateWhseWkshLine(ToBinContent, FromBinContent, MovementQtyBase);
RemainQtyToReplenishBase := RemainQtyToReplenishBase - MovementQtyBase;
end;
end;
until (FromBinContent.Next() = 0) or (RemainQtyToReplenishBase = 0);
TempWhseWkshLine.Copy(WhseWkshLine2);
end;
if AllowBreakBulk then
if RemainQtyToReplenishBase > 0 then
FindBreakbulkBin(ToBinContent);
end;
procedure SetRemainQtyToReplenishBase(NewRemainQtyToReplenishBase: Decimal)
begin
RemainQtyToReplenishBase := NewRemainQtyToReplenishBase;
end;
procedure FindBreakbulkBin(ToBinContent: Record "Bin Content")
var
FromBinContent: Record "Bin Content";
WhseWkshLine2: Record "Whse. Worksheet Line";
QtyAvailToTakeBase: Decimal;
MovementQtyBase: Decimal;
SkipItemUnitOfMeasure: Boolean;
begin
ItemUnitOfMeasure.Reset();
ItemUnitOfMeasure.SetCurrentKey("Item No.", "Qty. per Unit of Measure");
ItemUnitOfMeasure.SetRange("Item No.", ToBinContent."Item No.");
ItemUnitOfMeasure.SetFilter(
"Qty. per Unit of Measure", '>%1', ToBinContent."Qty. per Unit of Measure");
if ItemUnitOfMeasure.Find('-') then
repeat
FromBinContent.Reset();
FromBinContent.SetCurrentKey(
"Location Code", "Item No.", "Variant Code", "Cross-Dock Bin",
"Qty. per Unit of Measure", "Bin Ranking");
FromBinContent.SetRange("Location Code", ToBinContent."Location Code");
FromBinContent.SetRange("Item No.", ToBinContent."Item No.");
FromBinContent.SetRange("Variant Code", ToBinContent."Variant Code");
FromBinContent.SetRange("Cross-Dock Bin", false);
FromBinContent.SetRange(
"Qty. per Unit of Measure", ItemUnitOfMeasure."Qty. per Unit of Measure");
FromBinContent.SetFilter("Bin Ranking", '<%1', ToBinContent."Bin Ranking");
FromBinContent.Ascending(false);
SkipItemUnitOfMeasure := false;
OnFindBreakbulkBinOnAfterFromBinContentSetFilters(FromBinContent, ToBinContent, ItemUnitOfMeasure, SkipItemUnitOfMeasure);
if not SkipItemUnitOfMeasure then
if FromBinContent.Find('-') then begin
WhseWkshLine2.Copy(TempWhseWkshLine);
TempWhseWkshLine.SetCurrentKey(
"Item No.", "From Bin Code", "Location Code", "Variant Code", "From Unit of Measure Code");
TempWhseWkshLine.SetRange("Item No.", FromBinContent."Item No.");
TempWhseWkshLine.SetRange("Location Code", FromBinContent."Location Code");
TempWhseWkshLine.SetRange("Variant Code", FromBinContent."Variant Code");
repeat
if UseForReplenishment(FromBinContent) then begin
QtyAvailToTakeBase := FromBinContent.CalcQtyAvailToTake(0);
TempWhseWkshLine.SetRange("From Bin Code", FromBinContent."Bin Code");
TempWhseWkshLine.SetRange("From Unit of Measure Code", FromBinContent."Unit of Measure Code");
TempWhseWkshLine.CalcSums("Qty. (Base)");
QtyAvailToTakeBase := QtyAvailToTakeBase - TempWhseWkshLine."Qty. (Base)";
if QtyAvailToTakeBase > 0 then begin
MovementQtyBase := QtyAvailToTakeBase;
if RemainQtyToReplenishBase < MovementQtyBase then
MovementQtyBase := RemainQtyToReplenishBase;
CreateWhseWkshLine(ToBinContent, FromBinContent, MovementQtyBase);
RemainQtyToReplenishBase := RemainQtyToReplenishBase - MovementQtyBase;
end;
end;
until (FromBinContent.Next() = 0) or (RemainQtyToReplenishBase = 0);
TempWhseWkshLine.Copy(WhseWkshLine2);
end;
until (ItemUnitOfMeasure.Next() = 0) or (RemainQtyToReplenishBase = 0);
end;
procedure CreateWhseWkshLine(ToBinContent: Record "Bin Content"; FromBinContent: Record "Bin Content"; MovementQtyBase: Decimal)
begin
TempWhseWkshLine.Init();
TempWhseWkshLine."Worksheet Template Name" := WhseWkshTemplateName;
TempWhseWkshLine.Name := WhseWkshName;
TempWhseWkshLine."Location Code" := LocationCode;
TempWhseWkshLine."Line No." := NextLineNo;
TempWhseWkshLine."From Bin Code" := FromBinContent."Bin Code";
TempWhseWkshLine."From Zone Code" := FromBinContent."Zone Code";
TempWhseWkshLine."From Unit of Measure Code" := FromBinContent."Unit of Measure Code";
TempWhseWkshLine."Qty. per From Unit of Measure" := FromBinContent."Qty. per Unit of Measure";
TempWhseWkshLine."To Bin Code" := ToBinContent."Bin Code";
TempWhseWkshLine."To Zone Code" := ToBinContent."Zone Code";
TempWhseWkshLine."Unit of Measure Code" := ToBinContent."Unit of Measure Code";
TempWhseWkshLine."Qty. per Unit of Measure" := ToBinContent."Qty. per Unit of Measure";
TempWhseWkshLine."Item No." := ToBinContent."Item No.";
TempWhseWkshLine.Validate("Variant Code", ToBinContent."Variant Code");
TempWhseWkshLine.Validate(Quantity, Round(MovementQtyBase / ToBinContent."Qty. per Unit of Measure", UOMMgt.QtyRndPrecision()));
TempWhseWkshLine."Qty. (Base)" := MovementQtyBase;
TempWhseWkshLine."Qty. Outstanding (Base)" := MovementQtyBase;
TempWhseWkshLine."Qty. to Handle (Base)" := MovementQtyBase;
TempWhseWkshLine."Whse. Document Type" := TempWhseWkshLine."Whse. Document Type"::"Whse. Mov.-Worksheet";
TempWhseWkshLine."Whse. Document No." := WhseWkshName;
TempWhseWkshLine."Whse. Document Line No." := TempWhseWkshLine."Line No.";
OnCreateWhseWkshLineOnBeforeInsertTempWhseWkshLine(TempWhseWkshLine, ToBinContent);
TempWhseWkshLine.Insert();
NextLineNo := NextLineNo + 10000;
end;
procedure GetTempWhseWkshLine(var TempWhseWorksheetLineOut: Record "Whse. Worksheet Line" temporary)
begin
TempWhseWorksheetLineOut.Reset();
TempWhseWorksheetLineOut.Copy(TempWhseWkshLine, true);
end;
procedure InsertWhseWkshLine() Result: Boolean
var
WhseWkshLine: Record "Whse. Worksheet Line";
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeInsertWhseWkshLine(TempWhseWkshLine, DoNotFillQtytoHandle, Result, IsHandled);
if IsHandled then
exit(Result);
TempWhseWkshLine.Reset();
TempWhseWkshLine.SetFilter(Quantity, '>0');
if TempWhseWkshLine.Find('-') then begin
repeat
WhseWkshLine.Init();
WhseWkshLine := TempWhseWkshLine;
if DoNotFillQtytoHandle then begin
WhseWkshLine."Qty. to Handle" := 0;
WhseWkshLine."Qty. to Handle (Base)" := 0;
end;
if PickAccordingToFEFO(TempWhseWkshLine."Item No.", TempWhseWkshLine."Variant Code") then begin
WhseWkshLine."From Zone Code" := '';
WhseWkshLine."From Bin Code" := '';
end;
WhseWkshLine.Insert();
OnInsertWhseWkshLineOnAfterWhseWkshLineInsert(WhseWkshLine);
until TempWhseWkshLine.Next() = 0;
exit(true);
end;
exit(false);
end;
local procedure BinBlockedInbound(LocationCode2: Code[10]; BinCode2: Code[20]) Blocked: Boolean
begin
GetBin(LocationCode2, BinCode2);
Blocked := Bin."Block Movement" in
[Bin."Block Movement"::Inbound, Bin."Block Movement"::All];
exit(Blocked);
end;
procedure UseForReplenishment(FromBinContent: Record "Bin Content"): Boolean
begin
if FromBinContent."Block Movement" in
[FromBinContent."Block Movement"::Outbound,
FromBinContent."Block Movement"::All]
then
exit(false);
GetBinType(FromBinContent."Bin Type Code");
exit(not (BinType.Receive or BinType.Ship));
end;
local procedure GetBinType(BinTypeCode: Code[10])
begin
if BinTypeCode = '' then begin
Clear(BinType);
BinType.Init();
end else
if BinType.Code <> BinTypeCode then
BinType.Get(BinTypeCode);
end;
local procedure GetBin(LocationCode2: Code[10]; BinCode2: Code[20])
begin
if (Bin."Location Code" <> LocationCode2) or
(Bin.Code <> BinCode2)
then
Bin.Get(LocationCode2, BinCode2);
end;
procedure SetWhseWorksheet(WhseWkshTemplateName2: Code[10]; WhseWkshName2: Code[10]; LocationCode2: Code[10]; DoNotFillQtytoHandle2: Boolean)
var
WhseWorksheetLine: Record "Whse. Worksheet Line";
begin
TempWhseWkshLine.DeleteAll();
WhseWorksheetLine.SetRange("Worksheet Template Name", WhseWkshTemplateName2);
WhseWorksheetLine.SetRange(Name, WhseWkshName2);
WhseWorksheetLine.SetRange("Location Code", LocationCode2);
OnSetWhseWorksheetOnAfterWhseWorksheetLineSetFilters(WhseWorksheetLine);
if WhseWorksheetLine.FindLast() then
NextLineNo := WhseWorksheetLine."Line No." + 10000
else
NextLineNo := 10000;
WhseWkshTemplateName := WhseWkshTemplateName2;
WhseWkshName := WhseWkshName2;
LocationCode := LocationCode2;
Location.Get(LocationCode);
DoNotFillQtytoHandle := DoNotFillQtytoHandle2;
end;
local procedure PickAccordingToFEFO(ItemNo: Code[20]; VariantCode: Code[10]): Boolean
var
DummyItemTrackingSetup: Record "Item Tracking Setup";
ItemTrackingMgt: Codeunit "Item Tracking Management";
EntriesExist: Boolean;
IsHandled: Boolean;
Result: Boolean;
begin
IsHandled := false;
OnBeforePickAccordingToFEFO(Location, ItemNo, VariantCode, Result, IsHandled);
if IsHandled then
exit(Result);
if not Location."Pick According to FEFO" then
exit(false);
if not ItemTrackingMgt.GetWhseItemTrkgSetup(ItemNo) then
exit(false);
if Location."Directed Put-away and Pick" or (Location."Require Receive" and Location."Require Shipment") then
if ItemTrackingMgt.ExistingExpirationDate(ItemNo, VariantCode, DummyItemTrackingSetup, false, EntriesExist) <> 0D then
exit(true);
if ItemTrackingMgt.WhseExistingExpirationDate(ItemNo, VariantCode, Location, DummyItemTrackingSetup, EntriesExist) <> 0D then
exit(true);
exit(false);
end;
[IntegrationEvent(false, false)]
local procedure OnBeforePickAccordingToFEFO(Location: Record Location; ItemNo: Code[20]; VariantCode: Code[10]; var Result: Boolean; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnCreateWhseWkshLineOnBeforeInsertTempWhseWkshLine(var TempWhseWkshLine: Record "Whse. Worksheet Line" temporary; var ToBinContent: Record "Bin Content")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnFindReplenishmtBinOnAfterFromBinContentSetFilters(var FromBinContent: Record "Bin Content"; var ToBinContent: Record "Bin Content")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnInsertWhseWkshLineOnAfterWhseWkshLineInsert(var WhseWkshLine: Record "Whse. Worksheet Line")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnFindReplenishmtBinOnBeforeCalcQtyAvailToTakeBase(FromBinContent: Record "Bin Content"; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeInsertWhseWkshLine(var TempWhseWkshLine: Record "Whse. Worksheet Line" temporary; DoNotFillQtytoHandle: Boolean; var Result: Boolean; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeFindReplenishmtBin(var TempWhseWkshLine: Record "Whse. Worksheet Line" temporary; ToBinContent: Record "Bin Content"; AllowBreakBulk: Boolean; var NextLineNo: Integer; WhseWkshTemplateName: Code[10]; WhseWkshName: Code[10]; LocationCode: Code[10]; DoNotFillQtytoHandle: Boolean; RemainQtyToReplenishBase: Decimal; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnReplenishBinOnAfterAssignExcludedQtyBase(ToBinContent: Record "Bin Content"; var ExcludedQtyBase: Decimal)
begin
end;
[IntegrationEvent(true, false)]
local procedure OnBeforeReplenishBin(ToBinContent: Record "Bin Content"; var IsHandled: Boolean; RemainQtyToReplenishBase: Decimal; AllowBreakBulk: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnFindBreakbulkBinOnAfterFromBinContentSetFilters(var FromBinContent: Record "Bin Content"; var ToBinContent: Record "Bin Content"; ItemUnitOfMeasure: Record "Item Unit of Measure"; var SkipItemUnitOfMeasure: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnSetWhseWorksheetOnAfterWhseWorksheetLineSetFilters(var WhseWorksheetLine: Record "Whse. Worksheet Line")
begin
end;
}