Hi, Readers.
Today I would like to talk about Item Tracking Lines in Business Central.
As you know, companies may want to keep track of items from the moment they enter the company. In this situation, the purchase order is often the central document, although item tracking may be handled from any inbound document and its posted entries displayed in the related item ledger entries.
First, let’s take a look at how to use Item Tracking Lines briefly in Business Central.
1. Setup
Set up item tracking codes: An item tracking code reflects the different considerations a company has regarding the use of serial and lot numbers for items moving through the inventory.
Item Card: Item Tracking Code and Lot No./Serial No. must be set.
2. To assign serial or lot numbers during an inbound transaction
For example: Lot numbers on Purchase Order page.
Select the purchase order line and on the Lines FastTab, choose the Line action, and then choose the Item Tracking Lines action.
Automatically, by choosing Assign Serial No. or Assign Lot No. to assign serial/lot numbers from predefined number series.
Manually, by entering serial or lot numbers directly, for example, the vendor’s numbers.
Then choose Related -> Lot No. Information Card.
Choose New.
Add Lot No. Information.
Return to the Purchase Order page, the Item Tracking Line information in the first line is added. Therefore, if there are 1000 purchase order lines, the above assign operation must be done 1000 times.
3. How to create Item Tracking Lines automatically
Let’s go back to the topic.
If you see the information about Item Tracking Lines page, you will find the source table of this page is temporary. So where is this data stored?
The data is stored in table 337 “Reservation Entry”.
As shown below, I can find the Item Tracking Line I just added to the table.
OK, assume that one Purchase Order Line corresponds to only one Item Tracking Line.
I can process according to the following flow in the code.
1. Add a new action on Purchase Order page called Update Tracking lines.
2.1. If Reservation Entry of Purchase Line already exists, update it.
2.1. If Reservation Entry of Purchase Line does not exist, create a new one.
3. Assign a new Lot number from the Lot No. set in the Item card.
4.1. If Lot No. information of Reservation already exists, update it.
4.2. If Lot No. information of Reservation already does not exist, create a new one.
Test Video:
Source code: For reference only
pageextension 50111 PurchaseOrderExt extends "Purchase Order"
{
actions
{
addlast(processing)
{
action(UpdateTrackingLines)
{
Caption = 'Update Tracking lines';
Image = CreateDocument;
ApplicationArea = All;
PromotedCategory = Process;
PromotedIsBig = true;
Promoted = true;
trigger OnAction()
begin
UpdateItemTrackingLines();
end;
}
}
}
local procedure UpdateItemTrackingLines()
begin
IsUpdated := false;
LastEntryNo := 0;
PurchaseLines.Reset();
PurchaseLines.SetRange("Document Type", Rec."Document Type");
PurchaseLines.SetRange("Document No.", Rec."No.");
PurchaseLines.SetFilter("Qty. to Invoice", '<>0');
if PurchaseLines.FindSet() then
repeat
if IsReservationEntryExist() then
ModifyReservationEntry()
else
CreateReservationEntry();
IF IsLotInfoExist() THEN
ModifyLotInfo()
else
CreateLotNoInfo();
until PurchaseLines.Next = 0;
if IsUpdated then
Message(ItemTrackinglinesHasUpdated)
else
Message(NothingUpdate);
end;
local procedure IsReservationEntryExist(): Boolean
begin
ReservationEntry.Reset();
ReservationEntry.SetRange("Source Type", Database::"Purchase Line");
ReservationEntry.SetRange("Source ID", PurchaseLines."Document No.");
ReservationEntry.SetRange("Source Ref. No.", PurchaseLines."Line No.");
if ReservationEntry.FindSet then
exit(true);
exit(false);
end;
local procedure ModifyReservationEntry()
begin
ReservationEntry.Description := PurchaseLines.Description;
ReservationEntry.VALIDATE("Quantity (Base)", PurchaseLines."Qty. to Receive (Base)");
ReservationEntry."Qty. per Unit of Measure" := PurchaseLines."Qty. per Unit of Measure";
ReservationEntry."Expected Receipt Date" := PurchaseLines."Expected Receipt Date";
ReservationEntry."Creation Date" := WorkDate();
ReservationEntry."Created By" := UserId;
ReservationEntry.Modify();
IsUpdated := true;
end;
local procedure CreateReservationEntry()
begin
if not Item.Get(PurchaseLines."No.") then
exit;
Item.TestField("Item Tracking Code");
Item.TestField("Lot Nos.");
ReservationEntry.Init();
ReservationEntry."Entry No." := NextEntryNo;
ReservationEntry."Item No." := PurchaseLines."No.";
ReservationEntry.Description := PurchaseLines.Description;
ReservationEntry."Location Code" := PurchaseLines."Location Code";
ReservationEntry."Variant Code" := PurchaseLines."Variant Code";
ReservationEntry.Validate("Quantity (Base)", PurchaseLines."Qty. to Receive (Base)");
ReservationEntry."Reservation Status" := ReservationEntry."Reservation Status"::Surplus;
ReservationEntry."Source Type" := Database::"Purchase Line";
ReservationEntry."Source Subtype" := ReservationEntry."Source Subtype"::"1";
ReservationEntry."Source ID" := PurchaseLines."Document No.";
ReservationEntry."Source Ref. No." := PurchaseLines."Line No.";
ReservationEntry."Expected Receipt Date" := PurchaseLines."Expected Receipt Date";
ReservationEntry."Qty. per Unit of Measure" := PurchaseLines."Qty. per Unit of Measure";
ReservationEntry.VALIDATE("Lot No.", NoSeriesMgt.GetNextNo(Item."Lot Nos.", WorkDate(), true));
ReservationEntry."Item Tracking" := ReservationEntry."Item Tracking"::"Lot No.";
ReservationEntry."Created By" := UserId;
ReservationEntry.Positive := true;
ReservationEntry."Creation Date" := WorkDate();
ReservationEntry.Insert();
end;
local procedure IsLotInfoExist(): Boolean
var
myInt: Integer;
begin
IF LotNoInfo.Get(ReservationEntry."Item No.", ReservationEntry."Variant Code", ReservationEntry."Lot No.") then
exit(true);
exit(false);
end;
local procedure ModifyLotInfo()
var
myInt: Integer;
begin
LotNoInfo.Description := ReservationEntry.Description;
//You can add custom fields in Lot Information.
LotNoInfo.Modify();
IsUpdated := true;
end;
local procedure CreateLotNoInfo()
var
myInt: Integer;
begin
LotNoInfo.Init();
LotNoInfo."Item No." := ReservationEntry."Item No.";
LotNoInfo."Variant Code" := ReservationEntry."Variant Code";
LotNoInfo."Lot No." := ReservationEntry."Lot No.";
LotNoInfo.Description := ReservationEntry.Description;
//You can add custom fields in Lot Information.
LotNoInfo.Insert();
IsUpdated := true;
end;
local procedure NextEntryNo(): Integer
var
ReserveEntry: Record "Reservation Entry";
begin
ReserveEntry.Reset();
if LastEntryNo = 0 then
if ReserveEntry.FindLast() then
LastEntryNo := ReserveEntry."Entry No.";
LastEntryNo += 1;
exit(LastEntryNo);
end;
var
PurchaseLines: Record "Purchase Line";
IsUpdated: Boolean;
ItemTrackinglinesHasUpdated: Label 'Item Tracking lines has been updated.';
NothingUpdate: Label 'Nothing update.';
ReservationEntry: Record "Reservation Entry";
LotNoInfo: Record "Lot No. Information";
Item: Record Item;
LastEntryNo: Integer;
NoSeriesMgt: Codeunit NoSeriesManagement;
}
Find out more about Work with Serial and Lot Numbers from Microsoft Docs.
END
Hope this will help.
Thanks for reading.
ZHU
コメント