I've created a custom lookup form in Axapta 3.0 in which a user can select an OprId from a ProdRoute datasource. Before displaying the lookup the ProdId is set and may not be altered by the user. The user may only select an OprId from the ProdRoute of the production order with the valid ProdId. According to documentation, one can prevent the user from altering the query by locking the range. I've done so like this:
qbrProdId.value(queryValue(_prodId));
qbrProdId.status(RangeStatus::Locked);
Here qbrProdId is a variable of type QueryBuildRange and _prodId specifies the ProdId.
When the lookup is displayed and the user tries to change the filter the ProdId is locked. Good. However, when the user presses Ctrl+F on the ProdId field of the lookup, or if the user clicks on Search on the toolbar a different ProdId can be entered.
How can I prevent this?
I've thought of changing the ProdId field in the grid of the lookup to be of type "Display" instead of being a datasource field. But isn't there a better solution for this?
(By the way, the query is not automatically created but created manually in the "init" method of the form datasource).
OK, than you can just override the task() method.
This should disable the filter functionallity on the lookup form.
public int task(int _taskId)
{
int ret;
switch(_taskId)
{
case 2855:
case 2844:
case 2837:
case 799:
return 0;
}
ret = super(_taskId);
return ret;
}
Just use a dynalink instead of range.
HTH
Related
I have added a table in the purchase order form as a data source. because its data is shown in a tab of the purchase order form. This table is filled in a form that is open from the purchase order form. At first, the link type of the joined source was Delayed. but the user asks me to show a field of the table in the purchase order grid, which should be filterable. As you know if the link type is delayed then its values are shown when the record is selected. because this is a kind of parent-child relationship. a child needs to know its parent.
On the other hand, if I choose the outer join link type, when I want to change the purchase order or adding a new one, the warning shown that the table mandatory fields must be filled. However, these fields always filled later even after confirming the purchase order.
So what is your suggestion? is there any way that I can add the field to the purchase order grid in which the user can filter it?
You need to create an extension for your datasource and not call next in write and validateWrite methods if you use an outer join:
[ExtensionOf(formDatasourceStr(PurchTable, NewDataSource))]
public final class PurchTableNewDataSourceDS_Extension
{
public void write()
{
//next write();
}
public boolean validateWrite()
{
boolean ret = true;
//ret = next validateWrite();
return ret;
}
}
I have created a command button in the CustGroup form action pane.
I have added a new base enum edt field to both the CustGroup and CustTable tables and forms.
When you click on the button the data that was previously changed in the CustGroup table must be reflected in the cust table form.
I have written code in button on click event handler but it's not updating.
What to do, any suggestions?
If I understand your question correctly, you want to transfer a change of a new field in a customer group to all customers that share this customer group.
This kind of mass data update is usually not done by code in a form, because that code is executed on the client tier, which results in a bad performance. Instead, you should create a class that is set to execute on the server tier. If you create a main method for this class, you can easily create an action menu item for it, which let's you easily integrate the call to this class as a button in the CustGroup form.
In the main method you can access the CustGroup record for which the button was clicked via the Args object. This gives you the value of your new field that was changed. With this value, you can then use code similar to the following to update your customers:
public void updateCustomersWithNewCustGroupFieldValue(CustGroup _custGroup)
{
CustTable custTable;
ttsBegin;
while select forUpdate custTable
where custTable.CustGroup == _custGroup.CustGroup
{
custTable.MyNewEnumField = _custGroup.MyNewEnumField;
if (custTable.validateWrite())
{
custTable.update();
}
else
{
error('Please implement some error handling');
}
}
ttsCommit;
}
I have a custom form which has two datasouces. Lets say to make it easer that my form has the Salestable and SalesLines datasources.
for example I could say that I have a filter which is bounded with the ItemGroup edt .
I want to filter the SalesTable Datasource through this filter in order to 'show' in a grid which is connected with the SalesOrders datasouce :
''all SalesOrders which 'have' saleslines with saleslines.ItemGroup == somethingfromFilter''.
Whatever I tried is faild. Can someone help me?
FYI: the datasources properties I asume that are proper linked:
SalesLine.JoinSource = SalesTable
All of my tries was in modified method of the filter.
I will assume you have an ItemGroupId field in the SalesLine table.
This is not standard.
Also I will assume you have a filter field in the form called ItemGroupIdCtrl.
Add a helper datasource SalesLineEx:
Name: SalesLineEx
Table: SalesLine
Allow...: No
JoinSource: SalesTable
LinkType: ExistJoin
In the SalesTable datasource executeQuery modthod:
public void executeQuery()
{
SysQuery::findOrCreateRange(salesLineEx_ds.queryBuildDataSource(), fieldNum(SalesLine,ItemGroupId)).value(ItemGroupIdCtrl.text());
salesLineEx_ds.queryBuildDataSource().enabled(ItemGroupIdCtrl.text() != '');
super();
}
This will check the existence of sales lines with a matching field if the filter field has a value. If no value is entered the filtering datasource is disabled.
Most likely you will want to research after change of filter value:
public boolean modified()
{
boolean ret = super();
salesTable_ds.executeQuery();
return ret;
}
I may be misreading your question, but if you are asking how to filter with ranges, it's a pretty basic task.
Look at \Forms\PurchTable\Data Sources\PurchLine\Methods\init to see how they exclude lines that are "Deleted".
If you want to join SalesLines to InventTable in order to get the item group, you can look at how you can modify the form's query in another example here:
\Forms\PurchTable\Data Sources\PurchTable\Methods\linkActive
Disclimer: I do not have a AX2012 now. I have posted screenshots from AX2009. Functional is the same
Prerequisite: you should have a cross-references to use this functional.
Repro steps:
open a form
click toolbar button Advanced Filter/Sort or Ctrl+F3
mouse right-click on Sales order table in the Structure tree.
choose and click on 1:n and than Order Lines to add additional table in a filter (you should have a cross-reference)
mouse right-click on Order line table in the Structure tree.
choose and click on n:1 and Items (Item number) to add additional table in a filter (you should have a cross-reference)
click on Add button and choose talble Items and field Item groups in a Range grid. Specify a criteria = somethingfromFilter
See screenshots below.
Note: Axapta uses additional tables in query only. You need to change a form business logic in AOT to display additional tables/fields on the form.
Filter in a code:
I have a custom form which has two datasouces.
form has the Salestable and SalesLines datasources.
I want to filter
'all SalesOrders which 'have' saleslines with saleslines.ItemGroup == somethingfromFilter''
Prerequisite: a custom form use two joined datasources. Join type is one of: Delayed, InnerJoin.
Solution
It need to modify a method Init in SalesLine datasource.
this.query().datasource(tablenum(salesLine)).addDatasource(...)
...
See examples in any form with init-method and addDatasource text )
I have modified a validate method of form control. On this control I'm typing the product name.
In validate method I'm checking if this product name exists in the table. If it does not exists the error is thrown.
My issue is that after the error is thrown I want to clear control. Here is my code:
public boolean validate()
{
InventTable inventTable;
boolean ret = super();
select inventTable
where inventTable.nameAlias == this.text();
if (!inventTable.recid)
{
error("error");
this.text("");
}
return ret;
}
this.text(""); does not work. So how can I clear the control? The control is a field from my datasource.
In validate methods you do not need to clear the field. The system does that for you when validate returns false.
So instead of this.text('')) just return false.
But I doubt that the idea of users entering the full name is really useful at all.
If you use NameAlias as an alternate item number an even easier option exist.
Change the AliasFor property on the InventTable.NameAlias field to point to ItemId.
When entering in an ItemId and you enter a NameAlias instead, it is translated to the corresponding item id by the AX run-time. This happens everywhere an item id is entered and validated.
I need to add an additional field to InventJournalTrans, that after posting will show up in the InventTrans table. The field is a reference column to a record in another table. What method(s) do I need to modify to make this behavior happen?
Currently, I have already added the fields to both tables and modified the Form to allow the user to enter and save the new field. I just can't seem to find the bottom of the rabbit hole on where the actual posting to InventTrans is occurring.
Ideally, it should just be a:
inventTrans.ReasonRefRecId = inventJournalTrans.ReasonRefRecId;
assignment statement before the
inventTrans.insert();
call. Anybody have a clue on where this is at?
The link above does contain the solution -- I have included the code from that page in case that page disappears or no longer becomes available. Thanks to gl00mie for answering on that site and providing this answer.
You should create a new InventMovement method like this:
public MyNewFieldType myNewField()
{
return MyNewFieldType::DefaultValue; // suppose your new field is an enum
}
Then modify \Classes\InventMovement\initInventTransFromBuffer
void initInventTransFromBuffer(InventTrans _inventTrans, InventMovement _movement_orig)
{
// ... append this line to the end of whatever else is already in this method
_inventTrans.MyNewField = this.myNewField();
}
And finally overload the new method in the InventMov_Journal class:
public MyNewFieldType myNewField()
{
return inventJournalTrans.MyNewField;
}