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