web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

No record found.

News and Announcements icon
Community site session details

Community site session details

Session Id :
Microsoft Dynamics AX (Archived)

X++ Pick & Pack Serial Numbers in Transfer Orders

(0) ShareShare
ReportReport
Posted on by

Im trying to write x++ code to do the pick & pack of serial numbers in a transfer order. I managed to do that in sales orders, but i got at the last point in the transfer order and got stuck! I made a class to handle the transfer order <MPOSTransferOrders> in it I have a few methods.

The first method is the one handles the creation of the transfer order:

(Note: I have created two tables <MPOSTransOrders> which is a regular table, and <MPOSTransOrdersTemp> which is an inmemory table to hold my initial serial numbers 

public void createOrder(int TransferID)
{
    MPOSTransOrders         mposTransOrders;
    MPOSTransOrdersTemp     mposTransOrdersTemp;
    MPOSDeviceSerialInfo    mposDeviceSerialInfo;
    InventTransferTable     inventTransferTable;
    InventTransferLine      inventTransferLine;
    InventDim               inventDim;


    select mposTransOrders where mposTransOrders.TransferID == TransferID;



    try
    {
        ttsbegin;

        // loop into sold serials & fill temp table
        while select
            mposTransOrders
            join mposDeviceSerialInfo
            where mposTransOrders.DeviceSerial == mposDeviceSerialInfo.InventSerialID
            && mposTransOrders.TransferID == TransferID
        {
            mposTransOrdersTemp.TransferDate = mposTransOrders.TransferDate;
            mposTransOrdersTemp.TransferFromSite = mposTransOrders.TransferFromSite;
            mposTransOrdersTemp.TransferFromWH = mposTransOrders.TransferFromWH;
            mposTransOrdersTemp.TransferToWH = mposTransOrders.TransferToWH;
            mposTransOrdersTemp.DeviceID = mposDeviceSerialInfo.ItemID;
            mposTransOrdersTemp.DeviceName = mposDeviceSerialInfo.NameAlias;
            mposTransOrdersTemp.DeviceSerial = mposTransOrders.DeviceSerial;
            mposTransOrdersTemp.insert();
        }

        info('Temp table populated ...');



        // transfer header
        inventTransferTable.clear();
        inventTransferTable.initValue();
        inventTransferTable.TransferId = InventTransferTable::numberSeq().num();
        inventTransferTable.InventLocationIdFrom = mposTransOrdersTemp.TransferFromWH;
        inventTransferTable.InventLocationIdTo = mposTransOrdersTemp.TransferToWH;
        inventTransferTable.DlvModeId = CustVendTransportPointLine::defaultDeliveryMode(inventTransferTable.InventLocationIdFrom,'','','','',inventTransferTable.InventLocationIdTo);
        inventTransferTable.InventLocationIdTransit = InventLocation::find(inventTransferTable.InventLocationIdFrom).InventLocationIdTransit;

        inventTransferTable.initFromAddress();
        inventTransferTable.initToAddress();
        inventTransferTable.ShipDate = mposTransOrdersTemp.TransferDate;
        inventTransferTable.ReceiveDate = mposTransOrdersTemp.TransferDate;

        if (!inventTransferTable.validateWrite())
        {
            throw Exception::Error;
        }

        // insert transfer header
        inventTransferTable.insert();
        info('Trans Order header created ...');

        while select DeviceID, count(DeviceName), TransferFromSite, TransferFromWH, TransferDate
        from mposTransOrdersTemp group by DeviceID, TransferFromSite, TransferFromWH, TransferDate
        {
            // transfer item line
            inventDim.clear();
            inventDim.InventSiteId = mposTransOrdersTemp.TransferFromSite;
            inventDim.InventLocationId = mposTransOrdersTemp.TransferFromWH;
            inventTransferLine.clear();
            inventTransferLine.initValue();
            inventTransferLine.ItemId = mposTransOrdersTemp.DeviceID;
            inventTransferLine.InventDimId = InventDim::findOrCreate(inventDim).inventDimId;
            inventTransferLine.QtyTransfer = str2int(mposTransOrdersTemp.DeviceName);
            inventTransferLine.initFromInventTableModule(InventTableModule::find(inventTransferLine.ItemId,ModuleInventPurchSales::Invent));
            inventTransferLine.QtyRemainReceive = inventTransferLine.QtyTransfer;
            inventTransferLine.QtyRemainShip = inventTransferLine.QtyTransfer;
            inventTransferLine.ShipDate = mposTransOrdersTemp.TransferDate;
            inventTransferLine.ReceiveDate = mposTransOrdersTemp.TransferDate;
            inventTransferLine.initFromInventTransferTable(inventTransferTable, false);
            inventTransferLine.LineNum = InventTransferLine::lastLineNum(inventTransferLine.TransferId) + 1.0;

            if (inventTransferLine.validateWrite())
            {
                inventTransferLine.insert();
                info('Item: ' + mposTransOrdersTemp.DeviceID + ' & Qty: ' + mposTransOrdersTemp.DeviceName);
            }
            else
            {
                throw Exception::Error;
            }
        }




        ttscommit;

        // start the split
        this.splitItemLines(inventTransferTable.TransferId);


        // link the serials
        this.pickSerials(inventTransferTable.TransferId);

    }
    catch
    {
        throw Exception::Error;

    }

    info("Done!");

}

Then second method is <splitItemLines> which handles the items splitting in the pick screen (and this one works fine)

public void splitItemLines(InventTransferId transferID)
{

    // declerations for item splitting (picking)
    InventTrans             inventTrans;
    InventTransOrigin       inventTransOrigin;
    InventTransferLine      inventTransLine;
    int                     rowCount;
    int                     i = 0;
    int                     j = 0;

    ttsBegin;
    /*      start splitting lines - pick process        */

    // starting split process
    info('starting split process');

    // get rows count in transferLine
    select count(RecId) from inventTransLine where inventTransLine.TransferId == transferID;
    info(strFmt("TransferLine has %1 records.", inventTransLine.RecId));

    // loop on items in transferLine
    while select InventTransId from inventTransLine where inventTransLine.TransferId == transferID
    {
        info(strFmt("Splitting InventTransID: %1.", inventTransLine.InventTransId));

        // get InventTransOrigin record using sales line InventTransId
        inventTransOrigin = InventTransOrigin::findByInventTransId(inventTransLine.InventTransId, false);
        info(strFmt("Locating InventTransOrigin RecId: %1", inventTransOrigin.RecId));

        // get invent trans line to split
        inventTrans = InventTrans::findByInventTransOrigin(inventTransOrigin.RecId, false);

        // get qty to split into lines
        rowCount = real2int(abs(inventTrans.Qty));
        info(strFmt("Qty: %1", abs(inventTrans.Qty)));

        for (i = 1; i < rowCount; i++)
        {
            inventTrans = InventTrans::findByInventTransOrigin(inventTransOrigin.RecId, false);
            inventTrans.updateSplit(-1);
        }

    }

    ttsCommit;

    info('split process completed');
    /*      end splitting lines - pick process          */

}

The third method is the <pickSerials> method, which supposed to handle the passing / selection of serials into the pick screen, and here is where i am stuck. 

public void pickSerials(InventTransferId transferID)
{

    InventTransferLine          inventTransLine;
    InventTrans                 inventTrans;
    InventTrans                 inventTransRecord;
    InventTransOrigin           inventTransOrigin;
    InventDim                   inventDim;
    MPOSTransOrders             mposTransOrders;


    try
    {
        ttsbegin;

        info('starting pick process...');

        // loop on <SalesLine> using the <SalesId> to get items sold
        // each item will have a line with a unique <SalesLine>.<InventTransId>
        // which will be used in the <InventTrans> loop
        while select inventTransLine where inventTransLine.TransferId == transferID
        {

            // get <inventTransOrigin.RecId> to loop item lines in <inventTrans>
            select inventTransOrigin where inventTransOrigin.InventTransId == inventTransLine.InventTransId;
            // start loop on <inventTrans> to get each item line
            while select inventTrans where inventTrans.InventTransOrigin == inventTransOrigin.RecId
            {


                // select record from <MPOSCustSales> with no <InventDimID>
                select forupdate mposTransOrders where mposTransOrders.TransferID == 1;
                //mposTransOrders.TransferId == transferID && mposTransOrders.InventDimID == '';

                // get record from <inventDim> using <MPOSCustSales.DeviceSerial> &
                // <MPOSCustSales.MPOSUserID> which equals <inventDim.InventLocationId>
                select inventDim where inventDim.inventSerialId == mposTransOrders.DeviceSerial
                && inventDim.InventLocationId == mposTransOrders.TransferFromWH;


                // update <MPOSCustSales> with new <InventDimID>
                //mposTransOrders.InventDimID = inventDim.InventDimId;
                //mposTransOrders.update();

                // execute the pick & packing
                this.pickAndPackingSlip(inventTransLine.InventTransId , inventDim.inventDimId, 1);

                info(strFmt("Updated Serial: '%1' with InventDimID: '%2'", mposTransOrders.DeviceSerial, inventDim.inventDimId));


            }


        }

        ttscommit;


    }
    catch (Exception::Error)
    {
        throw Global::error("need to get warning");
        //info('Error ...');
    }
}


This method calls another method <pickAndPackingSlip>, which I found and works just fine for sales orders:

private void pickAndPackingSlip(
    InventtransId   _InventtransId,
    InventDimId     _InventDimId,
    Int             _Qty)
{

    TmpInventTransWMS               tmpInventTransWMS;
    InventMovement                  InventMovement;
    InventTransOrigin               InventTransOrigin;
    SalesLine                       SalesLine;
    InventTrans                     InventTrans;
    MPOSinventTransWMS_Pick         inventTransWMS_Pick;
    Query                           inventTransQuery;
    QueryBuildDataSource            QueryBuildDataSource;

    SalesFormLetter                 SalesFormLetter;
    SalesTable                      SalesTable;

    System.String                   netString = "Net string.";
    System.Exception                netExcepn;

    try
    {
        inventTransQuery                = new Query();
        QueryBuildDataSource            = inventTransQuery.addDataSource(tableNum(InventTrans));
        InventTrans                     = InventTrans::findTransId(_InventtransId);
        InventTransOrigin               = InventTransorigin::findByInventTransId(_InventtransId);
        QueryBuildDataSource.addRange(fieldNum(InventTrans,RecId)).value(int642str(InventTrans.recid));


        delete_from tmpInventTransWMS;
        tmpInventTransWMS.clear();
        inventTransWMS_Pick             = MPOSInventTransWMS_Pick::newStandard(tmpInventTransWMS,inventTransQuery);
        tmpInventTransWMS.initFromInventTrans(InventTrans);
        tmpInventTransWMS.initFromInventTransOrigin(InventTransOrigin);
        tmpInventTransWMS.InventQty     = _Qty;
        tmpInventTransWMS.InventDimId   = _InventDimId;
        inventTransWMS_Pick.writeTmpInventTransWMS(tmpInventTransWMS);
        inventTransWMS_Pick.updateInvent();

        /*
        SalesFormLetter                 = SalesFormLetter::construct(DocumentStatus::PackingSlip);
        SalesLine                       = salesline::findInventTransId(_InventtransId);
        SalesTable                      = SalesTable::Find(SalesLine.salesId);
        SalesFormLetter.update(SalesTable,systemDateGet(), SalesUpdate::PickingList, AccountOrder::None, false, false);
        */

    }
    catch(Exception::Error)
    {
        throw Exception::Error;
    }
    catch(Exception::Info)
    {
        throw Exception::Info;
    }
    catch(Exception::CLRError)
    {
        //throw Exception::CLRError;
        netExcepn = CLRInterop::getLastException();
    }
}


As you can notice, the last few lines, which in the sales orders update the actual sales order through using the <SalesFormLetter> class, and that what I would like to find its equivalent in transfer order?

*This post is locked for comments

I have the same question (0)
  • Verified answer
    Community Member Profile Picture
    on at

    Found solution:

    here is the method for shipping:

    private void shipTransferOrder(InventTransferId transferID)
    
    {
    
        InventTransferParmTable     inventTransferParmTable;
        InventTransferTable         inventTransferTable;
        InventTransferUpdShip       inventTransferUpdShip;
        InventTransferLine          inventTransferLine;
        InventTransferParmUpdate    inventTransferParmUpdate;
        InventTransferUpd           invTranUpd;
    
        select * from inventTransferTable where inventTransferTable.TransferId == transferID;
        inventTransferParmUpdate.ParmId = RunBaseMultiParm::getSysParmId();
        inventTransferParmUpdate.insert();
        inventTransferParmTable.initValue();
        inventTransferParmTable.ParmId = inventTransferParmUpdate.ParmId;
        inventTransferParmTable.TransferId = inventTransferTable.TransferId;
        inventTransferParmTable.ShipUpdateQty = InventTransferShipUpdateQty::All;
        inventTransferParmTable.EditLines = NoYes::Yes;
        inventTransferParmTable.AutoReceiveQty = NoYes::No;
        inventTransferParmTable.UpdateType = InventTransferUpdateType::Shipment;
        inventTransferParmTable.insert();
        //Transfer Order created above should have status as shipped
        invTranUpd = InventTransferUpdShip::newParmBuffer(inventTransferParmTable);
        invTranUpd.run();
    
    
    
    }


    and here is the method for receiving:

    public void receiveTransferOrder(InventTransferId transferID)
    
    {
    
        InventTransferParmTable     inventTransferParmTable;
        InventTransferTable         inventTransferTable;
        InventTransferUpdReceive    inventTransferUpdReceive;
        InventTransferLine          inventTransferLine;
        InventTransferParmUpdate    inventTransferParmUpdate;
        InventTransferUpd           invTranUpd;
    
        select * from inventTransferTable where inventTransferTable.TransferId == transferID;
        inventTransferParmUpdate.ParmId = RunBaseMultiParm::getSysParmId();
        inventTransferParmUpdate.insert();
        inventTransferParmTable.initValue();
        inventTransferParmTable.ParmId = inventTransferParmUpdate.ParmId;
        inventTransferParmTable.TransferId = inventTransferTable.TransferId;
        inventTransferParmTable.ReceiveUpdateQty = InventTransferReceiveUpdateQty::All;
        inventTransferParmTable.EditLines = NoYes::Yes;
        inventTransferParmTable.AutoReceiveQty = NoYes::No;
        inventTransferParmTable.UpdateType = InventTransferUpdateType::Receive;
        inventTransferParmTable.insert();
        invTranUpd = inventTransferUpdReceive::newParmBuffer(inventTransferParmTable);
        invTranUpd.run();
    
    }


Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Introducing the 2026 Season 1 community Super Users

Congratulations to our 2026 Super Stars!

Meet the Microsoft Dynamics 365 Contact Center Champions

We are thrilled to have these Champions in our Community!

Congratulations to the March Top 10 Community Leaders

These are the community rock stars!

Leaderboard > 🔒一 Microsoft Dynamics AX (Archived)

#1
Joris dG Profile Picture

Joris dG 5

#2
Alexey Lekanov Profile Picture

Alexey Lekanov 2

#2
Henrik Nordlöf Profile Picture

Henrik Nordlöf 2 User Group Leader

Last 30 days Overall leaderboard

Featured topics

Product updates

Dynamics 365 release plans