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 + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Пометка удаления</v8:content> + </v8:item> + + + 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, Остаток); + НовСтр.Остаток = Остаток; КонецЦикла; - СерииГруппы.Сортировать("ЭтоМастер Убыв, Остаток Убыв, Серия"); + СерииГруппы.Сортировать("ПометкаУдаления, ЭтоМастер Убыв, Остаток Убыв, Серия"); КонецПроцедуры