Tuesday, June 23, 2015
C# - Creating a custom AX AIF web service that accesses logic defined within an AX AOT Class object.
In order to support legacy applications sometimes you may need to pull in data from AX into standalone applications.
Below will show you how to pull in the customer names via a custom class defined within AX but called within C#
Step 1(in AX) Create Class called CustomerInfo.
Step 2(in AX) Add method called getCustomerNameList() It should contain the following
/// <summary>
/// Get a list of customer names
/// </summary>
/// <returns>
/// List of customer names
/// </returns>
/// <remarks>
/// Used for AIF Intergration with Escalus
/// </remarks>
[SysEntryPointAttribute(true),AifCollectionTypeAttribute('return', Types::String)]
public List getCustomerNameList()
{
CustTable custTable;
DirPartyTable dirPartyTable;
List customerNames = new List(Types::String);
//select all customers and names
while select * from custTable
join dirPartyTable
where dirPartyTable.RecId == custTable.Party
{
//save the current customer
customerNames.addEnd(dirPartyTable.Name);
}
return customerNames;
}
Step 3(in AX) Create a new service called CustomerInfo. Defined the class as 'CustomerInfo' under the properties for the service.
Then right click on the 'Operations' node on the new service and defined the method (under properties) as getCustomerNameList or whatever you called the method in step 2.
Step 4(in AX) Create a new service group called Customers and include the service CustomerInfo or whatever the service was called in step 3.
Step 5(in C#) Add the following webservice to your project http://<AOSServer>:8101/DynamicsAx/Services/Customers (Customers is the service group created in step 4)
Step 6(in C#) Add the following using statement using <C# Project Class Name>.<WebService Name> example: using AXAIFTest.Customers;
Step 7(in C#) Add the following code to your load statement or a method that can be called via load
CustomerInfoClient axClient = new CustomerInfoClient();
CallContext axContext = new CallContext();
//called the method that exists within an AX class object
string[] customerList = axClient.getCustomerNameList(axContext);
CustomerNames.DataSource = customerList;
As you can see from my previous posts of http://axcalated.blogspot.com/2015/06/c-creating-aif-webservice-to-access-ax.html and http://axcalated.blogspot.com/2014/10/accessing-ax-custtable-dirpatytable.html you can access data and/or logic from within
AX multiple ways. It really just depends on where you want to write the majority your code (C#, AX/X++, or by creating aot objects within AX) and what are the requirements for the client. Personally I would recommend writing a web service to access your data
that way it could not only be implemented within C#/.NET framework languages but any language that supports accessing web services which is really just about any language these days. The only requirement as well for accessing a web service is intranet/internet access
so it leaves a small footprint on the users system along with "planning for the future" as we all know everything is moving to the web including AX 7.
C# - Creating an AX AIF webservice to access AX CustTable & DirPatyTable (Customer Info) query
In order to support legacy applications sometimes you may need to pull in data from AX into standalone applications.
Below will show you how to pull in customer id's + names (CustTable + DirPartyTable) via a webservice from a query that is defined within AX that will allow you to accomplish the same thing as http://axcalated.blogspot.com/2014/10/accessing-ax-custtable-dirpatytable.html
but without requiring the user to install AX as its a webservice so technically you could implament this solution in any language.
Step 1(in AX) Create a query called CustomerInfo. This should contain the table CustTable and sub datasource table DirPartyTable. Only include the fields CustTable.AccountNum & DirPartyTable.Name so that the footprint is as small as can be.
Its a good idea to also add an order by of DirPartyTable.Name so the results are sorted A-Z. But you can sort by number as well.
Step 2(in C#) Add the following webservice to your project http://<AOSServer>:8101/DynamicsAx/Services/QueryService (by default the port is 8101 but if you changed it during the install you would need to change it in the url as well.
This is a default/built-in webservice provided by AX and should not require you to create anything within AX in order to access it.
Step 3 (in C#) Add the following code
//this will create a container for the customer number & name
public class Customer
{
public string AccountNum { get; set; }
public string Name { get; set; }
}
add the following to the load method or create a new method that can be called from the load method
List<Customer> axList = new List<Customer>();
DataSet dataSet;
AXQueryService.QueryServiceClient client = new AXQueryService.QueryServiceClient();
AXQueryService.Paging paging = null;
//execute a static query defined with the AX AOT
dataSet = client.ExecuteStaticQuery("CustomerInfo", ref paging);
//go thru all of the results of the query and add them to your customer object list
for (int custCounter = 0; custCounter <= dataSet.Tables[0].Rows.Count - 1; ++custCounter)
{
//get the current row information for the 2 tables
DataRow custRow = dataSet.Tables["CustTable"].Rows[custCounter];
DataRow dirPartyTableRow = dataSet.Tables["DirPartyTable.DirPartyTable"].Rows[custCounter];
//create new customer entry
Customer axCustomer = new Customer()
{
AccountNum = custRow["AccountNum"].ToString(),
Name = dirPartyTableRow["Name"].ToString()
};
//add current customer to the overall list
axList.Add(axCustomer);
}
//tie our newly created customer list to your data source
CustomerNames.DataSource = axList;
CustomerNames.DisplayMember = "Name";
CustomerNames.ValueMember = "AccountNum";
CustomerIds.DataSource = axList;
CustomerIds.DisplayMember = "AccountNum";
CustomerIds.ValueMember = "AccountNum";
That's it. You should now have 2 dropdowns being displayed on the form that are linked to each other.
Below will show you how to pull in customer id's + names (CustTable + DirPartyTable) via a webservice from a query that is defined within AX that will allow you to accomplish the same thing as http://axcalated.blogspot.com/2014/10/accessing-ax-custtable-dirpatytable.html
but without requiring the user to install AX as its a webservice so technically you could implament this solution in any language.
Step 1(in AX) Create a query called CustomerInfo. This should contain the table CustTable and sub datasource table DirPartyTable. Only include the fields CustTable.AccountNum & DirPartyTable.Name so that the footprint is as small as can be.
Its a good idea to also add an order by of DirPartyTable.Name so the results are sorted A-Z. But you can sort by number as well.
Step 2(in C#) Add the following webservice to your project http://<AOSServer>:8101/DynamicsAx/Services/QueryService (by default the port is 8101 but if you changed it during the install you would need to change it in the url as well.
This is a default/built-in webservice provided by AX and should not require you to create anything within AX in order to access it.
Step 3 (in C#) Add the following code
//this will create a container for the customer number & name
public class Customer
{
public string AccountNum { get; set; }
public string Name { get; set; }
}
add the following to the load method or create a new method that can be called from the load method
List<Customer> axList = new List<Customer>();
DataSet dataSet;
AXQueryService.QueryServiceClient client = new AXQueryService.QueryServiceClient();
AXQueryService.Paging paging = null;
//execute a static query defined with the AX AOT
dataSet = client.ExecuteStaticQuery("CustomerInfo", ref paging);
//go thru all of the results of the query and add them to your customer object list
for (int custCounter = 0; custCounter <= dataSet.Tables[0].Rows.Count - 1; ++custCounter)
{
//get the current row information for the 2 tables
DataRow custRow = dataSet.Tables["CustTable"].Rows[custCounter];
DataRow dirPartyTableRow = dataSet.Tables["DirPartyTable.DirPartyTable"].Rows[custCounter];
//create new customer entry
Customer axCustomer = new Customer()
{
AccountNum = custRow["AccountNum"].ToString(),
Name = dirPartyTableRow["Name"].ToString()
};
//add current customer to the overall list
axList.Add(axCustomer);
}
//tie our newly created customer list to your data source
CustomerNames.DataSource = axList;
CustomerNames.DisplayMember = "Name";
CustomerNames.ValueMember = "AccountNum";
CustomerIds.DataSource = axList;
CustomerIds.DisplayMember = "AccountNum";
CustomerIds.ValueMember = "AccountNum";
That's it. You should now have 2 dropdowns being displayed on the form that are linked to each other.
Monday, June 22, 2015
How to get contact's email addresses from a customer or vendor
How to get customer email addresses from all contacts associated with a customer from Company/Accounts receivable/Common/Customers/All customers/Contacts/Contact Info
Method exists on \Tables\CustTable
public container getInvoiceContacts()
{
container invoiceEmailAddresses;
DirPartyTable dirParty;
LogisticsElectronicAddress electronicAddress;
DirPartyLocation dirPartyLoc;
ContactPerson contactPerson;
//find all of the customer contact email addresses that are currently active
while select * from contactPerson
where contactPerson.CustAccount == this.AccountNum && contactPerson.Inactive == NoYes::No
join RecId from dirParty
where dirParty.RecId == contactPerson.Party
join Location, Type, SendInvoice, Locator FROM electronicAddress
EXISTS JOIN Location, Party FROM dirPartyLoc
WHERE electronicAddress.Location == dirPartyLoc.Location && dirParty.RecId==dirPartyLoc.Party
&& electronicAddress.Type == LogisticsElectronicAddressMethodType::Email
{
invoiceEmailAddresses += electronicAddress.Locator;
}
return invoiceEmailAddresses;
}
How to get vendor email addresses from all contacts associated with a vendor from Company/Accounts payable/Common/Vendors/All vendors/Contacts/Contact Info
Method exists on \Tables\VendTable
public container getRemittanceContacts()
{
container remittanceEmailAddresses;
DirPartyTable dirParty;
LogisticsElectronicAddress electronicAddress;
DirPartyLocation dirPartyLoc;
ContactPerson contactPerson;
//find all of the vendor contact email addresses that are currently active
while select * from contactPerson
where contactPerson.ContactForParty == this.Party && contactPerson.Inactive == NoYes::No
join RecId from dirParty
where dirParty.RecId == contactPerson.Party
join Location, Type, SendRemittance, Locator FROM electronicAddress
EXISTS JOIN Location, Party FROM dirPartyLoc
WHERE electronicAddress.Location == dirPartyLoc.Location && dirParty.RecId==dirPartyLoc.Party
&& electronicAddress.Type == LogisticsElectronicAddressMethodType::Email
{
remittanceEmailAddresses += electronicAddress.Locator;
}
return remittanceEmailAddresses;
}
As you can see customer & vendors operate pretty much the same except for the association of custaccount(customer) vs contactforparty(vendor) on the contactperson table.
I'm posting this since AX seems to love to use the view "DirPartyPostalAddressView" as the main listing for these contacts on the form. So it can take a little while of digging to discover the true relationship between these tables.
Method exists on \Tables\CustTable
public container getInvoiceContacts()
{
container invoiceEmailAddresses;
DirPartyTable dirParty;
LogisticsElectronicAddress electronicAddress;
DirPartyLocation dirPartyLoc;
ContactPerson contactPerson;
//find all of the customer contact email addresses that are currently active
while select * from contactPerson
where contactPerson.CustAccount == this.AccountNum && contactPerson.Inactive == NoYes::No
join RecId from dirParty
where dirParty.RecId == contactPerson.Party
join Location, Type, SendInvoice, Locator FROM electronicAddress
EXISTS JOIN Location, Party FROM dirPartyLoc
WHERE electronicAddress.Location == dirPartyLoc.Location && dirParty.RecId==dirPartyLoc.Party
&& electronicAddress.Type == LogisticsElectronicAddressMethodType::Email
{
invoiceEmailAddresses += electronicAddress.Locator;
}
return invoiceEmailAddresses;
}
How to get vendor email addresses from all contacts associated with a vendor from Company/Accounts payable/Common/Vendors/All vendors/Contacts/Contact Info
Method exists on \Tables\VendTable
public container getRemittanceContacts()
{
container remittanceEmailAddresses;
DirPartyTable dirParty;
LogisticsElectronicAddress electronicAddress;
DirPartyLocation dirPartyLoc;
ContactPerson contactPerson;
//find all of the vendor contact email addresses that are currently active
while select * from contactPerson
where contactPerson.ContactForParty == this.Party && contactPerson.Inactive == NoYes::No
join RecId from dirParty
where dirParty.RecId == contactPerson.Party
join Location, Type, SendRemittance, Locator FROM electronicAddress
EXISTS JOIN Location, Party FROM dirPartyLoc
WHERE electronicAddress.Location == dirPartyLoc.Location && dirParty.RecId==dirPartyLoc.Party
&& electronicAddress.Type == LogisticsElectronicAddressMethodType::Email
{
remittanceEmailAddresses += electronicAddress.Locator;
}
return remittanceEmailAddresses;
}
As you can see customer & vendors operate pretty much the same except for the association of custaccount(customer) vs contactforparty(vendor) on the contactperson table.
I'm posting this since AX seems to love to use the view "DirPartyPostalAddressView" as the main listing for these contacts on the form. So it can take a little while of digging to discover the true relationship between these tables.
Monday, June 8, 2015
Unable to save. Version of [object] on the server is newer
I seem to be getting the following message on a very specific object whenever I check it out and make a modification. Unable to save. Version of <object> on the server is newer.
You usually get this message whenever someone else has modified the object since you opened MorphX/AX. However I was the one who checked this out and have tried closing out of AX completely and I would still get the message and I know no one else is accessing this object.
I found that sometimes it would allow me to save the change but then would never show it in the Client. I would restart the client and check the AOT object but it would not have saved my change made. If I exported the object from a different environment and imported into the dev environment (where is the issue was happening) then everything from the import would save ok but it would still not allow me to manually make changes.
In order to fix this error right click (in MorphX/AOT) on the object and choose "Restore" This doesn't seem to discharge my changes but now whenever I add something to this object it seems to save it to the DB and displays correctly in the client.
According to https://msdn.microsoft.com/en-us/library/aa846291.aspx this shortcut "Reads the selected element from the database and discards the changes that were made since the last save."
You usually get this message whenever someone else has modified the object since you opened MorphX/AX. However I was the one who checked this out and have tried closing out of AX completely and I would still get the message and I know no one else is accessing this object.
I found that sometimes it would allow me to save the change but then would never show it in the Client. I would restart the client and check the AOT object but it would not have saved my change made. If I exported the object from a different environment and imported into the dev environment (where is the issue was happening) then everything from the import would save ok but it would still not allow me to manually make changes.
In order to fix this error right click (in MorphX/AOT) on the object and choose "Restore" This doesn't seem to discharge my changes but now whenever I add something to this object it seems to save it to the DB and displays correctly in the client.
According to https://msdn.microsoft.com/en-us/library/aa846291.aspx this shortcut "Reads the selected element from the database and discards the changes that were made since the last save."
Wednesday, May 13, 2015
Worker cannot be deleted while dependent Position worker assignments exist. Delete dependent Position worker assignments and try again
While trying to remove a worker from the HR module we got the following error and AX would not allow us to remove the worker.
"Worker cannot be deleted while dependent Position worker assignments exist. Delete dependent Position worker assignments and try again"
Currently in order to fix this you need to do the following
Step 1
Company/Human resources/Common/Organization/Positions/Positions
Find the worker name > edit the record > go to Worker assignment > End > choose a date time that has already happened unless you want to wait for the nightly job
Step 2
Company/Human resources/Common/Workers/Workers
Find the worker name > edit the record > employment (menu on left side) > Employment details > edit > change employment end date to same time as the one listed in step 1. Once you hit ok the record will be removed
I didn't get a chance to test this but executing step 2 might actually execute step 1 as well. I just don't have any more records atm that I can verify this on.
"Worker cannot be deleted while dependent Position worker assignments exist. Delete dependent Position worker assignments and try again"
Currently in order to fix this you need to do the following
Step 1
Company/Human resources/Common/Organization/Positions/Positions
Find the worker name > edit the record > go to Worker assignment > End > choose a date time that has already happened unless you want to wait for the nightly job
Step 2
Company/Human resources/Common/Workers/Workers
Find the worker name > edit the record > employment (menu on left side) > Employment details > edit > change employment end date to same time as the one listed in step 1. Once you hit ok the record will be removed
I didn't get a chance to test this but executing step 2 might actually execute step 1 as well. I just don't have any more records atm that I can verify this on.
Monday, April 20, 2015
Error executing code: Insufficient memory to run script. (objects with large buffer ex: xml reponse streams)
If you see the error "Error executing code: Insufficient memory to run script"
This means that an object/variable within AX is trying to load something into a variable that exceeds the max buffer size for a variable.
When you see this error you have 2 options to fix the issue. 1. reprogram the large object to only load sections at a time. However the bad part about this is you cant just load the large objects in chunks and then combine them into 1 because when you combine them they also can not exceed the max limit. So you would need to grab part 1/4 and display/process. Then dispose of the object and get part 2/4 then dispose and get part 3/4 if you wanted to view 1/4 then you would need to dispose of 3/4 then reload part 1/4.
However you also have option 2 which is you can up the maxbuffersize for variables. This is done via the ax config file (.axc files) that the client loads. This should not be confused with the buffer size set on an AOS server that is normally 48KB. By default AX is set to allow 4mb for this variable buffer size property however in some instances doing the "partial load" doesn't make sense so you need to bump it. For instance when returning large XML data response streams you may need to up this so you can read the response in and then parse it.
If you wish to up the size of the maxbuffersize for variables within X++ the setting that needs to be added to the config file is
maxbuffersize,Text,125
where 125 is the size in MB of the new max buffer size. You can make it 0 which will allow it to be unlimited however that is highly not recommend.
You can also add the change via the registry however in 2012 R2 I did not have much luck getting the client to respect it.
Client Registry
Key name: [HKCU\Software\Microsoft\Dynamics\6.0\Configuration\]
Value name: maxbuffersize
Value type: REG_SZ
Value: 125
This means that an object/variable within AX is trying to load something into a variable that exceeds the max buffer size for a variable.
When you see this error you have 2 options to fix the issue. 1. reprogram the large object to only load sections at a time. However the bad part about this is you cant just load the large objects in chunks and then combine them into 1 because when you combine them they also can not exceed the max limit. So you would need to grab part 1/4 and display/process. Then dispose of the object and get part 2/4 then dispose and get part 3/4 if you wanted to view 1/4 then you would need to dispose of 3/4 then reload part 1/4.
However you also have option 2 which is you can up the maxbuffersize for variables. This is done via the ax config file (.axc files) that the client loads. This should not be confused with the buffer size set on an AOS server that is normally 48KB. By default AX is set to allow 4mb for this variable buffer size property however in some instances doing the "partial load" doesn't make sense so you need to bump it. For instance when returning large XML data response streams you may need to up this so you can read the response in and then parse it.
If you wish to up the size of the maxbuffersize for variables within X++ the setting that needs to be added to the config file is
maxbuffersize,Text,125
where 125 is the size in MB of the new max buffer size. You can make it 0 which will allow it to be unlimited however that is highly not recommend.
You can also add the change via the registry however in 2012 R2 I did not have much luck getting the client to respect it.
Client Registry
Key name: [HKCU\Software\Microsoft\Dynamics\6.0\Configuration\]
Value name: maxbuffersize
Value type: REG_SZ
Value: 125
Monday, April 13, 2015
Cannot create a record in tablename. The record already exists. / Get new recid for a table
I've seen this error a couple times within the past week after we migrated our data from PROD into DEV
"Cannot create a record in <table description> (<table name>). The record already exists."
What I was finding is the index was ok and everything was unique but for some odd reason we kept getting this error, even though I did a search on the data that was being inserted and it did not exist like the system was telling us.
What I figured out is sometimes the recid count gets messed up with transferring data and you need to reset it to a value greater than the max rec id of the current table. Here are the steps to fix it.
1. Create a Job to get the table id of the table having problems inserting data
static void GetTableIdFromNameJob(Args _args)
{
info(strFmt("%1", tableName2id("<table name>")));
}
2. In sql mgt studio
select max(recid) from <table name from step 1>
3. In sql mgt studio
Edit table SYSTEMSEQUENCES
Select the record where tabid = '<table id from info box in step 1>
Take the max id from step 2 and add 100 to it to be safe and update the field 'nextval' from systemsequences on the tableid you have selected.
4. Restart AOS (the changes will not take affect until you restart the AOS)
"Cannot create a record in <table description> (<table name>). The record already exists."
What I was finding is the index was ok and everything was unique but for some odd reason we kept getting this error, even though I did a search on the data that was being inserted and it did not exist like the system was telling us.
What I figured out is sometimes the recid count gets messed up with transferring data and you need to reset it to a value greater than the max rec id of the current table. Here are the steps to fix it.
1. Create a Job to get the table id of the table having problems inserting data
static void GetTableIdFromNameJob(Args _args)
{
info(strFmt("%1", tableName2id("<table name>")));
}
2. In sql mgt studio
select max(recid) from <table name from step 1>
3. In sql mgt studio
Edit table SYSTEMSEQUENCES
Select the record where tabid = '<table id from info box in step 1>
Take the max id from step 2 and add 100 to it to be safe and update the field 'nextval' from systemsequences on the tableid you have selected.
4. Restart AOS (the changes will not take affect until you restart the AOS)
Tuesday, April 7, 2015
AX client crashes whenever you check out a label file that is in version control/TFS (Dynamics AX 2012 R2)
I ran across something funky today where whenever we tried to check out or modify a label file it would crash the AX Client.
The following is present within the event viewer logs
Application: Ax32.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
Stack:
at Microsoft.Dynamics.Kernel.Client.ActionPaneInterop.ClickEventHelper.Clicked(System.Object, System.EventArgs)
at Microsoft.Dynamics.Framework.UI.WinForms.Controls.ActionItem.OnButtonClick()
at Microsoft.Dynamics.Framework.UI.WinForms.Controls.ActionButton.OnMouseUp(System.Windows.Forms.MouseEventArgs)
at System.Windows.Forms.Control.WmMouseUp(System.Windows.Forms.Message ByRef, System.Windows.Forms.MouseButtons, Int32)
at System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message ByRef)
at System.Windows.Forms.Control+ControlNativeWindow.OnMessage(System.Windows.Forms.Message ByRef)
at System.Windows.Forms.Control+ControlNativeWindow.WndProc(System.Windows.Forms.Message ByRef)
at System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr)
at <Module>._wWinMainCRTStartup()
It appears there is a KB/Hot fix for this issue listed under
KB 2902776, Bug Id 773311: Access violations when synchronizing, checking in or checking out with TFS
It will have you modify the following objects
\Class\SysLabelFile\ & \tables\SysVersionControlSynchronizeLog
Take a look within Lifecycle services for the official code changes on these objects. Its a pretty quick fix though.
The following is present within the event viewer logs
Application: Ax32.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
Stack:
at Microsoft.Dynamics.Kernel.Client.ActionPaneInterop.ClickEventHelper.Clicked(System.Object, System.EventArgs)
at Microsoft.Dynamics.Framework.UI.WinForms.Controls.ActionItem.OnButtonClick()
at Microsoft.Dynamics.Framework.UI.WinForms.Controls.ActionButton.OnMouseUp(System.Windows.Forms.MouseEventArgs)
at System.Windows.Forms.Control.WmMouseUp(System.Windows.Forms.Message ByRef, System.Windows.Forms.MouseButtons, Int32)
at System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message ByRef)
at System.Windows.Forms.Control+ControlNativeWindow.OnMessage(System.Windows.Forms.Message ByRef)
at System.Windows.Forms.Control+ControlNativeWindow.WndProc(System.Windows.Forms.Message ByRef)
at System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr)
at <Module>._wWinMainCRTStartup()
It appears there is a KB/Hot fix for this issue listed under
KB 2902776, Bug Id 773311: Access violations when synchronizing, checking in or checking out with TFS
It will have you modify the following objects
\Class\SysLabelFile\ & \tables\SysVersionControlSynchronizeLog
Take a look within Lifecycle services for the official code changes on these objects. Its a pretty quick fix though.
Tuesday, March 31, 2015
Duplicate type with name ‘Dynamics.Ax.application.*’ in assembly ‘Dynamics.Ax.application.* (2012 R2)
You may get an error while doing a CIL that says Duplicate type with name ‘Dynamics.Ax.application.*’ in assembly ‘Dynamics.Ax.application.* Which may be a result of you deleting an object and then reimporting it.
A result of this issue is many things within AX may stop working and if you go into
<Company>/System administration/Setup/Services and Application Integration Framework/Inbound Ports you will see many of the services have stopped and can not be restarted thus causing issues within the AX instance.
In order to fix this issue you will need to do the following(steps are listed as if you have a cluster of AOS instances)
You should now look at the inbound ports to make sure everything now starts correctly. If this does not work you will need to run a full compile of the AOS and repeat the steps listed above.
A result of this issue is many things within AX may stop working and if you go into
<Company>/System administration/Setup/Services and Application Integration Framework/Inbound Ports you will see many of the services have stopped and can not be restarted thus causing issues within the AX instance.
In order to fix this issue you will need to do the following(steps are listed as if you have a cluster of AOS instances)
- Stop all AOS instances
- Delete all files on the AOS server under C:\Program Files\Microsoft Dynamics AX\60\Server\<aos instance name>\bin\XppIL
- Connect to the model db via SQL Management studio
- Truncate the table SYSXPPASSEMBLY which lists all of the files found in step 2
- You can do this via the command: TRUNCATE TABLE SYSXPPASSEMBLY
- Start 1 AOS instance
- Run Full CIL
- Start remaining AOS instances
You should now look at the inbound ports to make sure everything now starts correctly. If this does not work you will need to run a full compile of the AOS and repeat the steps listed above.
Wednesday, March 11, 2015
Firming planned order returns error message "Can not edit a record in net requirements(ReqTrans). An Update conflict occurred to another user process deleting or changing one or more fields in the record."
When firming a planned order that has pegged orders you may get the error message
"Can not edit a record in net requirements(ReqTrans). An Update conflict occurred to another user process deleting or changing one or more fields in the record." which is
Check to see if the issue still happens, or if you now get a "forupdate was never selected or incorrect ttsbegin/commit" message go to step 2.
Step 2. Install update KB2910673
Check to see if the issue still happens. If it does go to step 3
Step 3. If you have made it this far then you are experiencing a known issue within AX. Here's what you will need to go in order to fix it.
_reqTrans.RefType = _refType;
_reqTrans.RefId = _refId;
_reqTrans.IsForecastPurch = NoYes::No;
_reqTrans.update();
//delete reqPo
_reqPO.delete(true);
and replace with the following
variable objects needed:
ReqTrans reqTransCopy, updateReqTrans;
ReqPO reqPoCopy, removeReqPO;
//update the transaction record
ttsBegin;
select forUpdate * from updateReqTrans where updateReqTrans.RecId == _reqTrans.RecId;
updateReqTrans.InventTransOrigin = _inventTransOriginId;
updateReqTrans.RefType = _refType;
updateReqTrans.RefId = _refId;
updateReqTrans.IsForecastPurch = NoYes::No;
updateReqTrans.update();
ttsCommit;
//delete the planned order
ttsBegin;
delete_from removeReqPO
where removeReqPO.RecId == _reqPO.RecId;
ttsCommit;
After completing all 3 steps the issue should be resolved.
"Can not edit a record in net requirements(ReqTrans). An Update conflict occurred to another user process deleting or changing one or more fields in the record." which is
In order to fix the issue you will need to do the following:
Step 1. Update ReqTrans
- Go to \Tables\ReqTrans
- Change the property OccEnabled from "yes" to "no"
Check to see if the issue still happens, or if you now get a "forupdate was never selected or incorrect ttsbegin/commit" message go to step 2.
Step 2. Install update KB2910673
- KB2910673 - When using the "Plan planning formula" window to firm batch orders the system displays the error "Cannot edit a record in Net requirements (ReqTrans)"
Check to see if the issue still happens. If it does go to step 3
Step 3. If you have made it this far then you are experiencing a known issue within AX. Here's what you will need to go in order to fix it.
- Go to \class\ReqTransPoMarkFirm.updateFirmedReqTrans()
- At the bottom of the method find the following code
_reqTrans.RefType = _refType;
_reqTrans.RefId = _refId;
_reqTrans.IsForecastPurch = NoYes::No;
_reqTrans.update();
//delete reqPo
_reqPO.delete(true);
and replace with the following
variable objects needed:
ReqTrans reqTransCopy, updateReqTrans;
ReqPO reqPoCopy, removeReqPO;
//update the transaction record
ttsBegin;
select forUpdate * from updateReqTrans where updateReqTrans.RecId == _reqTrans.RecId;
updateReqTrans.InventTransOrigin = _inventTransOriginId;
updateReqTrans.RefType = _refType;
updateReqTrans.RefId = _refId;
updateReqTrans.IsForecastPurch = NoYes::No;
updateReqTrans.update();
ttsCommit;
//delete the planned order
ttsBegin;
delete_from removeReqPO
where removeReqPO.RecId == _reqPO.RecId;
ttsCommit;
After completing all 3 steps the issue should be resolved.
Subscribe to:
Posts (Atom)
