Thursday, 26 January 2017

Set Delivery Address on Sales order through code X++ AX 2012

In this post we will learn how to set delivery address / over rider the default customer delivery address on a Sales order.

This method will return the  LogisticsPostalAddress recId, which we will assign to parm method of AXsalesTable class..
axsalesTable.parmDeliveryPostalAddress(this.setDeliveryAddress(_tmpSalesheaders));
private RecId setDeliveryAddress(TmpSalesTable           _tmpSalesheaders)
{
    DirPartyPostalAddressView   addressView, ret;
    DirPartyRecId                        partyRecId;
    DirParty                                 dirParty;
    LogisticsPostalAddress          postalAddress;
    ;
    //Create new Name
    partyRecId = DirPartyTable::createNew(DirPartyType::None, _tmpSalesheaders.DeliveryName).RecId;
   
    addressView.CountryRegionId = _tmpSalesheaders.DeliveryCountryRegionId;//"AUS";
    addressView.State = _tmpSalesheaders.DeliveryState;//"VIC";
    addressView.ZipCode = _tmpSalesheaders.DeliveryZipCode;//"3000";
    addressView.Street  = _tmpSalesheaders.DeliveryStreet;//"238 Flinders St";
    addressView.Party = partyRecId;
   
    //Handel errors for addresses
    if (!LogisticsAddressCountryRegion::exist(addressView.CountryRegionId))
        throw error(strFmt("@SYS9347",addressView.CountryRegionId));
    if (addressView.County && !LogisticsAddressCounty::exist(addressView.CountryRegionId, addressView.State, addressView.County))
        throw error(strFmt("@SYS72719",addressView.County));
    if (addressView.State && !LogisticsAddressState::exist(addressView.CountryRegionId, addressView.State))
        throw error(strFmt("@SYS72786",addressView.State));
    if (!LogisticsAddressZipCode::exist(addressView.ZipCode))
        throw error(strFmt("@SYS24626",addressView.ZipCode));

    addressView.Party  = partyRecId;
    if( addressView.Street || addressView.ZipCode || addressView.City || addressView.State || addressView.CountryRegionId)
    {
        DirParty = DirParty::constructFromPartyRecId(addressView.Party );
        ret = DirParty.createOrUpdatePostalAddress(addressView);
        postalAddress = LogisticsPostalAddress::findByLocation(ret.Location);
    }
    return postalAddress.RecId;
}

Monday, 23 January 2017

X++ code to copy Ledger from company (A) to Company (B)


public void copyLedgerSetup()
{
    Ledger   fromLedger = Ledger::findByLegalEntity(CompanyInfo::findDataArea(fromCompany).RecId);
    Ledger   toLedger   = Ledger::findByLegalEntity(CompanyInfo::findDataArea(toCompany).RecId);
    LedgerStructure fromLedgerStructure, toLedgerStructure;
    LedgerGainLossAccount fromLedgerGainLossAccount, toLedgerGainLossAccount;

    if (fromLedger && !toLedger)
    {
        toLedger.data(fromLedger);
        toLedger.PrimaryForLegalEntity = CompanyInfo::findDataArea(toCompany).RecId;
        toLedger.Name = toCompany;
        toLedger.doInsert();

        while select fromLedgerStructure
            where fromLedgerStructure.Ledger == fromLedger.RecId
        {
            toLedgerStructure.data(fromLedgerStructure);
            toLedgerStructure.Ledger = toLedger.RecId;
            toLedgerStructure.insert();
        }

        while select fromLedgerGainLossAccount
            where fromLedgerGainLossAccount.Ledger == fromLedger.RecId
        {
            toLedgerGainLossAccount.data(fromLedgerGainLossAccount);
            toLedgerGainLossAccount.Ledger = toLedger.RecId;
            toLedgerGainLossAccount.insert();
        }
    }
}

X++ code to copy Number sequence from one company(A) to other (B)

