You can create new app items in apps. For example, if the process context
contains a variable of the App type order, you can create a new item of this app as follows:
If the context of a process, app, or widget contains an App type field, its value will contain a link to this object. To get the object itself, request it
using the [[ApplicationItemRef.fetch]] method:
const order = await Context.data.order.fetch();
If the field stores multiple values, you can request all associated objects
using the ApplicationField.fetchAll method:
For a query divided into pages, use the following methods:
Search.from to define the number of items to skip
from the start.
Search.size to define the number of results on a page
(the maximum value is 10,000, the default is 10).
Search.sort to determine how results need to be sorted.
You can set a filter using Search.where. The filter is a closure
with two arguments:
f is the set of filters to define conditions
for specific object fields.
g represents global filter functions for full-text search and
for complex filters GlobalFilters.
For example, if you want to select orders of a certain customer with the order name
starting with “ab” that were created less than two weeks ago, here is the request
that you will need to use:
A filter is a closure to which three arguments are passed.
The first f and the third g are similar to the ones passed to the closure
via the Search.where method described above. The second argument c
is a set of operands used to get a value from the context.
A filter is applied to the field itself; it is not only used on a certain form
or in a business process. So, if a filter is not needed any longer,
you can clear it using the StaticApplicationFieldData.clearFilter method:
When you get an app item, you can change the values of its fields. After that
you need to call the [[ApplicationItem.save]] method to apply the changes:
const order = await Context.data.order.fetch();
// Apply a discount
order.data.total = order.data.total.multiply(0.75);
await order.save();
To delete app items, the [[ApplicationItem.delete]] method is used.
It marks the item as deleted (by filling in the Deleted on field, BaseItemData.__deletedAt).
The item will still be available in search and accessible by link.
Also, to delete an item, you don’t need to get the entire object, a link is enough:
The status of an app item can be changed via the [[ApplicationItem.setStatus]]
method:
// Changing the status of a recently created object that has not yet been savedconst request = await Context.data.request.fetch();
const finalStatus = request.fields.__status.variants.completed;
await request.setStatus(finalStatus, 'Closed automatically');
The Application object has access to the list of processes Application.processes.
It can be used to start a process. Processes are started asynchronously, which means that the process will not yet be launched
while the run function is being executed.
For example, you can launch a business process that manages service requests in a loop for all requests in the context:
Let’s say we obtained items of an app that has a Users type field, and we need to get
the data of these users. Before optimization (N+1 requests will run consequentially):
const teams = await Namespace.app.komandy.search(...).all();
for (const team of teams) {
\t const lead = await team.data.lead.fetch();
\t const name = lead.data.__name;
\t ...
}
After optimization (two requests will run consequently):
const teams = await Namespace.app.komandy.search(...).all();
// Get the users’ IDslet teamLeadIds = teams.map(t => t.data.lead.id);
// Delete duplicates of user IDs
teamLeadIds = teamLeadIds.filter(function(elem, index, self) {
return index === self.indexOf(elem);
});
// Get all users in one requestconst users = await System.users.search().where(f => f.__id.in(teamLeadIds)).size(10000).all();
// Form an object of the following type: {user_ID: user_full_name}const namesById: { [key: string]: string } = {};
for (const user of users) {
\t namesById[user.id] = user.data.__name;
}
Manage apps
You can access an app in several ways:
Create an app
You can create new app items in apps. For example, if the process context contains a variable of the App type
order
, you can create a new item of this app as follows:const order = Context.fields.order.app.create(); order.data.client = Context.data.client; await order.save(); Context.data.order = order;
Get an app using a link
If the context of a process, app, or widget contains an App type field, its value will contain a link to this object. To get the object itself, request it using the [[ApplicationItemRef.fetch]] method:
const order = await Context.data.order.fetch();
If the field stores multiple values, you can request all associated objects using the ApplicationField.fetchAll method:
const orders = await Context.fields.orders.fetchAll();
In the same way, you can use an app item that references another app to get the app items it has links to:
const order = await Context.data.order.fetch(); const client = await order.data.client.fetch();
Get the current status of an app item
You can get the current status of an app item in the following way:
const currentStatus = item.data.__status; Context.data.__comment = `Current status: ${ currentStatus.name }`;
You can change an app item’s status using the [[ApplicationItem.setStatus]] method.
Search
To search for an item in a collection, use the Search object that you can get from the app’s description:
const pinnedClients = await Context.fields.client.app.search() .where(f => f.agent.eq(Context.data.__createdBy)) .all();
With the Search object, you can request:
For a query divided into pages, use the following methods:
You can set a filter using Search.where. The filter is a closure with two arguments:
f
is the set of filters to define conditions for specific object fields.g
represents global filter functions for full-text search and for complex filters GlobalFilters.For example, if you want to select orders of a certain customer with the order name starting with “ab” that were created less than two weeks ago, here is the request that you will need to use:
const weekAgo = (new Datetime()).addDate(0, 0, -7); const orders = await Application.search() .where((f, g) => g.and( f.client.eq(Context.data.client), f.__name.like('ab%'), f.__createdAt.gt(weekAgo), )) .all();
If you want to search orders by status (for example, to find all orders with the
done
status), use the following request:const doneStatus = Application.fields.__status.variants.done; const orders = await Application.search() .where(f => f.__status.eq(doneStatus)) .all();
To get app items that refer to items of another app, use the following request:
const clients = await Application.search() .where(f => f.client.link(Context.data.order) .all();
The
f
object is created based on the descriptions of the app’s fields. For fields with multiple values, FieldArrayOperand is formed. For fields that expand (TString, TPhone, TEmail, TFullName, TLink and TEnum), StringFieldOperand is formed. For the rest, FieldOperand.Filtering for App type fields
If you need to limit options available in an App type field, you can use the StaticApplicationFieldData.setFilter method:
Context.fields.cars.data.setFilter((f, c, g) => g.and( f.active.eq(true), f.year_of_issue.gte(c.year) ));;
A filter is a closure to which three arguments are passed. The first
f
and the thirdg
are similar to the ones passed to the closure via the Search.where method described above. The second argumentc
is a set of operands used to get a value from the context.A filter is applied to the field itself; it is not only used on a certain form or in a business process. So, if a filter is not needed any longer, you can clear it using the StaticApplicationFieldData.clearFilter method:
Edit an app item
When you get an app item, you can change the values of its fields. After that you need to call the [[ApplicationItem.save]] method to apply the changes:
const order = await Context.data.order.fetch(); // Apply a discount order.data.total = order.data.total.multiply(0.75); await order.save();
Deleting an app item
To delete app items, the [[ApplicationItem.delete]] method is used. It marks the item as deleted (by filling in the Deleted on field, BaseItemData.__deletedAt). The item will still be available in search and accessible by link. Also, to delete an item, you don’t need to get the entire object, a link is enough:
await Context.data.order.delete(); Context.data.order = undefined;
Change the status of an app item
The status of an app item can be changed via the [[ApplicationItem.setStatus]] method:
// Changing the status of a recently created object that has not yet been saved const request = await Context.data.request.fetch(); const finalStatus = request.fields.__status.variants.completed; await request.setStatus(finalStatus, 'Closed automatically');
Start a business process
The Application object has access to the list of processes Application.processes. It can be used to start a process. Processes are started asynchronously, which means that the process will not yet be launched while the run function is being executed.
For example, you can launch a business process that manages service requests in a loop for all requests in the context:
for(let request of Context.data.service_requests) { await Application.processes.process_code.run({ service_request: request }); }
Read more about working with processes in Process.
Get items from one collection or app in one request
Let’s say we obtained items of an app that has a Users type field, and we need to get the data of these users. Before optimization (N+1 requests will run consequentially):
const teams = await Namespace.app.komandy.search(...).all(); for (const team of teams) { \t const lead = await team.data.lead.fetch(); \t const name = lead.data.__name; \t ... }
After optimization (two requests will run consequently):
const teams = await Namespace.app.komandy.search(...).all(); // Get the users’ IDs let teamLeadIds = teams.map(t => t.data.lead.id); // Delete duplicates of user IDs teamLeadIds = teamLeadIds.filter(function(elem, index, self) { return index === self.indexOf(elem); }); // Get all users in one request const users = await System.users.search().where(f => f.__id.in(teamLeadIds)).size(10000).all(); // Form an object of the following type: {user_ID: user_full_name} const namesById: { [key: string]: string } = {}; for (const user of users) { \t namesById[user.id] = user.data.__name; }