code:-
appl.setDefaultCompany(Legalentitycode, false);
code:-
appl.setDefaultCompany(Legalentitycode, false);
code:-
sql:-
select DISTINCT vendPackingSlipTrans.PACKINGSLIPID from vendInvoiceTrans
inner join vendInvoiceJour
on vendInvoiceTrans.PurchID = vendInvoiceJour.PurchId and
vendInvoiceTrans.InvoiceId = vendInvoiceJour.InvoiceId and
vendInvoiceTrans.InvoiceDate = vendInvoiceJour.InvoiceDate and
vendInvoiceTrans.NumberSequenceGroup = vendInvoiceJour.NumberSequenceGroup and
vendInvoiceTrans.InternalInvoiceId = vendInvoiceJour.InternalInvoiceId
inner join vendInvoicePackingSlipQuantityMatch
on vendInvoicePackingSlipQuantityMatch.InvoiceSourceDocumentLIne = vendInvoiceTrans.SourceDocumentLine
inner join vendPackingSlipTrans
on vendPackingSlipTrans.SourceDocumentLine = vendInvoicePackingSlipQuantityMatch.PackingSlipSourceDocumentLine
and vendInvoiceJour.LEDGERVOUCHER='pass your journal vocuher'
Step1;- Here my Role name I want to assign is System admin
SELECT RecId,* FROM SecurityRole WHERE Name = 'System administrator';
step 2:- User name here is sai and pass recid from above to below query
insert into SECURITYUSERROLE (USER_, SECURITYROLE, ASSIGNMENTSTATUS, ASSIGNMENTMODE)
VALUES ('sai', 171,1,1);
Thats it!! refresh and check
For deleting of roles through SSMS
Step1:-SELECT RecId,* FROM SecurityRole WHERE Name = 'System administrator';
pass recid from above to below query
Step 2:-DELETE FROM SECURITYUSERROLE WHERE USER_='sai'and SECURITYROLE=171;
Thank you!!
To get all dimension with - separated with provided dimension recid
Code:-
public static str Getdimensionset(RecId recid)
{
str descriptionLedgerLoc = '';
boolean first = true;
DimensionAttributeLevelValueAllView view,viewloc;
DimensionAttributeValue dimValue;
DimensionAttributeValueGroup dimensionAttributeValueGroup;
container con;
select firstonly viewloc
where viewloc.ValueCombinationRecId==recid;
while select view order by view.ValueOrdinal asc
where view.ValueCombinationRecId == recid
&& view.DimensionAttributeValueGroup==viewloc.DimensionAttributeValueGroup
{
if (!first)
{
descriptionLedgerLoc += " - ";
}
descriptionLedgerLoc +=view.DisplayValue ;
first = false;
}
return descriptionLedgerLoc;
}
Note:-dimensions will get with - separated
Thank you!!
To get Dimensions value as displayed in Control level
Code:-
LedgerDimensionFacade::getDisplayValueForLedgerDimension(DimensionRecid);
Note:- dimensions will get with ~ separatedlink to run a class from front end through sysclassrunner
dynamics url/?mi=SysClassRunner&cls=classname
Scenario:- When you need to get amount with required exchange rate.
Case :- It also depends on whether we are going with Account currency exchange rate or Budget exchange rate type as shown in image below
Case 1:- If it is Budget exchange
Code:-
CurrencyCode currencyCode = SystemParameters::find().SystemCurrencyCode;
str fromcurrency='USD';
str tocurrency='CAD';
real amount=120;
CurrencyExchangeHelper currencyExchangeHelper;
currencyExchangeHelper = currencyExchangeHelper::construct();
currencyExchangeHelper.parmLedgerRecId(Ledger::current());
currencyExchangeHelper.parmExchangeRateTypeRecId(Ledger::budgetExchangeRateType());
Info(strFmt("%1",currencyExchangeHelper.calculateCurrencyToCurrency(fromcurrency, tocurrency,amount, true)));
Case 2:- If it is Account currency exchange rate
Code:-
CurrencyCode currencyCode = SystemParameters::find().SystemCurrencyCode;
str fromcurrency='USD';
str tocurrency='CAD';
real amount=120;
CurrencyExchangeHelper currencyExchangeHelper;
currencyExchangeHelper = currencyExchangeHelper::construct();
currencyExchangeHelper.parmLedgerRecId(Ledger::current());
currencyExchangeHelper.parmExchangeRateTypeRecId(Ledger::defaultExchangeRateType());
Info(strFmt("%1",currencyExchangeHelper.calculateCurrencyToCurrency(fromcurrency, tocurrency,amount, true)));
scenario :- Generally in Dynamics there are some workflows with globally and some are Legal entity specific . With association type as shown in below
Step 1:- To make a workflow global or Legal entity specific. Go to visual studio >
find the workflow type and click on properties and in Association type choose the type you need as shown in below
Note :- Don't change this for standard workflows. And can use this for Custom mostly.
Step 1:- Get Backpac file to your dev machine
Step2:- move this file to location as shown in below

