Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added automatic creation of predefined elements #144

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
65 changes: 65 additions & 0 deletions docs/ПредопределенныеЗначения.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,71 @@
КонецПроцедуры
```

## Уникальность предопределенных элементов

Для обеспечения целостности данных и управления предопределёнными значениями реализован механизм контроля изменений. Он основан на вычислении хеша с использованием алгоритма **MD5**, учёте пометки на удаление, ручных изменений и проверке уникальности идентификаторов.

### Основные этапы проверки
1. **Первоначальная проверка уникальности идентификаторов:**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Кстати а это в оповещениях учтено? Или только если нужно разрешить конфликт?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- На этапе инициализации идентификаторы всех элементов проверяются на уникальность.
- Если обнаружены коллизии (дублирующиеся идентификаторы), будет выдано сообщение об ошибке, и такие элементы будут пропущены.
2. **Хеш и состояние элемента:**
- Хеш вычисляется для каждого элемента и сохраняется в регистре **состояний предопределённых элементов**.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нужно написать на основании каких данных формируется хэш - что там не учитываются изменяемые реквизиты

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- **Ключи хеша:**
- ИдентификаторНастройки
- Наименование
- Родитель (если включена иерархия)
- ЭтоГруппа (если включена иерархия групп и элементов)
- Изменяемые реквизиты при расчете не учитываются
- Остальные ключи опционально, зависят от типа объекта метаданных (см. [область Структуры колонок таблиц](../src/cf/CommonModules/пбп_ПредопределенныеЗначенияПереопределяемый/Ext/Module.bsl#247-343) и [исключаемые поля для расчета хеша](../src/cf/CommonModules/пбп_ПредопределенныеЗначенияПереопределяемый/Ext/Module.bsl#345-381))
- Если элемент изменяется в пользовательском режиме, устанавливается флаг **ручное изменение:**
- Такой элемент исключается из проверки хеша при последующих обновлениях.
3. **Обработка элементов с пометкой на удаление:**
- Если элемент помечен на удаление и его хеш отличается от нового:
- Значения элемента обновляются данными из кода.
- Пометка на удаление снимается автоматически.
- Если элемент не помечен на удаление и его хеш отличается от нового:
- Формируется уведомление о конфликте для дальнейшего разрешения.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нужно описать пример конфликта и его решения

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


**Пример решения конфликтов при создании/обновлении предопределенных элементов**

![image](images/ФормаРазрешенияКонфликтов.png)

Виды ошибок:
- Коллизии идентификаторов
- Эта ошибка не решается в пользовательском режиме, для ее устранения необходимо перейти в общий модуль ``пбп_ПредопределенныеЗначенияПереопределяемый`` и исправить конфликтующие элементы.
- Расхождение элемента с кодом
- Для элемента установлен флаг обновления: Элемент будет обновлен данными из программного кода, а также обновится хеш элемента в регистре сведений **``пбп_СостоянияПредопределенныхЭлементов``**.
- Для элемента не установлен флаг обновления: Элемент не будет обновлен. В записи регистра сведений **``пбп_СостоянияПредопределенныхЭлементов``** будет установлен флаг **``Ручное изменение``**, указывающий на то, что элемент был изменен вручную и не подлежит автоматическому обновлению в будущем.

**Примечание** - Флаг ``Заменить элементом из кода`` активен только для элементов с видом ошибки ``Расхождение элемента с кодом``

## Автоматическое создание новых элементов

Для автоматизации процесса заполнения предопределенных элементов необходимо модифицировать/добавить в расширение общий модуль **``ОбщегоНазначенияПереопределяемый``**. В процедуре **``ПриДобавленииСерверныхОповещений``** требуется добавить новое серверное оповещение.

**Пример кода для подключения через расширение**

```BSL
&После("ПриДобавленииСерверныхОповещений")
Процедура пбп_ПриДобавленииСерверныхОповещений(Оповещения)

// Создаем новое серверное оповещение для предопределённых значений
Оповещение = СерверныеОповещения.НовоеСерверноеОповещение("пбп_ПредопределенныеЗначения");

