Thursday, November 28, 2019

Enable navigation bar in D365FO new version

Microsoft was removed the navigation bar in newer version of D365FO.

But many customer requested the navigation bar in D365FO. So microsoft brings the navigation bar as parameter setup in Client performance options forms.

If you required just enable the option in Client performance options

1.      Go to system administration > setup > Client performance options



 And Enable legacy navigation bar toggle.


Click Ok in the bottom of the page.

Refresh the browser. 

The legacy navigation bar will be available now.

Wednesday, November 27, 2019

SQL "IN" Operator

Microsoft Introduce IN Operator in X++ Syntax, but it will work with Enums  only.

Following are the example how you can use this

SalesTable  salesTable;
container   con = [SalesType::Sales,
SalesType::ReturnItem,
SalesType::Subscription];

while select SalesId from salesTable
where salesTable.SalesType in con
{
Info(salesTable.SalesId);
}

Update AX system fields either CreatedDateTime or ModifiedDateTime

Sometimes while creating a record if we need to update the created date time or modified date time system field in D365FO. Please find the below code to update the createddatetime field during the record creation.

This method will help you to update createDateTime field while inserting the record.

static void updateCreatedDateTime(Args _args)
{
CustGroup custGroup;

ttsBegin;
new OverwriteSystemfieldsPermission().assert();
custGroup.overwriteSystemfields(true);
custGroup.custGroupId= “Abcd”;
custGroup.Name= “Abcd”;
custGroup.(fieldnum(custGroup,CreatedDateTime))= str2datetime( “2019/11/28 05:30:00” ,321 );
custGroup.doInsert();
custGroup.overwriteSystemfields(false);
CodeAccessPermission::revertAssert();
ttsCommit;
}


static void updateCreatedDateTime(Args _args)
{
        CustGroup custGroup;

ttsBegin;
new OverwriteSystemfieldsPermission().assert();
custGroup.overwriteSystemfields(true);
custGroup = custGroup::find("Abcd");
custGroup.Name= “Abcd”;
custGroup.(fieldnum(custGroup,ModifiedDateTime))= str2datetime( “2019/11/28 06:30:00” ,321 );
custGroup.doUpdate();
custGroup.overwriteSystemfields(false);
CodeAccessPermission::revertAssert();
ttsCommit;
}

Tuesday, November 26, 2019

UnitOfMeasureConverter::convert() method is depreciated

Hi All,

In new D365FO the UnitOfMeasureConverter::convert() method is depreciated so we need to use EcoResProductUnitConverter method for unit conversion.

Please refer below code, the EcoResProductUnitConverter::convertGivenUnitSymbolsForReleasedProduct method will convert the quantity from invent quantity to sales quantity

public PurchQty convertSalesQty(ItemId _itemId,InventDimId _inventDimId, Qty _qty, SalesUnit _salesUnit)
    {
        SalesQty        salesQty;
        InventUnitId    inventUnit;

        inventUnit  = InventTableModule::find(_itemId,ModuleInventPurchSales::Invent).UnitId;
       

         //salesQty    = UnitOfMeasureConverter::convert(_qty
        //                                            , UnitOfMeasure::unitOfMeasureIdBySymbol(inventUnit)
        //                                            , UnitOfMeasure::unitOfMeasureIdBySymbol(_salesUnit)
        //                                            , NoYes::Yes
        //                                            , InventTable::itemProduct(_itemId));

In AX2012 we used UnitOfMeasureConverter::convert() method to convert the unit from invent to sales. But if we use same method in D365Fo we will receive the best practices error like the method UnitOfMeasureConverter::convert() is depreciated use EcoResProductUnitConverter class.

Please find below how to use EcoResProductUnitConverter class in D365FO to convert unit.

        salesQty = EcoResProductUnitConverter::convertGivenUnitSymbolsForReleasedProduct(_itemId
                                                                                        , _inventDimId
                                                                                        , _qty
                                                                                        , inventUnit
                                                                                        , _salesUnit
                                                                                        , NoYes::Yes
                                                                                        , NoYes::No);

        return salesQty;
    }

//Refer smmSalesCustItemStatisticsDP class

EcoResProductUnitConverter productUnitConverter = EcoResProductUnitConverter::newGivenUnitSymbolsForReleasedProduct(
                                                                                                _itemId, 
                                                                                                _inventDimId, 
                                                                                                _unitFrom,
                                                                                                unitInvent, 
                                                                                                NoYes::Yes);

Tuesday, November 19, 2019

Transfer order picking list registration

Below code will help you to register picking list for transfer order

public void registerPickingRoute(PickingRouteId _pickingRouteId)
{
            pickingRoute = WMSPickingRoute::find(_pickingRouteId,true);
            if(pickingRoute)
            {
                pickingRoute.finish();
            }
}

