Friday, May 24, 2019

Timezone and TZId field in Dynamics

Timezone descriptionTimeZoneTZId
(GMT-12:00) International Date Line West2424001
(GMT-11:00) Midway Island, Samoa6565001
(GMT-10:00) Hawaii3939001
(GMT-09:00) Alaska22001
(GMT-08:00) Pacific Time (US & Canada)5858001
(GMT-08:00) Tijuana, Baja California5959001
(GMT-07:00) Arizona7575001
(GMT-07:00) Mountain Time (US & Canada)4747001
(GMT-07:00) Chihuahua, La Paz, Mazatlan4848001
(GMT-06:00) Central America1515001
(GMT-06:00) Central Time (US & Canada)2121001
(GMT-06:00) Guadalajara, Mexico City, Monterrey2222001
(GMT-06:00) Saskatchewan1111001
(GMT-05:00) Bogota, Lima, Quito, Rio Branco6363001
(GMT-05:00) Eastern Time (US & Canada)2929001
(GMT-05:00) Indiana (East)7474001
(GMT-04:00) Atlantic Time (Canada)66001
(GMT-04:00) La Paz6464001
(GMT-04:00) Manaus1717001
(GMT-04:00) Santiago5757001
(GMT-04:30) Caracas8585001
(GMT-03:30) Newfoundland5454001
(GMT-03:00) Brasilia2828001
(GMT-03:00) Buenos Aires, Georgetown6262001
(GMT-03:00) Greenland3636001
(GMT-03:00) Montevideo8383001
(GMT-02:00) Mid-Atlantic4545001
(GMT-01:00) Azores1010001
(GMT-01:00) Cape Verde Is.1212001
(GMT) Casablanca, Monrovia, Reykjavik3737001
(GMT) Greenwich Mean Time : Dublin, Edinburgh, Lisbon, Londo3535001
(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna7979001
(GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Pragu1818001
(GMT+01:00) Brussels, Copenhagen, Madrid, Paris6060001
(GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb1919001
(GMT+01:00) West Central Africa7878001
(GMT+02:00) Amman4343001
(GMT+02:00) Athens, Bucharest, Istanbul3838001
(GMT+02:00) Beirut4646001
(GMT+02:00) Minsk2727001
(GMT+02:00) Cairo3030001
(GMT+02:00) Harare, Pretoria6868001
(GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius3333001
(GMT+02:00) Jerusalem4242001
(GMT+02:00) Windhoek5151001
(GMT+03:00) Baghdad55001
(GMT+03:00) Kuwait, Riyadh33001
(GMT+03:00) Moscow, St. Petersburg, Volgograd6161001
(GMT+03:00) Nairobi2525001
(GMT+03:00) Tbilisi3434001
(GMT+03:30) Tehran4141001
(GMT+04:00) Abu Dhabi, Muscat44001
(GMT+04:00) Baku99001
(GMT+04:00) Caucasus Standard Time8484001
(GMT+04:00) Yerevan1313001
(GMT+04:30) Kabul11001
(GMT+05:00) Ekaterinburg3131001
(GMT+05:00) Islamabad, Karachi, Tashkent8080001
(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi4040001
(GMT+05:30) Sri Jayawardenepura6969001
(GMT+05:45) Kathmandu5252001
(GMT+06:00) Almaty, Novosibirsk5050001
(GMT+06:00) Astana, Dhaka1616001
(GMT+06:30) Yangon (Rangoon)4949001
(GMT+07:00) Bangkok, Hanoi, Jakarta6666001
(GMT+07:00) Krasnoyarsk5656001
(GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi2323001
(GMT+08:00) Irkutsk, Ulaan Bataar5555001
(GMT+08:00) Kuala Lumpur, Singapore6767001
(GMT+08:00) Perth7777001
(GMT+08:00) Taipei7070001
(GMT+09:00) Osaka, Sapporo, Tokyo7272001
(GMT+09:00) Seoul4444001
(GMT+09:00) Yakutsk8282001
(GMT+09:30) Adelaide1414001
(GMT+09:30) Darwin77001
(GMT+10:00) Brisbane2626001
(GMT+10:00) Canberra, Melbourne, Sydney88001
(GMT+10:00) Guam, Port Moresby8181001
(GMT+10:00) Hobart7171001
(GMT+10:00) Vladivostok7676001
(GMT+11:00) Magadan, Solomon Is., New Caledonia2020001
(GMT+12:00) Auckland, Wellington5353001
(GMT+12:00) Fiji, Kamchatka, Marshall Is.3232001
(GMT+13:00) Nuku’alofa7373001

Tuesday, May 21, 2019

Multiselect lookup form control on D365 FO



//Event Handler code for Onlookup event

//Form Control with DS associate

FormControlCancelableSuperEventArgs event = e as FormControlCancelableSuperEventArgs;

        FormDataSource fds;
        FormControl fc = sender as FormControl;
        fds = fc.formRun().Datasource(tableStr(<DS Name>));

        FormRun fr = fc.formRun();

        FormStringControl   DummyrecIds = fr.design().controlName(formControlStr(<Form Name>, DummyRecIds)) as FormStringControl; //Create control on form and make it visible NO and Auto declaration yes. Its for dummy purpose
        FormStringControl   DummyStrIds = fr.design().controlName(formControlStr(<Form Name>, DummyStrIds)) as FormStringControl; //Create control on form and make it visible NO and Auto declaration yes.Its for dummy purpose

        TableName    tableBuffer= fds.cursor();

        Query lookupQuery = new Query();

        var selectField = [tableNum(<Table Name>), fieldNum(<Table Name>, <Field Name>)];

        QueryBuildDataSource qbds= lookupQuery.addDataSource(tableNum(<Table Name>));
        qbds.addSelectionField(fieldNum(<Table Name>, Name));

        San_SyslookupMultiSelectGrid  lookupLocation;
        lookupLocation = new San_SyslookupMultiSelectGrid();
     
        lookupLocation = San_SyslookupMultiSelectGrid::lookup(lookupQuery,
                                                                selectField,
                                                                sender,
                                                                DummyrecIds,
                                                                DummyStrIds,  <Table Name>.<FieldName>);

         
        <Table Name>.<FieldName> = lookupLocation.getSelectedStringsJoined();

        event.CancelSuperCall(); //Cancel default lookup call on string control

//Event handler code end


//Lookup class
class San_SyslookupMultiSelectGrid extends SysLookupMultiSelectGrid
{
    #SysOperation
    private const str CollectionValueSeparator = #CollectionValueSeparator;

    Public static San_SyslookupMultiSelectGrid lookup(Query _query, container _selectField, FormStringControl _callingCtrl, FormStringControl _recIdsControl, FormStringControl _strIdsControl, str _currentStrIds, queryRun _queryRun = null)
    {
        _strIdsControl.text(_currentStrIds);
        _recIdsControl.text('');

        var lookupMS = new San_SyslookupMultiSelectGrid();

        lookupMS.parmCallingControl(_callingCtrl);
        lookupMS.parmCallingControlId(_recIdsControl);
        lookupMS.parmCallingControlStr(_strIdsControl);
        lookupMS.parmQuery(_query);
        lookupMS.parmQueryRun(_queryRun);
        lookupMS.parmSelectField(_selectField);
        lookupMS.run();

        return lookupMS;
    }

      Public container getSelectedStrings()
    {
        return selectedStr;
    }


    Public SysLookupMultiSelectValues getSelectedStringsJoined()
    {
        return SysOperationHelper::convertMultiSelectedValueString(selectedStr);
    }

      Public static boolean stringListContainsItem(str _stringList, str _possibleItem)
    {
        container items = str2con(_stringList, CollectionValueSeparator);
        for (int i = 1 ; i <= conLen(items) ; i++)
        {
            str item = conPeek(items, i);
            if (item == _possibleItem)
            {
                return true;
            }
        }
        return false;
    }

}


//Multi select lookup with Form Control without DS
FormRun fr = sender.formRun() as FormRun;
        Query                   query = new Query();
        QueryBuildDataSource    qbd;
        TableId     multiSelectTableNum = tableNum(ForecastModel);
        container   selectedFields      = [multiSelectTableNum, fieldName2id(multiSelectTableNum, fieldStr(ForecastModel, ModelId))];
      
        qbd = query.addDataSource(tableNum(ForecastModel));
        qbd.addSelectionField(fieldNum(ForecastModel, ModelId));
        qbd.fields().dynamic(NoYes::No);
        qbd.fields().clearFieldList();
        qbd.fields().addField(fieldNum(ForecastModel, ModelId));
        qbd.fields().addField(fieldNum(ForecastModel, Txt));
      
        SysLookupMultiSelectCtrl::constructWithQuery(fr, sender, query, false, selectedFields);

Tuesday, May 14, 2019

Save file to AZURE blob storage account in D365 FO

using BlobStorage = Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.Dynamics.AX.Framework.FileManagement;
using Microsoft.Azure;
using fileShareStorage = Microsoft.WindowsAzure.Storage.File;
/// <summary>
/// Class Saving File to Azure Storage contianer Blob or file share folder
/// </summary>
class SONFileToAzureStorage
{
    NoYes               IsSuccess;
    public Str          accountName;
    public Str          accountKey;

    /// <summary>
    /// Get /set Operation completion status
    /// </summary>
    /// <param name = "_IsSuccess">setting Operational current status</param>
    /// <returns>operational Status</returns>
    public NoYes parmOperationSuccess(NoYes _IsSuccess = IsSuccess)
    {
        IsSuccess = _IsSuccess;
        return IsSuccess;
    }

    /// <summary>
    /// Get /set Operation completion status
    /// </summary>
    public void initialize()
    {
        accountName = "";// TODO - Need to map
        accountKey = "";// TODO - Need to Map
    }

    /// <summary>
    /// Method will execute code to save file to Azure storage folders based current system setup
    /// </summary>
    /// <param name = "_fileName">Getting file name to process in to Azure storage</param>
    /// <param name = "_fileContent">Get total fiel count to process</param>
    /// <param name = "_containerName">Get specific azure container to process
    /// <param name = "_fileFormat">Get specific file format to process
    /// </param>
    public void saveFileInAzureBlobStorage(str _fileName,str _fileContent,Str  _containerName, Str  _fileFormat)
    {
        System.Exception            ex;
     
        try
        {           
            TextStreamIo            file = TextStreamIo::constructForWrite();
            container               mainContainer; 
            mainContainer = conNull();
            mainContainer = conIns(mainContainer,1,_fileContent);
     
            file.writeExp(mainContainer);

            str filetemppath = File::SendFileToTempStore(file.getStream(),_fileName);
            System.IO.Stream fileStream = File::UseFileFromURL(filetemppath);

            var storageCredentials = new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(accountName, accountKey);
            BlobStorage.CloudStorageAccount storageAccount = new Microsoft.WindowsAzure.Storage.CloudStorageAccount(storageCredentials, true);
            if (storageAccount)
            {
                fileShareStorage.CloudFileClient fileClient = storageAccount.CreateCloudFileClient();
                fileShareStorage.CloudFileShare share = fileClient.GetShareReference(_containerName);

                //Create container in blob if not exists
                // var blobcli = storageAccount.CreateCloudBlobClient();
                //Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer cont = blobcli.GetContainerReference("from-d365")

                if (!share.Exists(null, null))
                {
                    throw error(strFmt("@SSY:AzureFileShareIsMissing",_containerName));
                }

                fileShareStorage.CloudFileDirectory cloudDir = share.GetRootDirectoryReference();
                fileShareStorage.CloudFile fileToSave = cloudDir.GetFileReference(_fileName);

                try
                {
                    fileToSave.UploadFromStreamAsync(fileStream,null,null,null);
                    info(strFmt("@SSY:FilePlacedInAzure",_fileName));
                    this.parmOperationSuccess(NoYes::Yes);
                }
                catch(Exception::Error)
                {
                    ex = CLRInterop::getLastException();
                    error(ex.ToString());
                    //info("@SSY:ErrorWhileUploadingFileInAzureBlobStoarge");
                }
                Catch(Exception::Warning)
                {
                    ex = CLRInterop::getLastException();
                    warning(ex.ToString());
                }
                Catch(Exception::CLRError)
                {
                    ex = CLRInterop::getLastException();
                    checkFailed(ex.ToString());
                }
         
            }
            else
            {
                info("@SSY:ErrorInAzureStorageAccount");
            }
        }
        catch(Exception::Error)
        {
            ex = CLRInterop::getLastException();
            error(ex.ToString());
            //info("@SSY:ErrorWhileUploadingFileInAzureBlobStoarge");
        }
        Catch(Exception::Warning)
        {
            ex = CLRInterop::getLastException();
            warning(ex.ToString());
        }
        Catch(Exception::CLRError)
        {
            ex = CLRInterop::getLastException();
            checkFailed(ex.ToString());
        }

    }

    public static SONFileToAzureStorage construct()
    {
        return new SONFileToAzureStorage();
    }

}


//Test
Static void Man(Args  _args)
{
//TODO. Map Account Name and Account key
SONFileToAzureStorage azureStorage;
azureStorage = new SONFileToAzureStorage();
azureStorage.Intialize();
azureStorage.saveFileInAzureBlobStorage("Test.txt","Blob file content","TestCon",".txt");
if(azureStorage.parmOperationSuccess())
{
//File placed in to specified folder
}
}

Monday, May 13, 2019

Get Instance of Class in EventHander method D365

[PostHandlerFor(classStr(TestCustomDP), methodstr(TestCustomDP, processReport))] public static void getTmpTablePostHandler(XppPrePostArgs arguments) { TestCustomDP getDpInstance = arguments.getThis() as TestCustomDP; TestCustomTmp tmpTable = getDpInstance.getTmpTestCustomTmp();
ttsbegin; while select forUpdate tmpTable { // TODO - write your own business logic } ttscommit; }

Wednesday, April 17, 2019

Dynamics AX 365 - insert not allowed for fields In Data Entity

Dynamics AX 365 - insert not allowed for fields

Data entity related

Solution 1:
1. Data entity and staging table those error fields shouldn't set property for AllowEdit and AllowEditOnCreate to "NO".
2. Chaneg those field property to "Yes"
3. Rebuild solution and SYNC DB
4. Refresh entity List

Solution 2:
1. Code:
 this. skipDatasourceValidationField(FieldNum(<DS Name>, <DS Field Name>), true);
2. Write above on data entity methods (mapEntityToDatasource and intializedEntityDatasource
3. Rebuild soluton

Wednesday, April 3, 2019

Explore metadata search feature in Visual Studio D365 FO


Access the Metadata search tool window from the Dynamics 365 > Metadata Search.


Search Keyword Description
Code # Search for a specific code. Use quotes around code snippets. The matching source code is the elements that contain the specified code snippet.
Type # Filter the elements by type  Each comma-separated value should be the name of an element or sub-element type (root type or subtype) (i.e. table, class, field). Logic of filtering is:
Model # Filter the elements by model Each comma-separated value should be the name of a model in your application
Name # Filter the elements by name This is the default filter, meaning if you just type a filter value, it is assumed to be an element name. Each comma-separated value is an acceptable element name.
Property # Search for element with the property with the specific value  Each comma-separated value should be in the form property_name=property_value



Note: Make sure there should not be any space in between Type values otherwise it will show "Invalid query" error.

Cleaning up cross-reference DB in Dynamics 365 for finance and operation ON DEV VM


// For unwanted cross reference data clean Up on DB (DYNAMICSXREFDB)

DELETE [REFERENCES] FROM [REFERENCES]
    JOIN Names 
ON (Names.Id = [REFERENCES].SourceId 
OR Names.Id = [REFERENCES].TargetId)
    JOIN Modules 
ON Names.ModuleId = Modules.Id


Monday, March 18, 2019

Get selected Query Range in X++ Dynamics 365 finance and operation

        Query                  query;
        QueryBuildDataSource   qbds;
        QueryBuildRange      qbr;
        int i,j;
        int                   countDS, countRange;
        query              = New Query(queryStr(CustBalanceList));
        countDS           = query.dataSourceCount();

        for(i =1; i<= countDS; i++)
        {
            qbds = query.dataSourceNo(i);
            countRange = qbds.rangeCount();
            for(j=1; j<= countRange;j++)
            {
                qbr =  qbds.range(j);
                info(strFmt("Datasource: %3, field: %1, values: %2", qbr.fieldName(), qbr.value(), qbr.dataSource().name()));
            }
        }

Thursday, February 14, 2019

Turn off all the D365F&O services in DEV VM

To turn off all the D365F&O services

Steps:
1. Open PowerShell as an admin
2. Type "stop-d365environment"
3. click -> Enter


To start
Start-d365environment

Get Tax Amount for each line in Ax 2012/Dynamics 365 for finance and operation

Way 1->
private TaxAmountCur getTaxAmount(TableId   _transTableId, RefRecId _transRecId)
    {
        TaxTrans    taxTrans;
        select sum(SourceTaxAmountCur) from taxTrans
                where taxTrans.SourceTableId == _transTableId
                    && taxTrans.SourceRecId == _transRecId;
        return taxTrans.SourceTaxAmountCur > 0 ? taxTrans.SourceTaxAmountCur : -taxTrans.SourceTaxAmountCur;
    }

Way - 2->
    public TaxAmountCur getSalesTaxAmount(TableId   _transTableId, RefRecId _transRecId)
    {
        TaxAmountCur    taxAmountCur;
        TransDate       transDate = DateTimeUtil::getSystemDate(DateTimeUtil::getUserPreferredTimeZone());
        SalesLine       SalesLine = SalesLine::findRecId(_transRecId);

        TaxAmountCur = Tax::calcTaxAmount(salesline.TaxGroup,
                                            salesline.TaxItemGroup,
                                            transDate,
                                            salesline.CurrencyCode,
                                            salesline.LineAmount,
                                            TaxModuleType::Sales,
                                            salesline.SalesQty,
                                            salesline.SalesUnit,
                                            salesline.ItemId,
                                            TaxDirection::OutgoingTax);

        return taxAmountCur;
    }

Way 3->
TmpTaxWorkTrans             tmpTax;
            SalesTable                  salesTable;
            SalesTotals                 salesTotals;
            SalesLine                   SalesLine = SalesLine::findRecId(_transRecId);
 
            salesTable  = SalesTable::find(salesline.SalesId);
            salesTotals = SalesTotals::construct(salesTable);
            salesTotals.calc();
            tmpTax.setTmpData(salesTotals.tax().tmpTaxWorkTrans());
            select sum(TaxAmount) from tmpTax
                where tmpTax.InventTransId == salesline.InventTransId;            
            taxAmountCur = tmpTax.TaxAmount;


Way 4-> (If price incl of tax)
(salesline.calcLineAmount() - salesline.calcLineAmountExclTax())

Export label custom content

 GRID => Properties "Export Label" => "SalesReportMexico" To get download file with custom naming.