// Указываем модуль для получения и отправки сообщений
Оповещение.ИмяМодуляОтправки = ""; // В данном случае используется рег. задание для отправки
Оповещение.ИмяМодуляПолучения = "пбп_ПредопределенныеЗначенияСлужебныйКлиент";

// Настраиваем периодичность проверки (в секундах)
Оповещение.ПериодПроверки = 300;

// Добавляем новое оповещение в список оповещений
Оповещения.Вставить(Оповещение.Имя, Оповещение);

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

## Добавление новых элементов

В модуле **пбп_ПредопределенныеЗначенияПереопределяемый** значения добавляются через метод **Добавить()** коллекции **Результат**, которая представляет собой таблицу предопределённых значений. Каждая новая запись в этой таблице может быть настроена как группа путём установки свойства ЭтоГруппа в значение Истина.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@
<ContextMenu name="ТаблицаКонфликтовЗаменитьЭлементомИзКодаКонтекстноеМеню" id="27"/>
<ExtendedTooltip name="ТаблицаКонфликтовЗаменитьЭлементомИзКодаРасширеннаяПодсказка" id="28"/>
</CheckBoxField>
<InputField name="ТаблицаКонфликтовКоллизииИдентификатора" id="36">
<DataPath>ТаблицаКонфликтов.Ошибка</DataPath>
<ReadOnly>true</ReadOnly>
<EditMode>EnterOnInput</EditMode>
<ExtendedEditMultipleValues>true</ExtendedEditMultipleValues>
<ContextMenu name="ТаблицаКонфликтовКоллизииИдентификатораКонтекстноеМеню" id="37"/>
<ExtendedTooltip name="ТаблицаКонфликтовКоллизииИдентификатораРасширеннаяПодсказка" id="38"/>
</InputField>
<ColumnGroup name="ГруппаЭлементВБазе" id="19">
<Title>
<v8:item>
Expand Down Expand Up @@ -176,6 +184,17 @@
<v8:Type>xs:boolean</v8:Type>
</Type>
</Column>
<Column name="Ошибка" id="2">
<Title>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Ошибка</v8:content>
</v8:item>
</Title>
<Type>
<v8:Type>cfg:EnumRef.пбп_ВидыОшибокПредопределенныхЭлементов</v8:Type>
</Type>
</Column>
</Columns>
</Attribute>
<Attribute name="ОбработатьЭлементы" id="4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
ОбработатьКонфликтныеЭлементы(АдресТаблицы);
КонецЕсли;

УстановитьУсловноеОформление();

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

&НаКлиенте
Expand Down Expand Up @@ -76,13 +78,14 @@
ДобавляемыеРеквизиты = Новый Структура;
Для Каждого Колонка Из Таблица.Колонки Цикл
Если ИсключаемыеПоля.Свойство(Колонка.Имя)
Или СтрНачинаетсяС(Колонка.Имя, "Служеб_") Тогда
Или СтрНачинаетсяС(Колонка.Имя, "Служебный_") Тогда
Продолжить;
КонецЕсли;
ДобавляемыеРеквизиты.Вставить(ПрефиксКод + Колонка.Имя, Колонка.ТипЗначения);
ДобавляемыеРеквизиты.Вставить(ПрефиксБаза + Колонка.Имя, Колонка.ТипЗначения);
Поля.Добавить(Колонка.Имя, Колонка.Имя);
КонецЦикла;

пбп_РаботаСФормами.СоздатьРеквизитыТаблицы(ЭтотОбъект, "ТаблицаКонфликтов", ДобавляемыеРеквизиты);

ШиринаКолонки = 5;
Expand Down Expand Up @@ -121,7 +124,7 @@

МенеджерОбъекта = пбп_ОбщегоНазначенияСлужебный.МенеджерОбъектаПоПолномуИмени(ИмяФормыВладельца);

СписокПредопределенных = Таблица.ВыгрузитьКолонку("Служеб_ПредопределенныйЭлемент");
СписокПредопределенных = Таблица.ВыгрузитьКолонку("Служебный_ПредопределенныйЭлемент");

