В процессе автоматизации учета в 1С:Бухгалтерия 3.0 часто возникает задача автоматического формирования цепочки документов. Например, при проведении документа ОтчетОКомиссионерах необходимо сразу создать ПриходныйКассовыйОрдер (ПКО). Однако на практике не для всех контрагентов это действие должно выполняться автоматически. Разберем по шагам, как реализовать этот механизм, начиная от простых условий и заканчивая профессиональным использованием механизмов Библиотеки стандартных подсистем (БСП).
Рассмотрим исходную ситуацию. Для программного создания документа используется метод СоздатьДокумент(), а для заполнения данными на основании другого объекта — метод ОбработкаЗаполнения(). Базовый код, который размещается в модуле формы или модуля объекта, выглядит следующим образом:
Док = Документы.ПриходныйКассовыйОрдер.СоздатьДокумент();
// Заполняем ПКО данными из текущего объекта (Отчет о комиссионерах)
Док.ОбработкаЗаполнения(Объект.Ссылка, Истина);
Док.Дата = ТекущаяДата();
// Проводим новый документ
Док.Записать(РежимЗаписиДокумента.Проведение);
Этот код работает корректно, но он создает ПКО для всех контрагентов без разбора. Наша задача — добавить условие-фильтр.
Если список исключений мал и стабилен (например, всего один контрагент "СтройКапитал"), можно использовать проверку по имени или ссылке. Проанализируем вариант с проверкой вхождения строки в наименование, чтобы избежать проблем с лишними пробелами или регистром символов.
// Приводим наименование к верхнему регистру для точного сравнения
НаименованиеКонтрагента = ВРег(Объект.Контрагент.Наименование);
ИсключениеНаименование = ВРег("СтройКапитал");
Если СтрНайти(НаименованиеКонтрагента, ИсключениеНаименование) = 0 Тогда
// Если "СтройКапитал" не найден в наименовании, создаем документ
НовыйПКО = Документы.ПриходныйКассовыйОрдер.СоздатьДокумент();
НовыйПКО.ОбработкаЗаполнения(Объект.Ссылка, Истина);
НовыйПКО.Дата = ТекущаяДата();
НовыйПКО.Записать(РежимЗаписиДокумента.Проведение);
КонецЕсли;
Важный нюанс: поиск по строке (наименованию) считается "плохим тоном" в разработке 1С. Если пользователь переименует контрагента в справочнике, код перестанет работать. Более надежный программный способ — поиск по ссылке через НайтиПоНаименованию в начале процедуры, но он также требует наличия жестко заданных строк в коде.
Чтобы сделать систему гибкой и позволить пользователю (бухгалтеру) самостоятельно определять, для каких контрагентов не нужно создавать ПКО, воспользуемся механизмом Дополнительных реквизитов. В 1С:Бухгалтерия это стандартный функционал.
Разберем алгоритм настройки:
Контрагенты новый реквизит с типом Булево, назовем его, например, "Не создавать ПКО автоматически".Теперь проанализируем, как проверить это значение в программном коде. В современных конфигурациях данные дополнительных реквизитов хранятся в табличной части ДополнительныеРеквизиты объекта.
// 1. Находим само свойство (реквизит) в плане видов характеристик
СвойствоИсключения = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Не создавать ПКО автоматически");
Если НЕ СвойствоИсключения.Пустая() Тогда
// 2. Ищем строку с этим свойством у текущего контрагента
СтруктураПоиска = Новый Структура("Свойство", СвойствоИсключения);
НайденныеСтроки = Объект.Контрагент.ДополнительныеРеквизиты.НайтиСтроки(СтруктураПоиска);
НужноСоздавать = Истина;
Если НайденныеСтроки.Количество() > 0 Тогда
// Если флаг установлен в Истина, значит создавать НЕ нужно
Если НайденныеСтроки[0].Значение = Истина Тогда
НужноСоздавать = Ложь;
КонецЕсли;
КонецЕсли;
Если НужноСоздавать Тогда
// Код создания ПКО
ДокПКО = Документы.ПриходныйКассовыйОрдер.СоздатьДокумент();
ДокПКО.ОбработкаЗаполнения(Объект.Ссылка, Истина);
ДокПКО.Записать(РежимЗаписиДокумента.Проведение);
КонецЕсли;
КонецЕсли;
Если конфигурация использует актуальную версию БСП, мы можем значительно сократить код и сделать его более производительным. Вместо ручного перебора табличной части воспользуемся программным интерфейсом модуля УправлениеСвойствами.
// Получаем значение свойства одной командой
ЗначениеСвойства = УправлениеСвойствами.ЗначениеСвойства(Объект.Контрагент, "НеСоздаватьПКОАвтоматически");
// Если реквизит не найден или не установлен, ЗначениеСвойства будет Ложь
Если НЕ ЗначениеСвойства Тогда
// Выполняем создание ПКО
// ...
КонецЕсли;
Примечание: Имя "НеСоздаватьПКОАвтоматически" должно соответствовать внутреннему идентификатору (имени) дополнительного реквизита, если он задан в метаданных или через программный поиск по уникальному коду.
Проанализируем ситуацию глубже. Создание документа в процедуре ПослеЗаписиНаСервере формы — это лишь вершина айсберга. Рассмотрим две критические проблемы:
Отчете о комиссионерах ваш код будет создавать новый ПКО. Это приведет к замусориванию базы. Перед созданием необходимо проверить, не создан ли ПКО ранее.Рассмотрим правильный подход к проверке дублей с помощью запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ПриходныйКассовыйОрдер.Ссылка КАК Ссылка
|ИЗ
| Документ.ПриходныйКассовыйОрдер КАК ПриходныйКассовыйОрдер
|ГДЕ
| ПриходныйКассовыйОрдер.ДокументОснование = &Основание
| И НЕ ПриходныйКассовыйОрдер.ПометкаУдаления";
Запрос.УстановитьПараметр("Основание", Объект.Ссылка);
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
// Только если ПКО еще не существует, создаем его
// [Ваш код создания документа]
КонецЕсли;
Для начинающего программиста путь развития в данной задаче выглядит так:
1. На этапе обучения допустимо использовать простое условие Если Объект.Контрагент.Наименование <> "СтройКапитал" Тогда....
2. Для рабочей базы правильнее использовать дополнительные реквизиты. Это избавит вас от необходимости менять программный код каждый раз, когда список "исключений" пополнится новым контрагентом.
3. Для качественной архитектуры выносите логику создания связанных документов в Подписку на событие ОбработкаПроведения. Это обеспечит целостность данных вне зависимости от того, как именно проводится документ — вручную через форму или программно.
Используя предложенные методы, вы создадите надежный механизм автоматизации, который будет легко поддерживать и развивать в будущем.