Почему удаляются записи в регистре накопления при закрытии смены в 1С и как это исправить?

Программист 1С v8.3 (Управляемые формы) 1С:Розница Управленческий учет Торговля и дистрибуция
← На главную

При разработке расширений для типовых конфигураций «1С:Предприятие 8.3» (таких как «1С:Розница», «1С:Управление торговлей» или «1С:Комплексная автоматизация») программисты часто сталкиваются с загадочным поведением системы: записи в новом регистре накопления, привязанные к документу ЧекККМ, успешно создаются в течение дня, но бесследно исчезают после закрытия кассовой смены или перезапуска программы. Выясним причину этого поведения и подробно разберем, как правильно спроектировать архитектуру решения, чтобы избежать потери данных.

Почему на самом деле удаляются записи? Анализируем механизмы платформы

Для начала проанализируем стандартную логику работы розничных конфигураций 1С. Документ ЧекККМ (Чек ККМ) предназначен для оперативного учета продаж в течение одной кассовой смены. При этом в системе заложен жесткий регламент работы с этими документами:

  1. Проведение в течение смены: При оформлении продажи чек проводится и делает оперативные движения по регистрам (например, списывает товары, фиксирует выручку).
  2. Закрытие кассовой смены: В конце дня при запуске процедуры закрытия смены создается сводный документ «Отчет о розничных продажах» (далее — ОРП). Этот документ аккумулирует в себе информацию из всех чеков за день.
  3. Архивация чеков: После успешного формирования и проведения ОРП запускается процедура архивации чеков ККМ. В зависимости от настроек программы чеки либо распроводятся (снимаются с проведения), либо помечаются специальным статусом «Архивный» с полной очисткой движений.

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

Рассмотрим, какими путями можно решить эту проблему, сохранив целостность данных и не нарушив типовую методологию «1С:Предприятия».

Решение 1. Классический подход 1С: Перенос движений в «Отчет о розничных продажах»

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

Разберем по шагам, как это реализовать:

  1. Добавление регистратора в расширении: Откройте свойства вашего регистра накопления Расш1_Взаиморасчеты в расширении и в список разрешенных регистраторов добавьте, помимо документа ЧекККМ, документ ОтчетОРозничныхПродажах.
  2. Разделение логики накопления:
    • В течение дня движения по взаиморасчетам делает каждый конкретный ЧекККМ. Это позволяет оперативно видеть долги покупателей в режиме реального времени.
    • При закрытии смены чеки архивируются, и их движения по вашему регистру удаляются платформой автоматически. Но в этот же момент проводится ОРП, который должен зафиксировать итоговые движения за всю смену.
  3. Доработка проведения ОРП: Необходимо перехватить обработку проведения документа ОтчетОРозничныхПродажах с помощью механизма расширений (аннотация &После или &Вместо для процедуры ОбработкаПроведения в модуле документа).

Посмотрим на пример кода, который собирает информацию по долгам из чеков смены и записывает их в движения «Отчета о розничных продажах»:


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

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

Преимущества: Полное соответствие методологии 1С, отсутствие дублирования данных, корректный расчет остатков на конец смены.

Решение 2. Использование независимого регистра сведений

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

Выясним причину, почему это решает проблему удаления:

У независимого регистра сведений в метаданных отсутствует жесткая связь «Регистратор — Движения». Платформа не отслеживает состояние документов, указанных в измерениях такого регистра, и никогда не очищает его данные автоматически при распроведении документов.

Рассмотрим порядок действий для перехода на этот вариант:

  1. Создайте в расширении независимый регистр сведений (например, Расш1_ИсторияВзаиморасчетовЧеков).
  2. Добавьте измерение ДокументСсылка с типом ДокументСсылка.ЧекККМ.
  3. Добавьте необходимые измерения (например, Контрагент, Продавец) и ресурс СуммаДолга.
  4. Записывайте данные программно в момент пробития чека. Напишем пример процедуры для записи данных в независимый регистр:

Процедура Расш1_ЗаписатьВзаиморасчетыВРегистрСведений(ОбъектЧекККМ, СуммаДолга, ОбъектРМК) Экспорт

	НаборЗаписей = РегистрыСведений.Расш1_ИсторияВзаиморасчетовЧеков.СоздатьНаборЗаписей();
	НаборЗаписей.Отбор.ДокументСсылка.Установить(ОбъектЧекККМ.Ссылка);
	
	НоваяЗапись = НаборЗаписей.Добавить();
	НоваяЗапись.Период = ТекущаяДата();
	НоваяЗапись.ДокументСсылка = ОбъектЧекККМ.Ссылка;
	НоваяЗапись.Продавец = ОбъектРМК.Продавец;
	НоваяЗапись.Контрагент = ОбъектЧекККМ.Контрагент;
	НоваяЗапись.СуммаДолга = СуммаДолга;
	
	Попытка
		НаборЗаписей.Записать(Истина);
	Исключение
		ЗаписьЖурналаРегистрации("Расширение.Взаиморасчеты", 
			УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
	КонецПопытки;

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

При закрытии смены статус документа ЧекККМ изменится на «Архивный», но запись в регистре сведений останется нетронутой, так как платформа не связывает этот регистр с механизмом проведения документов.

Решение 3. Использование промежуточного документа-регистратора

Если вам критически важно использовать именно регистр накопления (например, для построения сложных отчетов по остаткам), но переписывать механизмы заполнения «Отчета о розничных продажах» не представляется возможным, можно применить схему со сторонним регистратором.

Проанализируем эту схему:

Поскольку при закрытии смены архивируются и распроводятся только чеки ККМ, ваши созданные технические документы Расш1_ОперацияВзаиморасчетов останутся проведенными, и движения по регистру накопления не пострадают.

Важные рекомендации по качеству кода 1С

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


// Пример некорректной записи в обход транзакции проведения:
НаборЗаписей = РегистрыНакопления.Расш1_Взаиморасчеты.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(ОбъектЧекККМ.Ссылка);
// Заполнение записи...
НаборЗаписей.Записать();

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

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

← На главную