[Bug]: Warehouse Journal Line.CalcReservEntryQuantity uses uninitialized global WhseJnlLine instead of Rec for tracking filter (regression since BC18)

オープン 初心者向け
#13,635 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
64/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
領域
backend

調査の方向性

src/Layers/W1/BaseApp/Warehouse/Journal/WarehouseJournalLine.Table.alを読み、特にトラッキングフィルターの呼び出しに注目してCalcReservEntryQuantityを調べてください。現在のレコードがトラッキングフィルターを提供していることを確認し、関連する倉庫仕訳行のテストを確認するか、異なるロットの予約に対する回帰チェックを追加してください。予約検索で現在の行のトラッキングが使われ、報告された移動出荷のシナリオが成功すれば完了です。

索引モデルが issue の本文から書いたものです。

説明

Team: SCM
Describe the issue

Table 7311 "Warehouse Journal Line", procedure CalcReservEntryQuantity(), filters the Reservation Entry on an uninitialized global variable instead of the current record:

ReservEntry.SetTrackingFilterFromWhseJnlLine(WhseJnlLine);

WhseJnlLine is the table's protected global variable, not Rec. It is not initialized when CalcReservEntryQuantity is called from codeunit 7302 "WMS Management".CheckWhseJnlLineTracking, so the Reservation Entry is always filtered on Serial No. = '' and Lot No. = '' instead of the journal line's tracking.

This is a regression from the BC18 refactoring that moved the procedure from codeunit 7302 to table 7311.

BC17 – codeunit 7302 "WMS Management" (correct): the line is passed as a parameter named WhseJnlLine.

local procedure CalcReservEntryQuantity(WhseJnlLine: Record "Warehouse Journal Line"): Decimal
var
    ReservEntry: Record "Reservation Entry";
begin
    with WhseJnlLine do begin
        if "Source Type" = DATABASE::"Prod. Order Component" then begin
            ReservEntry.SetSourceFilter("Source Type", "Source Subtype", "Journal Template Name", "Source Subline No.", true);
            ReservEntry.SetSourceFilter("Journal Batch Name", "Source Line No.");
        end else begin
            ReservEntry.SetSourceFilter("Source Type", "Source Subtype", "Journal Template Name", "Source Line No.", true);
            ReservEntry.SetSourceFilter("Journal Batch Name", 0);
        end;
        ReservEntry.SetTrackingFilterFromWhseJnlLine(WhseJnlLine); // <- WhseJnlLine = the parameter (the actual line)
        if ReservEntry.FindFirst then
            exit(ReservEntry."Quantity (Base)");
        exit("Qty. (Base)");
    end;
end;

Called as:

CheckLotNo(
  "Item No.", "Variant Code", "Location Code", "From Bin Code",
  "Unit of Measure Code", "Lot No.", CalcReservEntryQuantity(WhseJnlLine));

BC18 to current main – table 7311 "Warehouse Journal Line" (wrong): the parameter was removed, but the reference was not changed to Rec. The name now resolves to the table's global variable WhseJnlLine.

procedure CalcReservEntryQuantity(): Decimal
var
    ReservEntry: Record "Reservation Entry";
begin
    if "Source Type" = ProdOrderComponentSourceID() then begin
        ReservEntry.SetSourceFilter("Source Type", "Source Subtype", "Journal Template Name", "Source Subline No.", true);
        ReservEntry.SetSourceFilter("Journal Batch Name", "Source Line No.");
    end else begin
        ReservEntry.SetSourceFilter("Source Type", "Source Subtype", "Journal Template Name", "Source Line No.", true);
        ReservEntry.SetSourceFilter("Journal Batch Name", 0);
    end;
    ReservEntry.SetTrackingFilterFromWhseJnlLine(WhseJnlLine); // <- WhseJnlLine = uninitialized global, NOT Rec
    if ReservEntry.FindFirst() then
        exit(ReservEntry."Quantity (Base)");
    exit("Qty. (Base)");
end;
protected var
    Item: Record Item;
    WhseJnlLine: Record "Warehouse Journal Line";   // global used above
    PhysInvtEntered: Boolean;

Called from codeunit 7302 "WMS Management".CheckWhseJnlLineTracking:

CheckLotNo(
  WarehouseJournalLine."Item No.", WarehouseJournalLine."Variant Code", WarehouseJournalLine."Location Code", WarehouseJournalLine."From Bin Code",
  WarehouseJournalLine."Unit of Measure Code", WarehouseJournalLine."Lot No.", WarehouseJournalLine.CalcReservEntryQuantity());

Impact: CheckLotNo / CheckSerialNo can receive the quantity of an unrelated, untracked reservation entry instead of the line's quantity, and posting fails with a false error such as:

Quantity (Base) must not be -2 in Bin Content Location Code='MK-MF',Bin Code='SCHEIA',Item No.='5615522',Variant Code='',Unit of Measure Code='BUC'.

even though the bin holds enough of the lot for the line being posted.

We hit this when posting / previewing a transfer order shipment on BC W1 29.0 (Platform 29.0.56814.0 + Application 29.0.54011.56829). In the debugger:

  • Effective Reservation Entry filters: Source Type = 5741, Source Subtype = 0, Source ID = '', Source Batch Name = '', Source Prod. Order Line = 0, Source Ref. No. = 40000, Serial No. = '', Lot No. = '', Package No. = ''
  • ReservEntry.FindFirst() = true, ReservEntry."Quantity (Base)" = -3 (an unrelated entry for another location)
  • Rec."Lot No." = the actual lot, Rec."Qty. (Base)" = 1
  • Bin content for the lot = 1, so the check computes 1 - 3 = -2 and raises the error.
Expected behavior

CalcReservEntryQuantity should filter the Reservation Entry on the tracking of the current record:

ReservEntry.SetTrackingFilterFromWhseJnlLine(Rec);

With this, the bin content check in CheckLotNo / CheckSerialNo uses the quantity of the line's own lot / serial number, and the transfer shipment in the scenario above posts successfully.

Steps to reproduce
  1. Create a location with Bin Mandatory = Yes and a bin B.
  2. Create an item with an item tracking code that has Lot Specific Tracking = Yes.
  3. Post 1 unit of lot L1 into bin B.
  4. Make sure a Reservation Entry exists with Source Type = 5741 (Transfer Line), Source Subtype = 0, Source ID = '', Source Batch Name = '', Source Ref. No. = 10000, Lot No. = '', Quantity (Base) = -3 (any item / location). In our case these were old orphaned entries; in a test it can be inserted directly.
  5. Create a transfer order from the location with one line (Line No. = 10000), Quantity = 1, lot L1, bin B.
  6. Post the transfer order (or Preview Posting) with option Ship.

Actual result: error "Quantity (Base) must not be -2 in Bin Content ...".

Expected result: the shipment posts. With Rec used in SetTrackingFilterFromWhseJnlLine, the filter includes Lot No. = L1, the unrelated entry does not match, and the procedure falls back to Rec."Qty. (Base)" (= 1), which the bin covers.

Additional context

Proposed fix (src/Layers/W1/BaseApp/Warehouse/Journal/WarehouseJournalLine.Table.al):

-        ReservEntry.SetTrackingFilterFromWhseJnlLine(WhseJnlLine);
+        ReservEntry.SetTrackingFilterFromWhseJnlLine(Rec);

Related observation (not part of the proposed fix): the source filter uses "Journal Template Name" / "Journal Batch Name" as Source ID / Source Batch Name:

ReservEntry.SetSourceFilter("Source Type", "Source Subtype", "Journal Template Name", "Source Line No.", true);
ReservEntry.SetSourceFilter("Journal Batch Name", 0);

This is correct for journal sources, but for document sources such as Transfer Line (set via WMSMgmt.SetTransferLine) both fields are blank. The filter then becomes Source ID = '' instead of the document number, and there is no Item No. / Location Code filter. This is why an unrelated entry could match at all. Changing it affects behavior more broadly, so we'd appreciate Microsoft's view on whether it should be handled separately.

Affected versions: BC18 through current main (verified in BC 23-29 and main).

I will provide a fix for a bug
  • I will provide a fix for a bug
主要言語
AL
スター
720
フォーク
488
平均マージ
2日 17時間
マージ済み PR(30日)
568

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

microsoft/BCApps のほかの issue

microsoft/BCApps の issue をすべて見る

似ている issue

Backend & API Design の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。