Step 2 :- Navigate to Download and Install SqlPackage - SQL Server | Microsoft Learn
and scroll down for windows package as shown in below
download the file and extract the zip file
Step 3:- open the file and copy location as shown in below
Step 4:-Open commnd promt with run of administrator and run cd paste the location copied from above as shown in below
Step5:-run this command SqlPackage.exe /a:import /sf:J:\MSSQL_BACKUP\uatbackup.bacpac /tsn:localhost /tdn:AXDB_New /TargetTrustServerCertificate:True /p:CommandTimeout=1500
Step 6:-Wait for 6 hours until you see DB restored sucessfully.
Step 7:-Go to SSMS >Database >AXDB>properites>makes multiuser to single user
then Rename to AXDB_OLD
Step 8:-Rename AXDB_New (new db restored) to AXDB
Make AXDB_OLD properties to single user
Step 9:-Restart all services. Now Dev machines runs with Tier 2 database
Note:- This process is when you have been given with bacpac file (usually when we export tier 2 it will be bacpac only.most of the time we get bacpac file only).
If we get bac file we can directly restore with in few steps and lesstime in ssms itself without cmd promt.
Thank you!!
Today in this blog we learn about how to see relations between tables in pictorial representation.
Step1:- Navigate to Github https://github.com/noakesey/d365fo-entity-schema and click on releases as shown in below
Step2:- Down the first DLL file as shown in below
Step3:-Once you have downloaded the file it will shown in warning file click on three dots >Keep>Keep anyway as shown in below
Step4:-Click on the properties of the file and click on unblock and apply as shown in below
Step5:-Copy the file and place in folder
Navigation:-
C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\Extensions\jalba1yr.dr0\AddinExtensions
If jalbalyr.dr0 folder not available then paste folder in C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\Extensions
Step6:-Go to any table>rightclik>Addins>Generate entity relation schema as shown in below
Step7:-Click on outward and inward >DBML as shown in below
Step8:-Copy the whole code and click on the link as shown in below
Step9:-then click on create diagram as shown in below
Step10:-Clear existing code in left pane and paste the code copied in VS as shown in below
Thank you!!
Scenario:- We can do some actions in workflow through code
1) Submit:-
Code:-
WorkflowTypeName workflowTypeName = workflowTypeStr(CustomWorkflowType);
Workflow::activateFromWorkflowType(workflowTypeName, Table.RecId, workflowComment, NoYes::No);
2) Approve:-
Code:-
WorkflowWorkItemTable workflowWorkItemTable;
WorkflowTypeName workflowTypeName = workflowTypeStr(CustomWorkflowType);
select firstonly workflowWorkItemTable
where workflowWorkItemTable.Type == WorkflowWorkItemType::WorkItem
&& workflowWorkItemTable.Status == WorkflowWorkItemStatus::Pending
&& workflowWorkItemTable.RefTableId== tableNum(EmployeeTable)
&& workflowWorkItemTable.RefRecId == 5637144576;
if(workflowWorkItemTable)
{
WorkflowWorkItemActionManager::dispatchWorkItemAction(workflowWorkItemTable,"Auto Approve by system",curUserId(), WorkflowWorkItemActionType::Complete,menuitemDisplayStr(Employee));
}
3) cancel or recall :-
Code:-
WorkflowWorkItemTable workflowWorkItemTable;
WorkflowTypeName workflowTypeName = workflowTypeStr(CustomWorkflowType);
select firstonly workflowWorkItemTable
where workflowWorkItemTable.Type == WorkflowWorkItemType::WorkItem
&& workflowWorkItemTable.Status == WorkflowWorkItemStatus::Pending
&& workflowWorkItemTable.RefTableId== tableNum(EmployeeTable)
&& workflowWorkItemTable.RefRecId == 5637146826;
if(workflowWorkItemTable)
{
Workflow::cancelWorkflow(workflowWorkItemTable.CorrelationId, "cancel by code");
}
4) Resume:-
Code:-
Workflowtrackingstatustable workflowTrackingStatusTable;
select * from workflowTrackingStatusTable where workflowTrackingStatusTable.CONTEXTRECID == 5637147576
&& workflowTrackingStatusTable.CONTEXTTABLEID == tableNum(EmployeeTable);
if(workflowTrackingStatusTable)
{
Workflow::resumeWorkflow(workflowTrackingStatusTable.CorrelationId, "resume by code");
}
Thankyou!!
Scenario:- If you want to run some logic in workflow at particular we can use WorkflowAutomatictask
Step1:- create a class
Code:-
class CustomWorkflowAutomatedEvnentHandler implements WorkflowElementExecutionEventHandler
{
public void execute(WorkflowElementEventArgs _workflowElementEventArgs)
{
WorkflowContext workflowContext = _workflowElementEventArgs.parmWorkflowContext();
RecId recid = workflowContext.parmRecId();
EmployeeTable emptable;
select * from emptable where emptable.RecId == recid;
info(strFmt("%1",emptable.EmployeeId));
}
}
Step2:- Add Workflowautomatictask and give properties as shown in below
Step3:-In the supported elements add this automatic task and give type as automatictask.
Step4:-Open frontend and drag this automatictask to run some logic as shown in below
Thankyou!!
Step1:-Create a class code as follows
Code;-
class CustomworkflowAssignmentProviderClass implements WorkflowParticipantprovider
{
public WorkflowParticipantTokenList getParticipantTokens()
{
WorkflowParticipantTokenList tokens = WorkflowParticipantTokenList::construct();
tokens.add("Level1","Level 1");
return tokens;
}
public WorkflowUserList resolve(WorkflowContext _context,
WorkflowParticipantToken _participantTokenName)
{
WorkflowUserList userList = WorkflowUserList::construct();
EmployeeTable emptable;
UserGroupInfo usergroupinfo;
UserGroupList usergrouplist;
switch(_participantTokenName)
{
case "Level1" :
select * from emptable
where emptable.RecId == _context.parmRecId();
if(emptable.AssigneeType == AssigneeType::User)
{
userList.add(emptable.User);
}
else
{
while select usergrouplist
where usergrouplist.groupId == emptable.User
{
userList.add(emptable.User);
}
}
break;
}
if (userList.getCount() == 0)
{
throw error(strFmt("User can not found"));
}
return userList;
}
}
Step2:-Add Workflow participant provide and give AssignmentProviderClass in properties and add
Workflow type with new element give workflow type as shown in below
Step3:-Build and sync then add this assignment provide in assignment section in Workflow configurator
That's all
Thankyou
If we want get output of workflow like dropdialog as some of standard workflows please follow steps
output expected:-
Step1:-Please develop basic workflow first by using link below
https://manidynamics.blogspot.com/2026/02/custom-workflow-in-d365fo.html
Step2:-Go to any standard forms , here i have chosen Purchtable confirm workflow and locate control as shown in below
Step3:-Go to that form and duplicate similar to your project as shown in below
Step4:-Change cord in Formlevel replace with your table and workflowtype names and in cansubmit instead caller use record.cansubmitworkflow
Step5:-Create a display menuitem for this form
Step6:-Create a buttongroup control and add button and give properties of menuitem created in above step.Also change normalimage property to Workflow as shown in below
Step7:-Remove formdesign properties workflowtype
Output :-
configure workflow in frontend .
Thankyou!!
In this blog we see all about Workflows development in D365fo
Output as shown in below
/// The CustomWorkflowTypeEventHandler workflow event handler.
/// </summary>
public class CustomWorkflowTypeEventHandler implements WorkflowCanceledEventHandler,
WorkflowCompletedEventHandler,
WorkflowStartedEventHandler
{
public void started(WorkflowEventArgs _workflowEventArgs)
{
// TODO: Write code to execute once the workflow is started.
EmployeeTable::updateWorkFlowStatus(_workflowEventArgs.parmWorkflowContext().parmRecId(), WorkflowStatus::Pending);
}
public void canceled(WorkflowEventArgs _workflowEventArgs)
{
// TODO: Write code to execute once the workflow is canceled.
EmployeeTable::updateWorkFlowStatus(_workflowEventArgs.parmWorkflowContext().parmRecId(), WorkflowStatus::Draft);
}
public void completed(WorkflowEventArgs _workflowEventArgs)
{
// TODO: Write code to execute once the workflow is completed.
EmployeeTable::updateWorkFlowStatus(_workflowEventArgs.parmWorkflowContext().parmRecId(), WorkflowStatus::Completed);
}
}
Step8:- Add code in Submitmanagerclass
Code:-
/// <summary>
/// The CustomWorkflowTypeSubmitManager menu item action event handler.
/// </summary>
public class CustomWorkflowTypeSubmitManager
{
public static void main(Args _args)
{
// TODO: Write code to execute once a work item is submitted.
EmployeeTable employeetable;
CustomWorkflowTypeSubmitManager submitManger = new CustomWorkflowTypeSubmitManager();
recId _recId =_args.record().RecId;
WorkflowCorrelationId _workflowCorrelationId;
workflowTypeName _workflowTypeName = workFlowTypeStr("CustomWorkflowType");
WorkflowComment note = "";
WorkflowSubmitDialog workflowSubmitDialog;
workflowSubmitDialog = WorkflowSubmitDialog::construct(_args.caller().getActiveWorkflowConfiguration());
workflowSubmitDialog.run();
if (workflowSubmitDialog.parmIsClosedOK())
{
employeetable = _args.record();
note = workflowSubmitDialog.parmWorkflowComment();
try
{
ttsbegin;
_workflowCorrelationId = Workflow::activateFromWorkflowType(_workflowTypeName, employeetable.RecId, note, NoYes::No);
employeetable.WorkflowStatus = WorkflowStatus::Submitted;
employeetable.update();
ttscommit;
info("Submitted to workflow.");
}
catch (Exception::Error)
{
error("Error on workflow activation.");
}
}
_args.caller().updateWorkFlowControls();
}
}
Step 9:-Add Workflow Approval
Provide details created in above steps
After clicking next system will create some classes and action menuitems
Step10:-Add code in Approval event handler
Code:-
/// <summary>
/// The CustomWorkflowApprovalEventHandler workflow outcome event handler.
/// </summary>
public final class CustomWorkflowApprovalEventHandler implements WorkflowElementCanceledEventHandler,
WorkflowElemChangeRequestedEventHandler,
WorkflowElementCompletedEventHandler,
WorkflowElementReturnedEventHandler,
WorkflowElementStartedEventHandler,
WorkflowElementDeniedEventHandler,
WorkflowWorkItemsCreatedEventHandler
{
public void started(WorkflowElementEventArgs _workflowElementEventArgs)
{
// TODO: Write code to execute once the workflow is started.
EmployeeTable::updateWorkFlowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), WorkflowStatus::InReview);
}
public void canceled(WorkflowElementEventArgs _workflowElementEventArgs)
{
// TODO: Write code to execute once the workflow is canceled.
EmployeeTable::updateWorkFlowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), WorkflowStatus::Draft);
}
public void completed(WorkflowElementEventArgs _workflowElementEventArgs)
{
// TODO: Write code to execute once the workflow is completed.
EmployeeTable::updateWorkFlowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), WorkflowStatus::Completed);
}
public void denied(WorkflowElementEventArgs _workflowElementEventArgs)
{
// TODO: Write code to execute once the workflow is denied.
EmployeeTable::updateWorkFlowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), WorkflowStatus::Rejected);
}
public void changeRequested(WorkflowElementEventArgs _workflowElementEventArgs)
{
// TODO: Write code to execute once change is requested for the workflow.
EmployeeTable::updateWorkFlowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), WorkflowStatus::ChangeRequest);
}
public void returned(WorkflowElementEventArgs _workflowElementEventArgs)
{
// TODO: Write code to execute once the workflow is returned.
EmployeeTable::updateWorkFlowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), WorkflowStatus::Rejected);
}
public void created(WorkflowWorkItemsEventArgs _workflowWorkItemsEventArgs)
{
// TODO: Write code to execute once work items are created.
}
}
Step11:-Write code in Resubmit class
/// <summary>
/// The CustomWorkflowApprovalResubmitActionMgr menu item action event handler.
/// </summary>
public class CustomWorkflowApprovalResubmitActionMgr
{
public static void main(Args _args)
{
// TODO: Write code to execute once work items are resubmitted.
if (!_args.record() || !_args.caller())
{
throw error(Error::wrongUseOfFunction(funcName()));
}
WorkflowWorkItemTable workItem = _args.caller().getActiveWorkflowWorkItem();
if (workItem)
{
try
{
WorkflowWorkItemActionDialog dialog = WorkflowWorkItemActionDialog::construct(
workItem,
WorkflowWorkItemActionType::Resubmit,
new MenuFunction(_args.menuItemName(),_args.menuItemType()));
dialog.run();
if (dialog.parmIsClosedOK())
{
workItem = _args.caller().getActiveWorkflowWorkItem();
WorkflowWorkItemActionManager::dispatchWorkItemAction(
workItem,
dialog.parmWorkflowComment(),
dialog.parmTargetUser(),
WorkflowWorkItemActionType::Resubmit,
_args.menuItemName());
RecID recID = _args.record().RecId;
ttsbegin;
EmployeeTable::updateWorkFlowStatus(recID, WorkflowStatus::Submitted);
info("@AccountsPayable:VendBankAccountChangeProposalResubmit_Success");
ttscommit;
}
}
catch(exception::Error)
{
info("@AccountsPayable:VednBankAccountChangeProposalResubmit_Error");
}
}
// make sure changes in status are reflected on the caller
if (FormDataUtil::isFormDataSource(_args.record()))
{
FormDataSource callerDS = FormDataUtil::getFormDatasource(_args.record());
callerDS.reread();
callerDS.refresh();
}
_args.caller().updateWorkflowControls();
}
}
Step12:-Change labels for action menu items that have been created by systems
Note:- for cancel put Recall
Step13:-In the Workflowtype add in supported elements and in the properties give workflowapproval and give Approval in type as shown in below
Step 14:-In form design properties changes properties of Workflow
Step15:- Create security privilege maintain and view for all action menuitems that have created in workflow
Thankyou!!
using Microsoft.Dynamics.AX.Framework.Utilities;
using Microsoft.Dynamics.ApplicationPlatform.Environment;In this blog we see how to send mail through SMTP by using template
Step 1:-
Code :-
Map templateTokens;
templateTokens = new Map(Types::String, Types::String);
SysMailerSMTP mailer = new SysMailerSMTP();
try
{
switch (workflowContext.parmTableId())
{
case tablenum(LedgerJournaltable) :
SysMailerMessageBuilder builder = new SysMailerMessageBuilder();
SysEmailParameters parameters = SysEmailParameters::find();
SysEmailMessageSystemTable messageTable;
str envUrl = URLUtility::getUrl();
select messageTable
where messageTable.EmailId == "Template name";
templateTokens.insert("envUrl",envUrl);
templateTokens.insert("Ledger journal table.JournalName",strFmt("%1",ledgerJournaltable.JournalName));
if (parameters.SMTPRelayServerName)
{
mailer.smtpRelayServer(parameters.SMTPRelayServerName,
parameters.SMTPPortNumber,
parameters.SMTPUserName,
SysEmailParameters::password(),
parameters.SMTPUseNTLM,parameters.SMTPRequireSSL);
}
else
{
warning("ServerNotFound");
}
if (messageTable.EmailId)
{
builder.setFrom(parameters.SMTPUserName);
builder.addTo(conPeek(con, i)).setSubject(strFmt("%1",messageTable.Subject + ledgerJournaltable.JournalNum)).setBody(SysEmailMessage::stringExpand(messageTable.Mail, SysEmailTable::htmlEncodeParameters(templateTokens)));
SysMailerFactory::getNonInteractiveMailer().sendNonInteractive(builder.getMessage());
info('Mail successfully sent');
}
}
}
catch (Exception::Error)
{
throw error("@SYS326780");
}
}
Today in this blog we will see how to debug in d365fo with Tier2 env's(uat,gc,preprod)
Step 1:- Request JIT access
If you have LCS access take JIT by providing IP of DEV Env or else
Request from Admin We will get credentials in the format shown below
Servername/DBname
Username
Password
Step 2:- Turn off All Services like w3,worldwide,batches services
Step 3:- Go to Folder from Filemanger K>AOSService\webroot as shown in image below and locate webconfig file
Step 5:- Copy the file and place it on desktop as back once debugging we need make back local DB
Step 6:- After that Right Click and open with latest visual studio(VS2022) as shown in below
Step 7:- After opening the file Press ctrlf and search AXDB and what ever credentials we got from LCS Replace with them as shown in below
Step 8:- After that for password ctrlf search for Password then change for Databaseacces.Sqlpwd as shown in below
Step 9:- Save the changes and restart all services and start debugging !!
Step 10:- Once you finish the process down the services and replace file and Turn on services to get back to normal
Thank You!!
code:- appl.setDefaultCompany(Legalentitycode, false);