Sorting on a calculated field with X++ - methods

I am a long time developer in MS Access but Now I need to develop in Microsoft Dynamics AX 2009.
I have a report that uses a method on the body of a report that calculates an "exp book date". Now I am being asked to sort on this field.
I am guessing I need to move the method to the query, in order to make the field able to be sorted.
But when I copy the method to the Method level of the query, it say that the field does not exist. Which it doesn't. How do i get the feild to be visiable?
display utcDatetime Test()
{
real AddDays;
utcDatetime CDate;
;
AddDays = smmQuotationPrognosisGroup::find(smmOpportunityTable_1.PrognosisId, false).PrognosisDays;
CDate = smmOpportunityTable::find(smmOpportunityTable_1.OpportunityId, false).createdDateTime;
return DateTimeUtil::addDays(CDate, AddDays);
}

Unfortunately it is not possible to sort directly by a display method.
Yet there are some workarounds, e.g.:
Use a temporary table with a field which is filled by your display method's logic before you run the report and then use this temporary table in your query.
Override the report's fetch method so that you have full control over
fetching the data via X++.
Depending on your report's size these actions can take some time.

Related

Adf column filter: which format does ADF use to generate the where clause in the VO's query?

TLDR; is there a way to understand at runtime which format is ADF using for dates behind the scenes? In particular the format used to render dates in dynamically generated sql code?
In the Oracle ADF Application I'm working on there are several table filters (by that I mean the field over the column in which I can write text/number/dates to query the table).
Filtering this way, the framework modifies the query of the View Object, adding the appropriate where clause. On the page there's also a button "Select all" that allows me to select all the data that's rendered in the table (there is a selection checkbox).
In the specific case, the query from the VO is used to aim two different goals:
update the rendered data in the table
if I press the "select all" button a function in the backend database is called (callable statement calling the function), passing as a parameter the query.
The first task is successfully reached (as the table is visually updated), but we had an issue with the second one.
The backend function uses the query to select all the extracted data (as iterating in ADF with java would be too slow).
The problem is that the where clause isn't correctly generated for the backend database (which is also oracle).
Basically the generated WHERE clause (which was added to VO's query automatically by the framework) was
WHERE record_date = '2020-10-12'
which I had to change to
WHERE record_date = to_date('2020-10-12', 'YYYY-MM-DD')
in order to have it correctly executed by the Oracle Db.
So now it's working (yay), but my concern is: isn't it dangerous to assume the date format will be 'YYYY-MM-DD' on every application's instance?
I think this 'YYYY-MM-DD' is the format in which ADF is managing dates (as the value is written as '2020-10-12' in the query).
But is there a way to understand at runtime which format is ADF using for dates behind the scenes? Or does it always use 'YYYY-MM-DD', or am I completely off-road and the storage format is another and I should ask which format does it use to render dates? But dates on page are visually rendered in another way :/
Sorry for my lack of expertise and have a nice day!
Update
The value of the query field, which I'm getting by calling
this.getNamedWhereClauseParams().getAttribute('vc_temp_1');
is of class
oracle.jbo.domain.Date
and by printing it I obtain the date in format YYYY-MM-DD.
Would it be possible that the framework was simply using Date.toString?
This would raise another question: how can I be sure of the pattern used by Date.toString? The documentation isn't clear about it (and it says that it should be used only in development, so this is quite a remote scenario).
What you named 'Filter' is called 'Query by Example' or QBE in short. See the doc for more info.
You can change the query passed to the server using a bean method. Look at e.g. JDev 12.2.1.3: Multi select component table filter for a sample.
Using dates in ADF is always dependent on the current user's settings. If the user don'T use a specific locale the default is 'yyyy-mm-dd'. This can be changed at different points, starting by the entity objects, view objects a,d finally in the UI by using converters.
The best way to use dates depends on the use case.

Trying to generate SSRS report based on input parameters in visual studio

I have an AX query dataset that I'm trying to use to generate an SSRS report. I want to the user to be able to enter 2 parameters (Date and ProjectId) and have the SSRS report return a table based on the query using the parameters inputted by the user. Can't write any code so it needs to be purely graphical.
You can simply add your parameters to query as query ranges.
In the AOT, click Queries, and locate the query that you want to define a range for.
Expand the query, click Data Sources, and then expand a data source.
Right-click Ranges, and then click New Range.
Right-click the new range, click Properties, and then select a field in the Field property list.
Type an expression in the Value property to specify which records are retrieved.
here it's a helpful link for creating queries with ranges:
https://msdn.microsoft.com/en-us/library/bb314753.aspx
Here is a walkthrough to follow:
https://technet.microsoft.com/en-us/library/cc636713.aspx

Best practice for single-valued result in SSRS 2012

I'm new to Reporting Services and using SQL Server Data Tools (Visual Studio 2012). I want to add an item that will display a single value - in this case, the result of a stored procedure call. The value would probably be displayed in the report header.
I've looked at the Tablix data parts that can be added to the report: table, list, and matrix. Not sure which of them, if any, would be appropriate. I could add a parameter item, but it seems that these function as user input choices.
I also looked at a read-only text box, but don't see how to populate it with a query result.
What is the accepted method of adding a single-value result to a report?
If this is to be displayed in the page header, your only option is a textbox; you can't add tablix type parts to page headers/footers.
The textbox expression would be something like:
=First(Fields!MyValue.Value, "DataSet1")
By using an aggregate expression like this you can make sure only one value is returned (even though you might always have only one) and you can also specify the aggregate's Scope; in this case the DataSet you want to query.
If this was going in the report body I would still recommend the same approach, though I wouldn't go so far as to call it best practise, any would work so it's really personal taste.
However, if you had multiple fields returned by the SP but still only one row, in that case I would recommend a table style tablix with one header-level row; easiest to maintain and layout.

How to use calculated fields in my LightSwitch Query?

in my lightswitch application im trying to create a Customers Screen for customers who have balance value, and my balance value is a Calculated Field in the Customer Entity
when i tried to put the logic in the Process Query Event Like This
query =( from i in query
where(i.Balance>0)
select i );
i get an exception .. what is the best way to handle these kind of situations ??
i saw an answer here but i didn't know how to implement it exactly i need a sample code for it can anyone help me ??
thanks in advance
The query will be executed by the data provider, which doesn't know about calculated fields. What you can do is to filter what you want via LINQ, referring to the actual fields, not the calculated ones.
For example, let's say Balance is your calculated field, that you defined as Credit - Debit (which are normal fields). You want your query to return the rows where Balance > 0. This is how you'd write the query (in the PreprocessQuery event, note there is no ProcessQuery event):
partial void TestQuery_PreprocessQuery(ref IQueryable<Customer> query)
{
query = (
from c in query
where ((c.Credit - c.Debit) > 0)
select c);
}
Another theoretical way of solving the problem would be setting a filter in the Executed event handler. However, for whatever the reason, when I do it, the filter is not applied to the screen. But even if this method would work, still you'd be filtering on the client side, which might not be what you want.
I'm actually looking for a solution to this problem
(unfortunately I can't just include the calculation from the calculated field, because my calculation uses another calculated field which uses recursion)
A couple of pointers I thought you might find helpful:
#julio.g - for the Executed event handler, the "result" parameter is an IEnumerable parameter (as opposed to the PreProcess_Query event handler, where the "query" parameter is a ref IEnumerable) so any changes you make to the "result" will only be local to that method
#3oon - afaik, SQL Views are not supported in LightSwitch. The best option I've come across so far is to create a WCF RIA Service based on a Stored Procedure, then adding it as a datasource.
This blog post should help get you started.
http://tejana.wordpress.com/2010/12/09/microsoft-lightswitch-and-stored-procedures-using-wcf-ria-services/
Hope that helps!

Visual Studio 2005 table rendering order

I'm working in Visual Studio 2005 Reporting and I'm trying to implement a workaround of nesting aggregate functions (I need to perform a Count of Sums). In the table details row, I have a call to custom code to increment an integer every time the value of one cell is >10, then the footer has a call to a custom code function that just returns that value.
The count was always returned as 0, so I threw in some MsgBox calls and noticed the table footer is being called before the details rows. I need the table details rows to be called first so that the "get" function in the footer will actually retrieve the value I need.
To be more specific, I'm looking to count the number of times a given table cell, whose value is calculated as (Sum / (Sum+Sum+Sum)) * 100, is greater than 10. Since aggregate functions can't be nested, and the use of aggregates on ReportItems!... can only be done in report headers/footers (in my case not helpful as it will display a different total on each page), I'm left with the option of custom code.
Is there any way to force the details row of a table to be rendered before the table footer?
Instead of using the table footer, I used a textbox beneath the table, so the table was rendered first, header and details rows, then the report processed the textbox below, leading to the correct value.
Hope that helps anyone that comes across this issue.

Resources