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