Wednesday, 19 November 2014

Adjustment allowed on SalesTaxForm for classes extending TAX

As , we know we are extending TAX class in order to have our own customization in place and then we use the below peice of code to show the Calculated TAX :

yourExtendedClass = new yourExtendedClass (buffer);
    yourExtendedClass .calc(true,false);
    Tax::showTaxes(menuitemDisplayStr(TaxTmpWorkSalesOrder),yourExtendedClass .CustTax(),buffer);


So now when you open the form , you will notice that Tab Adjustment is not available :




So what we need to do is , we have to override the method :


/// <summary>
/// Returns a Boolean value that indicates whether the current transaction being calculated supports
/// sales tax adjustments.
/// </summary>
/// <returns>
/// true if the current transaction supports sales tax adjustment; otherwise, false.
/// </returns>
/// <remarks>
/// By default, the current transaction does not supports sales tax adjustments.
/// </remarks>
public boolean useSalesTaxAdjustments()
{
    return true;
}



this will make sure that we are having Adjustment tab on same form :





Thursday, 22 May 2014

Retail Server Installation and Configuration

Ax 2012 R3 comes with a new App -Modern POS , As per Technet :

Microsoft Dynamics AX 2012 R3 includes Modern POS, a point-of-sale app for PCs, tablets, and phones. Sales staff can process sales transactions, customer orders, and perform daily operations and inventory management with mobile devices anywhere in the store, as well as at PC-based registers.

M-POS is dependent upon Retail server for communication with StoreDB , While activating the M-POS ,we were getting the error  : MPOS can not be activated , error in communication with Server.


So we found there are several points which we need to take care while installing the Retail server ,
  • Don't Configure the Retail Server using setup , unmark the check box of configuration in setup.
  • Update the rs-setting.xml file , which can be found in location : "C:\Program Files (x86)\Microsoft Dynamics AX\60\Retail Server\Tools"


  • Now configure the Retail Server using Powershell , you can use the below commands :
$Cred = @((New-Object
System.Management.Automation.PSCredential(‘domain\useraccount',(ConvertTo-SecureString
'password' -AsPlainText -Force))))


.\DeployRetailServer.ps1 -SettingsXmlFilePath .\rs-settings-updated.xml -TopologyXmlFilePath .\rs-topology-updated.xml -Credential $Cred -Authentication $Cred

Once you are done with configuration , launch IE with below URL :
http://<yourservername>:<portnumber of Retailserver>/<name of retailserver web site>/v1/$metadata ,

you should be able to see the meta data similar to 









Once this is done , you are good to go for MPOS installation and activation.


Wednesday, 16 April 2014

AX 2012 services not getting started

I was stuck in a issue , where i was not able to start the AX 2012 R3 service , it remains in starting mode after starting services and after some time(20-25  mins) , again come back to stop mode.

Then I tried to start services from command prompt with elevated permissions using the below command :
"net start AOS60$01"

And it works  , within 5-6 mins services started .

Wednesday, 13 November 2013

XML for AIF Inbound Testing


Usually whenever we start to test/debug AIF services , we are not able to proceed further because of input XML non-availability.Below job can be used to get the XML for any Service , just replace with correct service name .

static void GetXml(Args _args)
{

    AxdSalesOrder salesOrder;

    AifEntityKey    key;
    Map             map;
    XMLDocument xmlDoc;
    XML             XML;
    AifPropertyBag bag;
    FileName xmlFileName;
    map = new Map(Types::Integer, Types::Container);

    map.insert(fieldnum(SalesTable, SalesId), ['SO-101256']);
    key = new AifEntityKey();
    key.parmTableId(tablenum(SalesTable));
    key.parmKeyDataMap(map);

    try
    {
        salesOrder = new AxdSalesOrder();
        xmlFileName=@'C:\SO.XML';
        xml = salesOrder.read(key, null, new AifEndPointActionPolicyInfo(), new AifConstraintList(), bag);
        new FileIoPermission(xmlFileName, 'rw').assert();
        xmlDoc = XMLDocument::newXml(XML);
        xmlDoc.save(xmlFileName);
        CodeAccessPermission::revertAssert();

    }
    catch
    {
        throw error('Error in document service outbound');
    }
}

Sunday, 8 September 2013

VS 2010 " The Type Initializer for 'Microsoft.Dynamics.BusinessConnector.Session.SessionCache' threw an exception"

