# 🍬 RMG 365 | Dev Tools

Набор инструментов разработчика ELMA365

# Установка и настройка решения

<p class="callout info">Поддержка решения осуществляется на добровольной основе в канале [Telegram](https://t.me/elma365_randmgroup/948)</p>

Наcтройки:

[![image.png](https://kb.randmgroup.ru/uploads/images/gallery/2025-04/scaled-1680-/jtEYCBaKufHkpJhw-image.png)](https://kb.randmgroup.ru/uploads/images/gallery/2025-04/jtEYCBaKufHkpJhw-image.png)

где:

- Окружение - режим окружения системы (кроме Production будет отображаться вверху страницы). Доступные значения: 
    - Development
    - Testing
    - Stage
    - PreProd
    - Production
- Просмотр файлов - включает предпросмотр для файлов типа XML и JSON.
- Адрес ELMA365 и Токен ELMA365 - может использоваться как хелпер для вызова Web API.
- Логин ELMA365 и Пароль - может использоваться для вызова "ручек" фронта от имени конекреного пользователя

Кнопка проверить используется для проверки корректности ввода кредов выше:

[![image.png](https://kb.randmgroup.ru/uploads/images/gallery/2025-04/scaled-1680-/kKLWdZ61P5MyHmfJ-image.png)](https://kb.randmgroup.ru/uploads/images/gallery/2025-04/kKLWdZ61P5MyHmfJ-image.png)

# Логирование в скриптах

# Пример вызова в скрипте через Imports и Namespace.action

<p class="callout success">Доступно с версии 2024.2</p>

### Вариант с использованием Imports:

```typescript
async function action(): Promise<void> {
    const message = `${Context.data.__item!.namespace}.${Context.data.__item!.code}.${Context.data.__item!.id}`;
    const details = JSON.stringify((<any>Context).json(), null, 2);
    Imports?.devtools?.action?.save_to_log?.call({message: message, details: details});
}
```

Нужно подключить зависимость и определить псевдоним, в данном примере это **devtools**:

[![image.png](https://kb.randmgroup.ru/uploads/images/gallery/2024-02/scaled-1680-/5iqtcCDwweto1iTd-image.png)](https://kb.randmgroup.ru/uploads/images/gallery/2024-02/5iqtcCDwweto1iTd-image.png)

# Пример вызова в скрипте

<p class="callout success">Логирование поддерживается как в клиентских, так и серверных скриптах.</p>

На текущий момент нами был обнаружен единственный способ для решения данной задачи. Он не является изящным, но "на безрыбье и рак щука". Отдельное спасибо за идею Раису.

Для того, чтобы в лог (приложение в разделе системных справочников) попала информация, в скрипте необходимо вызнать следующий код:

```typescript
const message = 'Сообщение из серверного скрипта';
const details = 'Проверка вызова логирования из серверного скрипта в ' + Date().toString();
await System.templater.generateText(Context, `{ExtText('82fe0bc6-0564-4b8a-a7d4-4c136cf8a949', 'logger', '${message}', '${details}')}`);
```

Результатом выполнения будет следующее:

[![image.png](https://kb.randmgroup.ru/uploads/images/gallery/2023-11/scaled-1680-/Tg40ofc0wQIBAUDy-image.png)](https://kb.randmgroup.ru/uploads/images/gallery/2023-11/Tg40ofc0wQIBAUDy-image.png)

[![image.png](https://kb.randmgroup.ru/uploads/images/gallery/2023-11/scaled-1680-/rV4bEQN5K9OuAnn8-image.png)](https://kb.randmgroup.ru/uploads/images/gallery/2023-11/rV4bEQN5K9OuAnn8-image.png)

# Логирование данных в обработчике событий

Для того, чтобы понять, какие данные приходят в обработчик событий в модуле, можно использовать следующий код:

```typescript
async function action(): Promise<void> {
    const message = 'Сообщение о записи входящего разговора';
    const details = JSON.stringify((<any>Context).json(), null, 2);
    await System.templater.generateText(Context, `{ExtText('82fe0bc6-0564-4b8a-a7d4-4c136cf8a949', 'logger', '${message}', ${details}')}`);
}
```

В результате, в логе будет следующая информация:

[![image.png](https://kb.randmgroup.ru/uploads/images/gallery/2024-02/scaled-1680-/YjXXTY7GvBiZ9ypm-image.png)](https://kb.randmgroup.ru/uploads/images/gallery/2024-02/YjXXTY7GvBiZ9ypm-image.png)

[![image.png](https://kb.randmgroup.ru/uploads/images/gallery/2024-02/scaled-1680-/KOlbE7SC2YLr45aT-image.png)](https://kb.randmgroup.ru/uploads/images/gallery/2024-02/KOlbE7SC2YLr45aT-image.png)

# Получения режима окружения

Чтобы в своих решениях понять в каком режиме работает система необходимо в скриптах вызвать следующий метод:

```typescript
let env_mode = 'Production';
const result = await Imports?.devtools?.action?.env_mode?.call( { for_service: true } )
if (result?.mode)
        env_mode = result.mode;
```

for\_service указывает возвращять ли только 2 варианта: Staging или Production (Development не возвращается, т.к. зарезервировано для отладки), если не указано или false, то возвращаются все значения согласно настроек модуля.

devtools для импорта указан для примера и задается здесь:

[![image.png](https://kb.randmgroup.ru/uploads/images/gallery/2025-04/scaled-1680-/PcC5yR9YemFl1tJh-image.png)](https://kb.randmgroup.ru/uploads/images/gallery/2025-04/PcC5yR9YemFl1tJh-image.png)

# Полезное от WhatDaELMA365

[Сайт](https://whatdadev.ru)  
[TG канал](https://t.me/whatdaelma365)

Ежедневные находки и приёмы для работы в ELMA365: скрипты, шаблоны, автоматизация и быстрые решения.

# Custom Loader

Пример, как выглядит режим загрузки данных:  
<video controls="controls" height="270" src="https://kb.randmgroup.ru/attachments/12?open=true" width="480"></video>

В клиентский скрипт нужно добавить следующий код в самом начале:

```typescript
declare const window: any;
```

Для показа и скрытия анимации необходимо использовать следующий код, например:

```typescript
async function updateOrganizations(): Promise<void> {

  // Показать loader
  window.CustomLoader.show();
    
  ViewContext.data.show_organizations_update = true;
  await Server.rpc.updateOrganizations();
  ViewContext.data.show_organizations_update = false;
  
  // Скрыть loader
  window.CustomLoader.hide();
}
```

<p class="callout warning">Данный код работает только в клиентских скриптах и не работает в серверных.</p>