В процессе разработки в 1С часто возникает задача программного формирования движений по регистрам. Одной из типичных проблем является необходимость привязки новых записей к уже существующему документу, например, к «Корректировке записей регистров». Рассмотрим детально, как правильно найти нужный документ по его номеру и дате, а затем корректно записать данные в регистр накопления.
Первым шагом нам необходимо получить ссылку на конкретный документ. В 1С метод НайтиПоНомеру требует внимательного отношения к параметрам, особенно если в конфигурации используется периодическая нумерация (например, номера обнуляются каждый год).
Проанализируем ситуацию: если мы просто укажем номер, система может не найти документ, так как не понимает, в каком временном интервале искать. Рассмотрим правильный способ вызова метода:
// Определяем номер и примерную дату для поиска (начало года достаточно)
НомерДок = "Т0000000002";
ДатаПоиска = '20190101'; // Или Дата(2019, 1, 1)
// Ищем документ конкретного типа
ДокументСсылка = Документы.КорректировкаЗаписейРегистров.НайтиПоНомеру(НомерДок, ДатаПоиска);
Если ДокументСсылка.Пустая() Тогда
Сообщить("Документ с номером " + НомерДок + " не найден!");
Возврат;
КонецЕсли;
Важный момент: Если метод НайтиПоНомеру возвращает пустую ссылку, все последующие операции с регистром выдадут ошибку «Не установлен отбор по регистратору». Всегда проверяйте результат поиска через Пустая().
После того как ссылка на документ получена, мы переходим к работе с регистром. Для изменения движений конкретного документа используется объект НаборЗаписей. Разберем по шагам, как добавить новую запись в регистр «Продажи по дисконтным картам».
Прочитать().Рассмотрим реализацию в коде:
// 1. Создаем набор записей
НаборЗаписей = РегистрыНакопления.ПродажиПоДисконтнымКартам.СоздатьНаборЗаписей();
// 2. Устанавливаем жесткий отбор по нашему найденному документу
НаборЗаписей.Отбор.Регистратор.Установить(ДокументСсылка);
// 3. Читаем записи, которые уже могут быть в этом документе
НаборЗаписей.Прочитать();
// 4. Добавляем новую строку
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = ТекущаяДата(); // Рекомендуется использовать дату документа: ДокументСсылка.Дата
НоваяЗапись.Регистратор = ДокументСсылка; // Хотя отбор заполнит это поле сам, явное указание помогает избежать ошибок
НоваяЗапись.ДисконтнаяКарта = СсылкаНаКарту;
НоваяЗапись.Сумма = 100000;
// 5. Записываем набор обратно в базу данных
// Параметр Истина означает замещение: старые записи набора удалятся, новые запишутся
НаборЗаписей.Записать(Истина);
Выясним причину, по которой часто возникает эта ошибка. Даже если вы написали НаборЗаписей.Отбор.Регистратор.Установить(Документ), система может выдать отказ при методе Записать(). Это происходит в двух случаях:
Документ попала пустая ссылка. 1С не позволяет записывать движения «в никуда».НоваяЗапись.Регистратор = Документ.Проанализируем ситуацию с технической точки зрения. Документ КорректировкаЗаписейРегистров — это универсальный инструмент. Когда вы программно добавляете в него движения по новому регистру, важно помнить, что в самом документе обычно есть табличная часть (например, ТаблицаРегистров), где хранится список имен регистров, по которым данный документ делает движения.
Если вы добавили запись в регистр программно, но не добавили строку с именем этого регистра в служебную таблицу документа, то при открытии формы документа пользователь может не увидеть вашу корректировку. Чтобы этого избежать, используйте следующий подход:
// Получаем объект документа для редактирования его таблиц
ДокОбъект = ДокументСсылка.ПолучитьОбъект();
// Проверяем, есть ли запись о нашем регистре в списке корректируемых
ИмяРегистра = "ПродажиПоДисконтнымКартам";
СтрокаРегистра = ДокОбъект.ТаблицаРегистров.Найти(ИмяРегистра, "Имя");
Если СтрокаРегистра = Неопределено Тогда
НоваяСтрока = ДокОбъект.ТаблицаРегистров.Добавить();
НоваяСтрока.Имя = ИмяРегистра;
ДокОбъект.Записать();
КонецЕсли;
Для более профессиональной разработки вместо метода НайтиПоНомеру лучше использовать запрос. Это позволит избежать проблем с префиксами и точно идентифицировать документ, даже если их несколько с похожими номерами в разных периодах.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Корректировка.Ссылка КАК Ссылка
|ИЗ
| Документ.КорректировкаЗаписейРегистров КАК Корректировка
|ГДЕ
| Корректировка.Номер = &Номер
| И Корректировка.Дата МЕЖДУ &НачалоПериода И &КонецПериода";
Запрос.УстановитьПараметр("Номер", "Т0000000002");
Запрос.УстановитьПараметр("НачалоПериода", НачалоГода('20190101'));
Запрос.УстановитьПараметр("КонецПериода", КонецГода('20190101'));
РезультатЗапроса = Запрос.Выполнить();
Если НЕ РезультатЗапроса.Пустой() Тогда
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
ВыборкаДетальныеЗаписи.Следующий();
ДокументСсылка = ВыборкаДетальныеЗаписи.Ссылка;
// Далее работаем с набором записей...
КонецЕсли;
Заключение: Программная запись в регистры требует четкого соблюдения последовательности: надежный поиск документа (лучше через запрос), обязательная проверка ссылки на «пустоту», установка отбора в наборе записей и контроль заполнения обязательных полей (Период, Регистратор и аналитика регистра).