This blog is dedicated to all my technical learnings and findings. As they say use all the brains you have and borrow all the brains you can, so this is my share of lending my learnings to all you guys out there. I would like to acknowledge here that some parts of these posts would be reproduced as a part of my web-browsing mainly because having it all in one place is far more convenient.
Wednesday, July 11, 2018
Tuesday, May 15, 2018
Move AX database between environment
If the active directories are different then the sysadmin role mapping with the active directory will be required to be updated
select SID, Networkdomain, networkalias from userinfo
where networkalias = ''
select SID, Networkdomain, networkalias from userinfo
where networkalias = '
Find the SID for the user to be mapped in the new Active directory
Whoami /user
Copy the new SID for the desired user and update the same in the userinfo table
update userinfo set SID='', Networkdomain = '', networkalias = '' where id = 'admin'
Sunday, May 13, 2018
Windows 10 Task Bar Problems
Had a strange problem today when in the task bar search stopped working. Also the taskbar was opening disabled and i had to open it up multiple time to enable it back.
Follow the below steps to restore the taskbar setting using powershell script
Follow the below steps to restore the taskbar setting using powershell script
1. Find C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
2. Right-click and Run as Administrator
3. Copy this line:
Get-AppXPackage -AllUsers | Foreach {Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppXManifest.xml"}
Monday, January 29, 2018
Power BI D365 Integration
Every external application that needs an access to an Azure resource should be assigned necessary permissions. The registration process for Applications takes care of this.
To view the app registrations follow the following path: -
Goto Services and find App Registrations
Click on App Registrations and set the filter to All Apps
Then search of the name of the application as used when the app was registered on the PowerBI portal (in this case 365-hcpm-demo Power BI Integration )
Once you click on the app you will be able to see the details
At this location one should be able to view and manage most of the properties of the application.
Note: The secret key is only visible once when it is being created and thereafter hidden so if at all you have forgotten your key please delete the existing one and create a new one.
Name, Object id and other properties are visible using the properties tab page.
Reply urls tab page is used to alter the redirection page.
To view the app registrations follow the following path: -
Goto Services and find App Registrations
Click on App Registrations and set the filter to All Apps
Then search of the name of the application as used when the app was registered on the PowerBI portal (in this case 365-hcpm-demo Power BI Integration )
Once you click on the app you will be able to see the details
At this location one should be able to view and manage most of the properties of the application.
Note: The secret key is only visible once when it is being created and thereafter hidden so if at all you have forgotten your key please delete the existing one and create a new one.
Name, Object id and other properties are visible using the properties tab page.
Reply urls tab page is used to alter the redirection page.
Tuesday, January 02, 2018
Save RDP credentials
To be able to use saved credentials
1. Open Group Policy Editor via cmd -> gpedit.msc
2. Navigate to Local Computer Policy\Computer Configuration\Administrative Templates\System\Credentials Delegation\
3.Open Setting Allow Delegating Saved Credentials with NTLM-only Server Authentication, set it to Enabled
click on button Show... and in Show Contents window add Value TERMSRV/* Close all windows by pressing OK.
4. Run cmd and enter gpupdate command to update your policy
1. Open Group Policy Editor via cmd -> gpedit.msc
2. Navigate to Local Computer Policy\Computer Configuration\Administrative Templates\System\Credentials Delegation\
3.Open Setting Allow Delegating Saved Credentials with NTLM-only Server Authentication, set it to Enabled
click on button Show... and in Show Contents window add Value TERMSRV/* Close all windows by pressing OK.
4. Run cmd and enter gpupdate command to update your policy
Sunday, November 19, 2017
Cannot create a record in Workflow tracking status table (WorkflowTrackingStatusTable). Correlation ID: {70B17AE2-AF1A-47A9-937F-39F206AF91DE}, Pending. The record already exists.
Encountered this issue once the system recovered from the RecId max out in the workflow tables. There were certain transactions that were submitted and updated as In-review however the workflow was not triggered for them. The workflow bar was missing and on trying to Re-Submit the workflows the error was received.
Solution :
Solution :
- Shutdown all the AOS instance
- Bring up any one AOS, synchronize the database.
- Re-Submit the workflow for the failed records.
e.g:
TSTimesheetTable timesheets;
WorkflowTrackingStatusTable trackingstatus;
while select timesheets
where 1==1
&& timesheets.ApprovalStatus == TSAppStatus::Pending
//&& timesheets.TimesheetNbr == 'CCM-175040'
notexists join trackingstatus
where trackingstatus.ContextTableID == 4627
&& trackingstatus.ContextRecId == timesheets.RecId
{
/*
ttsBegin;
timesheets.ApprovalStatus = TSAppStatus::Create;
timesheets.update();
ttsCommit;
*/
Workflow::activateFromWorkflowType("TSDocumentTemplate",
timesheets.RecID,
"Resubmitted due to error",
false,
timesheets.createdBy );
info( timesheets.TimesheetNbr );
AX 2012-Cannot create a record in Workflow tracking status table
Got the message in the workflow. The messages can be seen in the EventViewer and can also be seen on screen if the workflow is triggered using the tutorial form.
The reason for this error is when the RECID of the tables involved and systemSequences is out of sync. Which means the RecId that the system tries to generate for a new record is something which is duplicate and has been generated in the past.
The reason why this mismatch occurs could be anything and is not known to me; however what is important at this point, is to get out of this situation. With the little R&D that i did, i realized the following facts.
The reason for this error is when the RECID of the tables involved and systemSequences is out of sync. Which means the RecId that the system tries to generate for a new record is something which is duplicate and has been generated in the past.
The reason why this mismatch occurs could be anything and is not known to me; however what is important at this point, is to get out of this situation. With the little R&D that i did, i realized the following facts.
- The RecIDs are not generated real time from the systemSequences table. In reality each AOS caches a certain amount of RecID and tries to use them.
- Due to the above stated fact the max RecId that is visible directly from SQL database, is different from the one that actually exists in the AOS. Hence it is important that when we are correcting the NextVal in the systemSequences table, the value is fetched using the AOS table and not from the database directly (using SQL scripts).
Solution :
- Check of the Maximum value of the RECID column for the table resulting in the error, in this case it is WorkflowTrackingTable.
- Make sure you check for the value of RECID from AOS and not using the SQL table as there might be records that are not committed to the database.
- Sort the table by RECID in descending order and copy the maximum RecID as reported by AOS.
- Update the systemSequences table by adding 250 to this value to be on the safer side and to avoid cached values.
- Compile the table giving the error on each of the AOS so that the cache's is cleared.
Monday, October 23, 2017
AX2012 Deploy ListPage with QuickLaunch menu
Generally when a List page is deployed it only gives an option to be deployed in the subsites that have been created in EP. There could be a scenario where one would want the list page to open with a quick launch menu (navigation pane on the left )
We had created a new list page which had to appear inside the Timesheet Quick Launch Menu. The problem with the deployment was there was no option to deploy inside the Timesheet node, and if the list page was deployed under the EmployeeServices node, the user would lose the Quick Launch Menu each time the url was clicked.
Below are the steps involved to deploy a list page inside a Quick Lauch menu
Step 1. Create a Display menu for the listpage
Step 2. Right click the display menu and deploy the list page to the root site. When the list page is deployed to EP the deployment process will automatically create a WebURL
Step 3. Right click the WebURL menu created and import the page.
Step 4. Select the page (in my case the page name is AFZ_AllocationsListPage) and change the WebModule address. I have added Timesheets in the existing link
Step 5. Now right click on the Page Definition and deploy the page to the new address that has been specified.
Step 6. Once the page has been deployed at the new location the URL can be updated to refer to the new address
Step 7. At this stage the WebURL can be added to the quick launch menu created for timesheets, and when this link is click it would open with the left navigation pane in place as shown below.
We had created a new list page which had to appear inside the Timesheet Quick Launch Menu. The problem with the deployment was there was no option to deploy inside the Timesheet node, and if the list page was deployed under the EmployeeServices node, the user would lose the Quick Launch Menu each time the url was clicked.
Below are the steps involved to deploy a list page inside a Quick Lauch menu
Step 1. Create a Display menu for the listpage
Step 2. Right click the display menu and deploy the list page to the root site. When the list page is deployed to EP the deployment process will automatically create a WebURL
Step 3. Right click the WebURL menu created and import the page.
Step 4. Select the page (in my case the page name is AFZ_AllocationsListPage) and change the WebModule address. I have added Timesheets in the existing link
Step 5. Now right click on the Page Definition and deploy the page to the new address that has been specified.
Step 6. Once the page has been deployed at the new location the URL can be updated to refer to the new address
Step 7. At this stage the WebURL can be added to the quick launch menu created for timesheets, and when this link is click it would open with the left navigation pane in place as shown below.
Remove Sharepoint Upgrade Bar
To remove the upgade bar the following command can be used in the sharepoint 2013 management shell
Note: Please make sure that the mangement shell is executed using elevated administrator privileges.
Get-SPWebApplication http://afz-svr-int:90 | Get-SPSite -Limit All -CompatibilityLevel 14 | Foreach-Object {$_.AllowSelfServiceUpgrade = $false }
The above command can be executed for each of the hosted sites.
Note: Please make sure that the mangement shell is executed using elevated administrator privileges.
Get-SPWebApplication http://afz-svr-int:90 | Get-SPSite -Limit All -CompatibilityLevel 14 | Foreach-Object {$_.AllowSelfServiceUpgrade = $false }
The above command can be executed for each of the hosted sites.
Sunday, February 05, 2017
Read a given segment value for a given account from the GL
Assuming that one has to read all the values from a MainAccount '20151026' where the Employee dimension 'D6_Employee' = 'E0028'
Below is a sample job for the same
static void Job10(Args _args)
{
GeneralJournalAccountEntry GJAE;
GeneralJournalEntry GJE;
FiscalCalendarPeriod FCP;
SubledgerVoucherGeneralJournalEntry SLVGJE;
DimensionAttributeValueGroupCombination DAVGC;
DimensionAttributeLevelValue DALV;
DimensionAttributeValue DAV;
DimensionAttribute DA;
SPYAmount claimAmount;
HcmPersonnelNumberId personnelNumber = HcmWorker::find(5637146086).PersonnelNumber;
while select *
from GJAE
join GJE
where GJE.RecId == GJAE.GeneralJournalEntry
&& GJE.AccountingDate >= mkDate(1,1,2017)
&& GJE.AccountingDate <= mkDate(31,1,2017)
&& GJAE.MainAccount == MainAccount::findByMainAccountId('20151026').RecId
join SLVGJE
where SLVGJE.GeneralJournalEntry == GJE.RecId
&& SLVGJE.VoucherDataAreaId == curext()
//reading the individual segments of the entry
join DAVGC
where DAVGC.DimensionAttributeValueCombination == GJAE.ledgerDimension
join DALV
where DALV.DimensionAttributeValueGroup == DAVGC.DimensionAttributeValueGroup
&& DALV.DisplayValue == personnelNumber
join DAV
where DAV.RECID == DALV.DimensionAttributeValue
join DA
where DA.RecID == DAV.DimensionAttribute
&& DA.Name == 'D6_Employee'
{
claimAmount += GJAE.AccountingCurrencyAmount;
}
}
Below is a sample job for the same
static void Job10(Args _args)
{
GeneralJournalAccountEntry GJAE;
GeneralJournalEntry GJE;
FiscalCalendarPeriod FCP;
SubledgerVoucherGeneralJournalEntry SLVGJE;
DimensionAttributeValueGroupCombination DAVGC;
DimensionAttributeLevelValue DALV;
DimensionAttributeValue DAV;
DimensionAttribute DA;
SPYAmount claimAmount;
HcmPersonnelNumberId personnelNumber = HcmWorker::find(5637146086).PersonnelNumber;
while select *
from GJAE
join GJE
where GJE.RecId == GJAE.GeneralJournalEntry
&& GJE.AccountingDate >= mkDate(1,1,2017)
&& GJE.AccountingDate <= mkDate(31,1,2017)
&& GJAE.MainAccount == MainAccount::findByMainAccountId('20151026').RecId
join SLVGJE
where SLVGJE.GeneralJournalEntry == GJE.RecId
&& SLVGJE.VoucherDataAreaId == curext()
//reading the individual segments of the entry
join DAVGC
where DAVGC.DimensionAttributeValueCombination == GJAE.ledgerDimension
join DALV
where DALV.DimensionAttributeValueGroup == DAVGC.DimensionAttributeValueGroup
&& DALV.DisplayValue == personnelNumber
join DAV
where DAV.RECID == DALV.DimensionAttributeValue
join DA
where DA.RecID == DAV.DimensionAttribute
&& DA.Name == 'D6_Employee'
{
claimAmount += GJAE.AccountingCurrencyAmount;
}
}
Sunday, November 20, 2016
SSRS Report UI Builder
UI Builder report is used to manipulate the request form rendered by the AX framework before a report is executed. The request form for a report is generated by the framework based on the meta data provided by the contract class.
Below are the steps that are required to manage the User Interface of a report
- Create a UI builder class by extending the class SrsReportDataContractUIBuilder.
- We will have to create event handlers for the control on the report contract.
- The event handlers created in step 2 will have to be attached to the control created by the reporting framework using the PostBuild method of the UIBuilder class.
- The contract class has to be modified to include a reference to the UIBuilder class. This is done by including the SysOperationContractProcessingAttribute on the contact class declaration.
[
DataContractAttribute
,SysOperationContractProcessingAttribute(classstr(STPLedgerBalanceReportUIBuilder))
]
class STPLedgerBalanceReportUIBuilder extends SrsReportDataContractUIBuilder
{
STPLedgerBalanceReportContract contract ;
}
public void build()
{
super();
Contract = this.dataContractObject();
}
public void lookup(FormStringControl _control)
{
container cnt;
Query query = new Query();
QueryBuildDataSource qbds, qbdsCI;
QueryBuildRange range, rangeDA;
qbds = query.addDataSource(tableNum(USERDATAAREAFILTER));
range = qbds.addRange( fieldNum( UserDataAreaFilter, User) );
range.value( SysQuery::value( curUserId())) ;
qbdsCI = qbds.addDataSource( tableNum( CompanyInfo) );
qbdsCI.addLink( fieldNum( UserDataAreaFilter, DataArea) , fieldNum( CompanyInfo, DataArea) );
qbdsCI.joinMode(JoinMode::InnerJoin);
if ( Global::hasTableAccess( tableNum( STPRowDefinitionLine) , AccessType::Delete) == false )
{
rangeDA = qbds.addRange( fieldNum( UserDataAreaFilter, DataArea) );
rangeDA.value( SysQuery::value( curext()) );
}
qbds.fields().clearFieldList();
qbds.fields().addField(fieldNum(USERDATAAREAFILTER, DataArea));
qbdsCI.fields().addField ( fieldNum( CompanyInfo,Name) ) ;
SysLookupMultiSelectGrid::lookup(query, _control, _control, cnt);
}
public void postBuild()
{
DialogField companyList;
super();
companyList = this.bindInfo().getDialogField( this.dataContractObject(), methodStr(STPLedgerBalanceReportContract, parmCompanyList) ) ;
companyList.registerOverrideMethod(
methodStr(FormStringControl, lookup),
methodStr(STPLedgerBalanceReportUIBuilder,Lookup),
this);
}
public void getFromDialog()
{
super();
}
Thursday, November 17, 2016
AX2012 invoke menuitem using X++ code
Below is the code to invoke a menu item on a click on command button.
The command button was required to execute some x++ code and then trigger the menu item, hence the menu item was not directly inserted as menu option instead the code was written on the click event.
Args _args = new Args();
new MenuFunction(identifierstr(STPLedgerBalanceCurrencyTranslation), MenuItemType::Action).run(_args);
The command button was required to execute some x++ code and then trigger the menu item, hence the menu item was not directly inserted as menu option instead the code was written on the click event.
Args _args = new Args();
new MenuFunction(identifierstr(STPLedgerBalanceCurrencyTranslation), MenuItemType::Action).run(_args);
Tuesday, November 01, 2016
AX2012 EP Pass Record context beween EP forms
Requirement : Open one modal form from another and pass the context.
The best way to pass the context is using the Dataset init method of the relevant table. In my case i had to pass the InventJournalTrans table's reference from a grid to a new form, where the details would be entered. Below are the steps for the same.
Step 1: Create the init method in the relevant table under the dataset.

The definition of the init method would be as follows:
public void init()
{
Common callerRecord = element.args().record();
super();
if ( callerRecord.TableId == tablenum(InventJournalTrans) )
{
this.query((EPQuery::makeRecIdQuery(this.query(),tablenum(InventJournalTrans),callerRecord.RecId)));
}
}
Once the above is done we are sure that a filter would be imposed on the database if the calling form is sending the record context of the InventJournalTrans table.
Step 2: Is to ensure that a record context is passed from the source. We first create a new sharepoint page with a new web control and render a presentation that we want to be displayed.
A url type of WebMenuItem would be required to point to the newly created sharepoint page and the new userControl created. Create a new webMenuItem as shown below

Step 3: Attach the menu item in the parent UserControl such that it has the right context. In my case it happens to be a grid control which has a toolbar attached to it. So simply drag the url menu item to the relevant webmenu, which in this case is AFZEPInventJournalLineToolbar

The best way to pass the context is using the Dataset init method of the relevant table. In my case i had to pass the InventJournalTrans table's reference from a grid to a new form, where the details would be entered. Below are the steps for the same.
Step 1: Create the init method in the relevant table under the dataset.
The definition of the init method would be as follows:
public void init()
{
Common callerRecord = element.args().record();
super();
if ( callerRecord.TableId == tablenum(InventJournalTrans) )
{
this.query((EPQuery::makeRecIdQuery(this.query(),tablenum(InventJournalTrans),callerRecord.RecId)));
}
}
Once the above is done we are sure that a filter would be imposed on the database if the calling form is sending the record context of the InventJournalTrans table.
Step 2: Is to ensure that a record context is passed from the source. We first create a new sharepoint page with a new web control and render a presentation that we want to be displayed.
A url type of WebMenuItem would be required to point to the newly created sharepoint page and the new userControl created. Create a new webMenuItem as shown below
Step 3: Attach the menu item in the parent UserControl such that it has the right context. In my case it happens to be a grid control which has a toolbar attached to it. So simply drag the url menu item to the relevant webmenu, which in this case is AFZEPInventJournalLineToolbar
Subscribe to:
Posts (Atom)






