diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9f41c81..ce2f8f1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,14 @@
---
+## 1.3.1.101 (2026-08-21)
+
+### РК_ПроверкаСерий — отображение пометки удаления дублей (#15)
+
+- В `ФормаИзмененияМастерСерии` добавлена колонка **Пометка удаления**; в списке видны и помеченные серии.
+- После объединения при включённой настройке пометки — оповещение и сообщение пользователю о числе помеченных дублей; комментарий в строке группы.
+- В поиске дублей не учитываются серии с пометкой удаления и без остатков.
+
## 1.3.1.100 (2026-08-20)
### РК_ПроверкаСерий — пометка дублей на удаление (#15)
diff --git a/VERSION b/VERSION
index 03fa7fa..4fbbd80 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.3.1.100
+1.3.1.101
diff --git a/src/ConfigDumpInfo.xml b/src/ConfigDumpInfo.xml
index 80b8d60..4041d0b 100644
--- a/src/ConfigDumpInfo.xml
+++ b/src/ConfigDumpInfo.xml
@@ -298,10 +298,10 @@
-
-
-
-
+
+
+
+
diff --git a/src/Configuration.xml b/src/Configuration.xml
index 10ae581..caa86e8 100644
--- a/src/Configuration.xml
+++ b/src/Configuration.xml
@@ -62,7 +62,7 @@
Role.РК_ОсновнаяРоль
- 1.3.1.100
+ 1.3.1.101
Language.Русский
diff --git a/src/DataProcessors/РК_ПроверкаСерий/Forms/Форма/Ext/Form/Module.bsl b/src/DataProcessors/РК_ПроверкаСерий/Forms/Форма/Ext/Form/Module.bsl
index 6bb5d76..f12cd01 100644
--- a/src/DataProcessors/РК_ПроверкаСерий/Forms/Форма/Ext/Form/Module.bsl
+++ b/src/DataProcessors/РК_ПроверкаСерий/Forms/Форма/Ext/Form/Module.bsl
@@ -290,7 +290,19 @@
Формат(Результат.ОбъединеноГрупп, "ЧН=0; ЧГ=0"),
Формат(Результат.Ошибок, "ЧН=0; ЧГ=0"),
?(Объект.РежимТест, " (тест)", ""));
+ Если Результат.Свойство("ПомеченоНаУдаление") И Результат.ПомеченоНаУдаление > 0 Тогда
+ Текст = Текст + Символы.ПС + СтрШаблон("Помечено на удаление дублей: %1",
+ Формат(Результат.ПомеченоНаУдаление, "ЧН=0; ЧГ=0"));
+ ИначеЕсли Объект.ПомечатьДублиСерииНаУдаление И Объект.РежимТест И Результат.ОбъединеноСсылок > 0 Тогда
+ Текст = Текст + Символы.ПС + СтрШаблон("В боевом режиме было бы помечено на удаление: %1",
+ Формат(Результат.ОбъединеноСсылок, "ЧН=0; ЧГ=0"));
+ КонецЕсли;
ПоказатьОповещениеПользователя("Дубли серий", , Текст);
+ Если Результат.Свойство("ПомеченоНаУдаление") И Результат.ПомеченоНаУдаление > 0 Тогда
+ ОбщегоНазначенияКлиент.СообщитьПользователю(СтрШаблон(
+ "Дублирующие серии помечены на удаление: %1",
+ Формат(Результат.ПомеченоНаУдаление, "ЧН=0; ЧГ=0")));
+ КонецЕсли;
КонецПроцедуры
@@ -1256,48 +1268,46 @@
Объект.ГруппыДублей.Очистить();
- ЗапросГруппы = Новый Запрос;
- ЗапросГруппы.Текст =
- "ВЫБРАТЬ
- | Сер.ВидНоменклатуры КАК ВидНоменклатуры,
- | Сер.Номер КАК Номер,
- | Сер.ГоденДо КАК ГоденДо,
- | КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Сер.Ссылка) КАК КоличествоСерий
- |ИЗ
- | Справочник.СерииНоменклатуры КАК Сер
- |ГДЕ
- | НЕ Сер.ПометкаУдаления
- |СГРУППИРОВАТЬ ПО
- | Сер.ВидНоменклатуры,
- | Сер.Номер,
- | Сер.ГоденДо
- |ИМЕЮЩИЕ
- | КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Сер.Ссылка) > 1";
+ Кандидаты = КандидатыСерийДляПоискаДублей();
+ Если Кандидаты.Количество() = 0 Тогда
+ Возврат 0;
+ КонецЕсли;
+
+ КлючиГрупп = Новый Соответствие;
+ Для Каждого СтрКандидат Из Кандидаты Цикл
+ Ключ = КлючГруппыДублей(СтрКандидат.ВидНоменклатуры, СтрКандидат.Номер, СтрКандидат.ГоденДо);
+ СерииКлюча = КлючиГрупп.Получить(Ключ);
+ Если СерииКлюча = Неопределено Тогда
+ СерииКлюча = Новый Массив;
+ КлючиГрупп.Вставить(Ключ, СерииКлюча);
+ КонецЕсли;
+ СерииКлюча.Добавить(СтрКандидат);
+ КонецЦикла;
- ВыбГруппы = ЗапросГруппы.Выполнить().Выбрать();
НомерГруппы = 0;
+ Для Каждого КлючИСерии Из КлючиГрупп Цикл
- Пока ВыбГруппы.Следующий() Цикл
-
- Мастер = НайтиСериюМастерГруппы(
- ВыбГруппы.ВидНоменклатуры,
- ВыбГруппы.Номер,
- ВыбГруппы.ГоденДо);
- Если Не ЗначениеЗаполнено(Мастер) Тогда
+ СтрокиКандидатов = КлючИСерии.Значение;
+ Если СтрокиКандидатов.Количество() < 2 Тогда
Продолжить;
КонецЕсли;
- СерииГруппы = СерииГруппыДублей(
- ВыбГруппы.ВидНоменклатуры,
- ВыбГруппы.Номер,
- ВыбГруппы.ГоденДо);
- Если СерииГруппы.Количество() < 2 Тогда
+ Первая = СтрокиКандидатов[0];
+ СерииГруппы = Новый Массив;
+ Для Каждого СтрКандидат Из СтрокиКандидатов Цикл
+ СерииГруппы.Добавить(СтрКандидат.Серия);
+ КонецЦикла;
+
+ Мастер = НайтиСериюМастерСредиСерий(СерииГруппы);
+ Если Не ЗначениеЗаполнено(Мастер) Тогда
Продолжить;
КонецЕсли;
Остатки = СведенияОстатковПоСериям(СерииГруппы).Остатки;
НомерГруппы = НомерГруппы + 1;
- ДобавитьСтрокуГруппыДублей(НомерГруппы, ВыбГруппы, Мастер, СерииГруппы, Остатки);
+ ДанныеГруппы = Новый Структура("ВидНоменклатуры, Номер, ГоденДо",
+ Первая.ВидНоменклатуры, Первая.Номер, Первая.ГоденДо);
+ ДобавитьСтрокуГруппыДублей(НомерГруппы, ДанныеГруппы, Мастер, СерииГруппы, Остатки);
КонецЦикла;
@@ -1306,7 +1316,63 @@
КонецФункции
&НаСервере
-Функция НайтиСериюМастерГруппы(Вид, Номер, ГоденДо)
+Функция КлючГруппыДублей(ВидНоменклатуры, Номер, ГоденДо)
+
+ ИдВида = "";
+ Если ЗначениеЗаполнено(ВидНоменклатуры) Тогда
+ ИдВида = XMLСтрока(ВидНоменклатуры.УникальныйИдентификатор());
+ КонецЕсли;
+ Возврат ИдВида + "|" + Номер + "|" + Формат(ГоденДо, "ДФ=yyyyMMdd; ДП=");
+
+КонецФункции
+
+&НаСервере
+Функция КандидатыСерийДляПоискаДублей()
+
+ // Учитываем все серии; помеченные на удаление без остатков исключаем.
+
+ Результат = Новый Массив;
+
+ Запрос = Новый Запрос;
+ Запрос.Текст =
+ "ВЫБРАТЬ
+ | Сер.Ссылка КАК Серия,
+ | Сер.ВидНоменклатуры КАК ВидНоменклатуры,
+ | Сер.Номер КАК Номер,
+ | Сер.ГоденДо КАК ГоденДо,
+ | Сер.ПометкаУдаления КАК ПометкаУдаления
+ |ИЗ
+ | Справочник.СерииНоменклатуры КАК Сер";
+
+ Выборка = Запрос.Выполнить().Выбрать();
+ СерииВсе = Новый Массив;
+ СтрокиВсе = Новый Массив;
+ Пока Выборка.Следующий() Цикл
+ Стр = Новый Структура("Серия, ВидНоменклатуры, Номер, ГоденДо, ПометкаУдаления",
+ Выборка.Серия, Выборка.ВидНоменклатуры, Выборка.Номер, Выборка.ГоденДо, Выборка.ПометкаУдаления);
+ СтрокиВсе.Добавить(Стр);
+ СерииВсе.Добавить(Выборка.Серия);
+ КонецЦикла;
+
+ Остатки = СведенияОстатковПоСериям(СерииВсе).Остатки;
+ Для Каждого Стр Из СтрокиВсе Цикл
+ Остаток = ОстатокСерииИзСоответствия(Остатки, Стр.Серия);
+ Если Стр.ПометкаУдаления И Остаток <= 0.000001 Тогда
+ Продолжить;
+ КонецЕсли;
+ Результат.Добавить(Стр);
+ КонецЦикла;
+
+ Возврат Результат;
+
+КонецФункции
+
+&НаСервере
+Функция НайтиСериюМастерСредиСерий(Серии)
+
+ Если Серии.Количество() = 0 Тогда
+ Возврат Справочники.СерииНоменклатуры.ПустаяСсылка();
+ КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
@@ -1317,24 +1383,27 @@
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ДвиженияСерийТоваров КАК Дв
| ПО Дв.Серия = Сер.Ссылка
|ГДЕ
- | Сер.ВидНоменклатуры = &Вид
- | И Сер.Номер = &Номер
- | И Сер.ГоденДо = &ГоденДо
- | И НЕ Сер.ПометкаУдаления
+ | Сер.Ссылка В (&Серии)
|СГРУППИРОВАТЬ ПО
| Сер.Ссылка
|УПОРЯДОЧИТЬ ПО
| КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Дв.Регистратор) УБЫВ,
| Сер.Ссылка";
- Запрос.УстановитьПараметр("Вид", Вид);
- Запрос.УстановитьПараметр("Номер", Номер);
- Запрос.УстановитьПараметр("ГоденДо", ГоденДо);
+ Запрос.УстановитьПараметр("Серии", Серии);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка;
КонецЕсли;
- Возврат Справочники.СерииНоменклатуры.ПустаяСсылка();
+ Возврат Серии[0];
+
+КонецФункции
+
+&НаСервере
+Функция НайтиСериюМастерГруппы(Вид, Номер, ГоденДо)
+
+ СерииГруппы = СерииГруппыДублей(Вид, Номер, ГоденДо);
+ Возврат НайтиСериюМастерСредиСерий(СерииГруппы);
КонецФункции
@@ -1344,22 +1413,34 @@
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
- | Сер.Ссылка КАК Серия
+ | Сер.Ссылка КАК Серия,
+ | Сер.ПометкаУдаления КАК ПометкаУдаления
|ИЗ
| Справочник.СерииНоменклатуры КАК Сер
|ГДЕ
| Сер.ВидНоменклатуры = &Вид
| И Сер.Номер = &Номер
- | И Сер.ГоденДо = &ГоденДо
- | И НЕ Сер.ПометкаУдаления";
+ | И Сер.ГоденДо = &ГоденДо";
Запрос.УстановитьПараметр("Вид", Вид);
Запрос.УстановитьПараметр("Номер", Номер);
Запрос.УстановитьПараметр("ГоденДо", ГоденДо);
- Результат = Новый Массив;
+ Строки = Новый Массив;
+ СерииВсе = Новый Массив;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
- Результат.Добавить(Выборка.Серия);
+ Строки.Добавить(Новый Структура("Серия, ПометкаУдаления", Выборка.Серия, Выборка.ПометкаУдаления));
+ СерииВсе.Добавить(Выборка.Серия);
+ КонецЦикла;
+
+ Остатки = СведенияОстатковПоСериям(СерииВсе).Остатки;
+ Результат = Новый Массив;
+ Для Каждого Стр Из Строки Цикл
+ Остаток = ОстатокСерииИзСоответствия(Остатки, Стр.Серия);
+ Если Стр.ПометкаУдаления И Остаток <= 0.000001 Тогда
+ Продолжить;
+ КонецЕсли;
+ Результат.Добавить(Стр.Серия);
КонецЦикла;
Возврат Результат;
@@ -1592,7 +1673,7 @@
&НаСервере
Функция ОбъединитьОтмеченныеГруппыНаСервере()
- Результат = Новый Структура("ОбъединеноСсылок, ОбъединеноГрупп, Ошибок", 0, 0, 0);
+ Результат = Новый Структура("ОбъединеноСсылок, ОбъединеноГрупп, Ошибок, ПомеченоНаУдаление", 0, 0, 0, 0);
Для Каждого СтрГруппа Из Объект.ГруппыДублей Цикл
@@ -1634,8 +1715,14 @@
КонецЕсли;
Иначе
ОбщегоНазначения.ЗаменитьСсылки(Заменяемые);
+ ПомеченоВГруппе = 0;
Если Объект.ПомечатьДублиСерииНаУдаление Тогда
- ПометитьДублиСерииНаУдаление(Заменяемые);
+ ПомеченоВГруппе = ПометитьДублиСерииНаУдаление(Заменяемые);
+ Результат.ПомеченоНаУдаление = Результат.ПомеченоНаУдаление + ПомеченоВГруппе;
+ Если ПомеченоВГруппе > 0 Тогда
+ СтрГруппа.Комментарий = "Дубли помечены на удаление: "
+ + Формат(ПомеченоВГруппе, "ЧН=0; ЧГ=0");
+ КонецЕсли;
КонецЕсли;
СтрГруппа.Объединено = Истина;
Результат.ОбъединеноСсылок = Результат.ОбъединеноСсылок + Заменяемые.Количество();
@@ -1653,8 +1740,9 @@
КонецФункции
&НаСервере
-Процедура ПометитьДублиСерииНаУдаление(Заменяемые)
+Функция ПометитьДублиСерииНаУдаление(Заменяемые)
+ Помечено = 0;
Для Каждого КлючИЗначение Из Заменяемые Цикл
СерияДубль = КлючИЗначение.Ключ;
Если Не ЗначениеЗаполнено(СерияДубль) Тогда
@@ -1665,8 +1753,10 @@
Продолжить;
КонецЕсли;
ОбСерии.УстановитьПометкуУдаления(Истина);
+ Помечено = Помечено + 1;
КонецЦикла;
+ Возврат Помечено;
-КонецПроцедуры
+КонецФункции
#КонецОбласти
diff --git a/src/DataProcessors/РК_ПроверкаСерий/Forms/ФормаИзмененияМастерСерии/Ext/Form.xml b/src/DataProcessors/РК_ПроверкаСерий/Forms/ФормаИзмененияМастерСерии/Ext/Form.xml
index 6943983..0a149f1 100644
--- a/src/DataProcessors/РК_ПроверкаСерий/Forms/ФормаИзмененияМастерСерии/Ext/Form.xml
+++ b/src/DataProcessors/РК_ПроверкаСерий/Forms/ФормаИзмененияМастерСерии/Ext/Form.xml
@@ -85,6 +85,14 @@
+
+ СерииГруппы.ПометкаУдаления
+ true
+ EnterOnInput
+ Auto
+
+
+
СерииГруппы.Серия
true
@@ -171,6 +179,17 @@
v8:UUID
+
+
+
+ ru
+ Пометка удаления
+
+
+
+ xs:boolean
+
+
diff --git a/src/DataProcessors/РК_ПроверкаСерий/Forms/ФормаИзмененияМастерСерии/Ext/Form/Module.bsl b/src/DataProcessors/РК_ПроверкаСерий/Forms/ФормаИзмененияМастерСерии/Ext/Form/Module.bsl
index 6bc4bc9..6468269 100644
--- a/src/DataProcessors/РК_ПроверкаСерий/Forms/ФормаИзмененияМастерСерии/Ext/Form/Module.bsl
+++ b/src/DataProcessors/РК_ПроверкаСерий/Forms/ФормаИзмененияМастерСерии/Ext/Form/Module.bsl
@@ -19,13 +19,18 @@
&НаКлиенте
Процедура Выбрать(Команда)
- ВыбраннаяСерия = ТекущаяВыбраннаяСерия();
- Если Не ЗначениеЗаполнено(ВыбраннаяСерия) Тогда
+ ТекущиеДанные = Элементы.СерииГруппы.ТекущиеДанные;
+ Если ТекущиеДанные = Неопределено Или Не ЗначениеЗаполнено(ТекущиеДанные.Серия) Тогда
ПоказатьПредупреждение(, "Выберите серию в таблице");
Возврат;
КонецЕсли;
- Закрыть(ВыбраннаяСерия);
+ Если ТекущиеДанные.ПометкаУдаления И ТекущиеДанные.Остаток <= 0 Тогда
+ ПоказатьПредупреждение(, "Нельзя выбрать мастер-серией помеченную на удаление серию без остатка");
+ Возврат;
+ КонецЕсли;
+
+ Закрыть(ТекущиеДанные.Серия);
КонецПроцедуры
@@ -37,10 +42,7 @@
Процедура СерииГруппыВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
- ВыбраннаяСерия = ТекущаяВыбраннаяСерия();
- Если ЗначениеЗаполнено(ВыбраннаяСерия) Тогда
- Закрыть(ВыбраннаяСерия);
- КонецЕсли;
+ Выбрать(Неопределено);
КонецПроцедуры
@@ -48,17 +50,6 @@
#Область СлужебныеПроцедурыИФункции
-&НаКлиенте
-Функция ТекущаяВыбраннаяСерия()
-
- Если Элементы.СерииГруппы.ТекущиеДанные = Неопределено Тогда
- Возврат Неопределено;
- КонецЕсли;
-
- Возврат Элементы.СерииГруппы.ТекущиеДанные.Серия;
-
-КонецФункции
-
&НаСервере
Процедура ЗаполнитьСерииГруппы(ВидНоменклатуры, Номер, ГоденДо)
@@ -67,35 +58,43 @@
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
- | Сер.Ссылка КАК Серия
+ | Сер.Ссылка КАК Серия,
+ | Сер.ПометкаУдаления КАК ПометкаУдаления
|ИЗ
| Справочник.СерииНоменклатуры КАК Сер
|ГДЕ
| Сер.ВидНоменклатуры = &Вид
| И Сер.Номер = &Номер
- | И Сер.ГоденДо = &ГоденДо
- | И НЕ Сер.ПометкаУдаления";
+ | И Сер.ГоденДо = &ГоденДо";
Запрос.УстановитьПараметр("Вид", ВидНоменклатуры);
Запрос.УстановитьПараметр("Номер", Номер);
Запрос.УстановитьПараметр("ГоденДо", ГоденДо);
Серии = Новый Массив;
+ Пометки = Новый Соответствие;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Серии.Добавить(Выборка.Серия);
+ Пометки.Вставить(Выборка.Серия, Выборка.ПометкаУдаления);
КонецЦикла;
Остатки = ОстаткиСерий(Серии);
Для Каждого Серия Из Серии Цикл
+ Остаток = Остатки.Получить(Серия);
+ Если Остаток = Неопределено Тогда
+ Остаток = 0;
+ КонецЕсли;
+ ПометкаУдаления = (Пометки.Получить(Серия) = Истина);
+ // Помеченные без остатка не предлагаем как мастер, но показываем в списке.
НовСтр = СерииГруппы.Добавить();
НовСтр.Серия = Серия;
НовСтр.ЭтоМастер = (Серия = СерияМастер);
+ НовСтр.ПометкаУдаления = ПометкаУдаления;
НовСтр.ИдентификаторСерии = Серия.УникальныйИдентификатор();
- Остаток = Остатки.Получить(Серия);
- НовСтр.Остаток = ?(Остаток = Неопределено, 0, Остаток);
+ НовСтр.Остаток = Остаток;
КонецЦикла;
- СерииГруппы.Сортировать("ЭтоМастер Убыв, Остаток Убыв, Серия");
+ СерииГруппы.Сортировать("ПометкаУдаления, ЭтоМастер Убыв, Остаток Убыв, Серия");
КонецПроцедуры