Citeck Records Query Examples

Working with records from JavaScript

Adding a user or group to a group

let rec = Records.get('emodel/person@someuser'); // пользователь или группа, которого(ую) нужно добавить в группу
rec.att('att_add_authorityGroups', 'emodel/authority-group@accountant'); // группа, в которую нужно добавить
rec.save();

Removing a user or group from a group

let rec = Records.get('emodel/person@someuser'); // пользователь или группа, которого(ую) нужно удалить из группы
rec.att('att_rem_authorityGroups', 'emodel/authority-group@accountant'); // группа, из которой нужно удалить
rec.save();

Checking whether a user or group belongs to a group

Checking whether the current user belongs to a group:

await Citeck.Records.get('emodel/person@CURRENT').load('authorities._has.GROUP_ECOS_ADMINISTRATORS?bool!')

Checking whether a specific user belongs to a group:

await Citeck.Records.get('emodel/person@someuser').load('authorities._has.GROUP_testers?bool!')

Checking whether a group belongs to another group is not yet supported.

Getting the list of assignees (authorities, recipients) from a document role

await Citeck.Records.get('emodel/sd-request-type@you-doc').load('_roles.assigneesOf.impl-first-line-role[]?str', true)

Role Computation Diagnostics

To check who is computed into a role, use the _roles.assigneesOf attribute:

// Проверить, кто вычислен в роль
await Records.get('emodel/your-type@doc-id').load('_roles.assigneesOf.myRole[]?raw')

If a role is computed based on an association, you can compare the association contents with the role computation result for diagnostics:

// Загрузить содержимое ассоциации и результат вычисления роли одновременно
await Records.get('emodel/your-type@doc-id').load([
  'myAssocAttr[]?raw',
  '_roles.assigneesOf.myRole[]?raw'
])

Loading identifiers from associations: .id and ?id

When working with associations in the system, it is important to understand the difference between the ways to retrieve an identifier:

Attribute .id — returns the part of the reference after @ (localId):

// emodel/person@ivan.petrov → "ivan.petrov"
// emodel/authority-group@accountant → "accountant"
document.load('myAssoc.id')

Scalar ?id — returns the full reference to the entity:

// → "emodel/person@ivan.petrov"
// → "emodel/authority-group@accountant"
document.load('myAssoc?id')

Important

To pass references to other associations, use full references via ?id.

Searching records and modifying them in a loop

var typeId = 'deal';

var typeRef = "emodel/type@" + typeId;

var sourceId = await Records.get(typeRef).load('sourceId');
var queryResult = await Records.query({
    sourceId,
    query: { t: 'eq', att: '_type', val: typeRef },
    language: 'predicate',
    page: { maxItems: 4000 }
});
var records = queryResult.records;

console.log("Found " + records.length);

var newStatus = 'old';
for (let i = 0; i < records.length; i++) {
    let record = Records.get(records[i]);
    let currentStatus = await record.load('_status?str', true);
    if (currentStatus == 'new') {
        console.log('change status for ' + record.id + " from " + currentStatus + " to " + newStatus);
        record.att('_status', newStatus);
        await record.save();
    }
}

Here the script searches for objects (max = 4000) with data type deal and status new, and changes the status to old (these statuses must be defined for the deal type).

Getting a value from the config (ecos config)

Citeck.Records.get('eapps/meta@').load('$cfg.service-desk-groups')
// либо
Citeck.Records.get('eapps/cfg@service-desk-groups').load('value')

A scope is needed if the goal is to retrieve from one microservice a config that is defined in another microservice.

Getting different localized values for the Status attribute (_status)

await Citeck.Records.get('emodel/ecos-contract@you-doc').load('_status._disp?json', true)

Response:

{
    "ru": "Новый",
    "en": "New"
}

Alternatively, you can get the value in a specific language:

await Citeck.Records.get('emodel/ecos-contract@you-doc').load('_status._disp.en', true)

Checking whether a specific record exists

await Citeck.Records.get('emodel/ecos-contract@you-doc').load('_notExists?bool!', true)

Checking that a record is a subtype of a specific type

await Citeck.Records.get('emodel/ecos-contract@you-doc').load('_type.isSubTypeOf.case?bool!', true)