D365FO Transfer order picking list registration with split quantity

During picking list registration in Transfer order we may need to split the lines for batch number or serial number registration.

below code will be used for split the transaction. (Select line -> Function -> Spilt)

public void split transactions(RefRecId _recId, Qty _qty)
{
            WMSOrderTrans     orderTrans;
             WMSOrderTrans    splitTrans;
             InventDim               inventDim;

          orderTrans                            = WMSOrderTrans::findOrderTrans(_recId,true);
          splitedTrans                          = orderTrans.split(_qty);
          inventDim                             =  orderTrans.inventDim();
          inventDim.inventBatchId     = shipmentDataTmp.InventBatchId;
          inventDim                             = InventDim::findOrCreate(inventDim);

           splitedTrans.selectForUpdate(true);
          splitedTrans.inventDimId    = inventDim.inventDimId;
           if(splitedTrans.validateWrite())
           {
                  splitedTrans.update();
           }
}

Note: findOrderTrans method will not be available in standard table. i have written extension class for WMSOrderTrans table.

[ExtensionOf(tableStr(WMSOrderTrans))]
final class WMSOrderTransExample_Extension
{

 static WMSOrderTrans findOrderTrans(RefRecId _recId, boolean _forupdate = false)
    {
        WMSOrderTrans   orderTrans;

        orderTrans.selectForUpdate(_forupdate);

        select firstonly orderTrans
            where orderTrans.RecId == _recId;

        return orderTrans;
    }
}

Monday, November 18, 2019

D365FO Receive transfer order with batch number registration using x++

The below code will used to Receive the transfer order with batch number registration through code

 public void processTransferOrder()
{
this.registerInventory("100001");
this.postTransferOrderReceive("10001",systemdateget());
}
public void postTransferOrderReceive(InventTransferOrderId _transferId, TransDate _postingDate)
{
        InventTransferTable         inventTransferTable;
        InventTransferParmTable     inventTransferParmTable;
        InventTransferUpdReceive    inventTransferUpdReceive;

        inventTransferTable = InventTransferTable::find(_transferId,true);
        if(inventTransferTable.TransferId)
        {
            inventTransferParmTable.initParmDefault();
            inventTransferParmTable.ParmId                  = RunBaseMultiParm::getSysParmId();
            inventTransferParmTable.TransferId              = inventTransferTable.TransferId;
            inventTransferParmTable.UpdateType              = InventTransferUpdateType::Receive;
            inventTransferParmTable.PrintTransferReceipt    = NoYes::No;
            inventTransferParmTable.ReceiveUpdateQty        = InventTransferReceiveUpdateQty::Registered;
            inventTransferParmTable.EditLines               = NoYes::Yes;
            inventTransferParmTable.ExplodeLines            = NoYes::Yes;
            inventTransferParmTable.TransDate               = _postingDate;

            inventTransferUpdReceive = InventTransferUpdReceive::newParmBuffer(inventTransferParmTable);
            inventTransferUpdReceive.run();
        }
}

public void postTransferOrderReceive(InventTransferOrderId _transferId)
{
        InventTransWMS_Register    inventTransWMS_register;
        TmpInventTransWMS           tmpInventTransWMS;
        InventTrans                            inventTranslocal;
        InventDim                              inventDimlocal;
        InventTransIdReceive            inventTransIdReceive;

 while select inventTransferLine
            where inventTransferLine.TransferId == _transferId
        {

            inventTranslocal        = InventTrans::findTransId(InventTransferLine.InventTransIdReceive, true);
            inventDimlocal          = inventTranslocal.inventDim();

            if(arrivalDataTmp.InventBatchId)
            {
                inventDimlocal.inventBatchId    = arrivalDataTmp.inventBatchId;
                inventDimlocal                  = InventDim::findOrCreate(inventDimlocal);
                inventTranslocal.inventDimId    = inventDimlocal.inventDimId;
            }

            inventTransWMS_register             = inventTransWMS_register::newStandard(tmpInventTransWMS);
            tmpInventTransWMS.clear();
            tmpInventTransWMS.initFromInventTrans(inventTranslocal);
            tmpInventTransWMS.ItemId            = inventTranslocal.ItemId;
            tmpInventTransWMS.InventQty         = arrivalDataTmp.qty;
            if(tmpInventTransWMS.validateWrite())
            {
                tmpInventTransWMS.insert();
                inventTransWMS_register.writeTmpInventTransWMS(tmpInventTransWMS
                                                           , inventTranslocal
                                                           , inventDimlocal);
     
                inventTransWMS_register.updateInvent(inventTranslocal);
            }
         
        }