I want to filter my object set for an object table using a function.
Let’s say that I have some Purchase Order Object set as input to an object table.
I want to aggregate the POs regionally and show only the region that meets a certain criteria for example number of quantities and margin rate.
Currently, I am inputting my region objects and PO objects which has 1-1 link between them. I created a typescript function that aggregates all POs based on the region. After, depending on the aggregated quality, I am choosing to include or exclude in the output object set.
However, I have noticed that for all the regions that does not meet the criteria. They are still included in the object table with “no values.” Is there anyway that we can set up a object table where input and output object is not one-to-one?
To achieve this, you could create a function which returns the region IDs which match your criteria. Then you could use this list of IDs to filter the Region ObjectSet in Workshop.
Since there is a 1:1 link between Region and Purchase Order, I assume that POs have a property such as regionId that identifies the linked region (edit: is it not a 1 region to many POs link rather, if you are able to aggregate POs per region?).
Once you have created the aggregation, the interesting piece is filtering the aggregation buckets based on some criteria, and then retrieving the filtered keys (bucket keys being regionId in this case) with .map().
You could also have multiple aggregations (like a sum and a count), with each a different criteria, and take the intersection of region IDs obtained with each criteria.
@Function()
public async getRegionIdsWithMoreThanXPurchaseOrders(
minimumNumberOfPOs: Integer,
purchaseOrders: ObjectSet<PurchaseOrder>,
): Promise<string[]> {
const countOfPOsPerRegion = await purchaseOrders.groupBy(
po => po.regionId.topValues() // Bucket by top 1000 values. If there are more than 1000 buckets, extra buckets are omitted.
).count();
const regionIdsWithCountAboveMin = countOfPOsPerRegion.buckets.filter(
bucket => bucket.value > minimumNumberOfPOs
).map(
bucket => bucket.key
);
return regionIdsWithCountAboveMin;
}
I have updated my post with the current code! Rather than region, I am using RnD model to aggregate. But the catch is that I have to also return the aggregated value that I am filtering my objects on.
Ah, do I understand correctly that you are using an object table with a function backed property?
If so, I believe all rows of the input object set will always be shown in the table, no matter what the function returns.
What you could do is filtering the object set which is the input of the object table: instead of having all regions as an input to your object table, you filter them using a function (which returns region IDs matching a given criteria, like the function I previously posted for instance). Then you use this filtered set as an input to the table. And in that table you can still use the existing aggregateTableCMRate function.
Basically, the function used in a function-backed property won’t allow you to filter the input object set, it just provides a mapping to the table to add an extra property for input rows, and missing mappings are displayed as “no values” as you noticed. It does not provide an output object set that would be displayed in the table. The only way to filter the rows of a table is to filter the object set before you provide it to the table.
Lastly, if you have 2 functions which do a similar aggregation (one to filter the regions, the other to return the property mapping), you could extract the common aggregation code in a separate function to make sure they stay in sync and to avoid code duplication.
Yup, so I created the logic part with a separate function which outputs a array of IDs. Then I use this array to filter the object sets, then do the aggregation after the filtering.