При разработке отчетов в системе «1С:Предприятие» программисты часто сталкиваются со сложной архитектурной задачей: необходимо вывести в одном отчете данные из проводок регистра бухгалтерии (например, суммы и количество) и специфическую аналитику, которая хранится только в табличной части (ТЧ) документа-регистратора (например, сведения о сотрудниках, выполнявших работу). Классический пример из практики — документ «Надой молока» в специализированных сельскохозяйственных конфигурациях, где в табличной части детально расписаны сотрудники (дояры/операторы), но в проводках по бухгалтерскому учету эта аналитика отсутствует за ненадобностью для регламентированной отчетности.
В этой статье мы подробно проанализируем, почему стандартные «простые» варианты связи таблиц часто приводят к критическим ошибкам в данных, выясним причину этих ошибок и разберем по шагам надежные, профессиональные методы решения этой задачи, одобренные стандартами разработки фирмы «1С».
Первое решение, которое часто приходит в голову начинающим разработчикам, — связать таблицу движений регистра бухгалтерии и табличную часть документа по двум полям: Ссылка / Регистратор и НомерСтроки. Рассмотрим подробнее, почему этот подход абсолютно некорректен и неизбежно приведет к искажению отчета в реальной базе данных:
НомерСтроки — это жесткий порядковый индекс строки на форме (1, 2, 3...). В регистре бухгалтерии поле НомерСтроки — это системный номер записи (проводки) в конкретном наборе движений по данному регистратору. Они генерируются независимо друг от друга.Проанализировав эти риски, мы приходим к выводу: прямое связывание по номеру строки использовать нельзя. Выясним, какие альтернативные методы существуют для решения этой задачи.
Если перед вами стоит жесткое ограничение — база данных является типовой, находится на поддержке, а использование расширений или изменение метаданных категорически запрещено, — единственным выходом будет написание сложного, но безопасного запроса в Схеме компоновки данных (СКД).
Этот метод заключается в том, что мы не пытаемся сопоставить строки жестко. Вместо этого мы группируем данные регистра бухгалтерии и табличной части по общим разрезам (например, по Регистратору и Номенклатуре), рассчитываем долю (вес) каждой строки документа и пропорционально распределяем бухгалтерские суммы по сотрудникам.
Разберем этот алгоритм по шагам в терминах языка запросов 1С:
Шаг 1. Получение итогов из регистра бухгалтерии. Сначала мы выбираем реальные суммы и количество, отраженные в учете, сгруппированные по регистратору и номенклатуре.
Шаг 2. Расчет общего количества по этой же номенклатуре в документе. Мы считаем суммарное количество по номенклатуре в табличной части документа, чтобы понять общий объем.
Шаг 3. Вычисление коэффициента (доли) строки. Для каждой строки табличной части мы делим количество строки конкретного сотрудника на общее количество по этой номенклатуре в документе.
Шаг 4. Расчет итоговых показателей. Умножаем реальную сумму и количество из регистра бухгалтерии на полученный коэффициент.
Посмотрим на пример реализации такого запроса:
ВЫБРАТЬ
ТЧ.Ссылка КАК Регистратор,
ТЧ.Номенклатура КАК Номенклатура,
ТЧ.Работник КАК Работник,
ТЧ.Количество КАК КоличествоВДокументе,
СуммыДокумента.ВсегоКоличествоВДокументе КАК ВсегоКоличествоВДокументе
ПОМЕСТИТЬ ВТ_ДанныеДокумента
ИЗ
Документ.НадойМолока.Продукция КАК ТЧ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ (
ВЫБРАТЬ
Ссылка КАК Ссылка,
Номенклатура КАК Номенклатура,
СУММА(Количество) КАК ВсегоКоличествоВДокументе
ИЗ
Документ.НадойМолока.Продукция
ГРУППИРОВАТЬ ПО
Ссылка,
Номенклатура
) КАК СуммыДокумента ПО ТЧ.Ссылка = СуммыДокумента.Ссылка
И ТЧ.Номенклатура = СуммыДокумента.Номенклатура
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Проводки.Регистратор КАК Регистратор,
Проводки.Субконто1 КАК Номенклатура,
СУММА(Проводки.Количество) КАК КоличествоБух,
СУММА(Проводки.Сумма) КАК СуммаБух
ПОМЕСТИТЬ ВТ_ДанныеБухгалтерии
ИЗ
РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто КАК Проводки
ГДЕ
Проводки.Регистратор ССЫЛКА Документ.НадойМолока
ГРУППИРОВАТЬ ПО
Проводки.Регистратор,
Проводки.Субконто1
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_ДанныеДокумента.Регистратор КАК Регистратор,
ВТ_ДанныеДокумента.Номенклатура КАК Номенклатура,
ВТ_ДанныеДокумента.Работник КАК Работник,
// Распределяем количество пропорционально
ВЫБОР
КОГДА ВТ_ДанныеДокумента.ВсегоКоличествоВДокументе = 0 ТОГДА 0
ИНАЧЕ (ВТ_ДанныеДокумента.КоличествоВДокументе / ВТ_ДанныеДокумента.ВсегоКоличествоВДокументе) * ЕСТЬNULL(ВТ_ДанныеБухгалтерии.КоличествоБух, 0)
КОНЕЦ КАК Количество,
// Распределяем сумму пропорционально
ВЫБОР
КОГДА ВТ_ДанныеДокумента.ВсегоКоличествоВДокументе = 0 ТОГДА 0
ИНАЧЕ (ВТ_ДанныеДокумента.КоличествоВДокументе / ВТ_ДанныеДокумента.ВсегоКоличествоВДокументе) * ЕСТЬNULL(ВТ_ДанныеБухгалтерии.СуммаБух, 0)
КОНЕЦ КАК Сумма
ИЗ
ВТ_ДанныеДокумента КАК ВТ_ДанныеДокумента
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ДанныеБухгалтерии КАК ВТ_ДанныеБухгалтерии
ПО ВТ_ДанныеДокумента.Регистратор = ВТ_ДанныеБухгалтерии.Регистратор
И ВТ_ДанныеДокумента.Номенклатура = ВТ_ДанныеБухгалтерии.Номенклатура
Преимущества метода: Полная безопасность для обновлений. База остается абсолютно типовой. Метод корректно обрабатывает ситуации, когда бухгалтер вручную скорректировал общую сумму проводки — измененная сумма все равно распределится по сотрудникам согласно их доле в документе.
Недостатки метода: Запрос получается достаточно ресурсоемким, особенно при больших объемах данных. Кроме того, при очень сложных ручных корректировках (например, если бухгалтер полностью заменил номенклатуру в проводках на другую) распределение может дать сбой из-за отсутствия совпадений по ключевым полям.
Если конфигурация поддерживает механизм расширений (что является стандартом для современных версий платформы «1С:Предприятие 8.3»), мы можем применить архитектурное решение, которое используется самой фирмой «1С» во всех современных типовых конфигурациях (ERP, Комплексная автоматизация, Управление торговлей).
Этот метод основан на генерации уникального идентификатора для каждой строки табличной части и последующей передаче этого идентификатора в проводки регистра.
Рассмотрим по шагам, как реализовать этот механизм:
КлючСвязи с типом Число (длина 10, без знака) или УникальныйИдентификатор.КлючСвязиСтроки в Регистр бухгалтерии «Хозрасчетный».ПриЗаписи или напишем обработчик в модуле объекта:
&Перед("ПередЗаписью")
Процедура Расшир_ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
МаксимальныйКлюч = 0;
// Сначала найдем максимальный существующий ключ, чтобы не дублировать
Для Каждого СтрокаТЧ Из ЭтотОбъект.Продукция Цикл
Если СтрокаТЧ.КлючСвязи > МаксимальныйКлюч Тогда
МаксимальныйКлюч = СтрокаТЧ.КлючСвязи;
КонецЕсли;
КонецЦикла;
// Заполняем пустые ключи новыми уникальными значениями в рамках этого документа
Для Каждого СтрокаТЧ Из ЭтотОбъект.Продукция Цикл
Если СтрокаТЧ.КлючСвязи = 0 Тогда
МаксимальныйКлюч = МаксимальныйКлюч + 1;
СтрокаТЧ.КлючСвязи = МаксимальныйКлюч;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
&После или &Вместо) при формировании набора записей регистра бухгалтерии в каждую проводку записывается соответствующий КлючСвязиСтроки из строки табличной части, на основании которой создана проводка.
ПО ТЧ.Ссылка = Движения.Регистратор
И ТЧ.КлючСвязи = Движения.КлючСвязиСтроки
Преимущества метода: Это наиболее надежный и профессиональный способ связи. Он гарантирует абсолютную точность сопоставления даже при наличии абсолютно одинаковых строк с разной аналитикой. При ручной корректировке движений (если программист позаботился о выводе поля КлючСвязиСтроки на форму ручной корректировки движений) связь также не теряется.
Недостатки метода: Требуется небольшое программирование в расширении и добавление новых реквизитов в структуру данных.
Еще один крайне элегантный методический способ решения проблемы, предложенный опытными методологами, — задействовать возможности самого бухгалтерского учета без внесения изменений в конфигурацию на уровне кода.
Если нам нужно собирать аналитику по сотрудникам, почему бы не отражать ее на забалансовом счете? Рассмотрим, как это сделать:
Номенклатура и Физические лица (или Сотрудники). Также включается ведение количественного и суммового учета.РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт или Обороты по нашему забалансовому счету. Никаких соединений табличной части документов и регистров больше делать не нужно!Преимущества метода: Чистота архитектуры. Данные хранятся в единой базе движений бухгалтерии. Исключены любые расхождения между «документом» и «регистром», поскольку вся информация извлекается из одного источника (оборотов забалансового счета). Бухгалтер может легко проверить правильность отчета стандартными отчетами (Оборотно-сальдовая ведомость по счету).
Подводя итоги нашего анализа, выделим оптимальные сценарии для применения каждого метода: