Как запретить перезапись документов и создавать дубликаты с разными видами цен при конвертации данных в 1С?

Программист 1С v8.3 (Управляемые формы)
← На главную

При работе с инструментом "Конвертация данных" в 1С, будь то редакции 2.x или 3.x, разработчики и программисты часто сталкиваются с задачами, требующими гибкого управления поведением документов при загрузке. Мы рассмотрим две ключевые ситуации: как запретить перезапись документов, которые уже существуют в базе-приемнике, и как создать несколько новых документов в базе-приемнике из одного документа-источника, но с различными реквизитами, например, с разными видами цен.

По умолчанию, при обмене данными между решениями 1С, номера документов в базе-приемнике могут устанавливаться такими же, как и в базе-отправителе. В процессе загрузки объект XDTO обычно ищется в базе-приемнике по ключевым полям. Если объект с такими же ключами найден, он будет обновлен (перезаписан); в противном случае будет создан новый. Наша задача — изменить это стандартное поведение.

Запрет перезаписи документа в базе-приемнике и создание нового

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

  1. Отключение поиска по внутреннему идентификатору (УИД)

    Одним из самых частых механизмов поиска является поиск по внутреннему идентификатору (УИД) объекта. В Правиле Конвертации Объектов (ПКО) присутствует флажок "Искать объект приемника по внутреннему идентификатору объекта источника".

    Как сделать:

    Мы должны снять этот флажок в свойствах нашего ПКО. Если флажок установлен, поиск объекта для модификации в базе-приемнике осуществляется по уникальному идентификатору объекта-источника. Снятие этого флажка приведет к тому, что поиск будет выполняться только по полям поиска, которые мы определим в ПКО. Если по этим полям объект не будет найден, система создаст новый документ.

  2. Формирование уникального номера документа

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

    Как сделать:

    1. Присвоение пустого значения номеру:

      Для того чтобы номер документа в базе-приемнике сгенерировался следующим по списку с внутренним префиксом, необходимо передать в качестве номера пустое значение. Это можно реализовать в обработчике "Перед выгрузкой" свойства "Номер" в ПКО:

      Значение = "";

      В этом случае система-приемник сама присвоит документу новый, следующий по порядку номер.

    2. Генерация нового уникального номера:

      Мы можем программно генерировать новый уникальный номер в обработчике "Перед выгрузкой" свойства "Номер" в ПКО. Это позволяет нам полностью контролировать формат и уникальность номера.

      Например, мы можем использовать встроенные функции для генерации нового номера:

      Значение = СгенеритьНовыйНомер;

      Или создать более сложную комбинацию с использованием текущей даты и времени, чтобы каждый раз получать гарантированно уникальный номер документа:

      
      Значение = "Вася" + Формат(ТекущаяДата() - Дата(1,1,1), "ЧГ=");
      // Или более читаемый вариант:
      // Значение = "Префикс" + Формат(ТекущаяДата(), "ДФ=yyyyMMddHHmmss");
      

      В этих примерах мы используем текущую дату и время, а также произвольный префикс, чтобы сделать номер уникальным. Обратите внимание, что формат "ЧГ=" возвращает число дней от начала века, что обеспечивает уникальность по времени, а более явный формат "ДФ=yyyyMMddHHmmss" создает читаемую строку из даты и времени.

  3. Использование полей поиска

    В ПКО мы можем явно указать поля, по которым будет осуществляться поиск объекта в базе-приемнике. Если по комбинации этих полей объект не найден, будет создан новый.

    Как сделать:

    Перейдите в свойства вашего ПКО и на вкладке "Поля поиска" добавьте те реквизиты документа, по которым система должна искать существующий объект. Например, это могут быть "Номер" и "Дата". Если по такой комбинации объект не найден, будет создан новый. Важно убедиться, что выбранные поля поиска действительно являются уникальными для каждого документа, который мы хотим создать.

Создание нескольких документов с разными реквизитами (например, видами цен) из одного источника

Задача создания нескольких документов в приемнике на основе одного документа-источника, но с разными реквизитами (например, с разными видами цен), является более сложной и требует использования продвинутых механизмов "Конвертации данных".