public void copyNumberSequence()
{
    NumberSequenceScope         fromNumberSequenceScope, toNumberSequenceScope;
    NumberSequenceTable         fromNumberSequenceTable, toNumberSequenceTable;
    NumberSequenceReference     fromNumberSequenceReference, toNumberSequenceReference;
    //mk
    Map                         mapKeyValue;
    MapEnumerator               enumer;
    MapIterator                 mapIter;
    int64                       iCurrentKey;
    int64                       sCurrentValue;

    while select fromNumberSequenceScope
        where (fromNumberSequenceScope.LegalEntity == CompanyInfo::findDataArea(fromCompany).RecId ||
              fromNumberSequenceScope.DataArea == fromCompany)
    {
        try
        {
            ttsBegin;
            toNumberSequenceScope = NumberSequenceScope::findByNaturalKey(
                                        toCompany,
                                        CompanyInfo::findDataArea(toCompany).RecId,
                                        fromNumberSequenceScope.OperatingUnit,
                                        fromNumberSequenceScope.FiscalCalendarPeriod,
                                        fromNumberSequenceScope.OperatingUnitType);

            if ((fromNumberSequenceScope.LegalEntity || fromNumberSequenceScope.DataArea) && !toNumberSequenceScope)
            {
                toNumberSequenceScope.clear();
                toNumberSequenceScope.data(fromNumberSequenceScope);
                if (toNumberSequenceScope.LegalEntity)
                {
                    toNumberSequenceScope.LegalEntity = CompanyInfo::findDataArea(toCompany).RecId;
                }
                if (toNumberSequenceScope.DataArea)
                {
                    toNumberSequenceScope.DataArea = toCompany;
                }
                toNumberSequenceScope.insert();
                mapKeyValue = null;
                mapKeyValue = new Map(Types::Int64,Types::Int64); //mk

                while select fromNumberSequenceTable
                    where fromNumberSequenceTable.NumberSequenceScope == fromNumberSequenceScope.RecId
                {
                    if (!NumberSequenceTable::findByNaturalKey(fromNumberSequenceTable.NumberSequence, toNumberSequenceScope.RecId))
                    {
                        toNumberSequenceTable.clear();
                        toNumberSequenceTable.data(fromNumberSequenceTable);
                        toNumberSequenceTable.NumberSequenceScope = toNumberSequenceScope.RecId;
                        toNumberSequenceTable.NextRec = toNumberSequenceTable.Lowest;
                        toNumberSequenceTable.insert();
                        if (!mapKeyValue.exists(fromNumberSequenceTable.RecId))
                        {
                            mapKeyValue.insert(fromNumberSequenceTable.RecId,toNumberSequenceTable.RecId); //mk
                        }
                    }
                }
                enumer = null;
                while select fromNumberSequenceReference
                    where fromNumberSequenceReference.NumberSequenceScope == fromNumberSequenceScope.RecId
                {
                    if (!NumberSequenceReference::findNaturalKey(toNumberSequenceScope.RecId, fromNumberSequenceReference.NumberSequenceDatatype))
                    {
                        toNumberSequenceReference.clear();
                        toNumberSequenceReference.data(fromNumberSequenceReference);
                        toNumberSequenceReference.NumberSequenceScope = toNumberSequenceScope.RecId;
                        enumer = mapKeyValue.getEnumerator();
                        iCurrentKey = 0;
                        sCurrentValue = 0;
                        while (enumer.moveNext())
                        {
                            iCurrentKey = enumer.currentKey();
                            if (fromNumberSequenceReference.NumberSequenceId == iCurrentKey)
                            {
                                sCurrentValue = enumer.currentValue();
                                //info(strFmt("Key: %1 and Value %2",iCurrentKey,sCurrentValue));
                                break;
                            }

                        }
                        if (sCurrentValue != 0)
                        {
                            toNumberSequenceReference.NumberSequenceId  = sCurrentValue; //mk
                        }
                        toNumberSequenceReference.insert();
                    }
                }
            }
            ttsCommit;
        }
        catch
        {
            warning("Error copying number sequence");
        }

    }

}

Sunday, 22 January 2017

X++ code to set Default Order Settings for an Item

