Урок 7. Справочники и документы из кода
Всё, что пользователь делает в формах — создаёт товары, заполняет и проводит документы, — можно сделать и кодом: загрузить прайс из файла, создать документы по расписанию, исправить тысячу записей разом. В этом уроке — главные приёмы на учебной конфигурации «Склад» из урока Конфигуратор: объекты конфигурации.
Весь код работы с данными выполняется на сервере. В обработке «Практика» из прошлых уроков пишите его в процедуре с директивой &НаСервереБезКонтекста и вызывайте её из обработчика кнопки, как в уроке Процедуры, функции и модули.
Менеджеры, ссылки и объекты
Доступ к данным начинается с менеджера: Справочники.Товары, Документы.ПриходТовара. Через менеджер создают новые объекты, ищут существующие и перебирают все.
Важно различать два вида значений:
- Ссылка (
СправочникСсылка.Товары) — указатель на запись в базе. Она лёгкая, её хранят в реквизитах, передают в процедуры, по ней можно прочитать реквизиты:Ссылка.Цена. Менять через неё ничего нельзя. - Объект (
СправочникОбъект.Товары) — запись, открытая для изменения. Его меняют и записывают методомЗаписать().
Создать элемент справочника
&НаСервереБезКонтекста
Процедура СоздатьТовар()
НовыйТовар = Справочники.Товары.СоздатьЭлемент();
НовыйТовар.Наименование = "Карандаш";
НовыйТовар.Цена = 1.5;
НовыйТовар.Записать();
Сообщить("Создан товар с кодом " + НовыйТовар.Код);
КонецПроцедурыСоздатьЭлемент() создаёт объект только в памяти — в базе он появится после Записать(). Код программа присвоит сама при записи.
Найти и изменить
&НаСервереБезКонтекста
Процедура ИзменитьЦену()
Ссылка = Справочники.Товары.НайтиПоНаименованию("Карандаш", Истина);
Если Ссылка.Пустая() Тогда
Сообщить("Товар не найден");
Возврат;
КонецЕсли;
ТоварОбъект = Ссылка.ПолучитьОбъект();
ТоварОбъект.Цена = 2;
ТоварОбъект.Записать();
Сообщить("Новая цена: " + Ссылка.Цена);
КонецПроцедурыНайтиПоНаименованиювозвращает ссылку или, если ничего не найдено, пустую ссылку — её проверяют методомПустая(). Второй параметрИстина— искать точное совпадение; без него найдётся и «Карандаш простой».НайтиПоКоду("000000001")ищет по коду.ПолучитьОбъект()открывает запись для изменения.
Поиск по наименованию находит первый подходящий элемент. Если названия повторяются, ищите по коду или по реквизиту запросом — об этом урок Запросы.
Перебрать все элементы
&НаСервереБезКонтекста
Процедура ВсеТовары()
Выборка = Справочники.Товары.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Наименование + " — " + Выборка.Цена);
КонецЦикла;
КонецПроцедурыВыбрать() возвращает выборку: она читает записи по одной, метод Следующий() переходит к следующей и возвращает Ложь, когда записи кончились. Отбирать и сортировать удобнее запросом — он в следующем уроке.
Пометка на удаление
ТоварОбъект = Ссылка.ПолучитьОбъект();
ТоварОбъект.УстановитьПометкуУдаления(Истина);Это то же, что Delete в списке: элемент помечается, а окончательно его удалит администратор вместе с другими помеченными. Метод Удалить() у объекта стирает запись сразу, без проверки ссылок на неё.
Удалить() не проверяет, используется ли элемент в документах. Документы останутся со ссылкой на несуществующий товар — в отчётах и формах появятся битые ссылки «<Объект не найден>». В рабочих базах используйте пометку на удаление.
Создать и провести документ
&НаСервереБезКонтекста
Процедура СоздатьПриход()
Склад = Справочники.Склады.НайтиПоНаименованию("Основной", Истина);
Товар = Справочники.Товары.НайтиПоНаименованию("Карандаш", Истина);
Если Склад.Пустая() ИЛИ Товар.Пустая() Тогда
Сообщить("Нет склада «Основной» или товара «Карандаш»");
Возврат;
КонецЕсли;
НовыйДокумент = Документы.ПриходТовара.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Склад = Склад;
Строка1 = НовыйДокумент.Товары.Добавить();
Строка1.Товар = Товар;
Строка1.Количество = 100;
НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
Сообщить("Проведён документ № " + НовыйДокумент.Номер);
КонецПроцедурыНовыйДокумент.Товары.Добавить()добавляет строку в табличную часть и возвращает её — дальше заполняются колонки.Записать(РежимЗаписиДокумента.Проведение)записывает и проводит. ПростоЗаписать()только записывает,РежимЗаписиДокумента.ОтменаПроведения— отменяет проведение.- Если проведение не удалось (например, обработка проведения установила отказ), возникнет ошибка — её можно перехватить блоком
Попытка.
Проведение документа
Что делает документ при проведении, описывает процедура ОбработкаПроведения в модуле объекта документа (в дереве конфигурации щёлкните документ правой кнопкой мыши → «Открыть модуль объекта»). Конструктор движений из урока 4 написал примерно такой код:
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиТоваров.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Товар = ТекСтрокаТовары.Товар;
Движение.Склад = Склад;
Движение.Количество = ТекСтрокаТовары.Количество;
КонецЦикла;
КонецПроцедурыРазберите по строкам:
- в модуле объекта реквизиты документа доступны прямо по имени:
Товары,Дата,Склад; Движения.ОстаткиТоваров— набор записей регистра этого документа;Записывать = Истина— записать его вместе с проведением;- для каждой строки табличной части добавляется движение вида
Приход— регистр прибавит количество к остатку; - для документа расхода было бы
ВидДвиженияНакопления.Расход.
При повторном проведении платформа сама заменяет старые движения документа новыми, а при отмене проведения — удаляет их. Если нужно запретить проведение (например, товара не хватает), в обработке проведения пишут Отказ = Истина; и сообщают пользователю причину.
Частые ошибки
- «Поле объекта не обнаружено» — опечатка в имени реквизита или обращение к реквизиту ссылки на клиенте. Разбор — в справке Ошибка «Поле объекта не обнаружено».
- Метод не найден на клиенте —
Справочники,Документы,Записать()вызываются только в серверном коде. - Изменения не сохранились — объект изменён, но не вызван
Записать(). - Ссылку пытаются изменить —
Ссылка.Цена = 2не работает: сначалаПолучитьОбъект().
Коротко
- Менеджер (
Справочники.Товары) создаёт, ищет и перебирает; ссылка — указатель, объект — запись для изменения. СоздатьЭлемент()/СоздатьДокумент()→ заполнить →Записать().НайтиПоНаименованию(…, Истина)иНайтиПоКоду()возвращают ссылку или пустую ссылку — проверкаПустая().- Документ проводится
Записать(РежимЗаписиДокумента.Проведение); движения пишетОбработкаПроведения. - Вместо
Удалить()в рабочих базах —УстановитьПометкуУдаления(Истина).