Запрос = Новый Запрос;
Запрос.Текст =
Expand Down Expand Up @@ -150,8 +153,14 @@
нСтрока[ПрефиксКод + КлючЗначение.Ключ] = КлючЗначение.Значение;
КонецЦикла;

Если Строка.Служебный_КоллизииИдентификаторов Тогда
нСтрока.Ошибка = Перечисления.пбп_ВидыОшибокПредопределенныхЭлементов.КоллизииИдентификаторов;
Иначе
нСтрока.Ошибка = Перечисления.пбп_ВидыОшибокПредопределенныхЭлементов.РасхождениеЭлементаСКодом;
КонецЕсли;

Выборка.Сбросить();
Если Выборка.НайтиСледующий(Строка.Служеб_ПредопределенныйЭлемент, "Ссылка") Тогда
Если Выборка.НайтиСледующий(Строка.Служебный_ПредопределенныйЭлемент, "Ссылка") Тогда
ЗаполнитьЗначенияСвойств(БазоваяСтруктура, Выборка);
Для Каждого КлючЗначение Из БазоваяСтруктура Цикл
нСтрока[ПрефиксБаза + КлючЗначение.Ключ] = КлючЗначение.Значение;
Expand Down Expand Up @@ -181,13 +190,23 @@
Таблица.Индексы.Добавить(ИдентификаторНастройки);
Для Каждого Строка Из ТаблицаКонфликтов Цикл
Стр = Таблица.Найти(Строка[ПрефиксКод + ИдентификаторНастройки], ИдентификаторНастройки);

Если Строка.Ошибка = Перечисления.пбп_ВидыОшибокПредопределенныхЭлементов.КоллизииИдентификаторов Тогда
Таблица.Удалить(Стр);
Продолжить;
КонецЕсли;

Если Строка.ЗаменитьЭлементомИзКода Тогда
Стр.Служеб_ОбновитьЭлемент = Истина;
Стр.Служебный_ОбновитьЭлемент = Истина;
Иначе
Стр.Служеб_УстановитьФлагРучноеИзменение = Истина;
Стр.Служебный_УстановитьФлагРучноеИзменение = Истина;
КонецЕсли;
КонецЦикла;

Если Не ЗначениеЗаполнено(Таблица) Тогда
Возврат;
КонецЕсли;

Менеджер = пбп_ОбщегоНазначенияСлужебный.МенеджерОбъектаПоПолномуИмени(ИмяФормыВладельца);
ДопПараметры = пбп_ПредопределенныеЗначения.ДопПараметрыОбработкиПредопределенныхЭлементов(
Таблица, Менеджер);
Expand All @@ -199,17 +218,40 @@
Процедура ЗаполнитьОтметки(ЗначениеОтметки)
Модифицированность = Истина;
Для Каждого Строка Из ТаблицаКонфликтов Цикл
Если Строка.Ошибка =
ПредопределенноеЗначение("Перечисление.пбп_ВидыОшибокПредопределенныхЭлементов.КоллизииИдентификаторов") Тогда
Продолжить;
КонецЕсли;
Copy link

@coderabbitai coderabbitai bot Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Исправьте сравнение значения ошибки

В строках 221-224 используется сравнение:

Если Строка.Ошибка =
    ПредопределенноеЗначение("Перечисление.пбп_ВидыОшибокПредопределенныхЭлементов.КоллизииИдентификаторов") Тогда

Использование ПредопределенноеЗначение в данном контексте может быть некорректным. Рекомендуется напрямую сравнивать с соответствующим значением перечисления.

Примените следующий дифф для исправления:

-	Если Строка.Ошибка =
-		ПредопределенноеЗначение("Перечисление.пбп_ВидыОшибокПредопределенныхЭлементов.КоллизииИдентификаторов") Тогда
+	Если Строка.Ошибка = Перечисления.пбп_ВидыОшибокПредопределенныхЭлементов.КоллизииИдентификаторов Тогда

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@denisushakov, спасибо за пояснение. Вы правы, на клиенте нельзя напрямую обратиться к значению перечисления, поэтому использование функции ПредопределенноеЗначение корректно в данном случае.


