Showing posts with label Dyn365FO. Show all posts
Showing posts with label Dyn365FO. Show all posts

Tuesday, May 12, 2020

Get SQL name of Temp table Dynamics 365

Using code below in runnable class we can find temporary table name, which is created in SQL tempDB.


// Declare a TempDB table buffer
TmpCustName tCustName;
   
// Insert data to create the table in TempDB database in SQL
tCustName.AccountName = '10001';
tCustName.insert();
   
// Display the name

info(tCustName.getPhysicalTableName());


Friday, April 17, 2020

D365 FO you are not authorized to login with your current credentials.


Error:
You are not authorized to login with your current credentials. You will be redirected to the login page in a few seconds.

Reason:
Database restored into developer environment from another environment.

Solution:
Case 1:
If you have credentials of the user, who was the Admin in the environment from where database is restored - Use it!

Case 2:
If environment is locally hosted, we don't have credentials, we can use "Admin provisioning tool" to provision Admin user again. shortcut of this application is available in desktop otherwise you can find it from
Check K:\AosService\PackagesLocalDirectory\Bin


Case 3:
If the environment is Microsoft hosted, we will not be able to run “AdminUserProvisioning” tool and face error as below.

Here we have access of SQL database, so we can use query below to update Admin account.
Note: Value used in update query below, you can find from another database in your environment.   
UPDATE U
SET U.NETWORKALIAS = 'MThacker@abc.com',
    U.NETWORKDOMAIN = 'https://sts.windows.net/',
    U.SID = 'S-1-19-1410091826-xxxx-4079435192',
    IDENTITYPROVIDER = 'https://sts.windows.net/',
    OBJECTID = '25E55EE6-AB98-xxxxxxxx-FE00ACD05DBB'
--    Enable = 1
FROM UserInfo U WHERE U.Id LIKE 'Admin'

For case 3, after using query above, I was able to login to FO environment but still i am not sure this single query is enough?! 
Let me know, if you have any other experience with this! 



Tuesday, March 12, 2019

Clear cache with code X++ Dynamics 365/AX 2012

Code below can be used to clear caches for Dynamics 365 for Operations as well as AX 2012.

In AX 2012, copy and past code below into Job to execute and clear cache.

In D365 create runnable class as below, set that class as startup object for the project, set that project as startup project for the solution and execute class.

class RunnableClassTest
{       
    /// <summary>
    /// Runs the class with the specified arguments.
    /// </summary>
    /// <param name = "_args">The specified arguments.</param>
    public static void main(Args _args)
    {
        xSession::removeAOC();
        SysTreeNode::refreshAll();
        SysFlushDictionary::main(null);
        SysFlushAOD::main(null);
        SysFlushData::main(null);
        //SysBPCheckAIFDataObject::flushCache(true); // only for AX 2012
        SysFlushReportServer::main(null);
        SysFlushSystemSequence::main(null);
        xSession::updateAOC();
        info("Executed.");
    }

}

Monday, March 11, 2019

Expression in query ranges example Dynamics 365/AX 2012


Override form lookup method along with OR condition in query range.

public void lookup(FormControl _formControl, str _filterStr)
{
    //super(_formControl, _filterStr);
    SysTableLookup sysTableLookup = SysTableLookup::newParameters(tableNum(InventLocation),_formControl);
    Query query = New Query();
    QueryBuildDataSource queryBuildDataSource = query.addDataSource(tableNum(InventLocation));
    QueryBuildRange queryBuildRange;
    ;

    sysTableLookup.addLookupfield(fieldNum(InventLocation, InventLocationId));
    sysTableLookup.addLookupfield(fieldNum(InventLocation, Name));
    sysTableLookup.addLookupfield(fieldNum(InventLocation, InventSiteId));

    queryBuildRange = queryBuildDataSource.addRange(fieldNum(InventLocation, RecId));
    queryBuildRange.value(strFmt('((InventLocationType == %1) || (InventLocationType == %2))',
                            any2int(InventLocationType::Standard),
                            any2int(InventLocationType::Transit)));
  
    sysTableLookup.parmQuery(query);
    sysTableLookup.performFormLookup();
}

Saturday, March 9, 2019

Dynamics 365 for Operations On-premise installation/Troubleshooting

I will keep updating this post with the helpful links for the installation and troubleshooting D365 for Operation on-premise version.

Install D365 On-Premise PU 12:
https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/deployment/setup-deploy-on-premises-pu12

