Создание удобных помощников для быстрого старта — отличная задача для начинающего разработчика 1С. Представим классическую ситуацию: перед нами чистая, только что созданная база конфигурации «1С:Розница», в которой еще не заполнены основные классификаторы. Нам необходимо разработать внешнюю обработку, которая позволит пользователю на одной удобной форме ввести все ключевые реквизиты организации и сохранить их в базу данных одним кликом.
В процессе реализации этой задачи разработчики часто сталкиваются с фундаментальными особенностями объектной модели платформы «1С:Предприятие 8». В этой статье мы подробно разберем, как правильно спроектировать такую обработку, научимся управлять видимостью полей для Юридического лица и ИП, а также разберем критически важные ошибки работы с объектами и ссылками базы данных.
Начинающие программисты в 1С часто совершают одну и ту же ошибку при попытке программного изменения данных. Давайте проанализируем типичный сценарий, который приводит к ошибке «Поле объекта недоступно для записи»:
&НаСервере
Процедура ЗаписатьНаСервере()
ТекущаяОрганизация = Справочники.Организации.НайтиПоНаименованию("ИП Иванов И. И.");
ТекущаяОрганизация.ИНН = РеквизитИНН; // Ошибка здесь!
ОрганизацияОбъект = ТекущаяОрганизация.ПолучитьОбъект();
ОрганизацияОбъект.Записать();
КонецПроцедуры
Выясним причину этой ошибки. Переменная ТекущаяОрганизация содержит тип данных СправочникСсылка.Организации. Ссылка в 1С — это лишь постоянный уникальный идентификатор записи в базе данных. Она предназначена исключительно для чтения и отображения данных на форме, изменять ее свойства напрямую нельзя.
Для того чтобы изменить данные, нам необходимо получить объект в оперативную память. Объект имеет тип СправочникОбъект.Организации. Только у объекта свойства и реквизиты открыты для записи.
Рассмотрим правильный алгоритм работы с базой данных на сервере:
ПолучитьОбъект() у найденной ссылки, чтобы перенести данные в оперативную память для редактирования.Записать() для сохранения изменений в базу данных.Ниже приведем корректный пример кода для записи реквизита:
&НаСервере
Процедура ЗаписатьНаСервере()
СсылкаНаОрганизацию = Справочники.Организации.НайтиПоНаименованию("ИП Иванов И. И.");
Если Не СсылкаНаОрганизацию.Пустая() Тогда
ОрганизацияОбъект = СсылкаНаОрганизацию.ПолучитьОбъект();
ОрганизацияОбъект.ИНН = РеквизитИНН; // РеквизитИНН — это реквизит нашей формы обработки
ОрганизацияОбъект.Записать();
КонецЕсли;
КонецПроцедуры
В условиях задачи автора было указано: «Допустим, имеется чистая с нуля база розница, в которой не заполнено вообще ничего». Если база абсолютно пустая, то поиск по наименованию НайтиПоНаименованию() вернет пустую ссылку. Попытка вызвать метод ПолучитьОбъект() у пустой ссылки неизбежно приведет к аварийному завершению программы с ошибкой «Метод объекта не обнаружен».
Проанализируем, как сделать код отказоустойчивым. Нам нужно проверять наличие организаций в базе данных. Если организаций нет, программа должна автоматически создать новый элемент справочника Организации.
Рассмотрим пример реализации такого алгоритма в процедуре чтения данных при открытии формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Попробуем получить первую попавшуюся организацию в базе данных
Выборка = Справочники.Организации.Выбрать();
Если Выборка.Следующий() Тогда
// Организация найдена, считываем её данные на форму
ТекущаяОрганизация = Выборка.Ссылка;
РеквизитИНН = ТекущаяОрганизация.ИНН;
РеквизитНаименование = ТекущаяОрганизация.Наименование;
ЮрФизЛицо = ТекущаяОрганизация.ЮрФизЛицо;
Иначе
// База пустая. Зададим значения по умолчанию для новой организации
ЮрФизЛицо = Перечисления.ЮрФизЛицо.ЮрЛицо;
РеквизитНаименование = "Наша Новая Организация";
КонецЕсли;
КонецПроцедуры
Теперь реализуем универсальную процедуру записи, которая будет либо обновлять существующую организацию, либо создавать новую в случае её отсутствия:
&НаСервере
Процедура ЗаписатьНаСервере()
Выборка = Справочники.Организации.Выбрать();
Если Выборка.Следующий() Тогда
// Редактируем существующую организацию
ОрганизацияОбъект = Выборка.Ссылка.ПолучитьОбъект();
Иначе
// Создаем новую организацию с нуля
ОрганизацияОбъект = Справочники.Организации.СоздатьЭлемент();
КонецЕсли;
// Заполняем реквизиты значениями из формы обработки
ОрганизацияОбъект.Наименование = РеквизитНаименование;
ОрганизацияОбъект.ИНН = РеквизитИНН;
ОрганизацияОбъект.ЮрФизЛицо = ЮрФизЛицо;
Попытка
ОрганизацияОбъект.Записать();
ЗначениеВРеквизитФормы(ОрганизацияОбъект, "Объект");
Исключение
ВызватьИсключение "Не удалось записать сведения об организации: " + ОписаниеОшибки();
КонецПопытки;
КонецПроцедуры
Для создания качественного пользовательского интерфейса (UX) нам необходимо динамически изменять состав полей ввода на форме обработки в зависимости от того, какой тип организации выбран пользователем: Юридическое лицо или Индивидуальный предприниматель.
У Индивидуального предпринимателя обязательно должно присутствовать поле для ввода ФИО физического лица, а ИНН состоит из 12 цифр. У Юридического лица ФИО отсутствует (вместо него заполняется наименование организации), ИНН содержит 10 цифр, а также добавляется поле КПП.
Разберем по шагам, как настроить динамическую видимость элементов формы:
ЮрФизЛицо с типом данных ПеречислениеСсылка.ЮрФизЛицо. Вынесем его на форму в виде переключателя (радиокнопки).ФИОФизическогоЛица), в группу формы ГруппаДеталиИП.КПП) в группу формы ГруппаДеталиЮрЛица.ПриИзменении, в котором будем управлять видимостью этих групп на клиенте без обращения к серверу.Посмотрим на пример реализации клиентского метода управления видимостью элементов:
&НаКлиенте
Процедура ЮрФизЛицоПриИзменении(Элемент)
УстановитьВидимостьПолей();
КонецПроцедуры
&НаКлиенте
Процедура УстановитьВидимостьПолей()
// Определяем текущий выбор пользователя
ЭтоИП = (ЮрФизЛицо = ПредопределенноеЗначение("Перечисление.ЮрФизЛицо.ИндивидуальныйПредприниматель"));
// Управляем видимостью групп элементов на форме
Элементы.ГруппаДеталиИП.Видимость = ЭтоИП;
Элементы.ГруппаДеталиЮрЛица.Видимость = Не ЭтоИП;
// Меняем маску ввода ИНН в зависимости от типа контрагента
Если ЭтоИП Тогда
Элементы.РеквизитИНН.ПодсказкаВвода = "12 цифр";
Иначе
Элементы.РеквизитИНН.ПодсказкаВвода = "10 цифр";
КонецЕсли;
КонецПроцедуры
Не забудем вызвать метод УстановитьВидимостьПолей() в конце процедуры открытия формы ПриОткрытии() на клиенте, чтобы форма изначально открылась в правильном и аккуратном виде.
При дальнейшей доработке нашей учебной обработки важно помнить, что в реальных конфигурациях семейства 1С некоторые реквизиты организации хранятся не внутри справочника Организации:
Для создания полноценных промышленных решений мы рекомендуем изучить внутренний код стандартного «Помощника быстрого старта», который уже встроен в типовую конфигурацию «1С:Розница». Вы найдете его в конфигураторе, изучив структуру общих форм и обработок начального заполнения.