将序列化项目跟踪详细信息添加到转移
Add serialized item tracking details to a transfer
因此,我们正在尝试通过实施 Microsoft Dynamics Business Central 365 来弥补一些差距。目前正在本地测试 v19 W1。我们的一个用例涉及序列化项目。为了帮助简化流程,由于序列号值在所有项目中都是唯一的,我们希望能够在序列级别管理项目。而不是采用先提供项目编号值然后为每个交易提供序列号值的两步过程。
这是一个基本示例。在转移订单页面,我们希望用户扫描条形码或将序列号手动键入新转移行的项目编号字段。通过我的 AL 代码,我将获取该序列号值,将其回溯到“父”项目编号,临时存储序列号值,然后将字段内容替换为正确的项目编号值。这是第一步。
然后,第二步将涉及为基础序列号添加预订条目行,以便项目跟踪能够正确反映与转移行相关联的序列号。当我加载我的 AL 扩展代码时,由于序列化,我遇到了数量错误。尽管我可以在该特定字段中手动提供相同的确切项目编号,并且该页面允许我继续提供数量和诸如此类的东西。
我被告知我需要以编程方式创建传输线,因此我尝试定义所有相关的 属性 值。我将粘贴我的 AL 代码以及验证错误的屏幕截图。一如既往,我们将不胜感激!
tableextension 50103 "DchApi_TransferTableExt" extends "Transfer Line"
{
fields
{
modify("Item No.")
{
trigger OnBeforeValidate()
var
Rec_ILE: Record "Item Ledger Entry";
Rec_ResEnt: Record "Reservation Entry" temporary;
Rec_ResEnt_Lu: Record "Reservation Entry";
Rec_TransLine: Record "Transfer Line";
Rec_Item: Record Item;
Rec_TransHdr: Record "Transfer Header";
CreateReservEntry: Codeunit "Create Reserv. Entry";
ItemTrackingMgt: Codeunit "Item Tracking Management";
ReservStatus: Enum "Reservation Status";
CurrentSourceRowID: Text[250];
SecondSourceRowID: Text[250];
SerialNo: Code[20];
ItemNo: Code[20];
ShortDim1Code: Code[20];
ShortDim2Code: Code[20];
Description: Text[100];
GenProdPostGrp: Code[20];
InvPostGrp: Code[20];
ItemCatCode: Code[20];
InTransCode: Code[10];
TransFromCode: Code[10];
TransToCode: Code[10];
LineNo: Integer;
begin
SerialNo := Rec."Item No.";
Rec_ILE.Reset();
Rec_ILE.SetRange("Entry Type", Rec_ILE."Entry Type"::Purchase);
Rec_ILE.SetRange("Item Tracking", Rec_ILE."Item Tracking"::"Serial No.");
Rec_ILE.SetFilter("Serial No.", '%1', SerialNo);
if Rec_ILE.FindFirst() then begin
ItemNo := Rec_ILE."Item No.";
Rec_Item.Reset();
Rec_Item.SetFilter("No.", ItemNo);
if Rec_Item.FindFirst() then begin
ShortDim1Code := Rec_Item."Global Dimension 1 Code";
ShortDim2Code := Rec_Item."Global Dimension 2 Code";
Description := Rec_Item.Description;
GenProdPostGrp := Rec_Item."Gen. Prod. Posting Group";
InvPostGrp := Rec_Item."Inventory Posting Group";
ItemCatCode := Rec_Item."Item Category Code";
Rec_TransHdr.Reset();
Rec_TransHdr.SetRange("No.", Rec."Document No.");
if Rec_TransHdr.FindFirst() then begin
InTransCode := Rec_TransHdr."In-Transit Code";
TransFromCode := Rec_TransHdr."Transfer-from Code";
TransToCode := Rec_TransHdr."Transfer-to Code";
Rec_TransLine.Reset();
Rec_TransLine.SetRange("Document No.", Rec."Document No.");
if Rec_TransLine.FindLast() then
LineNo := Rec_TransLine."Line No." + 10000
else
LineNo := 10000;
Validate(Rec."Document No.");
Validate(Rec."Line No.", LineNo);
Validate(Rec."Item No.", ItemNo);
Validate(Rec."Variant Code", '');
Validate(Rec."Shortcut Dimension 1 Code", ShortDim1Code);
Validate(Rec."Shortcut Dimension 2 Code", ShortDim2Code);
Validate(Rec.Description, Description);
Validate(Rec."Gen. Prod. Posting Group", GenProdPostGrp);
Validate(Rec."Inventory Posting Group", InvPostGrp);
Validate(Rec."Item Category Code", ItemCatCode);
Validate(Rec.Quantity, 1);
Validate(Rec."Unit of Measure Code", 'PCS');
Validate(Rec."Qty. to Ship", 1);
Validate(Rec."Qty. per Unit of Measure", 1);
Validate(Rec.Status, Rec.Status::Open);
Validate(Rec."In-Transit Code", InTransCode);
Validate(Rec."Transfer-from Code", TransFromCode);
Validate(Rec."Transfer-to Code", TransToCode);
Rec.Insert();
Rec_ResEnt.Init();
Rec_ResEnt_Lu.Reset();
if Rec_ResEnt_Lu.FindLast() then
Rec_ResEnt."Entry No." := Rec_ResEnt_Lu."Entry No." + 1
else
Rec_ResEnt."Entry No." := 1;
Rec_ResEnt."Expiration Date" := Today();
Rec_ResEnt.Quantity := 1;
Rec_ResEnt."Serial No." := SerialNo;
Rec_ResEnt.Insert();
CreateReservEntry.SetDates(0D, Rec_ResEnt."Expiration Date");
CreateReservEntry.CreateReservEntryFor(Database::"Transfer Line", 0, Rec."Document No.", '', Rec."Derived From Line No.", Rec."Line No.",
Rec."Qty. per Unit of Measure", Rec_ResEnt.Quantity, Rec."Qty. per Unit of Measure" * Rec_ResEnt.Quantity, Rec_ResEnt);
CreateReservEntry.CreateEntry(Rec."Item No.", Rec."Variant Code", Rec."Transfer-from Code", Rec.Description, Rec."Receipt Date", 0D, 0, ReservStatus::Surplus);
CurrentSourceRowID := ItemTrackingMgt.ComposeRowID(5741, 0, Rec."Document No.", '', 0, Rec."Line No.");
SecondSourceRowID := ItemTrackingMgt.ComposeRowID(5741, 1, Rec."Document No.", '', 0, Rec."Line No.");
ItemTrackingMgt.SynchronizeItemTracking(CurrentSourceRowID, SecondSourceRowID, '');
end;
end;
end;
end;
}
}
}
我明白了。我将序列号值添加为全局变量,并将预订条目和项目跟踪分解为 OnAfterValidate() 触发器。现在一切正常。完整源代码如下。
tableextension 50103 "DchApi_TransferTableExt" extends "Transfer Line"
{
fields
{
modify("Item No.")
{
trigger OnBeforeValidate()
var
Rec_ILE: Record "Item Ledger Entry";
Rec_TransLine: Record "Transfer Line";
Rec_Item: Record Item;
Rec_TransHdr: Record "Transfer Header";
ItemNo: Code[20];
SerialNo: Code[20];
ShortDim1Code: Code[20];
ShortDim2Code: Code[20];
Description: Text[100];
GenProdPostGrp: Code[20];
InvPostGrp: Code[20];
ItemCatCode: Code[20];
InTransCode: Code[10];
TransFromCode: Code[10];
TransToCode: Code[10];
LineNo: Integer;
InsertResult: Boolean;
begin
SerialNo := Rec."Item No.";
Rec_ILE.Reset();
Rec_ILE.SetRange("Entry Type", Rec_ILE."Entry Type"::Purchase);
Rec_ILE.SetRange("Item Tracking", Rec_ILE."Item Tracking"::"Serial No.");
Rec_ILE.SetFilter("Serial No.", '%1', SerialNo);
if Rec_ILE.FindFirst() then begin
ItemNo := Rec_ILE."Item No.";
Rec_Item.Reset();
Rec_Item.SetFilter("No.", ItemNo);
if Rec_Item.FindFirst() then begin
ShortDim1Code := Rec_Item."Global Dimension 1 Code";
ShortDim2Code := Rec_Item."Global Dimension 2 Code";
Description := Rec_Item.Description;
GenProdPostGrp := Rec_Item."Gen. Prod. Posting Group";
InvPostGrp := Rec_Item."Inventory Posting Group";
ItemCatCode := Rec_Item."Item Category Code";
Rec_TransHdr.Reset();
Rec_TransHdr.SetRange("No.", Rec."Document No.");
if Rec_TransHdr.FindFirst() then begin
InTransCode := Rec_TransHdr."In-Transit Code";
TransFromCode := Rec_TransHdr."Transfer-from Code";
TransToCode := Rec_TransHdr."Transfer-to Code";
Rec_TransLine.Reset();
Rec_TransLine.SetRange("Document No.", Rec."Document No.");
if Rec_TransLine.FindLast() then
LineNo := Rec_TransLine."Line No." + 10000
else
LineNo := 10000;
Validate(Rec."Document No.");
Validate(Rec."Line No.", LineNo);
Validate(Rec."Item No.", ItemNo);
Validate(Rec."Description 2", SerialNo);
gblSerialNo := Rec."Description 2";
Validate(Rec."Variant Code", '');
Validate(Rec."Shortcut Dimension 1 Code", '200');
Validate(Rec."Shortcut Dimension 2 Code", '01');
Validate(Rec.Description, Description);
Validate(Rec."Gen. Prod. Posting Group", GenProdPostGrp);
Validate(Rec."Inventory Posting Group", InvPostGrp);
Validate(Rec."Item Category Code", ItemCatCode);
Validate(Rec.Quantity, 1);
Validate(Rec."Unit of Measure Code", 'PCS');
Validate(Rec."Qty. to Ship", 1);
Validate(Rec."Qty. per Unit of Measure", 1);
Validate(Rec.Status, Rec.Status::Open);
Validate(Rec."In-Transit Code", InTransCode);
Validate(Rec."Transfer-from Code", TransFromCode);
Validate(Rec."Transfer-to Code", TransToCode);
InsertResult := Rec.Insert();
Commit();
end;
end;
end;
end;
trigger OnAfterValidate()
var
Rec_ResEnt: Record "Reservation Entry" temporary;
Rec_ResEnt_Lu: Record "Reservation Entry";
CreateReservEntry: Codeunit "Create Reserv. Entry";
ItemTrackingMgt: Codeunit "Item Tracking Management";
ReservStatus: Enum "Reservation Status";
CurrentSourceRowID: Text[250];
SecondSourceRowID: Text[250];
begin
Rec_ResEnt.Init();
Rec_ResEnt_Lu.Reset();
if Rec_ResEnt_Lu.FindLast() then
Rec_ResEnt."Entry No." := Rec_ResEnt_Lu."Entry No." + 1
else
Rec_ResEnt."Entry No." := 1;
Rec_ResEnt."Expiration Date" := Today();
Rec_ResEnt.Quantity := 1;
Rec_ResEnt."Serial No." := gblSerialNo;
Rec_ResEnt.Insert();
Commit();
CreateReservEntry.SetDates(0D, Rec_ResEnt."Expiration Date");
CreateReservEntry.CreateReservEntryFor(Database::"Transfer Line", 0, Rec."Document No.", '', Rec."Derived From Line No.", Rec."Line No.",
Rec."Qty. per Unit of Measure", Rec_ResEnt.Quantity, Rec."Qty. per Unit of Measure" * Rec_ResEnt.Quantity, Rec_ResEnt);
CreateReservEntry.CreateEntry(Rec."Item No.", Rec."Variant Code", Rec."Transfer-from Code", Rec.Description, Rec."Receipt Date", 0D, 0, ReservStatus::Surplus);
CurrentSourceRowID := ItemTrackingMgt.ComposeRowID(5741, 0, Rec."Document No.", '', 0, Rec."Line No.");
SecondSourceRowID := ItemTrackingMgt.ComposeRowID(5741, 1, Rec."Document No.", '', 0, Rec."Line No.");
ItemTrackingMgt.SynchronizeItemTracking(CurrentSourceRowID, SecondSourceRowID, '');
end;
}
}
var
gblSerialNo: Code[20];
}
因此,我们正在尝试通过实施 Microsoft Dynamics Business Central 365 来弥补一些差距。目前正在本地测试 v19 W1。我们的一个用例涉及序列化项目。为了帮助简化流程,由于序列号值在所有项目中都是唯一的,我们希望能够在序列级别管理项目。而不是采用先提供项目编号值然后为每个交易提供序列号值的两步过程。
这是一个基本示例。在转移订单页面,我们希望用户扫描条形码或将序列号手动键入新转移行的项目编号字段。通过我的 AL 代码,我将获取该序列号值,将其回溯到“父”项目编号,临时存储序列号值,然后将字段内容替换为正确的项目编号值。这是第一步。
然后,第二步将涉及为基础序列号添加预订条目行,以便项目跟踪能够正确反映与转移行相关联的序列号。当我加载我的 AL 扩展代码时,由于序列化,我遇到了数量错误。尽管我可以在该特定字段中手动提供相同的确切项目编号,并且该页面允许我继续提供数量和诸如此类的东西。
我被告知我需要以编程方式创建传输线,因此我尝试定义所有相关的 属性 值。我将粘贴我的 AL 代码以及验证错误的屏幕截图。一如既往,我们将不胜感激!
tableextension 50103 "DchApi_TransferTableExt" extends "Transfer Line"
{
fields
{
modify("Item No.")
{
trigger OnBeforeValidate()
var
Rec_ILE: Record "Item Ledger Entry";
Rec_ResEnt: Record "Reservation Entry" temporary;
Rec_ResEnt_Lu: Record "Reservation Entry";
Rec_TransLine: Record "Transfer Line";
Rec_Item: Record Item;
Rec_TransHdr: Record "Transfer Header";
CreateReservEntry: Codeunit "Create Reserv. Entry";
ItemTrackingMgt: Codeunit "Item Tracking Management";
ReservStatus: Enum "Reservation Status";
CurrentSourceRowID: Text[250];
SecondSourceRowID: Text[250];
SerialNo: Code[20];
ItemNo: Code[20];
ShortDim1Code: Code[20];
ShortDim2Code: Code[20];
Description: Text[100];
GenProdPostGrp: Code[20];
InvPostGrp: Code[20];
ItemCatCode: Code[20];
InTransCode: Code[10];
TransFromCode: Code[10];
TransToCode: Code[10];
LineNo: Integer;
begin
SerialNo := Rec."Item No.";
Rec_ILE.Reset();
Rec_ILE.SetRange("Entry Type", Rec_ILE."Entry Type"::Purchase);
Rec_ILE.SetRange("Item Tracking", Rec_ILE."Item Tracking"::"Serial No.");
Rec_ILE.SetFilter("Serial No.", '%1', SerialNo);
if Rec_ILE.FindFirst() then begin
ItemNo := Rec_ILE."Item No.";
Rec_Item.Reset();
Rec_Item.SetFilter("No.", ItemNo);
if Rec_Item.FindFirst() then begin
ShortDim1Code := Rec_Item."Global Dimension 1 Code";
ShortDim2Code := Rec_Item."Global Dimension 2 Code";
Description := Rec_Item.Description;
GenProdPostGrp := Rec_Item."Gen. Prod. Posting Group";
InvPostGrp := Rec_Item."Inventory Posting Group";
ItemCatCode := Rec_Item."Item Category Code";
Rec_TransHdr.Reset();
Rec_TransHdr.SetRange("No.", Rec."Document No.");
if Rec_TransHdr.FindFirst() then begin
InTransCode := Rec_TransHdr."In-Transit Code";
TransFromCode := Rec_TransHdr."Transfer-from Code";
TransToCode := Rec_TransHdr."Transfer-to Code";
Rec_TransLine.Reset();
Rec_TransLine.SetRange("Document No.", Rec."Document No.");
if Rec_TransLine.FindLast() then
LineNo := Rec_TransLine."Line No." + 10000
else
LineNo := 10000;
Validate(Rec."Document No.");
Validate(Rec."Line No.", LineNo);
Validate(Rec."Item No.", ItemNo);
Validate(Rec."Variant Code", '');
Validate(Rec."Shortcut Dimension 1 Code", ShortDim1Code);
Validate(Rec."Shortcut Dimension 2 Code", ShortDim2Code);
Validate(Rec.Description, Description);
Validate(Rec."Gen. Prod. Posting Group", GenProdPostGrp);
Validate(Rec."Inventory Posting Group", InvPostGrp);
Validate(Rec."Item Category Code", ItemCatCode);
Validate(Rec.Quantity, 1);
Validate(Rec."Unit of Measure Code", 'PCS');
Validate(Rec."Qty. to Ship", 1);
Validate(Rec."Qty. per Unit of Measure", 1);
Validate(Rec.Status, Rec.Status::Open);
Validate(Rec."In-Transit Code", InTransCode);
Validate(Rec."Transfer-from Code", TransFromCode);
Validate(Rec."Transfer-to Code", TransToCode);
Rec.Insert();
Rec_ResEnt.Init();
Rec_ResEnt_Lu.Reset();
if Rec_ResEnt_Lu.FindLast() then
Rec_ResEnt."Entry No." := Rec_ResEnt_Lu."Entry No." + 1
else
Rec_ResEnt."Entry No." := 1;
Rec_ResEnt."Expiration Date" := Today();
Rec_ResEnt.Quantity := 1;
Rec_ResEnt."Serial No." := SerialNo;
Rec_ResEnt.Insert();
CreateReservEntry.SetDates(0D, Rec_ResEnt."Expiration Date");
CreateReservEntry.CreateReservEntryFor(Database::"Transfer Line", 0, Rec."Document No.", '', Rec."Derived From Line No.", Rec."Line No.",
Rec."Qty. per Unit of Measure", Rec_ResEnt.Quantity, Rec."Qty. per Unit of Measure" * Rec_ResEnt.Quantity, Rec_ResEnt);
CreateReservEntry.CreateEntry(Rec."Item No.", Rec."Variant Code", Rec."Transfer-from Code", Rec.Description, Rec."Receipt Date", 0D, 0, ReservStatus::Surplus);
CurrentSourceRowID := ItemTrackingMgt.ComposeRowID(5741, 0, Rec."Document No.", '', 0, Rec."Line No.");
SecondSourceRowID := ItemTrackingMgt.ComposeRowID(5741, 1, Rec."Document No.", '', 0, Rec."Line No.");
ItemTrackingMgt.SynchronizeItemTracking(CurrentSourceRowID, SecondSourceRowID, '');
end;
end;
end;
end;
}
}
}
我明白了。我将序列号值添加为全局变量,并将预订条目和项目跟踪分解为 OnAfterValidate() 触发器。现在一切正常。完整源代码如下。
tableextension 50103 "DchApi_TransferTableExt" extends "Transfer Line"
{
fields
{
modify("Item No.")
{
trigger OnBeforeValidate()
var
Rec_ILE: Record "Item Ledger Entry";
Rec_TransLine: Record "Transfer Line";
Rec_Item: Record Item;
Rec_TransHdr: Record "Transfer Header";
ItemNo: Code[20];
SerialNo: Code[20];
ShortDim1Code: Code[20];
ShortDim2Code: Code[20];
Description: Text[100];
GenProdPostGrp: Code[20];
InvPostGrp: Code[20];
ItemCatCode: Code[20];
InTransCode: Code[10];
TransFromCode: Code[10];
TransToCode: Code[10];
LineNo: Integer;
InsertResult: Boolean;
begin
SerialNo := Rec."Item No.";
Rec_ILE.Reset();
Rec_ILE.SetRange("Entry Type", Rec_ILE."Entry Type"::Purchase);
Rec_ILE.SetRange("Item Tracking", Rec_ILE."Item Tracking"::"Serial No.");
Rec_ILE.SetFilter("Serial No.", '%1', SerialNo);
if Rec_ILE.FindFirst() then begin
ItemNo := Rec_ILE."Item No.";
Rec_Item.Reset();
Rec_Item.SetFilter("No.", ItemNo);
if Rec_Item.FindFirst() then begin
ShortDim1Code := Rec_Item."Global Dimension 1 Code";
ShortDim2Code := Rec_Item."Global Dimension 2 Code";
Description := Rec_Item.Description;
GenProdPostGrp := Rec_Item."Gen. Prod. Posting Group";
InvPostGrp := Rec_Item."Inventory Posting Group";
ItemCatCode := Rec_Item."Item Category Code";
Rec_TransHdr.Reset();
Rec_TransHdr.SetRange("No.", Rec."Document No.");
if Rec_TransHdr.FindFirst() then begin
InTransCode := Rec_TransHdr."In-Transit Code";
TransFromCode := Rec_TransHdr."Transfer-from Code";
TransToCode := Rec_TransHdr."Transfer-to Code";
Rec_TransLine.Reset();
Rec_TransLine.SetRange("Document No.", Rec."Document No.");
if Rec_TransLine.FindLast() then
LineNo := Rec_TransLine."Line No." + 10000
else
LineNo := 10000;
Validate(Rec."Document No.");
Validate(Rec."Line No.", LineNo);
Validate(Rec."Item No.", ItemNo);
Validate(Rec."Description 2", SerialNo);
gblSerialNo := Rec."Description 2";
Validate(Rec."Variant Code", '');
Validate(Rec."Shortcut Dimension 1 Code", '200');
Validate(Rec."Shortcut Dimension 2 Code", '01');
Validate(Rec.Description, Description);
Validate(Rec."Gen. Prod. Posting Group", GenProdPostGrp);
Validate(Rec."Inventory Posting Group", InvPostGrp);
Validate(Rec."Item Category Code", ItemCatCode);
Validate(Rec.Quantity, 1);
Validate(Rec."Unit of Measure Code", 'PCS');
Validate(Rec."Qty. to Ship", 1);
Validate(Rec."Qty. per Unit of Measure", 1);
Validate(Rec.Status, Rec.Status::Open);
Validate(Rec."In-Transit Code", InTransCode);
Validate(Rec."Transfer-from Code", TransFromCode);
Validate(Rec."Transfer-to Code", TransToCode);
InsertResult := Rec.Insert();
Commit();
end;
end;
end;
end;
trigger OnAfterValidate()
var
Rec_ResEnt: Record "Reservation Entry" temporary;
Rec_ResEnt_Lu: Record "Reservation Entry";
CreateReservEntry: Codeunit "Create Reserv. Entry";
ItemTrackingMgt: Codeunit "Item Tracking Management";
ReservStatus: Enum "Reservation Status";
CurrentSourceRowID: Text[250];
SecondSourceRowID: Text[250];
begin
Rec_ResEnt.Init();
Rec_ResEnt_Lu.Reset();
if Rec_ResEnt_Lu.FindLast() then
Rec_ResEnt."Entry No." := Rec_ResEnt_Lu."Entry No." + 1
else
Rec_ResEnt."Entry No." := 1;
Rec_ResEnt."Expiration Date" := Today();
Rec_ResEnt.Quantity := 1;
Rec_ResEnt."Serial No." := gblSerialNo;
Rec_ResEnt.Insert();
Commit();
CreateReservEntry.SetDates(0D, Rec_ResEnt."Expiration Date");
CreateReservEntry.CreateReservEntryFor(Database::"Transfer Line", 0, Rec."Document No.", '', Rec."Derived From Line No.", Rec."Line No.",
Rec."Qty. per Unit of Measure", Rec_ResEnt.Quantity, Rec."Qty. per Unit of Measure" * Rec_ResEnt.Quantity, Rec_ResEnt);
CreateReservEntry.CreateEntry(Rec."Item No.", Rec."Variant Code", Rec."Transfer-from Code", Rec.Description, Rec."Receipt Date", 0D, 0, ReservStatus::Surplus);
CurrentSourceRowID := ItemTrackingMgt.ComposeRowID(5741, 0, Rec."Document No.", '', 0, Rec."Line No.");
SecondSourceRowID := ItemTrackingMgt.ComposeRowID(5741, 1, Rec."Document No.", '', 0, Rec."Line No.");
ItemTrackingMgt.SynchronizeItemTracking(CurrentSourceRowID, SecondSourceRowID, '');
end;
}
}
var
gblSerialNo: Code[20];
}