Redeploy on-premise environment: Failed status.
https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/deployment/redeploy-on-prem

Setup Network Printer for On-Premise environment.
https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/analytics/install-network-printer-onprem

Troubleshooting:
https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/deployment/troubleshoot-on-prem



Errors and solutions while installing On-Premise D365 for Operations
ADFS Configuration error:
https://allaboutax.blogspot.com/2018/12/adfs-configuration-error-invalid-scope.html

AX 2012/Dynamics 365 operations Performance monitoring related links.

To troubleshoot performance of AX 2012 or Dynamics 365 operations, i am collecting some helpful links on this post.

I will keep updating this blogs as and when required accordingly.

Performance monitoring:

https://blogs.msdn.microsoft.com/axinthefield/ax-performance-monitor-101-setup-perfmon-for-continuous-monitoring-with-rolling-files/

Disk:
https://blogs.technet.microsoft.com/josebda/2014/10/13/diskspd-powershell-and-storage-performance-measuring-iops-throughput-and-latency-for-both-local-disks-and-smb-file-shares/

https://blogs.msdn.microsoft.com/axinthefield/assessing-your-disk-performance-and-your-needs-collecting-relevant-data-part-1/

https://blogs.msdn.microsoft.com/axinthefield/assessing-your-disk-performance-and-your-needs-analyzing-collected-data-part-2/

AX 2012

Performance dashboard
https://blogs.msdn.microsoft.com/axinthefield/3-powershell-scripts-for-dynamics-ax-refresh-report-and-monitor/

AX 2012 Forms performance
https://blogs.msdn.microsoft.com/axinthefield/how-to-measure-the-performance-of-the-dynamics-ax-2012-forms/

Client Access log: (how often they are accessing forms)
https://blogs.msdn.microsoft.com/axperf/2011/10/14/client-access-log-dynamics-ax-2012/

Saturday, February 23, 2019

Frequently used functions in D365 operations

Below listed are some frequently used functions in AX 2012, AX 2012 R2/R3, Dynamics 365 operations

1) Print text using label ids.
SysLabel::labelId2String2(literalStr("@DPL1228"))

2)

Wednesday, July 25, 2018

Create and release product variant Dynamics 365

Code below can be used to create and release product variant in Dynamics AX 2012 & Dynamics 365 Operations.

It will work straight forwardly for AX 2012.

For Dynamics 365 operations,you need to create runable class to execute the same.

I have checked and tested that below code is working fine in dynamics 365 operations for different application but not to import data.

As all the classes and tables used below are available in Dynamics 365 operations, it should work to import as well.

