﻿# Массовые действия с элементами в скрипте

> [HTML Version](batch-actions.html)

В ELMA365 вы можете массово добавлять или удалять элементы, а также обновлять их поля через [скрипт](type-script.md), используя методы на языке [TypeScript](https://www.typescriptlang.org/). Это позволяет снизить нагрузку на систему и уменьшить влияние установленных лимитов, когда нужно обработать большое количество данных. Например, если у вас настроена интеграция со сторонней системой, можно из неё загрузить каталог товаров в приложение.

Вы можете задать следующие методы в скриптах:

- `app.batch().save()` — массовое добавление элементов приложения;

- `app.batch().update()` — массовое обновление полей элементов приложения;

- `app.batch().delete()` — массовое удаление элементов приложения.

При написании скриптов с методами для массовых операций учитывайте следующие условия:

- за один запрос обрабатывается не более 10000 элементов. Это ограничение применяется ко всем указанным методам;

- чтобы выполнить массовое действие с элементами при помощи метода, у пользователя должны быть [права на импорт данных этого приложения](360007527512.md#assign). Это условие применяется не только к клиентским, но и серверным скриптам.

В статье рассмотрим на примерах, как использовать методы в скриптах. Подробнее читайте в [справке ELMA365 TS SDK](https://tssdk.elma365.com/ru/latest/pages/quick-start/intro_batch.html).

## Метод массового добавления элементов

С помощью `app.batch().save()` пакет элементов приложения обрабатывается за один запрос. 

Используйте этот метод, чтобы:

- сохранить новые элементы в приложение;

- обновить поля существующих элементов. В этом случае укажите их идентификаторы, чтобы по ним найти нужные элементы, внести в них изменения и сохранить отредактированные элементы в базе данных.

### Пример массового добавления

Предположим, компания использует для работы систему ELMA365. Сотрудники маркетинга также применяют сторонний сервис, в котором хранятся публикации по продукту и комментарии от клиентов.

Чтобы работники смежных отделов могли увидеть все данные в одном месте, информацию из этого внешнего сервиса можно массово перенести в ELMA365. Для этого нужно:

1. Создать приложения для загрузки публикаций и комментариев.

2. Настроить интеграцию через [пользовательский модуль](extentions.md) и добавить в интерфейс модуля две кнопки со скриптами:

- **Добавить посты** — для массового переноса всех публикаций из стороннего сервиса в ELMA365;

- **Добавить комментарии** — для загрузки всех комментариев к этим публикациям.

#### Шаг 1. Создать два приложения

Для начала создайте [приложения](360007235031.md), чтобы импортировать в них данные. При этом добавляйте свойства приложений в соответствии с полями публикаций и комментариев в сторонней системе. Рассмотрим на примере:

1. **Посты** — содержит свойства:

- **Название** (\[OBJECT\]) — системное свойство, создаётся автоматически;

- **Номер** (\[OBJECT\]) — тип [Число (целое)](360009707032.md#number) для идентификационного номера, по которому во внешней системе определяется связь между публикацией и комментариями к ней, т. е. значения этого поля равны в связанных элементах;

- **Дата создания** (\[OBJECT\]) — тип [Дата/время](360009707032.md#date-time) для хранения даты создания поста;

- **Заголовок** (\[OBJECT\]) — тип [Строка (строка)](360009707032.md#string) для заголовка публикации;

- **Текст** (\[OBJECT\]) — тип [Строка (текст)](360009707032.md#string) для текста публикации;

- **Комментарии** (\[OBJECT\]) — тип [Приложение (один)](app-data-type.md) для ссылки на связанный комментарий.

2. **Комментарии** — содержит свойства:

- **Название** (\[OBJECT\]) — системное свойство, создаётся автоматически;

- **Номер** (\[OBJECT\]) — тип **Число (целое)** для идентификационного номера, по которому во внешней системе определяется связь между публикацией и комментариями к ней, т. е. значения этого поля равны в связанных элементах;

- **Дата создания** (\[OBJECT\]) — тип **Дата/время** для хранения даты создания комментария;

- **Электронная почта пользователя** (\[OBJECT\]) — тип [Электронная почта](360009707032.md#email) для электронной почты пользователя, оставившего комментарий;

- **Сообщение** (\[OBJECT\]) — тип **Строка (текст)** для текста комментария;

- **Посты** (\[OBJECT\]) — тип **Приложение (один)** для ссылки на связанный пост.

С помощью этих свойств далее в скрипте определяются поля, в которые запишутся значения, переданные из внешнего сервиса. Подробнее про заполнение полей **Комментарии** и **Посты** типа **Приложение (один)** читайте в разделе [«Пример массового обновления полей»](#example-batch-update).

#### Шаг 2. Настроить загрузку данных через скрипт

После создания приложений настройте импорт данных из сторонней системы.

Для этого:

1. В настроенном модуле интеграции перейдите на вкладку [Настройки](extention-settings.md#settings) и нажмите кнопку **Изменить форму**.

2. В открывшемся дизайнере интерфейсов:

- создайте кнопки **Добавить посты** и **Добавить комментарии**;

- на вкладке **Скрипты** на стороне клиента пропишите код, используя \[OBJECT\]. Этот код позволит импортировать данные в приложения, когда пользователь нажмёт кнопку **Добавить посты** или **Добавить комментарии**.

Пример кода

````
  
/\* Client scripts module \*/  
declare const console: any;  
/\*  
// Асинхронная функция, чтобы импортировать комментарии из внешнего сервиса  
async function import\_comments(): Promise<void> \{  
// Выполняем запрос к внешнему сервису для получения комментариев  
    const result = await fetch('https://externalservicewebsite.com/comments');  
// Преобразуем ответ в формат JSON  
    const comments = await result.json();  
// Инициализируем массив для хранения элементов комментариев  
    const items: any = \[\];  
// Проходимся по каждому комментарию в полученном списке  
    for (let c of comments) \{  
// Создаём новый элемент комментария в приложении  
        const item = Context.fields.commentapp.app.create();  
// Заполняем поля элемента комментария  
        item.data.\_\_name = c.name;  
        item.data.email = \[\{ type: EmailType.Home, email: c.email \}\];  
        item.data.body = c.body;  
        item.data.postID = c.postId;   
        items.push(item);  
    \}  
// Пакетно сохраняем все созданные элементы комментариев  
    await Context.fields.commentapp.app.batch().save().items(items).all();  
\}  
// Асинхронная функция, чтобы импортировать посты из внешнего сервиса  
async function import\_posts(): Promise<void> \{  
// Выполняем запрос к внешнему сервису для получения постов  
    const result = await fetch('https:// externalservicewebsite.com/posts');  
// Преобразуем ответ в формат JSON  
    const posts = await result.json();  
// Инициализируем массив для хранения элементов постов  
    const items: any = \[\];  
// Проходимся по каждому посту в полученном списке  
    for (let p of posts) \{  
// Создаём новый элемент поста в приложении  
        const item = Context.fields.postsapp.app.create();  
// Заполняем поля элемента поста  
        item.data.\_\_name = p.title;  
        item.data.body = p.body;   
        item.data.postID = p.id;  
        items.push(item);  
    \}  
// Пакетно сохраняем все созданные элементы постов  
    await Context.fields.postsapp.app.batch().save().items(items).all();  
\}
````

3. ````
Сохраните и опубликуйте изменения.

После этого кнопки отобразятся в [настройках модуля](extention-settings.md#settings) интеграции. Теперь пользователь может использовать их, чтобы добавить новые элементы в приложения **Посты** и **Комментарии**.

## Метод массового обновления полей элементов

Чтобы обновить множество полей элементов за один запрос, используйте в скрипте метод \[OBJECT\]. При этом вы можете:

- указать правила такого обновления;

- определить критерии поиска элементов, которые нужно обновить;

- ограничить количество обновляемых элементов.

### Пример массового обновления полей

В [примере массового добавления элементов](#example-batch-save) мы перенесли из сторонней системы данные в приложения  **Посты** и **Комментарии**, используя в скрипте метод \[OBJECT\]. При этом поля **Посты** в карточках комментариев и **Комментарии** в карточках публикаций пока остались пустыми, т. к. ссылки на связанные элементы не передаются из внешней системы, а создаются в ELMA365.

Чтобы сотрудники при работе в этих приложениях могли быстро находить нужную информацию, заполним эти пустые поля ссылками на связанные элементы.

Рассмотрим, как массово обновить поля, используя метод \[OBJECT\].

В сторонней системе связь между публикациями и комментариями определяется через поле **Номер** (\[OBJECT\]). Значение в нём одинаково в связанных элементах. Используем это свойство в скрипте, чтобы по нему найти нужные публикации и добавить ссылки в поле **Посты** на карточки комментариев.

Для этого:

1. В настроенном модуле интеграции перейдите на вкладку [Настройки](extention-settings.md#settings) и нажмите кнопку **Изменить форму**.

2. В открывшемся дизайнере интерфейсов добавьте виджет [Кнопка](button_widget.md) с названием **Обновить поля**.

3. На вкладке **Скрипты** пропишите код, с помощью которого пользователь обновит связи между элементами приложений **Посты** и **Комментарии**. Если нажать кнопку **Обновить поля**, в карточках комментариев появятся ссылки в полях **Пост**.

Пример кода

````
  
// Асинхронная функция, чтобы обновить поле Посты в комментариях  
async function update\_comments(): Promise<void> \{  
// Ищем и получаем посты из приложения Посты  
    const posts = await Context.fields.postsapp.app.search().size(100).from(0).all();  
    for (let p of posts) \{  
// Пакетно обновляем значения в поле Посты на карточках комментариев, сравнивая значения в поле Номер (postID). Если значения совпадают, то в поле Посты добавляется ссылка на связанный элемент  
        await Context.fields.commentapp.app.batch().update().set("post", (f, op) => p).where((f) => f.postID.eq(p.data.postID ?? 0)).all();  
    \}  
\}
````

4. ````
Сохраните и опубликуйте изменения.

После этого кнопка **Обновить поля** отобразится в [настройках модуля](extention-settings.md) интеграции. Теперь пользователь может использовать её, чтобы обновить поле **Посты** в карточках комментариев.

## Метод массового удаления элементов

Вы можете удалить множество элементов приложения за один запрос, используя в скрипте метод \[OBJECT\]. При этом можно:

- определить условия поиска элементов, которые нужно удалить;

- указать количество удаляемых элементов.

### Пример массового удаления элементов 

В предыдущих примерах с помощью скриптов мы [добавили данные из сторонней системы](#example-batch-save) в приложения **Посты** и **Комментарии** и [обновили поля их элементов](#example-batch-update).

Теперь настроим массовое удаление данных с помощью скрипта. Добавим на страницу модуля интеграции со сторонней системой две кнопки. При нажатии на них пользователь сможет удалить устаревшие элементы приложений **Посты** или **Коментарии**, например, записи, которые созданы до 01.01.2024 г.

Для этого:

1. В модуле интеграции со сторонней системой перейдите на вкладку **Настройки** и нажмите кнопку **Изменить форму**.

2. В открывшемся дизайнере интерфейсов добавьте виджет **Кнопка**, задайте название **Удалить посты** и тип **Скрипт**.

3. К этой кнопке привяжите скрипт массового удаления. Укажите в нём условие поиска элементов и количество записей, удаляемых за один запрос. В процессе выполнения скрипта количество таких запросов определяется автоматически. В примере будем удалять элементы, созданные до 01.01.2024 г., по 100 штук.  
Для этого в настройках кнопки на вкладке **Основные** в поле **Выполняемый скрипт** укажите название функции \[OBJECT\]. Затем нажмите **Сохранить** и **Открыть**.

4. На открывшейся вкладке **Скрипты** добавьте следующий скрипт:

````
// Асинхронная функция, чтобы удалить все элементы из приложения Посты  
async function delete\_posts(): Promise<void> \{  
// указываем переменную, чтобы отследить количество удалённых элементов   
    let rows = 0;  
// используем цикл для удаления всех элементов  
    do \{  
        rows = await   
// Добавляем метод для массового удаления элементов в приложении Посты и указываем критерий отбора элементов, а также количество записей в одном запросе на удаление     
Context.fields.postsapp.app.batch().delete().where((f) => f.\_\_createdAt.lt(new Datetime('2024-01-01'))).size(100).from(0).all();  
    \}   
while (rows > 0)      
\}

5. ````
Теперь аналогичным образом нужно создать ещё одну кнопку для удаления записей в приложении **Комментарии**. Удалять элементы будем по тем же условиям — в зависимости от их даты создания, по 100 штук.  
Для этого на вкладке **Шаблон** добавьте виджет **Кнопка**. Выполните такие же настройки как для кнопки **Удалить посты**. При написании скрипта используйте код переменной приложения **Комментарии**.

6. Сохраните и опубликуйте обновления.

Теперь в настройках модуля отобразятся кнопки для удаления элементов из приложений **Посты** и **Комментарии** по дате их создания.

Также вы можете отслеживать создание или изменение элементов приложений через клиентский скрипт. Подробнее об этом читайте в статье [«Скрипты в виджетах»](client_server_scripts.md#app-events).