static void ASM_UpdateDefaultOrderSettings(Args _args)
{
    InventTable inventTable;
    InventItemInventSetup inventItemInventSetup;
    InventItemPurchSetup inventItemPurchSetup;
    InventItemSalesSetup inventItemSalesSetup;
    InventDim inventDim;
    DataArea                dataArea;
    InventDimid             inventDimid;
    InventSite              lInventSite;

   ;
 
   inventTable = InventTable::find("S403010", true);
     While select dataArea where !dataArea.isVirtual && ( dataArea.id == "xsd")
     {
        changeCompany(dataArea.Id)
        {
            inventDimid = "";
            inventTable = null;
            lInventSite = null;
            inventDim = null;
            select firstonly lInventSite where lInventSite.dataAreaId == dataArea.id;
            if (lInventSite.RecId)
            {
               while select * from inventTable
               {
                   ttsBegin;
                   //select firstonly lInventSite
                   inventDim.initValue();
                   inventDim.InventSiteId = lInventSite.SiteId;//"AUS";
                   inventDim.inventLocationId = "standard";
                   inventDim = InventDim::findOrCreate(inventDim);

                   //Site specific setup
                   /*
                   inventItemInventSetup.initValue();
                   inventItemInventSetup.InventDimId = inventDim.inventDimId;
                   inventItemInventSetup.ItemId = inventTable.ItemId;
                   inventItemInventSetup.insert();

                   inventItemPurchSetup.initValue();
                   inventItemPurchSetup.InventDimId = inventDim.inventDimId;
                   inventItemPurchSetup.ItemId = inventTable.ItemId;
                   inventItemPurchSetup.insert();

                   inventItemSalesSetup.initValue();
                   inventItemSalesSetup.InventDimId = inventDim.inventDimId;
                   inventItemSalesSetup.ItemId = inventTable.ItemId;
                   inventItemSalesSetup.insert(); */

                   //Default order settings
                   inventItemInventSetup= inventItemInventSetup::findDefault(inventTable.itemId, true);
                   if(inventItemInventSetup.RecId)
                   {
                        inventItemInventSetup.InventDimIdDefault = inventDim.inventDimId;
                        inventItemInventSetup.update();
                   }
                   else
                   {
                       inventItemInventSetup.initValue();
                       inventItemInventSetup.InventDimId = inventDim.inventDimId;
                       inventItemInventSetup.ItemId = inventTable.ItemId;
                       inventItemInventSetup.insert();
                     
                      /*  inventItemInventSetup= inventItemInventSetup::findDefault(inventTable.itemId, true);
                        inventItemInventSetup.InventDimIdDefault = inventDim.inventDimId;
                        inventItemInventSetup.update(); */
                     
                   }
                   inventItemPurchSetup = inventItemPurchSetup::findDefault(inventTable.itemId, true);
                   if (inventItemPurchSetup.RecId)
                   {
                       inventItemPurchSetup.InventDimIdDefault = inventDim.inventDimId;
                       inventItemPurchSetup.update();
                   }
                   else
                   {
                       inventItemPurchSetup.initValue();
                       inventItemPurchSetup.InventDimId = inventDim.inventDimId;
                       inventItemPurchSetup.ItemId = inventTable.ItemId;
                       inventItemPurchSetup.insert();
                     
                       /* inventItemPurchSetup = inventItemPurchSetup::findDefault(inventTable.itemId, true);
                        inventItemPurchSetup.InventDimIdDefault = inventDim.inventDimId;
                        inventItemPurchSetup.update(); */
                     
                 
                   }
                   inventItemSalesSetup= inventItemSalesSetup::findDefault(inventTable.itemId, true);
                   if(inventItemSalesSetup.RecId)
                   {
                        inventItemSalesSetup.InventDimIdDefault = inventDim.inventDimId;
                        inventItemSalesSetup.update();
                   }
                   else
                   {
                       inventItemSalesSetup.initValue();
                       inventItemSalesSetup.InventDimId = inventDim.inventDimId;
                       inventItemSalesSetup.ItemId = inventTable.ItemId;
                       inventItemSalesSetup.insert();
                     
                      /*  inventItemSalesSetup= inventItemSalesSetup::findDefault(inventTable.itemId, true);
                        inventItemSalesSetup.InventDimIdDefault = inventDim.inventDimId;
                        inventItemSalesSetup.update(); */
                 
                   }
                   ttsCommit;
               }
            }
        }
     }

}

Tuesday, 17 January 2017

Stock on Hand of a Item using X++ code

Here we will see how to find the Stock on hand of a Item using the X++ code.

Key things to know:

1. The stock on hand will vary depending on Inventory dimensions.
2. The standard Class "InventOnhand" will have all the methods to find out the different formats of stock.
3. Job:

static void MK_stockOnHand(Args _args)
{
    InventOnhand        inventOnHand;
    InventDim           inventDim;
    InventDimParm       inventDimParm;
    InventQty           stockOnHand;
    ItemId              itemid = "00001aTestInter";
   
    inventDim.InventSiteId = "VIC"; // site
    inventDim.InventLocationId = "SOM"; // warehouse
   // inventDim.InventLocationId = "RES";
   
    inventDimParm.initFromInventDim(inventDim);
   
    inventOnHand = InventOnhand::newParameters(itemid,inventDim,inventDimParm);
   
    stockOnHand = inventOnHand.availPhysical();
   
    info (strFmt(" Stock on Hand for Item %1 is %2",itemid,stockOnHand));
   
}

Happy learning...Mallik

Sunday, 15 January 2017

Unpick / unreserve a sales order line X++

Unreserve / Unpick a sales order line X++ 


In this article we will see how to unreserved or unpick the piked sales order line. In standard AX 2012 we can do it manually by using the 'Update line" and pick functionality.

For doing it automatically, I am going to add a button(Action Menu Item) on Sales order Header, using this button we will call the class to do the job. 

below is the code which dose the job.. 

One good thing about this job is, it also show the relation on InventTrans and SalesLine in AX 2012. As you all know that, there is no more InventTransID in InventTrans Table, we have to pick it from InventTransOrigin.

///
/// Contains the code that does the actual job of the class ---Mallik.
///
void  run()
{
    InventTrans                 inventTransLocal;
    InventTransOriginSalesLine  inventTransOriginSalesLine;
    InventTransOrigin           inventTransOrigin;
    SalesLine                   salesLine;
    InventTransWMS_Pick         inventTransWMS_Pick;
    TmpInventTransWMS           tmpInventTransWMS;
    Query                       baseQueryInventTrans;
    QueryBuildDataSource        qbdsInventTrans;

    baseQueryInventTrans =  new Query();
    qbdsInventTrans = baseQueryInventTrans.addDataSource(tableNum(InventTrans));
    baseQueryInventTrans.dataSourceTable(tableNum(InventTrans));
    qbdsInventTrans.clearDynalinks();
    qbdsInventTrans.clearRanges();
    qbdsInventTrans.addRange(fieldNum(InventTrans,StatusReceipt)).value(SysQuery::value(StatusReceipt::None));
    qbdsInventTrans.addRange(fieldNum(InventTrans,StatusIssue)).value(SysQuery::range(StatusIssue::Picked,StatusIssue::OnOrder));

    inventTransWMS_Pick = InventTransWMS_Pick::newStandard(tmpInventTransWMS,baseQueryInventTrans);
    while select forUpdate salesLine where salesLine.SalesId == salesTable.SalesId
        && salesLine.ILSLocked == true
    {
       select inventTransLocal
        where  inventTransLocal.ItemId                   == salesline.ItemId
            && inventTransLocal.StatusIssue              == StatusIssue::Picked
        exists join inventTransOrigin
        where   inventTransOrigin.RecId                  == inventTransLocal.InventTransOrigin
        exists join inventTransOriginSalesLine
            where inventTransOriginSalesLine.SalesLineInventTransId      == salesline.InventTransId;
        if (inventTransLocal.RecId)
        {
           
            inventTransWMS_Pick.createFromInventTrans(inventTransLocal);
        }
    }
    inventTransWMS_Pick.updateInvent();

}

Happy learning.. Mallik

Wednesday, 11 January 2017

Manual invoice inter-company purchase orders

Adding to the previous posts regarding the setup you require, ensure you have the below setup on the customer master card (which you probably have already since orders are being created in legal entities)
if your process dictates processing the respective documents (PO receipt and invoice) from the sales order you need to perform the folloing:
1. Once you post the packing slip from the sales order--> open the packing slip journal--> post the intercompany packing slip 
Result: PO receipt posted automatically
2. Post the invoice from the sales order and then go to invoice journal-->Intercompany invoice posting 
Result: PO invoice posted
Hope this helps. 

How to Disable “Advanced Filter or Sort” and Enforce Custom Filters on Any D365FO Form

 In Dynamics 365 Finance and Operations, users can apply filters through the “Advanced filter or sort” feature found under the Options tab...