Hi all,
While creating  a new SSRS project in VS2012 for AX 2012 , I got the error :

 " The Type Initializer for 'Microsoft.Dynamics.BusinessConnector.Session.SessionCache' threw an exception"


To resolve this error  ,
  • Open CMD , as administrator
  • Run the following command :
             lodctr /r
It helped me to create new Project .


Wednesday, 19 December 2012

Create and Post Trade agreement using X++ , AX 2012

Hi , below job will create Trade agreement in AX 2012.


static void idbExecutePricPriceDiscJourSvcJob(Args _args)
{
    // PricePrice Vars
    PricePriceDiscJournalService            PriceDiscSvc;
    PricePriceDiscJournal                   PriceDiscJour;
    PricePriceDiscJournal_PriceDiscAdmTrans PriceDiscJourAdmTrans;
    PricePriceDiscJournal_InventDim         PriceDiscJourDim;
   
    // keys return from create process
    AifEntityKeyList                        keys;
 
    PriceDiscSvc = PricePriceDiscJournalService::construct();
    PriceDiscJour = new PricePriceDiscJournal();
    PriceDiscJourAdmTrans = PriceDiscJour.createPriceDiscAdmTrans().addNew();
    PriceDiscJourDim = PriceDiscJourAdmTrans.createInventDim().addNew();

    // Set PriceDiscJourDim
    PriceDiscJourDim.parminventDimId("your dim id");

    // Set PriceDiscJourAdmTrans
   // PriceDiscJourAdmTrans.parmInventDim().add(PriceDiscJourDim);
    PriceDiscJourAdmTrans.parmItemRelation(InventTable::findByProduct( your product).ItemId);
    PriceDiscJourAdmTrans.parmItemCode(TableGroupAll::Table);
    PriceDiscJourAdmTrans.parmAmount(100.00);
    PriceDiscJourAdmTrans.parmFromDate(today());
    PriceDiscJourAdmTrans.parmAccountCode(TableGroupAll::All);
    PriceDiscJourAdmTrans.parmrelation(PriceType::PriceSales);
    PriceDiscJourAdmTrans.parmCurrency("USD");
   

    // Post PriceDiscJour
    keys = PriceDiscSvc.create(PriceDiscJour);
        }
    }
}



How ever , this will only create trade agreement .
If you want to post automatically, then you neeed to modify the "priceDiscAdmCheckPost" method of class


public void priceDiscAdmCheckPost()
{
    PriceDiscAdmCheckPost   priceDiscAdmCheckPost = new PriceDiscAdmCheckPost(false);//To make sure posting is happen

    if (initNoErrorsInInfolog == infolog.num(Exception::Error))
    {
        priceDiscAdmCheckPost.initJournalNum(priceDiscAdmTable.JournalNum);
        priceDiscAdmCheckPost.run();
    }
}


Wednesday, 7 November 2012

Create Pull jobs for newly created Tables in AX retail 2012


How To Create Pull  jobs for newly created Tables in AX retail 2012.

For creating Pull  jobs for newely created tables, we need to follow the following steps :

1 . Create a new table  as below :
 2.Add below fields in table other than your normal fields :

RetailTerminalId
RetailStoreId
RetailStatementId
RetailStaffId
ReplicationCounter

3.Add below two methods in your table :



  public RetailReplicationCounter maxReplicationCounterFromOrigin(RetailConnDistributionLocationId _locationId)
{
    RetailPosBatchTable  posBatchTable;
    RetailTerminalTable terminalTable;

    if (_locationId)
    {
        if (RetailStoreTable::find(_locationId))
        {
            select maxof(ReplicationCounter) from posBatchTable
            where posBatchTable.StoreId == _locationId;
        }
        else
        {
            terminalTable = RetailTerminalTable::find(_locationId);
            if (terminalTable)
            {
                select maxof(ReplicationCounter) from posBatchTable
                where posBatchTable.TerminalId == terminalTable.TerminalId;
            }
        }
    }

    return posBatchTable.ReplicationCounter;
}