✏️ Learnings added
Learnt from: denisushakov
PR: firstBitSportivnaya/PSSL#144
File: src/cf/CommonForms/пбп_ФормаРазрешенияКонфликтовПредопределенныхЭлементов/Ext/Form/Module.bsl:221-224
Timestamp: 2024-11-19T12:53:46.241Z
Learning: В клиентском коде на языке платформы 1С:Предприятие, в файле `src/cf/CommonForms/пбп_ФормаРазрешенияКонфликтовПредопределенныхЭлементов/Ext/Form/Module.bsl`, при сравнении значений перечислений необходимо использовать функцию `ПредопределенноеЗначение`, так как на клиенте нельзя напрямую обращаться к значениям перечислений.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Строка.ЗаменитьЭлементомИзКода = ЗначениеОтметки;
КонецЦикла;
КонецПроцедуры

&НаСервере
Процедура УстановитьУсловноеОформление()

УсловноеОформление.Элементы.Очистить();

Элемент = УсловноеОформление.Элементы.Добавить();

ПолеЭлемента = Элемент.Поля.Элементы.Добавить();
ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных(Элементы.ТаблицаКонфликтовЗаменитьЭлементомИзКода.Имя);

ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ТаблицаКонфликтов.Ошибка");
ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ОтборЭлемента.ПравоеЗначение = Перечисления.пбп_ВидыОшибокПредопределенныхЭлементов.КоллизииИдентификаторов;

Элемент.Оформление.УстановитьЗначениеПараметра("ТолькоПросмотр", Истина);

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

#Область СообщенияОСобытии

&НаСервере
Процедура СообщитьОбОтсутствииЭлемента(Идентификатор)

ТекстСообщения = НСтр("ru = 'Элемент '%1' отсутствуют в базе!';
|en = 'The element '%1' is missing from the database!'");
ТекстСообщения = НСтр("ru = 'Элемент ''%1'' отсутствует в базе!';
|en = 'The element ''%1'' is missing from the database!'");
ТекстСообщения = пбп_СтроковыеФункцииСлужебныйКлиентСервер.ПодставитьПараметрыВСтроку(
ТекстСообщения,
Идентификатор);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,15 @@

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

// Заполнение предопределенных элементов, с выводом серверного оповещения при возникновении конфликтов.
//
Процедура ЗаполнениеПредопределенныхЭлементов() Экспорт

пбп_ОбщегоНазначенияСлужебный.ПриНачалеВыполненияРегламентногоЗадания(
Метаданные.РегламентныеЗадания.пбп_ЗаполнениеПредопределенныхЭлементов);

пбп_ПредопределенныеЗначения.ЗаполнениеПредопределенныхЭлементов(Истина);

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

#КонецОбласти
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
Процедура ПриДобавленииПодсистемы(Описание) Экспорт

Описание.Имя = "ПроектнаяБиблиотекаПодсистем";
Описание.Версия = "1.0.3.12";
Описание.Версия = "1.0.4.13";

// Требуется библиотека стандартных подсистем.
Описание.ТребуемыеПодсистемы.Добавить("СтандартныеПодсистемы");
Expand Down Expand Up @@ -126,14 +126,7 @@

Процедура НачальноеЗаполнениеПредопределенныхЭлементов() Экспорт

Типы = Метаданные.ОпределяемыеТипы.пбп_ПредопределенныеВсеСсылкиПереопределяемый.Тип.Типы();

Для Каждого Тип Из Типы Цикл
ПолноеИмя = Метаданные.НайтиПоТипу(Тип).ПолноеИмя();
Менеджер = пбп_ОбщегоНазначенияСлужебный.МенеджерОбъектаПоПолномуИмени(ПолноеИмя);

пбп_ПредопределенныеЗначения.ИнициализироватьПредопределенныеЗначения(Менеджер);
КонецЦикла;
пбп_ПредопределенныеЗначения.ЗаполнениеПредопределенныхЭлементов();

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

Expand Down
Loading
Loading