Программный контроль границы последовательности партионного учета при проведении документов задним числом

04.11.15

Задачи пользователя - Адаптация типовых решений

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

Приступим...

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

Последовательность ПартионныйУчет

2. Создадим в общем модуле процедуру для подписки. Для хранения таблицы движений документа используем встроенный реквизит документа ДополнительныеСвойства. Информация, помещаемая в эту структуру, хранится всё время "путешествия" объекта по подпискам. Запомним движения по партиям до проведения, а также границу последовательности, которая была на момент проведения документа.

Процедура ПередЗаписьюСписанияТоваров(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
	Если НЕ Источник.ЭтоНовый() Тогда
		Если Источник.Движения.Найти("ПартииТоваровНаСкладах") <> Неопределено Тогда
			ТаблицаДвиженийПоПартиям = ВернутьТаблицуДвиженийПоПартиям(Источник.Ссылка);
			Источник.ДополнительныеСвойства.Вставить("ПартииДоПроведения", ТаблицаДвиженийПоПартиям);			
		КонецЕсли;
		ГраницаПартионногоУчета = Последовательности.ПартионныйУчет.ПолучитьГраницу();		
		Источник.ДополнительныеСвойства.Вставить("ГраницаПоследовательности", ГраницаПартионногоУчета);
	КонецЕсли;
КонецПроцедуры

Функция ВернутьТаблицуДвиженийПоПартиям(СсылкаНаОбъект) Экспорт
	Запрос = Новый Запрос("ВЫБРАТЬ РАЗРЕШЕННЫЕ
	                      |	ПартииТоваровНаСкладах.Номенклатура,
	                      |	ПартииТоваровНаСкладах.Склад,
	                      |	ПартииТоваровНаСкладах.ХарактеристикаНоменклатуры,
	                      |	ПартииТоваровНаСкладах.СерияНоменклатуры,
	                      |	ПартииТоваровНаСкладах.ДокументОприходования,
	                      |	ПартииТоваровНаСкладах.СтатусПартии,
	                      |	ПартииТоваровНаСкладах.Заказ,
	                      |	ПартииТоваровНаСкладах.Качество,
	                      |	ПартииТоваровНаСкладах.Количество,
	                      |	ПартииТоваровНаСкладах.Стоимость
	                      |ИЗ
	                      |	РегистрНакопления.ПартииТоваровНаСкладах КАК ПартииТоваровНаСкладах
	                      |ГДЕ
	                      |	ПартииТоваровНаСкладах.Регистратор = &Регистратор");
	Запрос.УстановитьПараметр("Регистратор", СсылкаНаОбъект);
	РезультатЗапроса = Запрос.Выполнить();
	Если РезультатЗапроса.Пустой() Тогда
		Возврат Новый ТаблицаЗначений;
	Иначе
		Возврат РезультатЗапроса.Выгрузить();
	КонецЕсли;
КонецФункции

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

Процедура ОбработкаПроведенияДляКонтроляГП(Источник, Отказ, РежимПроведения) Экспорт
    ВыполнитьКонтрольГП(Источник);
КонецПроцедуры

Процедура ВыполнитьКонтрольГП(Источник) Экспорт
    Если Источник.Метаданные().Реквизиты.Найти("ОтражатьВУправленческомУчете") <> Неопределено Тогда
        Если НЕ Источник.ОтражатьВУправленческомУчете Тогда
            Возврат;
        КонецЕсли;
    КонецЕсли;
    Если НЕ Источник.ЭтоНовый() Тогда
        Если Источник.Движения.Найти("ПартииТоваровНаСкладах") <> Неопределено Тогда
            ПартииПослеПроведения = Источник.Движения.ПартииТоваровНаСкладах.Выгрузить();
            Если ПартииПослеПроведения.Количество() = 0 Тогда
                // для части документов партии появляются после записи объекта в базу
                ПартииПослеПроведения = ВернутьТаблицуДвиженийПоПартиям(Источник.Ссылка);
            КонецЕсли;
            Источник.ДополнительныеСвойства.Вставить("ПартииПослеПроведения", ПартииПослеПроведения);
            ОпределитьНеобходимостьВозвращенияГП(Источник);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

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

Функция ОпределитьНеобходимостьВозвращенияГП(Источник) Экспорт
    ДополнительныеСвойства = Источник.ДополнительныеСвойства;
    ГраницаПоследовательностиДокумента = Неопределено;
    ДополнительныеСвойства.Свойство("ГраницаПоследовательности", ГраницаПоследовательностиДокумента);
    Идентичность = УстановитьИдентичностьТаблицДвиженийПоПартиям(ДополнительныеСвойства);
    ГраницаПоследовательностиТекущая = Последовательности.ПартионныйУчет.ПолучитьГраницу();
    Если ГраницаПоследовательностиДокумента <> Неопределено Тогда
        Если Идентичность И ГраницаПоследовательностиТекущая.Дата < ГраницаПоследовательностиДокумента.Дата Тогда
            // если таблицы идентичны, но текущая граница сдвинулась назад - вернем обратно
            Последовательности.ПартионныйУчет.УстановитьГраницу(ГраницаПоследовательностиДокумента);
            ЗаписьЖурналаРегистрации("Контроль ГП", УровеньЖурналаРегистрации.Информация, Источник.Метаданные(), Источник.Ссылка, "Граница последовательности возвращена на " + Строка(ГраницаПоследовательностиДокумента.Дата) + ", документ: " + Строка(ГраницаПоследовательностиДокумента.Ссылка));
        КонецЕсли;
    КонецЕсли;
КонецФункции
 Функция УстановитьИдентичностьТаблицДвиженийПоПартиям(ДополнительныеСвойства) Экспорт
    Идентичность = Ложь;
    ПартииДоПроведения = Неопределено;
    ДополнительныеСвойства.Свойство("ПартииДоПроведения", ПартииДоПроведения);
    ПартииПослеПроведения = Неопределено;
    ДополнительныеСвойства.Свойство("ПартииПослеПроведения", ПартииПослеПроведения);
    Если СравнитьТаблицыЗначений(ПартииДоПроведения, ПартииПослеПроведения) Тогда
        Идентичность = Истина;
    Иначе
        Идентичность = Ложь;
    КонецЕсли;        
    Возврат Идентичность;
КонецФункции

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

Механизм также полезен для ситуаций, когда пользователь открывает документ, проведенный задним числом, и вместо закрытия нажимает ОК. Граница улетает на "закрытый" таким образом документ.

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

	Если мУдалятьДвижения Тогда
		ОбщегоНазначения.УдалитьДвиженияРегистратора(ЭтотОбъект, Отказ);
	КонецЕсли;

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

контроль границы последовательности партионного учета партионный учет восстановление последовательности

См. также

Табличная часть в доп. реквизитах и формирование таблиц в шаблоне docx для 1С:ДО 3.0

Адаптация типовых решений Платформа 1С v8.3 1С:Документооборот Россия Платные (руб)

Расширение конфигурации для «1С:Документооборот КОРП», редакция 3.0. позволяет: 1.использовать произвольные табличные части в качестве дополнительных реквизитов к документу; 2 использовать произвольные табличные части в шаблонах в формате docx для автоматического заполнения таблиц.

29400 руб.

29.06.2023    4374    8    4    

17

Расширение для 1С:УНФ. Автоматическое снятие резервов в Заказах покупателей

Логистика, склад и ТМЦ Адаптация типовых решений Платформа 1С v8.3 1С:Управление нашей фирмой 1.6 1С:Управление нашей фирмой 3.0 Россия Управленческий учет Платные (руб)

Чтобы не допустить путаницы с обещаниями клиентам и для четкого контроля исполнения заказов мы используем резервирование товаров. Мы доработали УНФ, чтобы она автоматически отменяла старые резервы и не мешала эффективно продавать.

7200 руб.

02.08.2023    2899    4    0    

19

Создать на основании - своя кнопка (БСП). Проблема двух подменю Создать на основании

БСП (Библиотека стандартных подсистем) Адаптация типовых решений Платформа 1С v8.3 1С:ERP Управление предприятием 2 Бесплатно (free)

Понадобилось в подменю "Создать на основании" добавить свою команду, которая открывает обработку. В процессе доработок появилась проблема двух подменю "Создать на основании". В статье о том, как решились проблемы.

01.03.2024    1120    dimanich70    6    

13

Доработка отчета "Связанные документы" (структура подчиненности) для вывода объектов из любого расширения

Адаптация типовых решений Платформа 1С v8.3 1С:Управление торговлей 11 Россия Абонемент ($m)

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

1 стартмани

27.10.2023    1935    13    avmartynov    10    

43

Печать непроведенных документов для УТ, КА, ERP. Настройка печати по пользователям, документам и печатным формам

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    2023    21    progmaster    7    

3
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. karpik666 3759 05.11.15 05:08 Сейчас в теме
Код функции СравнитьТаблицыЗначений
// Функция сравнивает две таблицы значений на идентичность структуры и данных
//
// Параметры
//  ТаблицаЗначений1 - ТаблицаЗначений для сравнения
//  ТаблицаЗначений2 - ТаблицаЗначений для сравнения
//
// Возвращаемое значение:
//   Булево, идентичны или нет две таблицы
//
Функция СравнитьТаблицыЗначений(ТаблицаЗначений1, ТаблицаЗначений2)

	Если ТипЗнч(ТаблицаЗначений1) <> Тип("ТаблицаЗначений") ИЛИ ТипЗнч(ТаблицаЗначений2) <> Тип("ТаблицаЗначений") Тогда
		Возврат Ложь;
	КонецЕсли; 
	
	Если ТаблицаЗначений1.Количество() <> ТаблицаЗначений2.Количество() Тогда
		Возврат Ложь;
	КонецЕсли; 

	Если ТаблицаЗначений1.Колонки.Количество() <> ТаблицаЗначений2.Колонки.Количество() Тогда
		Возврат Ложь;
	КонецЕсли; 

	Для каждого Колонка Из ТаблицаЗначений1.Колонки Цикл
		
		Если ТаблицаЗначений2.Колонки.Найти(Колонка.Имя) = Неопределено Тогда
			Возврат Ложь;
		КонецЕсли;
		
		Для каждого СтрокаТаблицы Из ТаблицаЗначений1 Цикл
		
			Попытка
			
				Если СтрокаТаблицы[Колонка.Имя] <> ТаблицаЗначений2[ТаблицаЗначений1.Индекс(СтрокаТаблицы)][Колонка.Имя] Тогда
				
					Возврат Ложь;
				
				КонецЕсли;
			
			Исключение
				
				Возврат Ложь;
				
			КонецПопытки;
		
		КонецЦикла; 
	
	КонецЦикла; 
	
	Возврат Истина;
	
КонецФункции // СравнитьТаблицыЗначений()
Показать
2. cargobird 306 05.11.15 07:04 Сейчас в теме
(1) karpik666, спасибо, добавлю в статью.
10. vis_tmp 32 08.02.17 08:51 Сейчас в теме
(1)А не быстрее будет вместо поячеечного сравнения таблиц значений сравнить "ЗначениеВСтрокуВнутр()" их обоих?
3. insurgut 207 05.11.15 07:41 Сейчас в теме
Увеличивая нагрузку на проведение документа уменьшаем (возможно даже кратно) нагрузку на перепроведение по партиям. Неплохой вариант! На какой версии конфигурации отлажен механизм? Работает ли он с корректировками записей регистров?
4. cargobird 306 05.11.15 08:07 Сейчас в теме
(3) insurgut, Управление Торговлей, ред. 10.3. Версия конфигурации более чем двухгодовалой давности, даже затрудняюсь определиться с номером. При этом добавлялись необходимые новые документы, вроде корректировок поступления и реализации.
Корректировка записей регистров при перезаписи без изменений движений в партионном учете границу не роняет (и вроде это штатное поведение, не помню чтобы что-то там трогал), поэтому по нему дорабатывать не понадобилось.
5. svilsa 12 13.11.15 20:14 Сейчас в теме
Супер! Спасибо, это то что нужно. Особенно, когда настроен обмен УТ-БП, и все документы. которые "провелись по партиям" зря хотят выгрузиться в бухгалтерию. Очень-очень пригодилась статья! С помощью метода статьи надеюсь снизить в разы количество документов обмена из-за того, что в "Отчетах о розничных продажах" месячной давности бухгалтер меняет вид кредита банка.
cargobird; +1 Ответить
6. cargobird 306 14.11.15 08:12 Сейчас в теме
(5) svilsa, могу предложить еще одну оптимизацию работы, раз дорабатываете конфигурацию: если ввести дополнительный параметр сеанса типа Булево (назвать его, например, "ВосстановлениеПоследовательности"), перед восстановлением последовательности взвести его в Истина, и по Истина отключать работу этого механизма - последовательность будет восстанавливаться немного быстрее...
7. svilsa 12 14.11.15 13:10 Сейчас в теме
8. lx@ 20.11.15 10:16 Сейчас в теме
Мне показалось, что не хватает блокировок. Может получиться, что движения у документа остались, однако граница была сдвинута другим документом и посему возращать ее не надо.
9. cargobird 306 20.11.15 12:13 Сейчас в теме
(8) lx@, в УТ 10.3 механизм блокировок еще жесткий - при проведении блокируется вся таблица регистра целиком, поэтому пока проводится один документ, второй не проведется. Или дождется, или выпадет в транзакцию. То есть двигать границу может только один документ, который проводит и тот и двигает. Вроде так.
11. WWWolfy 132 12.03.20 00:36 Сейчас в теме
Можно не загонять в память сервера большие таблицы и не мучаться с их сравнением.
Как вариант - делать хеш MD5 и сравнивать их.
Пример:

	ХешированиеДанных  = Новый ХешированиеДанных(ХешФункция.MD5) ;
 	ХешированиеДанных.Добавить(  ЗначениеВСтрокуВнутр( ТЗДвижений ) );
	Хэш = НРег(СтрЗаменить(ХешированиеДанных.ХешСумма, " ", ""));


А чтобы не отрабатывать при перепроведениях и т.п. можно анализировать, что работаем из открытой Формы, для этого выставить флаг "ОткрытаФорма" в какой-нибудь общей процедуре, например:
Процедура УстановитьДоступностьПоляВводаНомера(МетаданныеОбъекта, ФормаОбъекта, ПодменюДействия, ПолеВводаНомера) Экспорт
	
	//Для всех документов вставим флаг, что работаем с ним из Формы. Нужно для проведения.
ФормаОбъекта.ДокументОбъект.ДополнительныеСвойства.Вставить("ЗаписанИзФормы", Истина );
12. vis_tmp 32 21.12.22 12:29 Сейчас в теме
Кажется, это очень дельное предложение по оптимизации проведения по партиям.
Особенно с учётом дополнений в комментариях.
Оставьте свое сообщение