public void setMaxReplicationCounter(RetailConnDistributionLocationId _locationId, RetailReplicationCounter _counter)
{
    RetailPosBatchTable  posBatchTable;
    RetailTerminalTable terminalTable;

    if (_locationId)
    {
        if (RetailStoreTable::find(_locationId))
        {
            ttsbegin;

            while select forupdate posBatchTable
            where posBatchTable.StoreId == _locationId
            && posBatchTable.ReplicationCounter >= _counter
            {
                posBatchTable.ReplicationCounter = _counter;
                posBatchTable.update();
            }

            ttscommit;
        }
        else
        {
            terminalTable = RetailTerminalTable::find(_locationId);
            if (terminalTable)
            {
                ttsbegin;

                while select forupdate posBatchTable
                where posBatchTable.TerminalId == terminalTable.TerminalId
                && posBatchTable.ReplicationCounter >= _counter
                {
                    posBatchTable.ReplicationCounter = _counter;
                    posBatchTable.update();
                }

                ttscommit;
            }
        }
    }
}



Replace the RetailPosBatchTable   with your table name.

4. Go to Retail ->Setup ->Retail Scheduler -> Distribution Location :
Select your distribution Location and click on Location table , select the table for which you want to pull data,click on Location fields , now you can add fields either Manually or you can use function button provided.
[Make sure to select only those fields which are available in corresponding AX table,else AX will throw error , filed in not available in table]
5. Now go to Retail ->Setup ->Retail Scheduler ->Scheduler subjob
Create a new subjob :

And set the important fields as below :

6.Click on Create TempDBStaging table , which will make a temporary table TableX .
TableX is being used by AX to hold staging data.
7. Now either you can create a new P-job or you can add this sub job in existing P-job.

Run the P-job and data will be pulled to AX from Store
[Off-course you should have retail settings in Place :) ]









Buf2Buf() vs Data() method

Hi all,
while creating a duplicate/replica of a record , generally we use table.data() method , in place of passing each  field one by one. The only issue with data() method is it copies the system fields as well , and hence if we are inserting data across companies , we can not use data() method.

So what should be solution for this, AX also provides one more generic method Buf2Buf(SourceRecord,TargetRecord) , the only difference between Buf2Buf() and data() method is that Buf2Buf() does not copy system fields.

Hence for intercompany insert of data , we should use Buf2Buf() method with changeCompany() method().


thanks,

Wednesday, 31 October 2012

Unit of Work

Hi all.

Unit of Work is a new framework , which is being introduced in AX 2012.
Now let us explore what is need of having this framework  :

Suppose we do have Two tables , TableHeader and TableLine.
Now we want to insert bulk data in these two tables , TableLine is linked with TableHeader by RecID.

So first we need to insert the data in TableHeader and then pass the recid of this table to Tableline and insert the record. So there are 2 major issue is : We need to hold recId of Parent table and pass to Tableline and we have to hit database with each insert.

Now Unit of Work framework come into picture and helps us , we dont have to hold the recid of parent table and also we can insert all data in a single trip . How ... Let us Implement this :

1.Create 2 table SKU_Table and SKU_Line.
2.SKU_Line is related to SKU_Table by RecId.
3.Go to relation of table and make sure property CreateNavigationPropertyMethods = true
by making this property true , system will add appropriate methods to table SKU_Line
4 . Now we are ready to go


public void Insert()
{
    SKU_Table                       SKU_Table;
    SKU_Line                        SKU_Line;      
    UnitofWork                      UnitofWork;
 
    UnitofWork                      =  new UnitofWork();
    while select aaaaa
    {
     //insert data in parent table
        SKU_Table.clear();   
        SKU_Table.somefield                 = cccc;      
        UnitofWork.insertonSaveChanges(SKU_Table);
   
        while select bbbb
        {
               //insert data in child table
            SKU_Line.clear();
            SKU_Line.somefield                 = ddddd;
            SKU_Line.SKU_Table(SKU_Table);
            UnitofWork.insertonSaveChanges(SKU_Line);
        }      
    }
//Now insert data in a single trip
    UnitofWork.saveChanges();
}

Thursday, 18 October 2012

Create Product Variant using X++


How to create a product variant with Dimensions provided  

ecoResDistinctProductVariant        ecoResDistinctProductVariant;
    EcoResProductVariantDimensionValue  EcoResProductVariantDimensionValue;
    RefRecId                                   ecoResDistinctProductVariantRecId;
    EcoResProductReleaseManagerBase     releaseManager;
    container productDimensions;


//Create a container to hold dimension values
productDimensions = EcoResProductVariantDimValue::getDimensionValuesContainer(ConfigurationName,
                                                                                        Size,
                                                                                        ColorId,
                                                                                        InventStyleId);