Awaiting for feedback, if any!
 static void dtReleaseProductAllVariant(Args _args)  
 {  
   ecoResDistinctProductVariant    ecoResDistinctProductVariant;  
   EcoResProductVariantDimensionValue EcoResProductVariantDimensionValue;  
   RefRecId              ecoResDistinctProductVariantRecId;  
   EcoResProductReleaseManagerBase   releaseManager;  
   container              productDimensions;  
   EcoResProduct            ecoResProduct;  
   EcoResProductDimensionAttribute   prodDimensionAttribute; //fix for perticular dim, using tableid  
   //Configuration  
   EcoResProductMasterConfiguration  productMasterConfiguration;  
   EcoResConfiguration         ecoResConfiguration;  
   //Color  
   EcoResProductMasterColor      productMasterColor;  
   EcoResColor             ecoResColor;  
   //Size  
   EcoResProductMasterSize       productMasterSize;  
   EcoResSize             ecoResSize;  
   //Style  
   EcoResProductMasterStyle      productMasterStyle;  
   EcoResStyle             ecoResStyle;  
   CommaTextIo         file;  
   container          rec;  
   Dialog       d;  
   DialogField     df1, df2;  
   int64        counter = 0;  
   ;  
   d = new Dialog("Release Product Variant");  
   df1 = d.addField(ExtendedTypeStr("FilenameOpen"));  
   if (d.run())  
   {  
     file = new CommaTextIo(df1.value(), 'r');  
     file.inFieldDelimiter(';');  
     try  
     {  
       while (file.status() == IO_Status::Ok)  
       {  
         rec = file.read();  
         if(!rec)  
           break;  
           ttsBegin;  
           ecoResProduct = EcoResProduct::findByProductNumber(conPeek(rec, 1));  
           //Configuration - Start  
           ecoResConfiguration = EcoResConfiguration::findByName(conPeek(rec, 2));  
           if (!ecoResConfiguration.RecId)  
           {  
             ecoResConfiguration.Name = conPeek(rec, 2);  
             ecoResConfiguration.insert();  
           }  
           select * from productMasterConfiguration where productMasterConfiguration.Configuration == ecoResConfiguration.RecId &&  
                             productMasterConfiguration.ConfigProductMaster == ecoResProduct.RecId;  
           if(!productMasterConfiguration.RecId)  
           {  
             select * from prodDimensionAttribute where prodDimensionAttribute.DimensionTableId == tableNum(EcoResConfiguration);  
             productMasterConfiguration.Configuration              = ecoResConfiguration.RecId;  
             productMasterConfiguration.ConfigProductDimensionAttribute     = prodDimensionAttribute.RecId;  
             productMasterConfiguration.ConfigProductMaster           = ecoResProduct.RecId;  
             productMasterConfiguration.insert();  
           }  
           //Configuration - End  
           //Size - Start  
           ecoResSize = EcoResSize::findByName(conPeek(rec, 3));  
           if (!ecoResSize.RecId)  
           {  
             ecoResSize.Name = conPeek(rec, 3);  
             ecoResSize.insert();  
           }  
           select * from productMasterSize where productMasterSize.Size == ecoResSize.RecId &&  
                             productMasterSize.SizeProductMaster == ecoResProduct.RecId;  
           if(!productMasterSize.RecId)  
           {  
             select * from prodDimensionAttribute where prodDimensionAttribute.DimensionTableId == tableNum(EcoResSize);  
             productMasterSize.Size              = ecoResSize.RecId;  
             productMasterSize.SizeProductDimensionAttribute  = prodDimensionAttribute.RecId;  
             productMasterSize.SizeProductMaster        = ecoResProduct.RecId;  
             productMasterSize.insert();  
           }  
           //Size - End  
           //Color - Start  
           ecoResColor = EcoResColor::findByName(conPeek(rec, 4));  
           if (!ecoResColor.RecId)  
           {  
             ecoResColor.Name = conPeek(rec, 4);  
             ecoResColor.insert();  
           }  
           select * from productMasterColor where productMasterColor.color == ecoResColor.RecId &&  
                             productMasterColor.ColorProductMaster == ecoResProduct.RecId;  
           if(!productMasterColor.RecId)  
           {  
             select * from prodDimensionAttribute where prodDimensionAttribute.DimensionTableId == tableNum(EcoResColor);  
             productMasterColor.Color              = ecoResColor.RecId;  
             productMasterColor.ColorProductDimensionAttribute  = prodDimensionAttribute.RecId;  
             productMasterColor.ColorProductMaster        = ecoResProduct.RecId;  
             productMasterColor.insert();  
           }  
           //Color - End  
           //Style - Start  
           ecoResStyle = EcoResStyle::findByName(conPeek(rec, 5));  
           if (!ecoResStyle.RecId)  
           {  
             ecoResStyle.Name = conPeek(rec, 5);  
             ecoResStyle.insert();  
           }  
           select * from productMasterStyle where productMasterStyle.Style == ecoResStyle.RecId &&  
                             productMasterStyle.StyleProductMaster == ecoResProduct.RecId;  
           if(!productMasterStyle.RecId)  
           {  
             select * from prodDimensionAttribute where prodDimensionAttribute.DimensionTableId == tableNum(EcoResStyle);  
             productMasterStyle.Style              = ecoResStyle.RecId;  
             productMasterStyle.StyleProductDimensionAttribute  = prodDimensionAttribute.RecId;  
             productMasterStyle.StyleProductMaster        = ecoResProduct.RecId;  
             productMasterStyle.insert();  
           }  
           //Style - End  
           //Create a container to hold dimension values  
           productDimensions = EcoResProductVariantDimValue::getDimensionValuesContainer(conPeek(rec, 2),  
                                                   conPeek(rec, 3),  
                                                   conPeek(rec, 4),  
                                                   conPeek(rec, 5));  
           //Create Product search name  
           ecoResDistinctProductVariant.DisplayProductNumber = EcoResProductNumberBuilderVariant::buildFromProductNumberAndDimensions(  
                                             conPeek(rec, 1),  
                                             productDimensions);  
           //Create Product variant with Product and dimensions provided  
           ecoResDistinctProductVariantRecId = EcoResProductVariantManager::createProductVariant(ecoResProduct.RecId,  
                                             ecoResDistinctProductVariant.DisplayProductNumber,  
                                             productDimensions);  
           //Find newly created Product Variant  
           ecoResDistinctProductVariant = ecoResDistinctProductVariant::find(ecoResDistinctProductVariantRecId);  
           //Now release the Product variant  
           releaseManager = EcoResProductReleaseManagerBase::newFromProduct(ecoResDistinctProductVariant);  
           releaseManager.release();  
           counter++;  
           ttsCommit;  
         info(strFmt("%1 Product variant released successfully",conPeek(rec, 1)));  
         info(strFmt("Total %1 Product variants released successfully",counter));  
       }  
     }  
     catch  
     {  
       info(strFmt("Total %1 Product variants released successfully",counter));  
       info(strFmt("Job terminated for product %1 and config %2 Size %3 Color %4 Style %5",conPeek(rec, 1),conPeek(rec, 2),conPeek(rec, 3),conPeek(rec, 4),conPeek(rec, 5)));  
     }  
   }  
 }  

