microsoft / microsoft/BCApps

[Bug]: Whse. Jnl.-Register Line (Cod. 7301) forces Base UoM at non-directed bin-mandatory locations, making it impossible to correct multi-UoM Bin Content via Item Journal

Open
#9,678 3 comments 0 reactions 1 assignee View on GitHub

@PredragMaricic is already working on this.

Since Aug 24, 2026.

Team: SCM
Dominant language
AL
Stars
683
Forks
459
Avg merge
3d 26m
Merged PRs (30d)
633

Description

Describe the issue

At a warehouse location with Require Pick/Require Put-away = Yes and Directed Put-away and Pick = No
(a "non-directed" bin-mandatory location), Bin Content (table 7302) legitimately supports one row per
Location/Bin/Item/Variant/Unit of Measure Code — that combination is the table's primary key, and
Quantity (Base) is a per-row FlowField, not shared across UoM rows for the same bin.

Codeunit 7301 "Whse. Jnl.-Register Line" breaks this invariant in two related ways:

1. InitWhseEntry unconditionally forces the Base UoM for non-directed locations, discarding whatever
UoM the warehouse/item journal line was actually entered in — for both positive and negative movements:

end else begin
    WhseEntry.Quantity := WhseJnlLine."Qty. (Absolute, Base)" * Sign;
    WhseEntry."Unit of Measure Code" := WMSMgt.GetBaseUOM(WhseJnlLine."Item No.");
    WhseEntry."Qty. per Unit of Measure" := 1;
end;

2. DeleteFromBinContent then looks up the Bin Content row to validate available quantity against,
using WhseEntry."Unit of Measure Code"
— which, because of (1), is always the base UoM, never the
UoM the negative line was actually entered in:

FromBinContent.Get(
    WhseEntry."Location Code", WhseEntry."Bin Code", WhseEntry."Item No.", WhseEntry."Variant Code",
    WhseEntry."Unit of Measure Code");

Practical consequence: once an item has Bin Content rows in more than one UoM at the same bin
(which the system itself can create — see point 3 below), it becomes impossible to post a standard
correcting Item Journal entry
(negative-adjustment-in-UoM-A / positive-adjustment-in-UoM-B) to
consolidate them: the negative line's availability check always resolves against the base-UoM row,
completely ignoring the non-base-UoM row's actual (sufficient) quantity.

3. Secondary instance of the same root inconsistency, on the insert/positive path, in the same
procedure — the existence check correctly uses the journal line's own entered UoM, but the actual row
write stamps the UoM from WhseEntry, which by this point has already been base-UoM-forced by (1):

if not ToBinContent.Get(
        WhseJnlLine."Location Code", BinCode, WhseJnlLine."Item No.", WhseJnlLine."Variant Code",
        WhseJnlLine."Unit of Measure Code")      // <- entered UoM used for the check
then
    InsertToBinContent(WhseEntry)                // <- but WhseEntry."Unit of Measure Code" is base UoM
// InsertToBinContent
BinContent."Unit of Measure Code" := WhseEntry."Unit of Measure Code";  // always base UoM here

Different UoM source for the existence check vs. the actual write, inside the same if block.

Expected behavior

A negative adjustment entered in a non-base UoM, at a non-directed bin-mandatory location, should be
validated against — and consolidated with — the Bin Content row for that same UoM, not silently
redirected to the base-UoM row. Posting a correcting pair of Item Journal lines (negative in the
"wrong" UoM, positive in the intended UoM) at the same bin should succeed whenever the wrong-UoM row
actually holds enough quantity.

Steps to reproduce
  1. Create a Location with Bin Mandatory = Yes (Require Pick / Require Put-away = Yes) and
    Directed Put-away and Pick = No.
  2. Create an Item with two Units of Measure, e.g. EA (base) and PACK (Qty. per UoM = 1, to keep the
    repro minimal — the defect does not require a real conversion factor).
  3. Post a Positive Adjustment (Item Journal, or Warehouse Journal) of, say, 32 PACK into a bin (e.g.
    VIRTUAL) at that location. This creates a Bin Content row keyed on
    (Location, Bin, Item, Variant, UoM=PACK) with Quantity (Base) = 32 (assuming 1:1 conversion).
  4. Attempt to post a correcting Item Journal batch consisting of:
    • a negative adjustment of 32 EA (the base UoM) at the same bin, and
    • a positive adjustment of 32 PACK at the same bin (net-zero, intended to reclassify/consolidate).
  5. Preview-post (or post) the negative EA line.
Additional behavior observed / error text

Reproduced live via Preview Posting on a production BC 27.5 environment (build 27.5.46862.52525):

Quantity (Base) is not sufficient to complete this action. The quantity in the bin is 0.
32 units are not available in Bin Content Location Code='WH2',Bin Code='VIRTUAL',Item No.='KBBB',
Variant Code='',Unit of Measure Code='EA'.

— even though the same bin's PACK-UoM Bin Content row has the full 32 units available. The negative
line is validated against the (non-existent / empty) base-UoM Bin Content row instead of the actual
PACK-UoM row that holds the quantity, because DeleteFromBinContent always looks up by base UoM at
non-directed locations, regardless of which UoM the line was entered in.

Source references

Original reviewStefanMaron/MSDyn365BC.Sandbox.Code.History, branch w1-27.5,
WhseJnlRegisterLine.Codeunit.al:

  • InitWhseEntry base-UoM-forcing block: ~lines 143–151
  • DeleteFromBinContent mismatched lookup: ~lines 217–220
  • Insert-path check/write mismatch: check ~line 184, write via InsertToBinContent ~line 424

Current reviewmicrosoft/bcapps, branch main (targeting app version 29.0.0.0), commit
096090d6f8f05d59fb490426f89cd51537d01d3c (2026-07-22),
src/Layers/W1/BaseApp/Warehouse/Journal/WhseJnlRegisterLine.Codeunit.al:

  • InitWhseEntry base-UoM-forcing block: lines 145–153
  • DeleteFromBinContent mismatched lookup: lines 219–222
  • Insert-path check/write mismatch: check lines 186–188, write via InsertToBinContent line 426

The logic is unchanged between these two checkpoints (spanning roughly BC 27.5 through the 29.0
development branch), so this affects every version in between as well as whatever is currently
supported in production. Note: the Base Application source only became visible in this public
bcapps repository on main via commit 748fdaa (2026-06-29, "Sync from BCAppsPrivate + NAV") — no
released version's Base App source (28.3 and earlier) is public here to diff against directly, but the
carried-forward logic strongly indicates the defect is present unmodified in all supported releases.

Suggested fix direction

Either (or both):

  1. DeleteFromBinContent should not blindly trust WhseEntry."Unit of Measure Code" (which is
    base-UoM-forced for non-directed locations). Before the FromBinContent.Get(...) call, it should
    check whether a Bin Content row exists for the entered line UoM at that bin with sufficient
    Quantity (Base), and prefer that row over the base-UoM row when it does.
  2. InitWhseEntry should not silently discard the entered UoM for non-directed locations in the
    first place when a non-base-UoM Bin Content row already exists for that Location/Bin/Item/Variant —
    at minimum, the existence check and the eventual write (in the insert path) should be consistent
    with each other, which they currently are not (see point 3 above).
  • I will provide a fix for a bug

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.