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