//Create Product search name

ecoResDistinctProductVariant.DisplayProductNumber = EcoResProductNumberBuilderVariant::buildFromProductNumberAndDimensions(
                                                                   EcoResProduct::find(InventTable.Product).productNumber(),
                                                                    productDimensions);

//Create Product variant with Product and dimensions provided

    ecoResDistinctProductVariantRecId = EcoResProductVariantManager::createProductVariant(InventTable.Product,ecoResDistinctProductVariant.DisplayProductNumber,productDimensions);

//Find newly created Product Variant
    ecoResDistinctProductVariant = ecoResDistinctProductVariant::find(ecoResDistinctProductVariantRecId);
//Now release the Product variant
    releaseManager = EcoResProductReleaseManagerBase::newFromProduct(ecoResDistinctProductVariant);
    releaseManager.release();



Hope this will help u guys :)



Wednesday, 10 October 2012

create Product master by using X++ , AX 2012

Following code to create Product master by using X++
static void ProductCreate(Args _args)
{

EcoResProductService erProdSvc;
EcoResEcoResProduct EcoResProd;
EcoResEcoResProduct_Product_Master ProdMast;
EcoResEcoResProduct_Translation Translation;
EcoResEcoResProduct_Identifier Identifier;
EcoResEcoResProduct_ProductDimGroup ProdDimGroup;

//Initialize the service object
erProdSvc = EcoResProductService::construct();
EcoResProd = new EcoResEcoResProduct();
ProdMast = new EcoResEcoResProduct_Product_Master();

//ProdDimGroup = new EcoResEcoResProduct_ProductDimGroup();
//Newly created and initialize prodMast
ProdMast.parmDisplayProductNumber("IDB-PM002");
ProdMast.parmProductType(EcoResProductType::Item);
ProdMast.parmSearchName("IDB Product Master 1");


//Create a new translation object:
Translation = ProdMast.createTranslation().addNew();

Translation.parmDescription("IDB product Master");
Translation.parmLanguageId("en-us");
Translation.parmName("IDB Product Master 1");
Identifier = ProdMast.createIdentifier().addNew();

Identifier.parmProductNumber("IDB-PM002");
ProdDimGroup = ProdMast.createProductDimGroup().addNew();
ProdDimGroup.parmProduct("IDB-PM001");
ProdDimGroup.parmProductDimensionGroup("Col");


ProdMast.parmVariantConfigurationTechnology(EcoResVariantConfigurationTechnologyType::PredefinedVariants);
EcoResProd.createProduct().add(ProdMast);

erProdSvc.create(EcoResProd);

Lookup for RealEdit Control in Ax2012

Lookup for RealEdit Control in Ax2012

we cant build the lookup for RealEdit control by using SysLookup functionality for that we have to customize the SysTableLookup class method performFormLookup()
Add the case for switch for handling the FormRealControl.
FormRealControl     callingRealControl;


 case classNum(FormRealControl):
            callingRealControl = callingControl;
            callingRealControl.performFormLookup(this.formRun());
            break;

Tuesday, 4 September 2012

Function DimensionValidation::validateByTree has been incorrectly called.

While Creating General Journal using X++ , we faced this error:
Function DimensionValidation::validateByTree has been incorrectly called.

First let us go through , why we are getting this :

This error is coming because we are passing the account and offset account in wrong manner to LedgerJournalTrans . The field OffsetLedgerDimension and LedgerDimension are of type :
DimensionDynamicAccount , so before passigng the Account to these field , we need to convert the account to correct type . How to do it:

For non ledger account(Bank, customer ..............) , we do have the API :
DimensionStorage::getDynamicAccount(A/cNo ,LedgerJournalACType::Bank);

we need to pass this AS :

LedgerJournalTrans .LedgerDimension  = DimensionStorage::getDynamicAccount(Hedging_table.AccountID,LedgerJournalACType::Bank);

There you go.......

But what to do with Ledger Account , you still can not pass these account directly as well .

Well there is one more API which can help us :

LedgerJournalTrans .getLedgerDimensionForLedgerType(Ledger A/c,jourTrans.Company);
LedgerJournalTrans .LedgerDimension  = 
LedgerJournalTrans .getLedgerDimensionForLedgerType(Ledger A/c,jourTrans.Company);



Please put your comment ,if you find it helpful or looking for some more info......


Thanks,