Рассмотрим ситуацию, когда у нас есть один документ-источник (например, "Акт переоценки"), и на его основе нам нужно создать два отдельных документа в базе-приемнике, каждый из которых будет иметь свой уникальный "Вид цены", но при этом содержать общие данные из исходного документа.

  1. Использование нескольких ПКО (с нюансами)

    Первоначальная идея, которая часто приходит на ум, — это создать два отдельных ПКО для одного и того же типа документа-источника. Каждое ПКО настраивается на свой "Вид цены".

    Почему это не всегда работает:

    Как показывает опыт на форуме, если поиск объекта в приемнике осуществляется только по УИД или по другим неуникальным для разных видов цен полям (например, по номеру и дате, которые одинаковы для исходного документа), это может привести к тому, что второй документ просто перезапишет первый. Для успешной работы этого подхода необходимо, чтобы каждый из двух документов, создаваемых по разным ПКО, имел уникальные ключи поиска в базе-приемнике.

  2. Многократный вызов ВыгрузитьПоПравилу() в ПВД

    Функция ВыгрузитьПоПравилу() является мощным инструментом для гибкой настройки выгрузки данных. Она позволяет программно вызывать правила конвертации объектов (ПКО) из обработчиков Правил Выгрузки Данных (ПВД) или других обработчиков. Это идеально подходит для случая, когда один объект-источник нужно конвертировать в несколько объектов-приемников.

    Как сделать по шагам:

    1. Настройка ПКО для документа-приемника:

      Прежде всего, создадим или используем существующее ПКО для нашего документа (например, "Акт переоценки"). В этом ПКО нам понадобится механизм для установки "Вида цены".

      • Снимите флажок "Искать объект приемника по внутреннему идентификатору объекта источника" в этом ПКО. Это критически важно, чтобы избежать перезаписи.
      • В обработчике "Перед выгрузкой" для свойства "Номер" документа реализуйте генерацию уникального номера, как мы рассматривали ранее. Это гарантирует, что каждый новый создаваемый документ получит уникальный номер. Например, можно использовать:
        
        Значение = "АП-" + Формат(ТекущаяДата(), "ДФ=yyyyMMddHHmmss") + СтрЗаменить(Строка(УникальныйИдентификатор()), "-", "");
        

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

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

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

      Для передачи параметров между ПВД и ПКО используются переменные Параметры, ИсходящиеДанные, ВходящиеДанные и ПараметрыОбъекта. ПараметрыОбъекта особенно полезны для передачи данных в обработчики конечной базы.

      Посмотрим на пример кода для обработчика ПВД:

      
      // Пример в обработчике "После выгрузки" в ПВД для документа-источника
      
      // Создаем параметры для первого документа
      ПараметрыПервогоДокумента = Новый Соответствие;
      ПараметрыПервогоДокумента.Вставить("ВидЦены", "Закупочная"); // Указываем вид цены для первого документа
      ПараметрыПервогоДокумента.Вставить("Источник", Объект); // Передаем ссылку на исходный документ
      
      // Вызываем ПКО для создания первого документа
      ВыгрузитьПоПравилу(Объект, , ИсходящиеДанные, ПараметрыПервогоДокумента, "ПКО_АктПереоценки", УзелСсылки, , , ,);
      
      // Создаем параметры для второго документа
      ПараметрыВторогоДокумента = Новый Соответствие;
      ПараметрыВторогоДокумента.Вставить("ВидЦены", "Розничная"); // Указываем другой вид цены для второго документа
      ПараметрыВторогоДокумента.Вставить("Источник", Объект); // Передаем ссылку на исходный документ
      
      // Вызываем ПКО для создания второго документа
      // Важно: если ПКО само не генерирует новый уникальный номер,
      // или если используются поля поиска, которые будут совпадать,
      // этот вызов может перезаписать предыдущий документ.
      // Убедитесь, что в ПКО настроена генерация уникального номера!
      ВыгрузитьПоПравилу(Объект, , ИсходящиеДанные, ПараметрыВторогоДокумента, "ПКО_АктПереоценки", УзелСсылки, , , ,);
      

      В данном примере "ПКО_АктПереоценки" — это имя вашего Правила Конвертации Объекта для документа "Акт переоценки".

    3. Обработка параметров в ПКО:

      В ПКО для документа "Акт переоценки" (который мы вызываем через ВыгрузитьПоПравилу()), мы должны принять переданный параметр "ВидЦены" и присвоить его соответствующему реквизиту документа.

      Это делается в обработчике "При загрузке" (или "Перед записью") вашего ПКО:

      
      // Пример в обработчике "При загрузке" в ПКО_АктПереоценки
      
      Если ВходящиеДанные.Свойство("ВидЦены") Тогда
          ОбъектПриемник.ВидЦены = ПланыВидовХарактеристик.ВидыЦен.НайтиПоНаименованию(ВходящиеДанные.ВидЦены);
          // Или более надежный поиск по УИД, если виды цен имеют УИД в источнике
          // ОбъектПриемник.ВидЦены = ПланыВидовХарактеристик.ВидыЦен.ПолучитьОбъектПоУИД(ВходящиеДанные.ВидЦеныУИД);
      КонецЕсли;
      

      Здесь мы используем ВходящиеДанные для доступа к параметрам, переданным из ВыгрузитьПоПравилу(). Метод НайтиПоНаименованию() или ПолучитьОбъектПоУИД() используется для поиска нужного элемента справочника "Виды цен" в базе-приемнике.

    Решение ошибки "Преобразование значения к типу Число не может быть выполнено"

    Если при использовании ВыгрузитьПоПравилу() мы сталкиваемся с ошибкой "Преобразование значения к типу Число не может быть выполнено", это, как правило, указывает на некорректную передачу типа данных или использование неверного значения в качестве параметра в каком-либо из обработчиков. Следует внимательно проверить, что передаваемые параметры имеют ожидаемый тип и корректно обрабатываются в соответствующих ПКО или ПКС (Правилах Конвертации Свойств). Часто эта ошибка возникает, когда ожидается число, а передается строка или неопределенное значение, или наоборот.

Дополнительные рекомендации

Таким образом, для успешного предотвращения перезаписи документов и создания дубликатов с различными реквизитами, нам необходимо внимательно управлять механизмами идентификации объектов в базе-приемнике. Комбинирование отключения поиска по УИД, генерации уникальных номеров и использования функции ВыгрузитьПоПравилу() позволяет добиться требуемого поведения при обмене данными.

← На главную