Field type returning numbers [Axapta] - axapta

I want to get the field types. My code is as follows:
tID = dict.tableName2Id(tableName);
counter = 0;
dt = new DictTable(tID);
if (dt)
{
counter = dt.fieldNext(counter);
while (counter)
{
df = dt.fieldObject(counter);
if (df)
{
fields = conIns(fields,1,df.baseType());
}
counter = dt.fieldNext(counter);
}
}
On return to .NET Business connector, the types are shown as numbers instead of strings.
Kindly help.
EDIT : DataField.baseType() returns "Types" can this be converted to string and then added to the container?
EDIT 2: Ok now, im getting a Types Enumeration. Is there any way to map this enumeration in AX and add to container as string?

Got it!! Here's the code :
tID = dict.tableName2Id(tableName);
counter = 0;
dt = new DictTable(tID);
if (dt)
{
counter = dt.fieldNext(counter);
while (counter)
{
df = dt.fieldObject(counter);
if (df)
{
t = df.baseType();
fields = conIns(fields,1,enum2str(t));
}
counter = dt.fieldNext(counter);
}
}

Related

Updating map value for a specific key in Kotlin

I am new at Kotlin and trying to catch up the language.
I have a function that returns DayofWeek as a key and an Int as a value.
The issue that I am facing is that I need to take a list of object that has another list of object inside that has an Int value which I need to save and increment for every time I see the same value.
Here is my function -
class OrdersAnalyzer {
data class Order(val orderId: Int, val creationDate: LocalDateTime, val orderLines: List<OrderLine>)
data class OrderLine(val productId: Int, val name: String, val quantity: Int, val unitPrice: BigDecimal)
fun totalDailySales(orders: List<Order>) : Map<DayOfWeek, Int> {
val map: MutableMap<DayOfWeek, Int>? = mutableMapOf(
Pair(DayOfWeek.SUNDAY, 0),
Pair(DayOfWeek.MONDAY, 0),
Pair(DayOfWeek.TUESDAY, 0),
Pair(DayOfWeek.WEDNESDAY, 0),
Pair(DayOfWeek.THURSDAY, 0),
Pair(DayOfWeek.FRIDAY, 0),
Pair(DayOfWeek.SATURDAY, 0)
)
for (order in orders) {
val dayOfWeek = order.creationDate.dayOfWeek
var quantity = 0
map?.put(dayOfWeek, quantity)
}
return map!!
}
}
So the issues I am facing right now are 2 -
1) How can I increment the value of each pair when it is the corrent DayOfWeek? I don't want to replace, I want to add it to the last value.
2) When returning the Map, I do not want to return the DayOfWeeks that have the value of 0. How can I do that?
Here is a modified version of the elegant answer provided by Arjan, with some test code.
Updated the answer after the comment from Alon Shlider -- now counting all order item quantities grouped by day of the week:
fun totalDailySales(orders: List<Order>): Map<DayOfWeek, Int> =
orders.groupBy { it.creationDate.dayOfWeek }
.mapValues { sumItemQuantities(it.value) }
fun sumItemQuantities(orders: List<Order>) =
orders.flatMap { it.orderLines.map { line -> line.quantity } }.sum()
fun main() {
val orders = listOf(
Order(
1,
LocalDateTime.now().minusDays(2),
listOf(
OrderLine(6, "laptop", 28, 1200.toBigDecimal())
)
),
Order(
2,
LocalDateTime.now().minusDays(1),
listOf(
OrderLine(496, "VR headset", 6, 400.toBigDecimal())
)
)
)
println(totalDailySales(orders))
}
Output:
{FRIDAY=28, SATURDAY=6}
With this approach, Kotlin functions do the grouping and counting for you. The groupBy function creates a map from DayOfWeek to a list of orders (grouping all orders with the same day of week in a list). The mapValues function transforms that map by replacing the lists with the result of the sumItemQuantities function (for each list).
In the for loop in your code, you can retrieve the current quantity for a specific day (or use zero if it isn't set yet), increase it by the right amount and then store it. To return only the map entries with non zero values, you could filter (return totalsPerDay.filter { it.value > 0 }) or start with an empty map. This is your function with some changes:
fun totalDailySales(orders: List<Order>): Map<DayOfWeek, Int> {
val totalsPerDay = mutableMapOf<DayOfWeek, Int>()
for (order in orders) {
val dayOfWeek = order.creationDate.dayOfWeek
val currentQuantity = totalsPerDay[dayOfWeek] ?: 0
// This is not the best way to increment by the sum of the order
// item quantities...
val orderItemQuantities = sumItemQuantities(listOf(order))
totalsPerDay[dayOfWeek] = currentQuantity + orderItemQuantities
}
return totalsPerDay
}
Output after calling it:
println(OrdersAnalyzer().totalDailySales(orders))
{FRIDAY=28, SATURDAY=6}
Updated answer (also thanks to Freek de Bruijn), with some test code.
I think it would be something like this:
fun totalDailySales(orders: List<Order>) : Map<DayOfWeek, Int> =
orders.groupBy { it.creationDate.dayOfWeek }
.mapValues { it.value.flatMap { it.orderLines } }
.mapValues { it.value.map { it.quantity } }
.mapValues { it.value.sum() }
groupBy creates a Map where the values are of type List<Order>, so you need to call a few steps to convert these values to Int. First we use flatMap to convert List<Order> to List<OrderLine> (map would convert to List<List<OrderLine>>). Then we use map to get the quantities out of List<OrderLine>, and finally sum() to add up all those quantities.
val orders = listOf(
Order(
2,
LocalDateTime.now().minusDays(2),
listOf(
OrderLine(5, "monitor", 10, 200.toBigDecimal()),
OrderLine(4, "keyboard", 5, 50.toBigDecimal())
)
)
)
println(totalDailySales(orders))
This results in the output:
{FRIDAY=15}

Javafx Tree Table view: how to assign serial number to the direct child nodes of the root node

I am trying to number the direct child nodes of the root node in a serial manner (child-1, child-2...).
Here is my method which sets the cell value factory for myColumn:
private void setCellValueFactory() {
myColumn.setPrefWidth(120);
final int[] si_SubsetCount = {
1
};
myColumn.setCellValueFactory(
(TreeTableColumn.CellDataFeatures < MyDataClass, String > p) - > {
TreeItem < JVCC_PageHeaderInfo > ti_Row = p.getValue();
MyDataClass myDataClass = p.getValue().getValue();
String text;
if (ti_Row.isLeaf()) {
//leaf
} else if (ti_Row.getParent() != null) {
text = "Child-" + si_SubsetCount[0];
si_SubsetCount[0]++;
} else {
si_SubsetCount[0] = 1;
text = "Root";
}
return new ReadOnlyObjectWrapper < > (text);
});
}
But my output is as below:
>Root
>child-4
>leaf
>leaf
>child-8
>leaf
>leaf
I don't understand why the numbering is like 4, 8... instead of 1, 2...
Can someone help me with this.
That is because you can not control, when the CellValueFactorys method for evaluating the value for each row is called. It might get called several times for a single row, which is why your counter does not show the correct value for each line.
A dynamical approach is prefered here. If you should only have to differ between 3 node levels like root/child/leaf, then you could do something like this:
myColumn.setCellValueFactory( ( final CellDataFeatures<String, String> p ) ->
{
final TreeItem<String> value = p.getValue();
String text = "";
if ( value.isLeaf() )
text = "leaf";
else if ( value.getParent() != null )
text = "Child-" + (value.getParent().getChildren().indexOf( value ) + 1);
else
text = "root";
return new ReadOnlyStringWrapper( text );
} );
Since the Children of a TreeItem are stored in an ObservableList, you can just ask them for their index and add 1, since index starts at zero.

How to increment a value in a map with Apex?

Is there a way to increment a value in a map without needing a second variable?
for example, this doesn't work:
counts = new Map<string,integer>();
counts.put('month_total',0);
counts.put('month_total',counts.get['month_total']++);
it returns "Initial term of field expression must be a concrete SObject: MAP"
instead I needed to do:
counts = new Map<string,integer>();
counts.put('month_total',0);
integer temp = 0;
temp++;
counts.put('month_total',temp);
is there any way to increment without needing an extra variable?
Replace
counts.put('month_total',counts.get['month_total']++);
with
counts.put('month_total',counts.get('month_total')++);
List<String> lststrings = new List<String>{'key','wewe','sdsd','key','dfdfd','wewe'};
Map<String,Integer> mapval = new Map<String,Integer>();
Integer count = 1;
for(string str : lststrings){
IF(mapval.containsKey(str)){
mapval.put(str,mapval.get(str)+1);
}
else{
mapval.put(str,count);
}
}
system.debug('value of mapval'+mapval);

linq sum and group [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Dynamic Anonymous type in Razor causes RuntimeBinderException
I have this Linq Agregate Query
var GruposQ = from lcGrupos in db.Merlin_ConceptosFacturacion_Kit_Componentes
where lcGrupos.NumIdConcepto == Item.NumIdConcepto & lcGrupos.BitComponenteVariable == true
select lcGrupos;
var GruposList = from comps in GruposQ
group comps by
new
{
NumIdGrupoProducto = comps.NumIdGrupoProducto,
} into g
select new
{
NumIdTransaccion = NumIdTransaccion,
NumIdGrupoProducto = g.Key.NumIdGrupoProducto,
NumCantidad = g.Sum(x=>x.NumCantidad),
Grupo = GruposQ.Where(x => x.NumIdGrupoProducto == g.Key.NumIdGrupoProducto)
};
ViewBag.CompsKit = GruposList.ToList();
My problem is when I try to get elements from ViewBag.CompsKit:
#foreach (var myTrans in ViewBag.CompsKit)
{
// Here it throws an error
// 'object' does not contain a definition for 'NumIdtransaccion'
<span>myTrans.NumIdtransaccion</span>
}
But if i look into this object it allready has the property.
myTrans { NumIdTransaccion = 15460
, NumIdGrupoProducto = 163
, NumCantidad = 100,000
, Grupo = System.Data.Common.Internal.Materialization.CompensatingCollection`1[ParadigmaNet.Areas.Items.Models.Merlin_ConceptosFacturacion_Kit_Componentes] } dynamic {<>f__AnonymousType7<decimal,decimal?,decimal,System.Linq.IQueryable<ParadigmaNet.Areas.Items.Models.Merlin_ConceptosFacturacion_Kit_Componentes>>}
How can I do to access the properties ? in this agregate ?
You can't use "dynamic" type in a Razor View.
You must use a typed object as Model.
You can do grouping and filtering in single query:
var numIdConcepto = Item.NumIdConcepto;
var query = from comps in db.Merlin_ConceptosFacturacion_Kit_Componentes
where comps.NumIdConcepto == numIdConcepto &&
comps.BitComponenteVariable
group comps by comps.NumIdGrupoProducto into g
select new
{
NumIdGrupoProducto = g.Key,
NumCantidad = g.Sum(x => x.NumCantidad),
Grupo = g.ToList()
};
ViewBag.CompsKit = query.ToList();
ViewBag.NumIdTransaccion = NumIdTransaccion;
Also
you don't need create anonymous object for grouping by single property
you don't need to compare boolean values with true/false
you can simply use g.Key when use single property for grouping
items in group already will have NumIdGrupoProducto equal to grouping key
Instead of assigning same NumIdTransaccion to each group in the query result, pass that value to view separately: ViewBag.NumIdTransaccion = NumIdTransaccion
View:
<span>ViewBag.NumIdTransaccion</span>
#foreach(var item in ViewBag.CompsKit)
{
<span>#item.NumIdGrupoProducto</span>
<span>#item.NumCantidad</span>
}
Consider also creating ViewModel for this view - thus you will be safe about typos and all such errors will be eliminated at compile time.

Specific row withing a DataTable

I have a data table which has a "Total" column. I want to be able to get a specific rows "Total" not all rows.
public void maxValue()
{
string pass = (String)Session["name"];
DataTable table = (DataTable)Session["CocaCola"];
int total = table.AsEnumerable().Sum(r => r.Field<int>("Total"));
int totalAllowed = table.AsEnumerable().Sum(r => r.Field<Int32>("Total Allowed"));
if (total >= totalAllowed)
{
Label1.Text = "Total value exceeded the maximum of " + totalAllowed;
}
else if (total < totalAllowed)
{
Label1.Text = "Total value which is allowed :" + totalAllowed;
}
if (pass.Equals("Low"))
{
Label1.Text = "You are not allowed any assets at this Stage";
//SNS.Checked = false;
//TT.Checked = false;
//Music.Checked = false;
//SNS.Enabled = false;
//TT.Enabled = false;
//Music.Enabled = false;
}
}
As you can see my method works but add the column up which i dont want to do. How would i go about changing it?
You can do it this way
int yourTargetindex = 0; //Change this to get the value of your target element
int total =(from row in table.AsEnumerable()
select row.Field<int>("Total")).ElementAt(yourTargetindex);
//This will return the first value of "total" in the DataTable
You don't have to use linq. DataTable has built-in methods for this kind of operations:
var selectedTotal = table.Compute("sum(Total)", "columnX == 'x'");
This tell the table to calculate the sum of all Total cells in rows where columnX has the specified value.
Of course you can use linq. You would need to add a Where() before you calculate the sum.

Resources