стандарт 766

ID: #std766

# Макеты: требования по локализации и поддержке разных языков интерфейса

#### 1.

Обычно перевод табличных, текстовых и HTML-макетов не требует специальных подготовительных действий.
Исключение: двоичные макеты, которые нужно переводить, и HTML-макеты с изображениями, где текст внутри изображений должен отличаться по языкам.

Такие макеты помечайте постфиксом в имени: `_кодЯзыка`, где код совпадает со свойством `Код языка` в метаданных.
Для русского языка это `_ru`.

#### Неправильно

Макет `ПФ_ODT_СчетНаОплату`

#### Правильно

Макет `ПФ_ODT_СчетНаОплату_ru`

При добавлении языков интерфейса добавляйте макеты с соответствующими постфиксами и выбирайте их в коде по языку.

#### Неправильно

```bsl
... = ПолучитьОбщийМакет("ПФ_ODT_СчетНаОплату");
```

#### Правильно

```bsl
... = ПолучитьОбщийМакет("ПФ_ODT_СчетНаОплату" + "_" + ТекущийЯзык());
```

Чтобы снизить риск ошибок при частичном переводе, получайте макет в три этапа:

- сначала по `ИмяМакета + "_" + ТекущийЯзык()`;
- если не найден, по `ИмяМакета + "_" + Метаданные.ОсновнойЯзык.КодЯзыка`;
- если не найден, по исходному имени `ИмяМакета`;
- затем устанавливайте `КодЯзыка` (для табличного документа) или `КодЯзыкаМакета` (для текстового документа и HTML-макета), как в п. 2.

#### 2.

В многоязычной конфигурации может потребоваться в одном сеансе формировать печатные формы на языке, отличном от текущего языка интерфейса.
Например, в англоязычном сеансе формировать счет на русском языке.

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

- `КодЯзыка` у табличного документа;
- `КодЯзыкаМакета` у текстового документа и HTML-макета.

#### Правильно

```bsl
Макет = ПолучитьОбщийМакет("ПечатнаяФорма");
Макет.КодЯзыкаМакета = "ru";
HTMLДокумент = Макет.ПолучитьДокументHTML();
```

#### 3.

В многоязычной конфигурации может понадобиться формировать печатные формы строго на одном языке независимо от текущего языка интерфейса.
Пример: регламентированная отчетность для госучреждений.

Для табличных и HTML-макетов такого типа:

- указывайте постфикс кода языка в имени (как в п. 1);
- при программном получении устанавливайте код языка макета (как в п. 2).

Такие макеты не переводите на другие языки интерфейса.
При программном формировании текстов для заполнения макета явно задавайте второй параметр в `НСтр()`, чтобы строки были на том же языке, что и макет.

#### Неправильно

```bsl
Макет = ПолучитьМакет("ПФ_MXL_СчетФактура");
...
Область.Текст = НСтр("ru='Заголовок печати';");
```

#### Правильно

```bsl
Макет = ПолучитьМакет("ПФ_MXL_СчетФактура_ru");
Макет.КодЯзыка = Метаданные.Языки.Русский.КодЯзыка;
...
Область.Текст = НСтр("ru='Заголовок печати';", Метаданные.Языки.Русский.КодЯзыка);
```

При использовании БСП и подсистемы `Печать` получение макета через
`УправлениеПечатью.МакетПечатнойФормы("ПФ_MXL_СчетФактура")` возвращает форму `ПФ_MXL_СчетФактура_ru` и устанавливает у макета свойство `КодЯзыка`.

#### 4.

Если в текстах макетов используются именованные параметры подстановки, соблюдайте требования [#std761: Интерфейсные тексты в коде: требования по локализации](https://v8std.ru/std/761/)

#### 5.

Используйте в макетах кодировку UTF-8.

#### 6.

По возможности группируйте однотипные макеты: используйте один макет вместо нескольких.

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

#### Неправильно

Изображение: Несколько однотипных макетов (766.image19.png)

```bsl
Макет = Обработки.ПереключениеРежимов.ПолучитьМакет("Сообщение");
```

#### Правильно

Изображение: Один макет для однотипных сообщений (766.image20.png)

```bsl
Макет = Обработки.ПереключениеРежимов.ПолучитьМакет(
    СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
        "Сообщения_%1",
        ОбщегоНазначения.КодОсновногоЯзыка()));
```

#### 7.

Внешние компоненты размещайте в макетах с типом `внешняя компонента`.

При разработке внешней компоненты обрабатывайте метод `SetLocale` для локализации по полученному коду локали.
Подробнее: [#metod3221: Технология создания внешних компонент](https://v8std.ru/metod8dev/3221/)

Если полученный код локали не поддерживается, компонент должен настроить свое окружение на использование английского языка.

#### Проверки

[#acc:450](https://v8std.ru/diagnostics/acc/450/)
[#acc:497](https://v8std.ru/diagnostics/acc/497/)
[#acc:1361](https://v8std.ru/diagnostics/acc/1361/)
#### Источник

https://its.1c.ru/db/v8std#content:766

Обычно перевод табличных, текстовых и HTML-макетов не требует специальных подготовительных действий. Исключение: двоичные макеты, которые нужно переводить, и HTML-макеты с...

В макете с типом "ВнешняяКомпонента" размешен файл с другим типом. АПК:1361

В макете используется кодировка, отличная от "UTF-8". АПК:450

В имени макета отсутствует суффикс (например, "_ru"). АПК:497

3221

Интерфейсные тексты в коде: требования по локализации #std761

Макеты: требования по локализации и поддержке разных языков интерфейса #std766


стандарт 767

ID: #std767

# Регламентные задания: требования по локализации

#### 1.

Для предопределенных регламентных заданий не задавайте наименование в конфигураторе.
Достаточно указать синоним предопределенного регламентного задания.

#### Неправильно

Изображение: Наименование задано вручную (767.image17.png)

#### Правильно

Изображение: Используется только синоним (767.image18.png)

Для непредопределенных (параметризованных) регламентных заданий наименование задавайте программно.
Оформляйте его через `НСтр`, при необходимости учитывайте контекст выполнения.

#### Правильно

```bsl
Задание = РегламентныеЗадания.СоздатьРегламентноеЗадание(Метаданные.РегламентныеЗадания.РассылкаОтчетов);
Задание.Наименование = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Рассылка отчетов: %1'"), РассылкаОтчетов);
Задание.Записать();
```

Если наименование не задано, платформа берет его из локализуемого синонима.
Если наименование задано вручную, будет использоваться именно оно, а оно не поддерживает локализацию.

#### Проверки
[#v8cs:mdo-scheduled-job-description](https://v8std.ru/diagnostics/v8-code-style/mdo-scheduled-job-description/)

#### См. также

- [#std540: Общие требования к регламентным заданиям](https://v8std.ru/std/540/)

#### Проверки

[#acc:449](https://v8std.ru/diagnostics/acc/449/)
#### Источник

https://its.1c.ru/db/v8std#content:767

Задано наименование предопределенного регламентного задания. АПК:449

Задано наименование предопределенного регламентного задания (mdo-scheduled-job-description)

Общие требования к регламентным заданиям #std540

Регламентные задания: требования по локализации #std767


стандарт 769

ID: #std769

# Поставка международной версии конфигурации

Стандарт применим к локализуемым конфигурациям (и входящим в них библиотекам), на базе которых выпускаются национальные решения для разных стран или регионов.

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

Локализованные версии рекомендуется разрабатывать на базе международной версии.

Требования группы стандартов по локализации одинаково применяются и к международной, и к национальным версиям.

Например, национальная версия также может поставляться с несколькими языками интерфейса.

Для снижения трудозатрат на выделение национальной специфики в первую очередь анализируйте зарубежные версии, опубликованные на портале 1С: https://releases.1c.ru.

#### 1.

Национальную (российскую) специфику в программном коде и формах выделяйте в отдельные объекты метаданных, которые отсутствуют в международной версии.

#### Неправильно

Изображение: Национальная специфика смешана с международной (769.localization-wrong.png)

#### Правильно

Изображение: Национальная специфика вынесена в отдельные объекты (769.localization-correct.png)

#### 1.1.

Реквизиты объектов, относящиеся к национальной специфике, можно оставлять в объектах, но конфигурация должна сохранять работоспособность при их удалении.

#### 1.2.

Если в форме к национальной специфике относится только часть элементов, выносите эти элементы в отдельную форму.

#### Пример

Изображение: Выделение национальных элементов формы (769.form-split.png)

#### 1.3.

К национальной специфике могут относиться и алгоритмы (например, загрузка курсов валют).
Такие алгоритмы также выделяйте в отдельные объекты метаданных.

#### 1.4.

Если подсистема или объект в основном международные, но нужно добавить национальную специфику, создавайте общие модули с постфиксом `Локализация`.

В алгоритмах, где нужно дополнить или переопределить поведение, делайте вызов в эти модули.
Процедуры размещайте в области `ПрограммныйИнтерфейс`.

В международной поставке модули с постфиксом `Локализация` не должны содержать прикладной код.

В национальной конфигурации код внутри процедур обрамляйте комментариями `Локализация` и `Конец Локализация`.
Если международная поставка изготавливается из национальной, такие фрагменты удаляются вместе с обрамляющими комментариями.

#### Пример: национальная конфигурация

```bsl
Процедура ПриОпределенииСимволовНациональногоАлфавита(СимволыНациональногоАлфавита, ДополнительныеДопустимыеСимволы) Экспорт

    // Локализация
    СимволыНациональногоАлфавита = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя";
    // Конец Локализация

КонецПроцедуры
```

#### Пример: международная поставка

```bsl
Процедура ПриОпределенииСимволовНациональногоАлфавита(СимволыНациональногоАлфавита, ДополнительныеДопустимыеСимволы) Экспорт

КонецПроцедуры
```

Не обрамляйте комментариями `Локализация` и `Конец Локализация` фрагменты кода в любых других объектах и модулях.
Иначе разработчик не сможет при необходимости доопределить национальную специфику.

#### Неправильно

```bsl
Функция АдресВОблачномСервисе(Сервис, Href) Экспорт

    АдресОбъекта = "";

    Если Сервис = "Box" Тогда
        АдресОбъекта = "https://app.box.com/files/0/";
    // Локализация
    ИначеЕсли Сервис = "Yandex" Тогда
        АдресОбъекта = "https://disk.yandex.ru/client/disk/";
    // Конец Локализация
    ИначеЕсли Сервис = "Dropbox" Тогда
        АдресОбъекта = "https://www.dropbox.com/home/";
    КонецЕсли;

    Возврат АдресОбъекта + Href;

КонецФункции
```

#### Правильно

```bsl
Функция АдресВОблачномСервисе(Сервис, Href) Экспорт

    АдресОбъекта = "";

    Если Сервис = "Box" Тогда
        АдресОбъекта = "https://app.box.com/files/0/";
    ИначеЕсли Сервис = "Dropbox" Тогда
        АдресОбъекта = "https://www.dropbox.com/home/";
    Иначе
        РаботаСФайламиЛокализация.ПриОпределенииАдресаОблачногоСервиса(Сервис, АдресОбъекта);
    КонецЕсли;

    Возврат АдресОбъекта + Href;

КонецФункции
```

В модуле `РаботаСФайламиЛокализация`:

```bsl
Процедура ПриОпределенииАдресаОблачногоСервиса(Сервис, АдресОбъекта)

    // Локализация
    Если Сервис = "Yandex" Тогда
        АдресОбъекта = "https://disk.yandex.ru/client/disk/";
    КонецЕсли;
    // Конец Локализация

КонецПроцедуры
```

Пример применения: функциональность закрытия месяца международная, но список этапов нужно дополнять национальными этапами.

Для этого добавляют общий модуль `ЗакрытиеМесяцаЛокализация`, а из процедуры `ЗакрытиеМесяца.ДобавитьЭтапыЗакрытияМесяца` вызывают его метод.

В международной поставке модуль `ЗакрытиеМесяцаЛокализация` содержит только определение метода `ДобавитьЭтапыЗакрытияМесяца`.

#### 1.5.

Если национальная специфика занимает большую часть подсистемы, относите к национальной специфике всю подсистему.

Пример: подсистема «Склонение представлений объектов».

#### 1.6.

Перечисляйте объекты метаданных с национальной спецификой в файле `ЛокализуемыеОбъекты.txt` и включайте файл в дистрибутив типовой конфигурации.

Файл содержит имена объектов в том виде, в котором их возвращает функция `ОбъектМетаданных.ПолноеИмя()`.
Каждый объект указывается с новой строки.
Допускаются комментарии, как в коде конфигурации.

#### Пример

```bsl
// Банки
Обработка.ЗагрузкаКлассификатораБанков
РегламентноеЗадание.ЗагрузкаКлассификатораБанков
Справочник.КлассификаторБанков.Реквизит.ИНН

// Валюты
Обработка.ЗагрузкаКурсовВалют
РегламентноеЗадание.ЗагрузкаКурсовВалют
```

#### 2.

Соблюдение требования п. 1 не должно ухудшать удобство интерфейса.

Если из-за переноса части формы в отдельные формы юзабилити существенно ухудшается, относите к национальной специфике всю форму.

#### 3.

В процедурах переопределяемых модулей размещайте только вызовы процедур конфигурации, содержащих прикладной код.

Это упрощает доработку переопределяемых модулей при локализации.

#### Неправильно

```bsl
// В модуле ВариантыОтчетовПереопределяемый
Процедура ОпределитьРазделыСВариантамиОтчетов(Разделы) Экспорт
    Разделы.Добавить(ВариантыОтчетовКлиентСервер.ИдентификаторНачальнойСтраницы(),
        НСтр("ru = 'Главное'"));

    Разделы.Добавить(Метаданные.Подсистемы.CRMИМаркетинг,
        НСтр("ru= 'Отчеты по CRM и маркетингу'"));

    Разделы.Добавить(Метаданные.Подсистемы.Закупки,
        НСтр("ru= 'Отчеты по закупкам'"));

    Разделы.Добавить(Метаданные.Подсистемы.Казначейство,
        НСтр("ru= 'Отчеты по казначейству'"));

    Разделы.Добавить(Метаданные.Подсистемы.Продажи,
        НСтр("ru= 'Отчеты по продажам'"));

    Разделы.Добавить(Метаданные.Подсистемы.Склад,
        НСтр("ru= 'Отчеты по складу'"));

    Разделы.Добавить(Метаданные.Подсистемы.ФинансовыйРезультатИКонтроллинг,
        НСтр("ru= 'Отчеты по финансовому результату'"));
КонецПроцедуры
```

#### Правильно

```bsl
// В модуле ВариантыОтчетовПереопределяемый
Процедура ОпределитьРазделыСВариантамиОтчетов(Разделы) Экспорт
    ВариантыОтчетовУТ.ОпределитьРазделыСВариантамиОтчетов(Разделы);
КонецПроцедуры

// В модуле ВариантыОтчетовУТ
Процедура ОпределитьРазделыСВариантамиОтчетов(Разделы) Экспорт
    Разделы.Добавить(ВариантыОтчетовКлиентСервер.ИдентификаторНачальнойСтраницы(),
        НСтр("ru = 'Главное'"));

    Разделы.Добавить(Метаданные.Подсистемы.CRMИМаркетинг,
        НСтр("ru= 'Отчеты по CRM и маркетингу'"));

    Разделы.Добавить(Метаданные.Подсистемы.Закупки,
        НСтр("ru= 'Отчеты по закупкам'"));

    Разделы.Добавить(Метаданные.Подсистемы.Казначейство,
        НСтр("ru= 'Отчеты по казначейству'"));

    Разделы.Добавить(Метаданные.Подсистемы.Продажи,
        НСтр("ru= 'Отчеты по продажам'"));

    Разделы.Добавить(Метаданные.Подсистемы.Склад,
        НСтр("ru= 'Отчеты по складу'"));

    Разделы.Добавить(Метаданные.Подсистемы.ФинансовыйРезультатИКонтроллинг,
        НСтр("ru= 'Отчеты по финансовому результату'"));
КонецПроцедуры
```

#### 4.

Обеспечивайте работоспособность международной конфигурации.

#### 5.

Международную и российскую версии выпускайте синхронно.

Для этого используйте одну из схем разработки:

- `a.` разработка российской версии в одном хранилище и автоматическая сборка международной версии удалением объектов национальной специфики и кода внутри процедур модулей с постфиксом `Локализация`;
- `b.` разработка российской и международной версий в двух хранилищах, где российская версия стоит на поддержке международной и содержит добавленные объекты национальной специфики.

Если локализатор берет за основу международную версию, рекомендуется:

- поставить национальную конфигурацию на поддержку международной;
- по мере необходимости добавить объекты из файла `ЛокализуемыеОбъекты.txt`, ориентируясь на аналогичные объекты российской версии;
- при необходимости добавить реализацию в процедуры общих модулей с постфиксом `Локализация`.

Если локализатор берет за основу российскую версию, рекомендуется:

- поставить национальную конфигурацию на поддержку российской;
- снять с поддержки и локализовать объекты из файла `ЛокализуемыеОбъекты.txt`;
- снять с поддержки и локализовать алгоритмы модулей с постфиксом `Локализация`.

Подготовку файла поставки международной версии можно упростить файлом настроек объединения.

#### Подсказка

Для автоматизации используйте обработку подготовки файла настроек объединения:
https://its.1c.ru/db/files/1CITS/EXE/V8Std/ПодготовкаФайлаНастроекОбъединения/ПодготовкаФайлаНастроекОбъединения.zip

#### См. также

- [#std761: Интерфейсные тексты в коде: требования по локализации](https://v8std.ru/std/761/)
- [#std762: Запросы, динамические списки и отчеты на СКД: требования по локализации](https://v8std.ru/std/762/)
- [#std763: Форматирование даты, числа, Булево: требования по локализации](https://v8std.ru/std/763/)
- [#std764: Строковые константные выражения в коде: требования по локализации](https://v8std.ru/std/764/)
- [#std765: Элементы форм: требования по локализации](https://v8std.ru/std/765/)
- [#std767: Регламентные задания: требования по локализации](https://v8std.ru/std/767/)
- [#std766: Макеты: требования по локализации](https://v8std.ru/std/766/)

#### Источник

https://its.1c.ru/db/v8std#content:769

Запросы, динамические списки и отчеты на СКД: требования по локализации #std762

Форматирование даты, числа, Булево: требования по локализации #std763

Строковые константные выражения в коде: требования по локализации #std764

Элементы форм: требования по локализации #std765

Поставка международной версии конфигурации #std769


стандарт 770

ID: #std770

# Ограничения на использование Выполнить и Вычислить на сервере

#### 1.

Опасность представляет не только прямое выполнение кода пользователя, но и выполнение строк, собранных из параметров и переданных в серверные процедуры/функции.

Ограничение относится к серверному коду.

Если в серверном методе используется `Выполнить` или `Вычислить` для строки из параметров, злоумышленник может подменить эту строку и запустить вредоносный код на сервере.

Риск выше, если такой метод доступен из модуля с признаком

- [x] `ВызовСервера`

#### 2.

Перед вызовом `Выполнить`/`Вычислить` в серверном коде включайте безопасный режим.

В модели сервиса учитывайте разделение данных: безопасный режим включайте и для разделителей.

#### Пример

```bsl
УстановитьБезопасныйРежим(Истина);
Выполнить Алгоритм;
```

#### Пример (модель сервиса)

```bsl
УстановитьБезопасныйРежим(Истина);
Для каждого ИмяРазделителя Из РазделителиКонфигурации() Цикл
    УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
КонецЦикла;
Выполнить Алгоритм;
```

Если используется БСП, применяйте:

- `ОбщегоНазначения.ВыполнитьВБезопасномРежиме()` вместо `Выполнить`;
- `ОбщегоНазначения.ВычислитьВБезопасномРежиме()` вместо `Вычислить`;
- `ОбщегоНазначения.ВыполнитьМетодКонфигурации()` и `ОбщегоНазначения.ВыполнитьМетодОбъекта()` вместо формирования строк вызова.

#### Проверки
[#v8cs:server-execution-safe-mode](https://v8std.ru/diagnostics/v8-code-style/server-execution-safe-mode/)

#### 3.

Если код нельзя выполнить в безопасном режиме (например, есть доступ к файлам), запускайте его только после аудита и только из контролируемого источника.

Рекомендуемый сценарий:

- передать внешний код администратору на аудит;
- хранить одобренный код в объекте, доступном на запись только администратору;
- выполнять код только через централизованную процедуру/функцию.

При использовании БСП для этого применяйте подсистему дополнительных отчетов и обработок.

#### 4.

Если конфигурация работает в модели сервиса и поддерживает перенос из локальной версии, отключайте пользовательские фрагменты кода и тексты запросов, пришедшие из локальной базы.

#### См. также

- [#std669: Ограничение на выполнение "внешнего" кода](https://v8std.ru/std/669/)
- [#std678: Безопасность прикладного программного интерфейса сервера](https://v8std.ru/std/678/)
- [Облачные технологии](https://v8.1c.ru/platforma/oblachnye-tehnologii/)

#### Проверки
[#bslls:DisableSafeMode](https://v8std.ru/diagnostics/bslls/DisableSafeMode/)
[#bslls:ExecuteExternalCodeInCommonModule](https://v8std.ru/diagnostics/bslls/ExecuteExternalCodeInCommonModule/)
[#bslls:ExecuteExternalCode](https://v8std.ru/diagnostics/bslls/ExecuteExternalCode/)

[#acc:486](https://v8std.ru/diagnostics/acc/486/)
[#acc:487](https://v8std.ru/diagnostics/acc/487/)
[#acc:488](https://v8std.ru/diagnostics/acc/488/)
[#acc:489](https://v8std.ru/diagnostics/acc/489/)
[#acc:490](https://v8std.ru/diagnostics/acc/490/)
#### Источник

https://its.1c.ru/db/v8std#content:770

Отсутствует включение безопасного режима перед вызовом метода "Выполнить" или "Вычислить". АПК:486

Обнаружен вызов метода "Выполнить" вместо "ОбщегоНазначения.ВыполнитьВБезопасномРежиме()". АПК:487

Обнаружен вызов метода "Вычислить" вместо "ОбщегоНазначения.ВычислитьВБезопасномРежиме()". АПК:488

Обнаружен вызов метода "Выполнить" вместо "РаботаВБезопасномРежиме.ВыполнитьВБезопасномРежиме()". АПК:489

Обнаружен вызов метода "Вычислить" вместо "РаботаВБезопасномРежиме.ВычислитьВБезопасномРежиме()". АПК:490

Отключение безопасного режима BSLLS:DisableSafeMode

Выполнение произвольного кода на сервере BSLLS:ExecuteExternalCode

Выполнение произвольного кода в общем модуле на сервере BSLLS:ExecuteExternalCodeInCommonModule

Отсутствует включение безопасного режима перед вызовом метода "Выполнить" или "Вычислить" (server-execution-safe-mode)

Ограничение на выполнение внешнего кода #std669

Безопасность прикладного программного интерфейса сервера #std678

Ограничения на использование Выполнить и Вычислить на сервере #std770


стандарт 771

ID: #std771

# Интеграция прикладных решений через формат EnterpriseData

#### 1.

Переходы с одной конфигурации на другую разрабатывайте на основе правил конвертации.
Обмен между конфигурациями, использующими БСП, выполняйте на основе формата `EnterpriseData`.

Новые обмены на основе правил конвертации не разрабатывайте.
Исключение: решения для бюджетных организаций, которые не охватываются форматом `EnterpriseData`.

#### 2.

Актуальные версии `EnterpriseData` берите из последней опубликованной версии БСП.
Они поставляются в виде объектов метаданных `Пакет XDTO` с именами вида `EnterpriseData_{X|XX}_{Y|YY}_{Z|ZZ}`, где `X`, `Y` - Major-версия, `Z` - Minor-версия.

Список поддерживаемых версий формируется так, чтобы сохранять баланс между:

- затратами на поддержку обменов;
- совместимостью прикладных решений.

Например, версии `1.0` и `1.1` сняты с поддержки, так как интервала `1.2-1.4` достаточно для обмена между широким диапазоном версий прикладных решений.

#### 3.

При разработке новых версий прикладных решений стремитесь поддерживать в обменах все актуальные версии `EnterpriseData`.
Это обеспечивает асинхронный выпуск версий у разработчиков и асинхронный переход пользователей.

Запрещается выпускать версию конфигурации, которая не поддерживает какую-либо из версий формата, поддерживаемых во встроенной версии БСП.

Например, если в конфигурацию встроена БСП `2.4.1`, необходимо поддерживать версии формата `1.2`, `1.3` и `1.4`.

#### 4.

Не поддерживайте в обмене версию `EnterpriseData`, если она не соответствует функциональным требованиям обмена.

Например, для интеграции двух конфигураций нужен обмен документами `Чек ККМ`.
Поддержка передачи этих данных есть только в версии `1.4`, значит в таком обмене поддерживаемые версии формата должны быть не ниже `1.4`.

#### 5.

В редких случаях обмен между прикладными решениями невозможен из-за отсутствия совместно поддерживаемых версий `EnterpriseData`.
Например, когда одна из конфигураций сильно устарела и требует обновления.

#### Рекомендация

Информируйте пользователей, какие версии `EnterpriseData` поддерживаются в прикладном решении.

#### 6.

При разработке типовых обменов не используйте свойство объектов формата `AdditionalInfo` для передачи сведений между информационными базами.

Чтобы расширить состав свойств формата, вносите согласованные изменения в формат.
Это позволяет всем группам разработки типовых конфигураций поддерживать новые возможности синхронизации.

`AdditionalInfo` разрешается использовать только в случаях:

- поддержки законодательства, когда не остается времени на выпуск новой версии формата;
- обхода критических ошибок, блокирующих синхронизацию из-за исключений.

#### Для информации

Данные, добавленные в `AdditionalInfo`, придется поддерживать длительное время для совместимости с прошлыми версиями.

#### См. также

- [Обмен данными с прикладными решениями на платформе «1С:Предприятие» в формате EnterpriseData](https://its.1c.ru/db/metod8dev/content/5851/hdoc)

#### Проверки

[#acc:518](https://v8std.ru/diagnostics/acc/518/)
[#acc:519](https://v8std.ru/diagnostics/acc/519/)
[#acc:520](https://v8std.ru/diagnostics/acc/520/)
#### Источник

https://its.1c.ru/db/v8std#content:771

Переходы с одной конфигурации на другую разрабатывайте на основе правил конвертации. Обмен между конфигурациями, использующими БСП, выполняйте на основе формата EnterpriseData.

Планом обмена поддерживается версия формата обмена EnterpriseData, не входящая в состав конфигурации. АПК:518

Планом обмена не поддерживается более высокая версия формата обмена EnterpriseData. АПК:519

Планом обмена не поддерживается более низкая версия формата обмена EnterpriseData. АПК:520

Интеграция прикладных решений через формат EnterpriseData #std771


стандарт 773

ID: #std773

# Использование признака ОбменДанными.Загрузка в обработчиках событий объекта

#### 1.

В обработчиках событий `ПередЗаписью`, `ПриЗаписи`, `ПередУдалением` сначала проверяйте признак `ОбменДанными.Загрузка`.

```bsl
Процедура ПередЗаписью(Отказ)

    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    // Код обработчика.
    ...

КонецПроцедуры
```

Это нужно, чтобы при обмене данными бизнес-логика объекта не выполнялась повторно.
Объект должен загружаться в базу «как есть»: без дополнительных проверок, изменений и действий, которые могут исказить данные или помешать загрузке.

Такой же подход применяйте и в других механизмах загрузки:

```bsl
Объект.ОбменДанными.Загрузка = Истина;
Объект.Записать();
```

Если механизм не учитывает особенности конкретной конфигурации, он должен иметь возможность записать объект так, как будто обработчика нет.

#### 2.

Исключение: обмен, который при загрузке регистрирует изменения для выгрузки на другие узлы плана обмена.

Если используется подсистема `Обмен данными` БСП и нужно отключить регистрацию объектов, добавляйте дополнительное свойство `ОтключитьМеханизмРегистрацииОбъектов`:

```bsl
Объект.ОбменДанными.Загрузка = Истина;
Объект.ДополнительныеСвойства.Вставить("ОтключитьМеханизмРегистрацииОбъектов");
Объект.Записать();
```

Если в конфигурации есть другие исключения из этого правила, обязательно поясняйте причину в комментарии к коду.

#### 3.

Требования этого стандарта действуют и для обработчиков подписок на те же события.

#### 4.

Если вызывающий код устанавливает `ОбменДанными.Загрузка = Истина`, он берет на себя ответственность за целостность данных объекта.

Например, в РИБ корректность обеспечивается в том узле, где объект был создан или изменен.
В остальных случаях вызывающая сторона должна сама обеспечить корректное заполнение объекта.

При загрузке по правилам конвертации или формату `EnterpriseData` выполняйте все необходимые действия по заполнению и дозаполнению объекта.
Рекомендуется выносить такие действия в экспортные процедуры самого объекта и вызывать их до записи в режиме обмена.

#### См. также

- [#std464: Обработчик события ПередЗаписью](https://v8std.ru/std/464/)
- [#std465: Обработчик события ПриЗаписи](https://v8std.ru/std/465/)
- [#std752: Обработчик события ПередУдалением](https://v8std.ru/std/752/)
- [#std771: Формат EnterpriseData](https://v8std.ru/std/771/)

#### Проверки
[#bslls:DataExchangeLoading](https://v8std.ru/diagnostics/bslls/DataExchangeLoading/)
[#v8cs:data-exchange-load](https://v8std.ru/diagnostics/v8-code-style/data-exchange-load/)

[#acc:75](https://v8std.ru/diagnostics/acc/75/)
#### Источник

https://its.1c.ru/db/v8std#content:773

В обработчиках событий ПередЗаписью, ПриЗаписи, ПередУдалением сначала проверяйте признак ОбменДанными.Загрузка.

Отсутствует обязательная конструкция "Если ОбменДанными.Загрузка Тогда ...". АПК:75

Отсутствует проверка признака ОбменДанными.Загрузка в обработчике событий объекта BSLLS:DataExchangeLoading

Проверка ОбменДанными.Загрузка в обработчике события (data-exchange-load)

Обработчик события ПередЗаписью #std464

Обработчик события ПриЗаписи #std465

Обработчик события ПередУдалением #std752

Использование признака ОбменДанными.Загрузка в обработчиках событий объекта #std773


стандарт 774

ID: #std774

# Безопасность запуска приложений

#### 1.

При запуске внешней программы из кода собирайте командную строку только из проверенных частей.

Если любая часть команды получена из:

- базы данных;
- пользовательского ввода в форме;
- хранилища настроек,

перед запуском проверяйте безопасность значения.

Небезопасными считайте строки, содержащие символы:

`$` `` ` `` `|` `||` `;` `&` `&&`

Требование распространяется на все способы запуска, включая:

- `КомандаСистемы()`;
- `ЗапуститьПриложение()`;
- `НачатьЗапускПриложения()`;
- `ПерейтиПоНавигационнойСсылке()`;
- COM-объекты `Wscript.Shell` и `Shell.Application`.

#### 2.

При использовании БСП для запуска внешних программ применяйте профильный API.

#### 2.1.

Чтобы открыть проводник с фокусом на каталоге/файле, используйте `ФайловаяСистемаКлиент.ОткрытьПроводник`.

#### Пример

```bsl
// Windows
ФайловаяСистемаКлиент.ОткрытьПроводник("C:\Users");
ФайловаяСистемаКлиент.ОткрытьПроводник("C:\Program Files\1cv8\common\1cestart.exe");

// Linux
ФайловаяСистемаКлиент.ОткрытьПроводник("/home/");
ФайловаяСистемаКлиент.ОткрытьПроводник("/opt/1C/v8.3/x86_64/1cv8c");
```

#### 2.2.

Чтобы открыть файл в ассоциированной программе, используйте `ФайловаяСистемаКлиент.ОткрытьФайл()`.

Метод блокирует запуск исполняемых файлов (`*.exe`, `*.bin`, `*.apk` и т.п.).

#### Пример

```bsl
ФайловаяСистемаКлиент.ОткрытьФайл(КаталогДокументов() + "test.pdf");
ФайловаяСистемаКлиент.ОткрытьФайл("D:\test.xlsx");
```

#### 2.3.

Чтобы открыть веб-страницу, вызвать программу по протоколу (`mailto:`, `skype:`, `tel:` и т.д.) или открыть навигационную ссылку ИБ, используйте `ФайловаяСистемаКлиент.ОткрытьНавигационнуюСсылку()`.

Для открытия файловой системы не формируйте `file://`-ссылки.
Для этого применяйте только `ОткрытьПроводник()` и `ОткрытьФайл()`.

#### Пример

```bsl
ФайловаяСистемаКлиент.ОткрытьНавигационнуюСсылку("https://1c.ru");
ФайловаяСистемаКлиент.ОткрытьНавигационнуюСсылку("e1cib/navigationpoint/startpage");
ФайловаяСистемаКлиент.ОткрытьНавигационнуюСсылку("mailto:help@1c.ru");
ФайловаяСистемаКлиент.ОткрытьНавигационнуюСсылку("skype:echo123?call");
```

#### 2.4.

Для запуска исполняемых файлов, системных команд и серверных команд, а также для получения `stdout`/`stderr` используйте:

- `ФайловаяСистемаКлиент.ЗапуститьПрограмму()` в клиентском коде;
- `ФайловаяСистема.ЗапуститьПрограмму()` в серверном коде.

#### Пример

```bsl
ФайловаяСистемаКлиент.ЗапуститьПрограмму("calc");

ПараметрыЗапуска = ФайловаяСистема.ПараметрыЗапускаПрограммы();
ПараметрыЗапуска.ДождатьсяЗавершения = Истина;
ПараметрыЗапуска.ПолучитьПотокВывода = Истина;
ПараметрыЗапуска.ПолучитьПотокОшибок = Истина;

Результат = ФайловаяСистема.ЗапуститьПрограмму("ping 127.0.0.1 -n 5", ПараметрыЗапуска);
КодВозврата = Результат.КодВозврата;
ПотокВывода = Результат.ПотокВывода;
ПотокОшибок = Результат.ПотокОшибок;
```

#### 2.5.

Не формируйте динамически исполняемые файлы во временном каталоге (например, `bat`-файлы с последующим запуском).

Это усложняет политику белых списков и создает дополнительный вектор атаки.

Вместо этого:

- передавайте команду напрямую в `ФайловаяСистема.ЗапуститьПрограмму()`;
- или используйте статический доверенный исполняемый файл и передавайте параметры через аргументы командной строки или неисполняемый файл параметров.

#### 3.

Если операция требует запуска внешней программы с повышением прав (например, UAC в Windows),
реализуйте ее как отдельную команду формы и отображайте на кнопке значок щита.

Изображение: Команда с повышением прав (774.img1.png)

Изображение: Пример кнопки с щитом (774.img2.png)

#### См. также

- [#std770: Ограничения на использование Выполнить и Вычислить на сервере](https://v8std.ru/std/770/)
- [#std775: Безопасность программного обеспечения, вызываемого через открытые интерфейсы](https://v8std.ru/std/775/)

#### Проверки
[#bslls:FileSystemAccess](https://v8std.ru/diagnostics/bslls/FileSystemAccess/)

[#acc:534](https://v8std.ru/diagnostics/acc/534/)
#### Источник

https://its.1c.ru/db/v8std#content:774

Небезопасный запуск приложения. АПК:534

Доступ к файловой системе BSLLS:FileSystemAccess

Безопасность программного обеспечения, вызываемого через открытые интерфейсы #std775

Безопасность запуска приложений #std774


стандарт 775

ID: #std775

# Безопасность программного обеспечения, вызываемого через открытые интерфейсы

#### 1.

При интеграции со сторонними приложениями через открытые интерфейсы (в частности, COM) отключайте исполнение произвольного кода средствами вызываемого приложения.

#### 2.

Перед программным открытием документов Microsoft Word и Microsoft Excel через COM запрещайте исполнение макросов.
Иначе документ может выполнить вредоносный макрос.

#### Неправильно

```bsl
ОбъектWord = Новый COMОбъект("Word.Application");
Документ = ОбъектWord.Documents.Open(ИмяФайла);
```

#### Правильно (Word)

```bsl
ОбъектWord = Новый COMОбъект("Word.Application");
ОбъектWord.WordBasic.DisableAutoMacros(1);
Документ = ОбъектWord.Documents.Open(ИмяФайла);
```

#### Правильно (Excel)

```bsl
ОбъектExcel = Новый COMОбъект("Excel.Application");
ОбъектExcel.AutomationSecurity = 3; // msoAutomationSecurityForceDisable = 3
Документ = ОбъектExcel.Workbooks.Open(ИмяФайла);
```

#### 3.

Если по прикладной задаче требуется разрешать автозапуск макросов, реализуйте явные настройки безопасности.

Настройки делайте отдельно для клиентского и серверного кода.
Варианты настроек:

- `Запретить автоматический запуск`;
- `Разрешить запуск подписанных макросов (рекомендуется)` (по умолчанию);
- `Разрешить запуск не подписанных макросов (опасно)`.

Требования к форме клиентских настроек:

- доступна каждому пользователю;
- настройки хранятся в разрезе пользователей;
- каждый пользователь видит только свои настройки.

Требования к форме серверных настроек:

- доступна только администратору;
- изменяется только администратором.

При программном открытии документов всегда учитывайте выбранные настройки.

#### 3.1.

Проверку подписи макросов в документах Microsoft Word можно реализовать так:

#### Пример (Word)

```bsl
ОбъектWord = Новый COMОбъект("Word.Application");
ОбъектWord.WordBasic.DisableAutoMacros(1); // Отключить автозапуск
Документ = ОбъектWord.Documents.Open(ФайлДокумента);
Если Документ.VBASigned Тогда
    ОбъектWord.WordBasic.DisableAutoMacros(0); // Включить автозапуск
    Документ.RunAutoMacro(2); // wdAutoOpen = 2
Иначе
    Документ.Close();
    ВызватьИсключение НСтр("ru = 'Документ не подписан. Открытие отменено.'");
КонецЕсли;
```

#### 3.2.

Проверку подписи макросов в документах Microsoft Excel можно реализовать так:

#### Пример (Excel)

```bsl
ОбъектExcel = Новый COMОбъект("Excel.Application");
ИсходныйУровеньБезопасности = ОбъектExcel.AutomationSecurity;
ОбъектExcel.AutomationSecurity = 3; // msoAutomationSecurityForceDisable = 3
Документ = ОбъектExcel.Workbooks.Open(ФайлДокумента);
ОбъектExcel.AutomationSecurity = ИсходныйУровеньБезопасности;
Если Документ.VBASigned Тогда
    Документ.Close();
    Документ = ОбъектExcel.Workbooks.Open(ФайлДокумента);
Иначе
    Документ.Close();
    ВызватьИсключение НСтр("ru = 'Документ не подписан. Открытие отменено.'");
КонецЕсли;
```

#### См. также

- [О параметрах исполнения макросов в Microsoft Excel](https://msdn.microsoft.com/en-us/vba/excel-vba/articles/application-automationsecurity-property-excel?f=255&MSPPError=-2147217396)

#### Проверки

[#acc:536](https://v8std.ru/diagnostics/acc/536/)
[#acc:537](https://v8std.ru/diagnostics/acc/537/)
#### Источник

https://its.1c.ru/db/v8std#content:775

Отсутствует отключение макросов при работе с документом Microsoft Word. АПК:536

Отсутствует отключение макросов при работе с документом Microsoft Excel. АПК:537


стандарт 777

ID: #std777

# Использование временных таблиц

#### 1.

В общем случае временные таблицы рекомендуется использовать для повышения производительности и стабильности запросов.

Их можно применять и для других целей (например, для улучшения архитектуры кода), но это в некоторых сценариях может снижать производительность.

#### 2.

Есть ситуации, когда временные таблицы не следует создавать или их создание нужно минимизировать.

#### 2.1.

Не следует создавать временные таблицы с очень большим объемом данных (сотни тысяч записей). Это может приводить к существенному замедлению при записи и к исчерпанию свободного места на диске.

Если алгоритму нужен большой объем данных, обработку следует выполнять порциями.

#### 2.2.

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

#### 2.3.

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

#### 2.4.

Не создавайте и не удаляйте временные таблицы в цикле, если можно создать одну таблицу до цикла.

#### 2.5.

Не копируйте одну временную таблицу в другую только ради переименования. Вместо этого передавайте имя таблицы.

#### 3.

Временные таблицы следует индексировать, когда это дает прирост производительности.

#### 3.1.

Индекс следует строить в случаях:

#### 3.1.1.

Большая временная таблица участвует в соединении (с любой стороны). В индекс включайте поля, используемые в условии `ПО`.

#### 3.1.2.

Есть обращение к временной таблице в подзапросе конструкции логического оператора `В (...)`.

В индекс включайте поля временной таблицы из списка выбора, соответствующие полям слева от `В (...)`.

См. также: [#std652: Несоответствие индексов и условий запроса](https://v8std.ru/std/652/)

#### 3.2.

Маленькие временные таблицы (менее 1000 записей) индексировать не нужно.

#### 3.3.

Если условий выборки/соединения с временной таблицей несколько, и часто проверяется только одно из них, индекс следует строить по наиболее часто проверяемому условию.

#### См. также

- [#std656: Ограничения на использование вложенных запросов в условии соединения](https://v8std.ru/std/656/)
- [#std655: Ограничения на соединения с вложенными запросами и виртуальными таблицами](https://v8std.ru/std/655/)

#### Источник

https://its.1c.ru/db/v8std#content:777

Несоответствие индексов и условий запроса #std652

Ограничения на соединения с вложенными запросами и виртуальными таблицами #std655

Ограничения на использование вложенных запросов в условии соединения #std656

Использование временных таблиц #std777


стандарт 778

ID: #std778

# Денежные поля: требования по локализации

#### 1.

Чтобы конфигурация корректно работала в странах с низким курсом национальной валюты, увеличивайте разрядность целой части числовых полей с денежным эквивалентом.
Примеры денежных полей: `Сумма`, `Цена`, `Себестоимость`.

В метаданных:

- для денежных полей, где возможны только положительные значения, вместо фиксированного типа `Число(15,2)` используйте определяемый тип `ДенежнаяСуммаНеотрицательная`;
- для денежных полей, где возможны отрицательные значения, используйте тип `ДенежнаяСуммаЛюбогоЗнака` со снятым флагом `Неотрицательное`.

Если определяемый тип указать нельзя (например, для параметра формы или в составном типе), задавайте `Число(31,2)`.
В отдельных случаях эту длину нужно уменьшать из-за ограничений СУБД, например в ресурсах регистров.

#### 2.

Если используется БСП, не применяйте конструктор типа `Число` для описания типа денежного поля.
Используйте функцию, которая возвращает описание на основе определяемого типа.

#### Неправильно

```bsl
ОписаниеТиповСумма = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15,2));
```

#### Правильно

```bsl
ОписаниеТиповСумма = РаботаСКурсамиВалют.ОписаниеТипаДенежногоПоля();
```

#### 3.

При [#std535: использовании `ВЫРАЗИТЬ` в запросах](https://v8std.ru/std/535/) для денежных полей применяйте приведение к типу `ЧИСЛО(31,2)`
Так поддерживается максимальная длина целой части 29.
Ограничение на 29 связано с поддержкой сервера DB2.

#### Неправильно

```sdbl
ВЫРАЗИТЬ(Т.Сумма / Т.Количество КАК ЧИСЛО(15,2))
```

#### Правильно

```sdbl
ВЫРАЗИТЬ(Т.Сумма / Т.Количество КАК ЧИСЛО(31,2))
```

#### 4.

При использовании функции `Формат`, а также при задании формата в свойствах элементов формы, полей наборов СКД и т.п. не задавайте общую длину числа.

#### Неправильно

```bsl
Формат(Выборка.СуммаДокумента, "ЧЦ=15; ЧДЦ=2")
```

#### Правильно

```bsl
Формат(Выборка.СуммаДокумента, "ЧДЦ=2")
```

#### Неправильно

Изображение: Формат с заданной общей длиной (778.1.png)

#### Правильно

Изображение: Формат без общей длины (778.2.png)

#### Источник

https://its.1c.ru/db/v8std#content:778

Чтобы конфигурация корректно работала в странах с низким курсом национальной валюты, увеличивайте разрядность целой части числовых полей с денежным эквивалентом. Примеры денежных...

Округление результатов арифметических операций в запросах #std535

Денежные поля: требования по локализации #std778


стандарт 781

ID: #std781

# Особенности сортировки в таблице значений

#### 1.

Если таблица значений сортируется по колонкам со ссылочными значениями, учитывайте: для каждой такой колонки по всем строкам система получает представление ссылки из информационной базы.

Поэтому рекомендуется:

- если нужна сортировка по наименованию, заранее добавлять в таблицу отдельные колонки с представлениями и сортировать по ним;
- в остальных случаях сортировать по ссылке, а не по представлению. Для этого в метод `Сортировать()` передавайте объект `СравнениеЗначений`.

```bsl
ОбъектСравнения = Новый СравнениеЗначений;
ТаблицаДокументов.Сортировать("Дата,Ссылка", ОбъектСравнения);
```

Это особенно важно для таблиц с сотнями и тысячами строк, когда алгоритм критичен ко времени выполнения.

#### См. также

- [#std412: Упорядочивание результатов запроса](https://v8std.ru/std/412/)

#### Источник

https://its.1c.ru/db/v8std#content:781

Если таблица значений сортируется по колонкам со ссылочными значениями, учитывайте: для каждой такой колонки по всем строкам система получает представление ссылки из информационной...

Упорядочивание результатов запроса #std412

Особенности сортировки в таблице значений #std781


стандарт 782

ID: #std782

# Массовая конкатенация строк

#### 1.

При массовых операциях конкатенации строк используйте методы платформы `СтрРазделить()` и `СтрСоединить()`.

#### Неправильно

```bsl
Для НомерКолонки = 1 По Макет.ШиринаТаблицы Цикл
    ИзвлеченныйТекст = ИзвлеченныйТекст + Символы.ПС + ТекстОбласти;
    …
```

#### Правильно

```bsl
ИзвлеченныеТексты = Новый Массив;
Для НомерКолонки = 1 По Макет.ШиринаТаблицы Цикл
    ИзвлеченныеТексты.Добавить(ТекстОбласти);
    …
ИзвлеченныйТекст = СтрСоединить(ИзвлеченныеТексты, Символы.ПС);
```

Такой подход обычно быстрее и снижает потребление оперативной памяти.

Ориентир для «массовых» операций: `1000 конкатенаций и более`.
При увеличении длины строк порог может быть ниже.
Особенно внимательно проверяйте конкатенацию в циклах и универсальных механизмах, работающих на больших объемах данных.

В остальных случаях отказываться от обычной конкатенации не нужно: она повышает читаемость кода.

#### См. также

- [#std437: Оформление текстов запросов, раздел «Конкатенация нескольких текстов запросов в пакет»](https://v8std.ru/std/437/)

#### Источник

https://its.1c.ru/db/v8std#content:782

При массовых операциях конкатенации строк используйте методы платформы СтрРазделить() и СтрСоединить().

Оформление текстов запросов #std437

Массовая конкатенация строк #std782


стандарт 783

ID: #std783

# Транзакции: правила использования

Транзакция - это действие, которое может быть выполнено только целиком. Если часть действия не выполнена - все действие отменяется.

#### 1.

Ошибка `В этой транзакции уже происходили ошибки` возникает из-за несоблюдения требований к написанию кода. Такие ошибки сложно воспроизводить и отлаживать их исправление.

Особенности работы с транзакциями в платформе:

- Не поддерживаются вложенные транзакции ([Вложенность транзакций](https://its.1c.ru/db/metod8dev/content/2334)).
- Если в транзакции возникло исключение транзакция может не завершится, даже если перехватить это исключение [Ошибки базы данных и транзакции](https://its.1c.ru/db/metod8dev/content/2313), [Особенности работы объектов при отмене транзакции](https://its.1c.ru/db/v8std#content:783).
- Платформа может начинать транзакции сама. Это называется неявные транзакции. [Глава 9.2. Механизм транзакций](https://its.1c.ru/db/v83doc/bookmark/dev/TI000000527).

#### 1.1.

Исключение не отменяет транзакцию.

Оно взводит служебный флажок транзакции `Запрет успешного завершения`.

Реальная отмена произойдет тогда, когда код дойдет до функции `ЗафиксироватьТранзакцию` или `ОтменитьТранзакцию`.
Для каждого метода `НачатьТранзакцию` должны быть парные методы `ЗафиксироватьТранзакцию` и `ОтменитьТранзакцию`.

#### В стандарте не указано

О том что такое флажки транзакции и как работает платформа смотрите в:

-  Профессиональная разработка в системе 1С Предприятие, Том 1, стр 107-108
- [Ошибки базы данных и транзакции](https://its.1c.ru/db/metod8dev/content/2313).
- [Глава 9.2.3. Вложенный вызов транзакций](https://its.1c.ru/db/v83doc#bookmark:dev:TI000000529)
- [ YouTube: Транзакции и блокировки: как их готовить программисту 1С?](https://www.youtube.com/watch?v=egJOPTDAgUQ)

#### 1.2.

Начало транзакции и ее завершение (фиксацию) выполняйте в одном методе.

Не должно быть разнесения начала и конца на несколько функций.

Тот, кто будет расследовать ошибку, скажет спасибо!

#### Неправильно

```bsl
Процедура ЗаписатьДанныеВИБ()

    НачатьТранзакцию();
    ЗаписатьДокумент();

КонецПроцедуры;

Процедура ЗаписатьДокумент()

    Попытка
        ... // чтение или запись данных
        ДокументОбъект.Записать()
        ЗафиксироватьТранзакцию();
    Исключение
        ОтменитьТранзакцию();
    ... // дополнительные действия по обработке исключения
    КонецПопытки;

КонецПроцедуры
```

#### Правильно

```bsl
Процедура ЗаписатьДанныеВИБ()

    НачатьТранзакцию();
    Попытка
        ... // чтение или запись данных
        ДокументОбъект.Записать()
        ЗафиксироватьТранзакцию();
    Исключение
        ОтменитьТранзакцию();
        ... // дополнительные действия по обработке исключения
    КонецПопытки;

КонецПроцедуры
```

#### 1.3.

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

#### Паттерн

```bsl
НачатьТранзакцию(); // (1)
Попытка
    БлокировкаДанных = Новый БлокировкаДанных;
    ЭлементБлокировкиДанных = БлокировкаДанных.Добавить("Документ.ПриходнаяНакладная");
    ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", СсылкаДляОбработки);
    ЭлементБлокировкиДанных.Режим = РежимБлокировкиДанных.Исключительный;
    БлокировкаДанных.Заблокировать();

    ... // чтение или запись данных (2)

    ДокументОбъект.Записать();

    ЗафиксироватьТранзакцию(); // (3)
Исключение
    ОтменитьТранзакцию(); // (4)

    ЗаписьЖурналаРегистрации(НСтр("ru = 'Выполнение операции'"), // (5)
        УровеньЖурналаРегистрации.Ошибка,
        ,
        ,
        ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));

    ВызватьИсключение; // (6)
КонецПопытки;
```

1. Метод `НачатьТранзакцию` должен быть вне блока `Попытка-Исключение` перед оператором `Попытка` и ничего между ними;

2. Все действия, выполняемые после метода `НачатьТранзакцию`, должны находиться в одном блоке `Попытка`, в том числе чтение, блокировка и обработка данных;

3. Метод `ЗафиксироватьТранзакцию` должен идти последним в блоке `Попытка` перед оператором `Исключение`, чтобы  гарантировать, что после `ЗафиксироватьТранзакцию` не возникнет исключение;

4. До обработки исключений в блоке `Исключение` сначала вызовите метод `ОтменитьТранзакцию`, а затем выполняйте другие действия, если они требуются;

5. В блоке `Исключение` делайте запись в журнал регистрации;

6. В конце блока `Исключение` добавляйте оператор `ВызватьИсключение`. В противном случае исключение не будет передано выше по стеку вызовов, там не сработает обработка исключения, внешняя транзакция не будет отменена и платформа вызовет исключение `В данной транзакции происходила ошибка`.

#### Проверки
[#v8cs:begin-transaction](https://v8std.ru/diagnostics/v8-code-style/begin-transaction/)
[#v8cs:commit-transaction](https://v8std.ru/diagnostics/v8-code-style/commit-transaction/)
[#v8cs:lock-out-of-try](https://v8std.ru/diagnostics/v8-code-style/lock-out-of-try/)
[#v8cs:rollback-transaction](https://v8std.ru/diagnostics/v8-code-style/rollback-transaction/)

#### Проверки
[#bslls:WrongUseOfRollbackTransactionMethod](https://v8std.ru/diagnostics/bslls/WrongUseOfRollbackTransactionMethod/)

#### 1.4.

Если можно избежать использования вложенных транзакций - постарайтесь избежать.

#### 1.4.1.

Не вызывайте `НачатьТранзакцию` если кроме записи объекта других действий не требуется. Платформа сделает все неявно сама, а читать код станет сложнее.

Избегайте открытия транзакции, если не требуется ответственное чтение данных [#std648: Ответственное чтение данных](https://v8std.ru/std/648/)

Например, при записи нового объекта или набора записей регистра обычно ответственное чтение не требуется.

При вызове методов `ПолучитьОбъект` (или `Прочитать` для наборов записей) анализируйте должно ли происходить чтение ответственно.

Если не должно - не вызывайте `НачатьТранзакцию`.

#### Неправильно

```bsl
НачатьТранзакцию();
Попытка
    ДокументОбъект = Документы.ПриходнаяНакладная.СоздатьДокумент();
    ... // действия по заполнению объекта
    ДокументОбъект.Записать();
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
КонецПопытки;
```

#### Правильно

```bsl
Попытка
    ДокументОбъект = Документы.ПриходнаяНакладная.СоздатьДокумент();
    ... // действия по заполнению объекта
    ДокументОбъект.Записать();
Исключение
    ... // действия по обработке исключения
КонецПопытки;
```

#### 1.4.2.

Если вы разрабатываете метод, который предназначен только для вызова из событий `ПередЗаписью`, `ОбработкаПроведения` и т.п., не открывайте внутри метода транзакций.

Они гарантированно будут вложенными.

#### В стандарте не указано

Имеет смысл добавить проверку, гарантирующую, что метод выполняется внутри транзакции, или описать это формально в описании к методу.

```bsl
Если Не ТранзакцияАктивна() Тогда
    ВызватьИсключение НСтр("ru = 'Метод предназначен для вызова внутри транзакции.'");
КонецЕсли;
```

#### 1.4.3.

Для детализации сообщений об ошибках предусмотрите свою обработку исключений. Так текст исключений можно сделать понятнее.

#### В стандарте не указано

С развитием [механизма отображения ошибок](https://wonderland.v8.1c.ru/blog/razvitie-mekhanizma-otobrazheniya-oshibok/) скорее всего подход будет изменен.

#### 1.4.4.

Не обращайтесь к базе данных, пока активна транзакция, в которой возникло исключение.

Это приведет к ошибке вида `В этой транзакции уже происходили ошибки`.

Помните о неявных обращениях, например для получения представления ссылки.

#### 2.

Не делайте транзакции длинными.

#### 2.1.

Выполняйте вместе только неделимые операции с точки зрения бизнес-логики.

#### Например

При проведении документа записывается документ и его движения в регистрах. Если не прошла запись хотя бы в один регистр вся операция проведения должна быть отменена.

#### 2.1.1.

Не объединяйте в одну транзакцию такие действия, которые с точки зрения бизнес-логики могут быть выполнены раздельно.

#### 2.1.2.

Исключения:

- Обработать несколько несвязных объектов вместе можно для оптимизации скорости работы.
- Надо правильно подобрать порции.
- Стремиться достигнуть золотую середину между длительностью одной транзакции и объемом фиксируемых данных с одной стороны и количеством транзакций с другой стороны.

#### 2.2.

Избегайте транзакций, которые выполняются долго.

#### Неправильно

При загрузке адресного классификатора записывать все данные, относящиеся к одной версии классификатора в одной транзакции.

В случае ошибки откатить целиком загружаемую версию классификатора.

    Данных по одной версии классификатора много (объем около 1 Гб). Для выполнения такой транзакции,

    - может не хватить оперативной памяти (особенно при использовании файловой информационной базы на 32-разрядной ОС)
    - такая операция будет выполняться достаточно долго и ее не получится оптимизировать за счет выполнения в несколько потоков

#### Правильно

Разбить загрузку новой версии классификатора на небольшие транзакции и реализовать функциональность по откату к предыдущей версии в случае ошибки.

- См. [Особенности использования транзакций при обмене данными](https://its.1c.ru/db/metod8dev/content/2274/hdoc)

#### 2.2.1.

Чем дольше выполняется транзакция, тем большее время будут заняты ресурсы сервера и СУБД.

Долгий захват ресурсов снизит эффективность работы системы:

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

#### 2.2.2.

Если транзакция пересеклась по блокировкам с другой транзакцией, она будет ждать возможности установить блокировку.

Время ожидания по умолчанию - 20 секунд.

Когда время ожидания истекло, транзакция будет завершена с исключением `Превышено время ожидания установки блокировки`.

Поэтому длинные транзакции снижают удобство параллельной работы нескольких пользователей.

Проведите анализ, обращая внимание на следующее:

- возможно, какие-то действия можно вынести за транзакцию [2.1.1](https://v8std.ru/std/783/#211)
- постарайтесь оптимизировать алгоритм выполнения действия;
- проанализируйте оптимальность устанавливаемых блокировок

#### 2.3.

Выполняйте вместе только неделимые операции с точки зрения бизнес-логики.

#### В стандарте не указано

Дополняет [2.1.](https://v8std.ru/std/783/#21)

- сложные, ресурсоемкие расчеты нужно стремиться делать до начала транзакции, если это позволяет бизнес-логика;
- если расчет должен выполняться в транзакции, то нужно стремиться сделать его как можно более простым;

#### Например
Контроль остатков можно делать уже после записи простым запросом к записываемому регистру;

- проверка заполнения объекта должна делаться вне транзакции (см. [#std463: Проверки, выполняемые в и вне транзакции записи объекта](https://v8std.ru/std/463/))
- запросы, перед выполнением которых не нужно устанавливать блокировку данных, нужно стремиться выполнять до начала транзакции (см. [#std648: Ответственное чтение данных](https://v8std.ru/std/648/))
- запросы, выполняемые в рамках транзакций нужно стремиться оптимизировать (см. группу стандартов Оптимизация запросов)

#### 3.

Операции, в которых отключаются итоги регистра, выполняйте в транзакции.

#### 3.1.

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

#### Неправильно

```bsl
РегистрыСведений.КурсыВалют.УстановитьИспользованиеИтогов(Ложь);
НаборЗаписей = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Валюта.Установить(ВалютаСсылка);
НаборЗаписей.Загрузить(ТаблицаКурсов);
НаборЗаписей.ОбменДанными.Загрузка = Истина;
НаборЗаписей.Записать();
РегистрыСведений.КурсыВалют.УстановитьИспользованиеИтогов(Истина);
РегистрыСведений.КурсыВалют.ПересчитатьИтоги();
```

#### Правильно

```bsl
НачатьТранзакцию();
Попытка
    РегистрыСведений.КурсыВалют.УстановитьИспользованиеИтогов(Ложь);
    НаборЗаписей = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.Валюта.Установить(ВалютаСсылка);
    НаборЗаписей.Загрузить(ТаблицаКурсов);
    НаборЗаписей.ОбменДанными.Загрузка = Истина;
    НаборЗаписей.Записать();
    РегистрыСведений.КурсыВалют.УстановитьИспользованиеИтогов(Истина);
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ВызватьИсключение;
КонецПопытки;

РегистрыСведений.КурсыВалют.ПересчитатьИтоги();
```

#### Проверки
[#bslls:PairingBrokenTransaction](https://v8std.ru/diagnostics/bslls/PairingBrokenTransaction/)

[#acc:325](https://v8std.ru/diagnostics/acc/325/)
[#acc:326](https://v8std.ru/diagnostics/acc/326/)
[#acc:327](https://v8std.ru/diagnostics/acc/327/)
[#acc:328](https://v8std.ru/diagnostics/acc/328/)
[#acc:329](https://v8std.ru/diagnostics/acc/329/)
[#acc:330](https://v8std.ru/diagnostics/acc/330/)
[#acc:331](https://v8std.ru/diagnostics/acc/331/)
[#acc:332](https://v8std.ru/diagnostics/acc/332/)
[#acc:415](https://v8std.ru/diagnostics/acc/415/)
[#acc:478](https://v8std.ru/diagnostics/acc/478/)
[#acc:521](https://v8std.ru/diagnostics/acc/521/)
[#acc:1319](https://v8std.ru/diagnostics/acc/1319/)
[#acc:1320](https://v8std.ru/diagnostics/acc/1320/)
#### Источник

https://its.1c.ru/db/v8std#content:783

После инициализации блокировки отсутствует вызов "Заблокировать()". АПК:1319

Вызов "Заблокировать()" находится вне попытки. АПК:1320

Нарушена схема работы с транзакциями: отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ЗафиксироватьТранзакцию()"/"ОтменитьТранзакцию()". АПК:325

Нарушена схема работы с транзакциями: для вызова "НачатьТранзакцию()" отсутствует парный вызов "ЗафиксироватьТранзакцию()". АПК:326

Нарушена схема работы с транзакциями: для вызова "НачатьТранзакцию()" отсутствует парный вызов "ОтменитьТранзакцию()". АПК:327

Нарушена схема работы с транзакциями: не найден оператор "Попытка" после вызова "НачатьТранзакцию()". АПК:328

Нарушена схема работы с транзакциями: вызов "ЗафиксироватьТранзакцию()" находится вне конструкции "Попытка... Исключение". АПК:329

Нарушена схема работы с транзакциями: между "ЗафиксироватьТранзакцию()" и "Исключение" есть исполняемый код, который может вызвать исключение. АПК:330

Нарушена схема работы с транзакциями: между "НачатьТранзакцию()" и "Попытка" есть исполняемый код. АПК:331

Нарушена схема работы с транзакциями: вызов "ОтменитьТранзакцию()" отсутствует в конструкции "Исключение... КонецПопытки". АПК:332

Нарушена схема работы с транзакциями: отличаются условия "Если ... Тогда" у методов работы с транзакциями. АПК:415

Нарушена схема работы с транзакциями: между "Исключение" и "ОтменитьТранзакцию()" есть исполняемый код. АПК:478

Нарушена схема работы с транзакциями: преждевременный выход из блока "Попытка..Исключение" без завершения или отмены транзакции. АПК:521

Нарушение парности использования методов "НачатьТранзакцию()" и "ЗафиксироватьТранзакцию()" / "ОтменитьТранзакцию()" BSLLS:PairingBrokenTransaction

Некорректное использование метода ОтменитьТранзакцию() BSLLS:WrongUseOfRollbackTransactionMethod

После начала транзакции отсуствует блок Попытка-Исключение (begin-transaction)

Проверка нарушения схемы работы с транзакциями (commit-transaction)

Вызов "Заблокировать()" находится вне попытки (lock-out-of-try)

Проверка нарушения схемы работы с транзакциями (rollback-transaction)

Обработчик события ОбработкаПроверкиЗаполнения #std463

Ответственное чтение данных #std648

Транзакции: правила использования #std783


стандарт 784

ID: #std784

# Автогенерированные данные в информационной базе: требования по локализации

#### 1.

Автогенерируемые строки, которые программно записываются в информационную базу и выводятся пользователям, формируйте не на языке текущего пользователя, а на языке информационной базы.

Это относится, например, к:

- начальному заполнению базы из макета;
- автогенерации комментария к проводке;
- определению значения параметра `ИмяСобытия` метода [#std498: ЗаписьЖурналаРегистрации](https://v8std.ru/std/498/)

Иначе один и тот же объект может получить разные строковые данные при работе пользователей с разными языками интерфейса.

Такие места в коде рекомендуется сопровождать комментарием, что строка является данными, а не интерфейсным текстом.

#### Неправильно

```bsl
Комментарий = НСтр("ru = 'Комментарий к проводке'");
```

#### Правильно

```bsl
Комментарий = НСтр("ru = 'Комментарий к проводке'", КодОсновногоЯзыка); // строка записывается в ИБ
```

`КодОсновногоЯзыка` это код языка хранения данных в ИБ.
Он выбирается при первом запуске из языков интерфейса конфигурации и сохраняется в константе `ОсновнойЯзык`.

При использовании БСП код языка хранения данных получайте через `ОбщегоНазначения.КодОсновногоЯзыка()`.

```bsl
Комментарий = НСтр("ru = 'Комментарий к проводке'", ОбщегоНазначения.КодОсновногоЯзыка()); // строка записывается в ИБ
```

#### 2.

Это же требование действует для обработчиков начального заполнения, которые заполняют строковые реквизиты предопределенных элементов справочников, ПВХ и т.п.

#### Правильно

```bsl
Процедура ПриДобавленииОбработчиковОбновления(Обработчики) Экспорт
    Обработчик = Обработчики.Добавить();
    Обработчик.НачальноеЗаполнение = Истина;
    Обработчик.Процедура = "ПользователиСлужебный.ЗаполнитьНаименованиеПредопределенныхГруппПользователей";
КонецПроцедуры

Процедура ЗаполнитьНаименованиеПредопределенныхГруппПользователей() Экспорт
    ГруппаПользователей = Справочники.ГруппыПользователей.ВсеПользователи.ПолучитьОбъект();
    ГруппаПользователей.Наименование = НСтр("ru='Все пользователи'", КодОсновногоЯзыка);
    ОбновлениеИнформационнойБазы.ЗаписатьОбъект(ГруппаПользователей);
КонецПроцедуры
```

При добавлении новых предопределенных элементов создавайте новый обработчик начального заполнения с указанием версии или дополняйте существующий.
См. стандарт [#std690: Обработчики обновления информационной базы](https://v8std.ru/std/690/)

Если используется БСП, не создавайте собственные обработчики начального заполнения.
Первоначальные данные размещайте в процедуре `ПриНачальномЗаполненииЭлементов` модуля менеджера объекта.
Для объектов, зарегистрированных в `ОбновлениеИнформационнойБазыПереопределяемый.ПриОпределенииНастроек`, эти процедуры вызываются автоматически.

При добавлении нового или изменении существующего элемента создавайте обработчик обновления перехода на версию и дублируйте изменения в `ПриНачальномЗаполненииЭлементов` модуля менеджера.
Подробнее: [документация к БСП](https://its.1c.ru/db/bspdoc).

#### Проверки

[#acc:152](https://v8std.ru/diagnostics/acc/152/)
[#acc:153](https://v8std.ru/diagnostics/acc/153/)
[#acc:154](https://v8std.ru/diagnostics/acc/154/)
[#acc:156](https://v8std.ru/diagnostics/acc/156/)
[#acc:157](https://v8std.ru/diagnostics/acc/157/)
[#acc:161](https://v8std.ru/diagnostics/acc/161/)
[#acc:370](https://v8std.ru/diagnostics/acc/370/)
[#acc:371](https://v8std.ru/diagnostics/acc/371/)
[#acc:1385](https://v8std.ru/diagnostics/acc/1385/)
#### Источник

https://its.1c.ru/db/v8std#content:784

Автогенерируемые строки, которые программно записываются в информационную базу и выводятся пользователям, формируйте не на языке текущего пользователя, а на языке информационной...

Отсутствует обработчик начального заполнения предопределенных элементов (ПриНачальномЗаполненииЭлементов и др.). АПК:1385

В параметре "ИмяСобытия" метода "ЗаписьЖурналаРегистрации()" имеется лишний пробел после точки. АПК:152

Не локализован параметр "Комментарий" метода "ЗаписьЖурналаРегистрации()". АПК:153

Если в параметре "Комментарий" метода "ЗаписьЖурналаРегистрации()" указано подробное описание ошибки, то уровень журнала должен быть "Ошибка". АПК:154

Не локализован параметр "ИмяСобытия" метода "ЗаписьЖурналаРегистрации()". АПК:156

Для параметра "ИмяСобытия" метода "ЗаписьЖурналаРегистрации()" не задан основной язык конфигурации. АПК:157

Параметр "ИмяСобытия" метода "ЗаписьЖурналаРегистрации()" инициализируется функцией, возращающей нелокализованную строку. АПК:161

Параметр "ИмяСобытия" метода "ЗаписьЖурналаРегистрации()" инициализируется переменной, содержащей нелокализованную строку. АПК:370

При локализации параметра "ИмяСобытия" для получения кода языка следует использовать функцию ОбщегоНазначенияКлиентСервер.КодОсновногоЯзыка(). АПК:371

Использование Журнала регистрации #std498

Обработчики обновления информационной базы #std690

Автогенерированные данные в информационной базе: требования по локализации #std784


стандарт 785

ID: #std785

# Версия платформы 1С:Предприятие для разработки

#### 1.

Минимальная версия платформы, на которой обеспечивается работа прикладного решения, устанавливается:

- не выше версии платформы, на которой основан последний сертифицированный релиз платформы, для прикладных решений государственных учреждений, оборонных предприятий и корпоративных клиентов, а также для библиотек, которые потенциально могут входить в такие решения;
- на усмотрение ответственных за конфигурацию для остальных прикладных решений.

Для решений из первой группы ориентируйтесь на последний сертифицированный релиз 1С:Предприятие 8.3z.
Номер релиза и версия платформы, принимаемая как минимальная, публикуются на [странице 1С:Предприятие 8.3z](http://online.1c.ru/catalog/files/13352/).
См. также [защищенный программный комплекс 1С:Предприятие 8.3z](https://solutions.1c.ru/news/314012/).

#### Пример

Если прикладное решение для государственных учреждений выпускается на версии платформы 1С:Предприятие 8.3.15 в режиме совместимости с 8.3.14,
и последний сертифицированный релиз 8.3.14.2032 основан на версии 8.3.14.1976,
то минимальной версией платформы должна быть 8.3.14.1976.

#### 1.1.

Если ошибку нельзя обойти на уровне прикладного решения, минимальную версию платформы можно увеличить.
Для решений государственных учреждений при этом новый релиз платформы должен быть сертифицирован в короткие сроки.

#### 1.2.

В исправительных релизах библиотек нельзя увеличивать минимальную версию платформы.
Такое решение принимают отдельно для каждого прикладного решения с учетом всех последствий.

#### 2.

Рекомендуемая версия платформы устанавливается:

- в прикладных конфигурациях на усмотрение ответственного за конфигурацию; ориентир — последний опубликованный релиз платформы, на котором ведутся разработка и тестирование;
- в исправительных релизах библиотек не повышается, так как решение должно приниматься с учетом последствий для каждого прикладного решения.

#### Пример

Прикладное решение выпускается на минимальной версии платформы 1С:Предприятие 8.3.14.
В качестве рекомендуемой версии указывается последний опубликованный релиз 8.3.15,
если в нем улучшены функции, важные для пользователей.

В прикладных решениях для государственных учреждений, оборонных предприятий и корпоративных клиентов рекомендуемая версия может быть выше версии, на которой основан последний сертифицированный релиз.
В этом случае пользователи могут продолжать работу на текущем сертифицированном релизе и одновременно получают рекомендацию по обновлению.

#### 3.

Запуск на платформе ниже минимальной версии блокируется средствами БСП.
Минимальная и рекомендуемая версии задаются в процедуре `ПриОпределенииОбщихПараметровБазовойФункциональности` общего модуля `ОбщегоНазначенияПереопределяемый`.

Минимальная и рекомендуемая версии также указываются в файле `readme.txt` из состава дистрибутива.

#### Пример для readme.txt

Минимальная версия платформы 1С:Предприятие для использования конфигурации: 8.3.14.1976.
Рекомендуемая версия платформы: 8.3.15.1700 (или больше).

#### Источник

https://its.1c.ru/db/v8std#content:785

Версия платформы 1С:Предприятие для разработки #std785


стандарт 787

ID: #std787

# Вычисление количества записей в запросах

#### 1.

При вычислении количества записей в запросе всегда используйте функцию `КОЛИЧЕСТВО`, а не `СУММА`.

Иначе при количестве записей 10 млн и более возможно переполнение, связанное с разрядностью чисел по умолчанию, используемых СУБД платформой 1С:Предприятие.

#### Правильно

```sdbl
КОЛИЧЕСТВО(*)
КОЛИЧЕСТВО(<Поле>)
```

#### Неправильно

```sdbl
СУММА(1)
ЕСТЬNULL(СУММА(1), 0)
```

#### 2.

Если количество нужно вычислять условно и `КОЛИЧЕСТВО` применить нельзя, расширяйте разрядность числа по умолчанию через `ВЫРАЗИТЬ` (например, до 17 разрядов).

#### Правильно

```sdbl
ВЫБРАТЬ
    КОЛИЧЕСТВО(*) КАК Количество,
    СУММА(ВЫБОР
        КОГДА Номенклатура.ЭтоГруппа
            ТОГДА ВЫРАЗИТЬ(1 КАК ЧИСЛО(17, 0))
        ИНАЧЕ 0
    КОНЕЦ) КАК КоличествоГрупп,
    СУММА(ВЫБОР
        КОГДА НЕ Номенклатура.ЭтоГруппа
            ТОГДА ВЫРАЗИТЬ(1 КАК ЧИСЛО(17, 0))
        ИНАЧЕ 0
    КОНЕЦ) КАК КоличествоЭлементов
ИЗ
    Справочник.Номенклатура КАК Номенклатура
```

#### Неправильно

```sdbl
ВЫБРАТЬ
    КОЛИЧЕСТВО(*) КАК Количество,
    СУММА(ВЫБОР
        КОГДА Номенклатура.ЭтоГруппа
            ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ) КАК КоличествоГрупп,
    СУММА(ВЫБОР
        КОГДА НЕ Номенклатура.ЭтоГруппа
            ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ) КАК КоличествоЭлементов
ИЗ
    Справочник.Номенклатура КАК Номенклатура
```

#### См. также

- [#std535: Округление результатов арифметических операций в запросах](https://v8std.ru/std/535/)

#### Источник

https://its.1c.ru/db/v8std#content:787

При вычислении количества записей в запросе всегда используйте функцию КОЛИЧЕСТВО, а не СУММА.

Округление результатов арифметических операций в запросах #std535

Вычисление количества записей в запросах #std787


стандарт 790

ID: #std790

# Вызов исключений в коде

#### 1.

В общем случае исключения в коде вызывать не требуется.

При ошибках в выполнении кода исключение формирует платформа, после чего:

- пользователю выводится сообщение с рекомендацией;
- в журнал регистрации пишется подробная диагностика со стеком вызовов;
- при необходимости данные отправляются в сервис регистрации ошибок платформы.

#### Пример 1

Исключение платформы с категорией `ОшибкаДоступаКЛокальномуФайлу`.

Изображение: Исключение платформы: ошибка доступа к локальному файлу (790.platform-exception-file.png)

Запись журнала регистрации с событием `Ошибка выполнения` и комментарием:

```log
Ошибка при вызове метода контекста (Открыть)
{Обработка.ПримерИсключения.Форма.Форма.Форма(14)}:Текст.Открыть("C:\not_exists_path\doc.txt");
[ОшибкаВоВремяВыполненияВстроенногоЯзыка]
по причине:
Каталог не обнаружен 'C:\not_exists_path\doc.txt'
[ОшибкаДоступаКЛокальномуФайлу]
```

#### Пример 2

Исключение платформы с категорией `ПрочаяОшибка`.

Изображение: Исключение платформы: прочая ошибка (790.platform-exception-generic.png)

Запись журнала регистрации с событием `Ошибка выполнения` и комментарием:

```log
Поле объекта не обнаружено (Организация)
{Обработка.ПримерИсключения.Форма.Форма.Форма(22)}:Если ЗначениеЗаполнено(Свойства.Организация) Тогда
[ОшибкаВоВремяВыполненияВстроенногоЯзыка, ОшибкаИспользованияВстроенногоЯзыка]
```

#### 2.

Тем не менее, иногда исключение нужно вызывать программно.

Для исключений бизнес-логики, которые выводятся пользователю, категорию ошибки можно не указывать (`ИсключениеВызванноеИзВстроенногоЯзыка`).
Для остальных случаев рекомендуется задавать категорию (`ОшибкаРаботыСПринтером`, `ОшибкаСети`, `НарушениеПравДоступа` и т.п.).

Тогда пользователь получает не только технический текст, но и типовую рекомендацию по решению.

Проверяйте внешний вид исключений без отладки и без режима технического специалиста: поведение окна исключения зависит от режима запуска.

#### 2.1.

Обычно для проверки прав доступа используйте `ВыполнитьПроверкуПравДоступа`.

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

#### Неправильно

```bsl
Если Не РольДоступна("ПодключениеИнтернетПоддержки") Тогда
    ТекстОшибки = НСтр("ru = 'Недостаточно прав для записи данных аутентификации Интернет-поддержки.'");
    ВызватьИсключение ТекстОшибки;
КонецЕсли;
```

Сообщение пользователю:

Изображение: Сообщение пользователю без категории ошибки (790.message-rights-no-category.png)

#### Правильно

```bsl
Если Не РольДоступна("ПодключениеИнтернетПоддержки") Тогда
    ТекстОшибки = НСтр("ru = 'Недостаточно прав для записи данных аутентификации Интернет-поддержки.'");
    ДляАдминистратора = НСтр("ru = 'Нет роли:'") + " " + Метаданные.Роли.ПодключениеИнтернетПоддержки.Представление();
    ВызватьИсключение(ТекстОшибки, КатегорияОшибки.НарушениеПравДоступа,, ДляАдминистратора);
КонецЕсли;
```

Сообщение пользователю:

Изображение: Сообщение пользователю с категорией нарушения прав доступа (790.message-rights-with-category.png)

#### 2.2.

Для диагностики программных ошибок (некорректные параметры, неверно встроенная подсистема и т.п.) используйте категорию `ОшибкаКонфигурации`.

Такие ошибки адресованы разработчику, а не пользователю.

#### Пример

```bsl
Если ТипЗнч(Количество) <> Тип("Число") Тогда
    ТекстОшибки = НСтр("ru = 'Недопустимое значение параметра'") + " " + "Количество";
    ВызватьИсключение(ТекстОшибки, КатегорияОшибки.ОшибкаКонфигурации);
КонецЕсли;
```

Сообщение пользователю:

Изображение: Сообщение о непредвиденной ошибке (ОшибкаКонфигурации) (790.message-config-error.png)

#### 2.3.

Если анализ типа исключения критичен для бизнес-логики, используйте один из подходов:

- не вызывать исключения, а возвращать строковые коды ошибок;
- анализировать категорию ошибки исключения, вызванного платформой;
- вызывать исключение со строковым кодом ошибки (параметр `Код` у `ВызватьИсключение`).

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

#### 2.3.1.

#### Пример

```bsl
РезультатЗагрузки = ЗагрузитьФайлИзИнтернета(...);
Если РезультатЗагрузки = "Успешно" Тогда
...
ИначеЕсли ...
```

#### 2.3.2.

#### Пример

```bsl
НомерПопытки = 1;
Пока НомерПопытки < 4 Цикл
    Попытка
        HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
    Исключение
        ИнформацияОбОшибке = ИнформацияОбОшибке();
        Если ИнформацияОбОшибке.ЯвляетсяОшибкойКатегории(КатегорияОшибки.ОшибкаСети) Тогда
            НомерПопытки = НомерПопытки + 1;
            Продолжить;
        КонецЕсли;
        ВызватьИсключение;
    КонецПопытки;
КонецЦикла;
```

#### 2.3.3.

#### Пример вызова исключения со строковым кодом

```bsl
Если КонфигурацияБазыДанныхИзмененаДинамически() Тогда
    ВызватьИсключение(НСтр("ru = 'Версия приложения обновлена, требуется перезапустить сеанс.'"),,
        "СтандартныеПодсистемы.БазоваяФункциональность.КонфигурацияИзмененаДинамически");
КонецЕсли;
```

Для уникальности кода включайте префикс подсистемы, например:

- `СтандартныеПодсистемы.БазоваяФункциональность.КонфигурацияИзмененаДинамически`;
- `СтандартныеПодсистемы.БазоваяФункциональность.РасширенияИзмененыДинамически`.

#### Пример обработки такого исключения

```bsl
Попытка
    ВыполнитьОбновление();
Исключение
    КодОшибки = ИнформацияОбОшибке().Код;
    Если КодОшибки = "СтандартныеПодсистемы.БазоваяФункциональность.КонфигурацияИзмененаДинамически"
     Или КодОшибки = "СтандартныеПодсистемы.БазоваяФункциональность.РасширенияИзмененыДинамически" Тогда
        ПерезапуститьЗаданиеОбновления();
        Возврат;
    КонецЕсли;
    ВызватьИсключение;
КонецПопытки;
```

Если используется БСП, удобно применять `ОбщегоНазначенияКлиентСервер.ЭтоИсключениеСКодомОшибки()`.
Метод рекурсивно ищет коды в цепочке вложенных исключений (`ИнформацияОбОшибке().Причина`).

#### Пример с использованием БСП

```bsl
Попытка
    ВыполнитьОбновление();
Исключение
    Если ОбщегоНазначенияКлиентСервер.ЭтоИсключениеСКодомОшибки(ИнформацияОбОшибке(),
            "СтандартныеПодсистемы.БазоваяФункциональность.КонфигурацияИзмененаДинамически
            |СтандартныеПодсистемы.БазоваяФункциональность.РасширенияИзмененыДинамически") Тогда
        ПерезапуститьЗаданиеОбновления();
        Возврат;
    КонецЕсли;
    ВызватьИсключение;
КонецПопытки;
```

#### 3.

Не используйте исключения в обработчиках `ОбработкаПроверкиЗаполнения`, `ОбработкаПроведения`, `ПередЗаписью`, `ПриЗаписи`, `ПередУдалением` и т.п. для обычных блокирующих предупреждений пользователю.

Вместо этого устанавливайте `Отказ = Истина` и выводите сообщение.
Пользователь должен видеть все блокирующие причины сразу, а не по одной.

#### Исключение

Если пользователь не может обработать предупреждение в рамках текущей операции или ошибка имеет исключительный характер и делает остальные проверки бессмысленными.

```bsl
Процедура ПередЗаписью(Отказ)

    Если Не ЗарегистрироватьИзмененияНаУзлахПлановОбмена() Тогда
        ТекстОшибки = НСтр("ru = 'Не удалось зарегистрировать изменения на узлах планов обмена. Обратитесь к администратору.'");
        ВызватьИсключение ТекстОшибки;
    КонецЕсли;
    ...
КонецПроцедуры
```

Подробнее:.

#### Источник

https://its.1c.ru/db/v8std#content:790

Вызов исключений в коде #std790


стандарт 791

ID: #std791

# Дополнительные индексы

**Дополнительный индекс** – это индекс сразу по нескольким полям объекта метаданных.

#### 1

Дополнительные индексы доступны только для КОРП платформы. Для ПРОФ платформы использовать не получится.

#### 2

При разработке надо тестировать производительность в двух случаях:

- доп. индексы включены
- доп. индексы выключены

Для таблиц до 1 млн записей должно работать быстро без доп. индексов.
Для больших таблиц - производительность должна гарантироваться доп. индексами.

#### В стандарте не указано

Доп. индексы управляются параметром информационной базы `Использовать дополнительные индексы`. Его можно изменить через конфигуратор или программно `УстановитьИспользованиеДополнительныхИндексов()`.

Реальное перестроение индекса произойдет при следующем обновлении конфигурации с реструктуризацией или запуском тестирования и исправления в режиме включения КОРП функций.

#### 3

Не используйте доп. индексы если можно достичь хорошей производительности без них.

#### 4

Не делайте несколько веток кода в зависимости от использования доп. индексов.

#### Неправильно

```bsl
Если ПолучитьИспользованиеДополнительныхИндексов() Тогда

    // Особенности при включенных доп. индексах

КонецЕсли;
```

#### 4.1

Все, что написано выше, можно игнорировать, потому что если очень хочется, то на небольшом объеме можно и доп. индексы использовать, и делать ветки в коде.

#### В стандарте не указано

Не понятно зачем нужен этот пункт "подстилка", ведь для того чтобы не исполнить стандарт разрешение стандарта не нужно :)

#### 5

Поле в доп. индекс добавляют в двух случаях:

- чтобы использовать в условиях запросов - как индексируемое (ключевое) поле
- чтобы исключить обращение к таблице - как дополнительное (неключевое) поле

#### В стандарте не указано

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

#### См. также

- [Индексы объектов метаданных](https://its.1c.ru/db/v8326doc#bookmark:dev:TI000002802)
- [Индексы таблиц базы данных](https://its.1c.ru/db/metod8dev#content:1590:hdoc)
- [Серверная лицензия](https://its.1c.ru/db/v8326doc#bookmark:adm:TI000001232)

#### Источник

https://its.1c.ru/db/v8std#content:791

Дополнительный индекс – это индекс сразу по нескольким полям объекта метаданных.

Дополнительные индексы #std791