Checking access permissions for a record

// Проверка права на чтение
await Citeck.Records.get('emodel/ecos-contract@you-doc').load('permissions._has.Read?bool!', true)

// Проверка права на запись
await Citeck.Records.get('emodel/ecos-contract@you-doc').load('permissions._has.Write?bool!', true)

// Проверка кастомного права
await Citeck.Records.get('emodel/ecos-contract@you-doc').load('permissions._has.bpmn-process-instance-read?bool!', true)

Checking communication between microservices: notifications -> eproc -> uiserv

await Citeck.Records.get('notifications/meta@').load('rec.eproc/meta@.rec.uiserv/meta@.time', true)

Getting attributes directly through an association

For a contract object, we get the counterparty and retrieve its TIN, creation date, and display name:

await Citeck.Records.get('emodel/ecos-contract@you-doc').load('counterparty{?disp,inn,_created}', true)

Example response:

{
    "?disp": "ООО Стальпром",
    "inn": "111111111111",
    "_created": "2023-08-03T09:28:49.071Z"
}

If the association is multiple, you can get the attributes of all objects:

await Citeck.Records.get('emodel/ecos-contract@you-doc').load('payments[]{plannedPaymentDate,amount?num}', true)

Example response:

[
    {
        "plannedPaymentDate": "2025-02-10T00:00:00Z",
        "amount": 1000
    },
    {
        "plannedPaymentDate": "2025-02-20T00:00:00Z",
        "amount": 10500
    }
]

If the association is multiple and you need attributes of only the first object:

await Citeck.Records.get('emodel/ecos-contract@you-doc').load('payments{plannedPaymentDate,amount?num}', true)

Example response:

{
  "plannedPaymentDate": "2025-02-10T00:00:00Z",
  "amount": 1000
}

Getting multiple attributes together with nested attributes

Getting multiple attributes together with attributes from an association:

await Citeck.Records.get('emodel/ecos-contract@you-doc').load(['?disp', 'payments[]{plannedPaymentDate,amount?num}'], true)

Example response:

{
  "?disp": "Договор №16808",
  "payments[]{plannedPaymentDate,amount?num}": [
    {
      "plannedPaymentDate": "2025-02-10T00:00:00Z",
      "amount": 1000
    },
    {
      "plannedPaymentDate": "2025-02-20T00:00:00Z",
      "amount": 10500
    }
  ]
}

You can also assign custom names to the retrieved attributes:

await Citeck.Records.get('emodel/ecos-contract@you-doc').load({'contractName': '?disp', 'payments': 'payments[]{plannedPaymentDate,amount?num}'}, true)

Example response:

{
  "contractName": "Договор №16808",
  "payments": [
    {
      "plannedPaymentDate": "2025-02-10T00:00:00Z",
      "amount": 1000
    },
    {
      "plannedPaymentDate": "2025-02-20T00:00:00Z",
      "amount": 10500
    }
  ]
}

Nested attributes can be retrieved not only from associations but also from any attributes that represent objects, for example the _content attribute:

await Citeck.Records.get('emodel/ecos-contract@you-doc').load({'name': '?disp', 'content': '_content{size,mimeType}'}, true)

Example response:

{
  "name": "Договор №16808",
  "content": {
    "size": "248446",
    "mimeType": "application/pdf"
  }
}

Working with Files

Working with files from the UI is possible either by loading content as a base64 string or by getting a download link.
The script retrieves the file content as a base64 string from the _content attribute:

await Records.get('emodel/ecos-contract@3a4e11cf-4227-44f4-98dd-1eeefba30e28').load('_content.bytes')

The script retrieves a download link for the file from the _content attribute:

await Records.get('emodel/ecos-contract@3a4e11cf-4227-44f4-98dd-1eeefba30e28').load('_content.url')

You can upload a file as formData at the following address:

/gateway/emodel/api/ecos/webapp/content

or via base64 (suitable only for small files).

Starting a business process for a document

let rec = Records.get('eproc/bpmn-proc@some-process-id'); // id процесса
rec.att('action', 'START');
rec.att('document', 'emodel/contract@0b54aed0-d288-4d29-aec3-c1ff37cfa089'); // Документ, для которого стартуем процесс
rec.save();