Wednesday, July 4, 2018

Create simple dialog dynamics 365 Operations

Below code can be used as base to create dialog in Dynamics 365 Operations.

To Start with, create new project in either existing model or create new model and add a new Runnable class with name ppPurchDeliveryScheduleCreateDialog.

Copy code below and past into your class code area, this contains all the basic methods, which are required to override while extending RunBase class.

Modify logic of this dialog as per your requirement.

/// <summary>
/// The <c>ppPurchDeliveryScheduleCreate</c> class takes inputs from user and creates delivery schedule lines.
/// </summary>
/// <remarks>
/// Create delivery schedule lines.
/// </remarks>
public class ppPurchDeliveryScheduleCreateDialog extends RunBase
{
    // User Input fields
    DialogField     fieldNoOfLines;
    
    // Variables to store user input
    ppNumberOfLines numberOfLines;

    // pack() and unpack() methods are used to load the last value from user
    // for our simple example we are not going to use them.
    public container pack()
    {
        return conNull();
    }

    public boolean unpack(container packedClass)
    {
        return true;
    }

    // Dialog method to capture runtime user inputs for customer details
    public Object dialog()
    {
        Dialog dialog = super();

        // Set a title for dialog
        dialog.caption( 'Enter number of lines:');

        // Add a new field to Dialog
        fieldNoOfLines = dialog.addField(extendedTypeStr(ppNumberOfLines), 'No of lines:');

        return dialog;
    }

    // Retrieve values from Dialog
    public boolean getFromDialog()
    {
        numberOfLines = fieldNoOfLines.value();
        return super();
    }

    //write business logic.
    public void run()
    {
        //TODO: User numberOfLines variable to create delivery schedule.
    }

    public static void main(Args _args)
    {
        ppPurchDeliveryScheduleCreateDialog deliverySchedule = new ppPurchDeliveryScheduleCreateDialog();

        // Prompt the dialog, if user clicks in OK it returns true
        if (deliverySchedule.prompt())
        {
            deliverySchedule.run();
        }
    }

}

Saturday, June 23, 2018

Retrieve last approver name for any workflow

Below code can be used to retrieve last approver name for any workflow activated in Dynamics AX/ 365 Finance and operations.

 static void dtGetLastApproverName(Args _args)  
 {  
    WorkflowTrackingStatusTable workflowTrackingStatus;  
    WorkflowTrackingTable workflowTrackingTable;  
    WorkflowTrackingCommentTable workflowTrackingCommentTable;  
    UserInfo userInfo;  

    select firstFast RecId, User from workflowTrackingTable  
     order by RecId desc   
     join workflowTrackingCommentTable   
    where workflowTrackingCommentTable.WorkflowTrackingTable ==   
          workflowTrackingTable.RecId  
    join UserInfo where UserInfo.id == WorkflowTrackingTable.User  
    exists join workflowTrackingStatus  
    where workflowTrackingTable.WorkflowTrackingStatusTable ==   
    workflowTrackingStatus.RecId  
    && workflowTrackingStatus.ContextRecId == _salesRecId //PurchRecID  
    && workflowTrackingStatus.ContextTableId == tableNum(SalesTable) //SalesTable  
    && workflowTrackingTable.TrackingType == WorkflowTrackingType::Approval;  

    if (workflowTrackingTable.RecId > 0)  
    {  
      info(strFmt(“%1 – %2 “,userInfo.name, workflowTrackingCommentTable.RecId));  
    }  
 }  

