X++: On-Hand Inventory (Location based)

X++: On-Hand Inventory (Location based)

ISSUE #T1

ยท

2 min read

Objective

To retrieve stock quantity (physical inventory) at a specific inventory dimension.

Code

public static void main(Args _args)
    {
        WMSLocation                wmsLocation;
        InventDim                inventDimCriteria;
        InventDimParm            inventDimParmCriteria;
        InventDimOnHand            inventDimOnHand;
        InventDimOnHandIterator    inventDimOnHandIterator;
        InventDimOnHandMember    inventDimOnHandMember;

        Qty    qty;
        ;

        select firstonly inventLocationId, wMSLocationId from wmsLocation
            where wmsLocation.inventLocationId == "REFACC-NAL"
               && wmsLocation.wMSLocationId == "101-02-51-0";

        // Inventory dimensions range
        inventDimCriteria.InventLocationId    = wmsLocation.inventLocationId;
        inventDimCriteria.wMSLocationId        = wmsLocation.wMSLocationId;
        inventDimCriteria = InventDim::findOrCreate(inventDimCriteria);

        inventDimParmCriteria.InventLocationIdFlag    = NoYes::Yes;
        inventDimParmCriteria.wmsLocationIdFlag        = NoYes::Yes;

        inventDimOnHand            = InventDimOnHand_Physical::newPhysical('', inventDimCriteria, inventDimParmCriteria, inventDimOnHandLevel::Item, null);

        inventDimOnHandIterator    = inventDimOnHand.onHandIterator();

        while (inventDimOnHandIterator.more())
        {
            // A location can contain multiple items in it.
            // Class <c>InventDimOnHand</c> consists of InventDimOnHandMember classes.
            // Each class <c>InventDimOnHandMember</c> instance contains information about item, inventory dimensions and quantity.
            inventDimOnHandMember    = inventDimOnHandIterator.value();

            qty += inventDimOnHandMember.parmInventQty();

            inventDimOnHandIterator.next();
        }

        info(strfmt("Warehouse %1 - location %2 has %3 quantity of items.", wmsLocation.inventLocationId, wmsLocation.wMSLocationId, num2str(qty, 2, 2, 1, 1)));
    }

Output

On-Hand list:

Form_Locations_OnHand_I.png

Form_Locations_OnHand_II.png

Runnable class:

RunnableClass_OnHand.png

Tip

One can leverage the standard classes to retrieve a varied combinations of on-hand quantities, described below:

  • InventDimOnHand_AvailPhysical [Available physical]

  • InventDimOnHand_PhysicalArrived [Physical inventory + Arrived]

Or can devise a tailor-made class - resonating the standard class pattern, returning on-hand quantity combination as per the business need.

For example, the following class contains the business logic to retrieve dimension-based stock quantity [Physical inventory + Arrived + Ordered].

Code:

/// <summary> Class containing business logic to retrieve dimension based stock quantity. </summary>
/// <Developer> Kunal Mahajan </Developer>
/// <Dated> 04-08-22 </Dated>
internal final class DC_InventDimOnHand_PhysicalArrivedOrdered extends InventDimOnHand
{
    InventQty onHandQty(InventOnHandQty _inventOnHandQty)
    {
        return _inventOnHandQty.physicalInvent() + _inventOnHandQty.arrived() + _inventOnHandQty.ordered();
    }

    /// <summary>
    /// This method returns CW physical arrived ordered.
    /// </summary>
    /// <param name="_inventOnHandQty">InventOnHandQty class</param>
    /// <returns>CW physical arrived ordered</returns>
    public PdsCWInventQty pdsCWOnHandQty(InventOnHandQty _inventOnHandQty)
    {
        return _inventOnHandQty.pdsCWPhysicalInvent() + _inventOnHandQty.pdsCWArrived() + _inventOnHandQty.pdsCWOrdered();
    }

    public static InventDimOnHand newPhysicalArrivedOrdered(
        ItemId                  _itemId,
        InventDim               _inventDimCriteria,
        InventDimParm           _inventDimParmCriteria,
        InventDimOnHandLevel    _inventDimOnHandLevel,
        InventDimParm           _inventDimParmOnHandLevel,
        NoYes                   _onlyPositiveOnHands = NoYes::No)
    {
        DC_InventDimOnHand_PhysicalArrivedOrdered inventDimOnHand = new DC_InventDimOnHand_PhysicalArrivedOrdered();

        inventDimOnHand.parmItemIdCriteria(_itemId);
        inventDimOnHand.parmInventDimCriteria(_inventDimCriteria);
        inventDimOnHand.parmInventDimParmCriteria(_inventDimParmCriteria);
        inventDimOnHand.parmInventDimOnHandLevel(_inventDimOnHandLevel);
        inventDimOnHand.parmInventDimParmOnHandLevel(_inventDimParmOnHandLevel);
        inventDimOnHand.parmOnlyPositiveOnHands(_onlyPositiveOnHands);
        inventDimOnHand.initialize();
        return inventDimOnHand;
    }

}

Method calling:

inventDimOnHand = DC_InventDimOnHand_PhysicalArrivedOrdered::newPhysicalArrivedOrdered('', inventDimCriteria, inventDimParmCriteria, inventDimOnHandLevel::Item, null);

Conclusion

That's the end of the blog post. I hope it helps understand the technical intricacies of X++ and provides a viable solution to the problem statement adhering to the dynamics standards.

Moreover, please hit ๐Ÿ‘ in case you find the content helpful to encourage me to share more of my day-to-day experiences.

Thank you!

Did you find this article valuable?

Support Kunal Mahajan by becoming a sponsor. Any amount is appreciated!

ย