Friday, June 22, 2018

Verify active/enabled product dimension

Below code can be used to verify active or enabled specific or all product dimensions.

 
   public static void main(Args _args)
   {
     InventTable   inventTable;  
     InventDimParm  inventDimParm;  
     ;  

     inventTable  = InventTable::find('ABC');  

     inventDimParm = InventDimParm::activeDimFlag(InventDimGroupSetup::newInventTable(inventTable));  

     if(inventDimParm.InventColorIdFlag)  
     {  
       info("Color Enabled."); 
     }  
   }

Production picking list reservation through X++

Reserve without changing dimension.
 dtProdBOMReserve(Args _args)   
 {   
   prodJournalBOM prodJournalBOM;
   InventUpd_Reservation reservation;   
   ;   

   select * from prodJournalBOM    
    where prodJournalBOM.RecId == 5637695365;   

   movement = InventMovement::construct(prodJournalBOM);   
   reserveQuantity = prodJournalBOM.BOMConsump - abs(movement.transIdSum().reserved());  
   if(reserveQuantity)
   {
     reservation = InventUpd_Reservation::newMovement(movement,-reserveQuantity,true);   
     reservation.updateNow();  
   } 
   info('Reserved.');   
  }   

Reserve for specific dimension.


static void dtProdBOMReserveWithDim(Args _args)  
 {  
   prodJournalBOM prodJournalBOM;;  
   InventDim InventDim;  
   InventUpd_Reservation reservation;  
   ;  
   select * from prodJournalBOM  
     where prodJournalBOM.RecId == 5637695365;  

   //Update dimension
   inventDim = prodJournalBOM.inventDim();  
   inventDim.wMSLocationId = '12420301';  

   movement = InventMovement::construct(prodJournalBOM);  

   reserveQuantity = prodJournalBOM.BOMConsump - abs(movement.transIdSum().reserved()); 
 
   if(reserveQuantity)
   {
     reservation = InventUpd_Reservation::newInventDim(movement,inventDim, -reserveQuantity,false);  
     reservation.updateNow();  
   }

   info('Reserved.');  
 }  

Monday, June 18, 2018

Cache weight item

Below method is to check, if cache weight is enabled or not for a particular Item.

AX 2012

Dynamics 365 Operations


Thursday, June 14, 2018

Unit conversion AX 2012/ D365FO

Code below can be used for unit conversion with rounding.
 public SalesQty dtConvert(Qty _salesQty,ItemId _itemId,SalesUnit _inventUnit,SalesUnit _salesUnit )  
 {  
      SalesQty salesQty;  
      salesQty = UnitOfMeasureConverter::convert(_salesQty,  
               UnitOfMeasure::unitOfMeasureIdBySymbol(_inventUnit),  
               UnitOfMeasure::unitOfMeasureIdBySymbol(_salesUnit),  
               NoYes::Yes,  
               InventTable::itemProduct(_itemId),  
               NoYes::Yes);  
     return salesQty;  
 }  

Saturday, June 9, 2018

OData Date time filter D365 Finance and operations

Date Time filter
OldFormat
https://usnconeboxax1aos.cloud.onebox.dynamics.com/data/Vendors?cross-company=true&$filter=ModifiedDateTime ge DateTime'2018-06-07T09:13:28'
New Format
https://usnconeboxax1aos.cloud.onebox.dynamics.com/data/Vendors?cross-company=true&$filter=ModifiedDateTime gt 2018-06-07T23:59:59.99Z


String Filter
https://usnconeboxax1aos.cloud.onebox.dynamics.com/data/Vendors?cross-company=true&$filter=VendorAccountNumber eq '1001'

Wednesday, June 6, 2018

Job in dynamics 365 Finance and Operations


Below option is to create Runnable Class, which is job in AX 2012 R3.



This will create class with static method as below.

As this class have only static method, this will execute without creating object of class, which is same as job.

To debug this job, set current project as start up project as well as current job class as start up object.


From Debug menu, select option Start Debugging.

This will hit break point.


Happening

Upgrade from AX 2012 to Latest Dynamics 365 Finance and Operation

Below are the steps defined by sequence. 1. Create new Upgrade project in Dynamics LCS. 2. Create VSTS Project and connect it with L...

Trending now