Новый документ в конфигураторе 1С 8.3: от объекта метаданных до проведения по регистрам

· 9 мин

Содержание

Новый тип документа создают в конфигураторе: в дереве метаданных правой кнопкой по ветке Документы → Добавить. Откроется окно редактирования объекта с вкладками — на них задают имя, реквизиты шапки, табличные части, нумерацию, регистры для движений и формы. Логику проведения пишут в модуле объекта, в обработчике ОбработкаПроведения.

Всё описанное относится к платформе 8.3 в целом и не зависит от конкретной конфигурации: так же собирают документ и в своей разработке, и в расширении к Бухгалтерии или Управлению торговлей. Порядок шагов — от объекта метаданных к коду проведения.

Подготовка: где создавать документ и как не сломать обновления

Перед тем как нажать Добавить, решите, куда вы вносите изменение. От этого зависит, как база будет обновляться дальше.

СитуацияГде создаватьПочему
Своя конфигурация с нуляПрямо в основной конфигурацииПоддержки поставщика нет, ограничений тоже
Типовая (БП, ЗУП, УТ) на поддержкеВ расширении конфигурацииОсновная конфигурация остаётся на поддержке, обновления ставятся без сравнения-объединения
Типовая, уже снятая с поддержкиВ основной или в расширенииРасширение всё равно проще переносить между релизами

Расширения появились в платформе 8.3.6. Документ, добавленный в расширение, полноценный: у него свои реквизиты, формы, модули и права. Регистры для его движений тоже можно создать в расширении.

Перед изменением конфигурации рабочей базы сделайте выгрузку в .dt. Для обновления структуры базы при добавлении нового объекта нужен монопольный доступ, если в базе работают пользователи — планируйте это на нерабочее время.

Создание объекта метаданных и его основные свойства

Объект создают в ветке Документы дерева конфигурации. На вкладке Основные заполняют:

  • 🏷️ Имя — идентификатор для кода, без пробелов: ПриходТовара. Его потом пишут в Документы.ПриходТовара.
  • 📝 Синоним — то, что видит пользователь: «Приход товара».
  • 📄 Представление объекта и Представление списка — заголовки формы документа и формы списка. Если не заполнить, платформа возьмёт синоним.

На вкладке Подсистемы отметьте раздел, в котором документ появится в командном интерфейсе. Без этого пользователь не найдёт его в меню, хотя объект существует.

Второй частый пропуск — права. Новый объект не доступен никому, кроме ролей с полными правами. Откройте нужную роль в ветке Общие → Роли и выдайте права на документ: чтение, добавление, изменение, проведение, отмена проведения, интерактивные действия. Если документ в расширении, права выдают через роль расширения.

Нумерация

Свойства номера собраны на вкладке Нумерация:

СвойствоЗначенияЧто даёт
Тип номераСтрока или ЧислоСтроковый номер позволяет префиксы: ПТ00-000123
Длина номеранапример, 11Максимум символов в номере
ПериодичностьНепрерывно, В пределах года, квартала, месяца, дняКогда нумерация начинается заново
АвтонумерацияфлажокНомер присваивается при первой записи
Контроль уникальностифлажокПлатформа не даст записать два документа с одинаковым номером в периоде

Если несколько видов документов должны идти в одной сквозной нумерации, создайте в ветке Документы → Нумераторы общий нумератор и укажите его в свойстве Нумератор каждого документа.

Префикс номера задают в модуле объекта:

Процедура ПриУстановкеНовогоНомера(СтандартнаяОбработка, Префикс)
	Префикс = "ПТ-";
КонецПроцедуры

Шапка и табличные части: какие данные хранит документ

У каждого документа уже есть стандартные реквизиты: Ссылка, Номер, Дата, Проведен, ПометкаУдаления. Создавать их не нужно. Свои данные добавляют на вкладке Данные.

Реквизиты шапки — значения, одинаковые для всего документа: склад, контрагент, организация, комментарий. Для каждого задают тип: ссылку на справочник, строку, число, дату.

Табличные части — строки однотипных данных: товары, услуги, сотрудники. У табличной части свои реквизиты: номенклатура, количество, цена, сумма. Номер строки НомерСтроки платформа ведёт сама.

Практичные настройки реквизитов:

  • ✅ Проверка заполнения = Выдавать ошибку — платформа не даст провести документ с пустым полем. Код писать не надо.
  • 🔢 Длина и точность числа: для количества хватит 15.3, для суммы — 15.2.
  • 🧷 Связи параметров выбора — например, договор выбирается только по указанному контрагенту.
  • 🔍 Индексировать — ставьте на реквизиты, по которым часто отбирают список.

💡 Не плодите реквизиты «на всякий случай». Каждый реквизит табличной части — это колонка в таблице базы данных, и лишние колонки замедляют запись больших документов.

Формы документа: интерфейс для пользователя

Формы создаются на вкладке Формы кнопкой с лупой — открывается конструктор формы. Обычно нужны три:

  1. Форма документа — для ввода и редактирования. Её основной реквизит Объект имеет тип ДокументОбъект.ПриходТовара.
  2. Форма списка — журнал документов этого вида с отбором и поиском.
  3. Форма выбора — когда документ выбирают в поле другого объекта.

Если форму не создать, платформа сгенерирует её автоматически. Для черновика это удобно, для работы пользователей — нет: в автоформе все реквизиты идут подряд без группировки.

В редакторе формы элементы перетаскивают из вкладки Реквизиты в дерево Элементы. Удобная раскладка для документа:

  • шапка разбита на две колонки через группы с горизонтальной группировкой;
  • табличная часть — на отдельной странице или занимает основную область;
  • итоги (сумма, количество строк) — в подвале под таблицей;
  • комментарий — внизу формы.

Не размещайте реквизиты, которые пользователь не должен менять, как обычные поля ввода. Для таких полей ставьте свойство ТолькоПросмотр или выводите их надписью.

Модуль формы: расчёты на клиенте и вызовы сервера

Модуль формы открывается на вкладке Модуль редактора формы. Код в нём делится директивами компиляции:

ДирективаГде выполняетсяДоступ к данным формы
&НаКлиентеНа компьютере пользователяДа, но без запросов к базе
&НаСервереНа сервереДа, данные формы передаются на сервер
&НаСервереБезКонтекстаНа сервереНет, только параметры процедуры — самый лёгкий вызов

Пересчёт суммы строки при изменении количества — типичный клиентский обработчик. Его создают в свойствах колонки табличной части, событие ПриИзменении:

&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
	ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
	ТекущиеДанные.Сумма = ТекущиеДанные.Количество * ТекущиеДанные.Цена;
КонецПроцедуры

Подстановку цены из базы выносят на сервер без контекста — так на сервер не уходит вся форма:

&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
	ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
	ТекущиеДанные.Цена = ЦенаНоменклатуры(ТекущиеДанные.Номенклатура);
	ТекущиеДанные.Сумма = ТекущиеДанные.Количество * ТекущиеДанные.Цена;
КонецПроцедуры

&НаСервереБезКонтекста
Функция ЦенаНоменклатуры(Номенклатура)
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Цены.Цена КАК Цена
	|ИЗ
	|	РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, Номенклатура = &Номенклатура) КАК Цены";
	Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
	Выборка = Запрос.Выполнить().Выбрать();
	Возврат ?(Выборка.Следующий(), Выборка.Цена, 0);
КонецФункции

Значения по умолчанию для нового документа задают на сервере в ПриСозданииНаСервере. Проверяйте, что это новый объект, иначе обработчик перезапишет данные при каждом открытии:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	Если Объект.Ссылка.Пустая() Тогда
		Объект.Комментарий = "Создан " + Формат(ТекущаяДатаСеанса(), "ДЛФ=D");
	КонецЕсли;
КонецПроцедуры

Модуль объекта: проведение и движения по регистрам

Чтобы документ мог проводиться, на вкладке Движения должны стоять:

  • Проведение — Разрешить;
  • в списке регистров — флажки на регистрах, по которым документ делает движения;
  • Удаление движений — обычно Удалять автоматически, чтобы при перепроведении старые записи стирались.

Кнопка Конструктор движений на той же вкладке генерирует заготовку обработчика ОбработкаПроведения: вы сопоставляете поля регистра с реквизитами документа, и код появляется в модуле объекта. Для простых документов этого хватает, для сложных — служит отправной точкой.

Минимальное проведение по регистру накопления остатков выглядит так:

Процедура ОбработкаПроведения(Отказ, РежимПроведения)
	Движения.ОстаткиТоваров.Записывать = Истина;
	Для Каждого СтрокаТовара Из Товары Цикл
		Движение = Движения.ОстаткиТоваров.Добавить();
		Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
		Движение.Период = Дата;
		Движение.Склад = Склад;
		Движение.Номенклатура = СтрокаТовара.Номенклатура;
		Движение.Количество = СтрокаТовара.Количество;
	КонецЦикла;
КонецПроцедуры

Флаг Записывать = Истина говорит платформе записать набор движений после завершения обработчика. Без него движения не сохранятся.

Другие обработчики модуля объекта, которые нужны почти каждому документу:

  • 🧩 ОбработкаПроверкиЗаполнения — сложные проверки, которые не задать флажком реквизита. Например, «количество в строке больше нуля». При ошибке ставят Отказ = Истина и выводят сообщение.
  • ✏️ ПередЗаписью — пересчёт итоговых реквизитов шапки перед записью. Параметр РежимЗаписи подсказывает, записывают документ, проводят или отменяют проведение.
  • 📥 ОбработкаЗаполнения — заполнение при вводе на основании. Сами основания отмечают на вкладке Ввод на основании.

Модуль объекта выполняется на сервере. Обращаться к элементам формы из него нельзя, только к реквизитам самого документа.

Оперативное проведение и управляемые блокировки

Свойство Оперативное проведение на вкладке Движения нужно, когда документ списывает остатки и важно не уйти в минус.

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

Чтобы два пользователя одновременно не списали один и тот же остаток, перед чтением остатков ставят управляемую блокировку. В свойствах корня конфигурации режим управления блокировкой данных должен быть Управляемый:

Процедура ОбработкаПроведения(Отказ, РежимПроведения)

	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиТоваров");
	ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
	ЭлементБлокировки.УстановитьЗначение("Склад", Склад);
	ЭлементБлокировки.ИсточникДанных = Товары;
	ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
	Блокировка.Заблокировать();

	Движения.ОстаткиТоваров.Записывать = Истина;
	Для Каждого СтрокаТовара Из Товары Цикл
		Движение = Движения.ОстаткиТоваров.Добавить();
		Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
		Движение.Период = Дата;
		Движение.Склад = Склад;
		Движение.Номенклатура = СтрокаТовара.Номенклатура;
		Движение.Количество = СтрокаТовара.Количество;
	КонецЦикла;
	Движения.Записать();

	Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
		ПроверитьОтрицательныеОстатки(Отказ);
	КонецЕсли;

КонецПроцедуры

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

Процедура ПроверитьОтрицательныеОстатки — ваша: запросом к таблице остатков регистра по номенклатуре документа ищите строки с количеством меньше нуля и при находке ставьте Отказ = Истина. Порядок «записать движения, затем проверить остатки» удобнее старого «прочитать остатки, сравнить, записать»: проверка видит итог с учётом самого документа.

Создание и проведение документа из кода

Программно документ создают через менеджер. Код выполняется на сервере — в обработке, регламентном задании или общем модуле:

Документ = Документы.ПриходТовара.СоздатьДокумент();
Документ.Дата = ТекущаяДатаСеанса();
Документ.Склад = Склад;

СтрокаТовара = Документ.Товары.Добавить();
СтрокаТовара.Номенклатура = Номенклатура;
СтрокаТовара.Количество = 10;
СтрокаТовара.Цена = 150;
СтрокаТовара.Сумма = 1500;

Попытка
	Документ.Записать(РежимЗаписиДокумента.Проведение);
Исключение
	Сообщить("Документ не проведён: " + ОписаниеОшибки());
КонецПопытки;

Для существующего документа объект получают из ссылки: ДокументОбъект = Ссылка.ПолучитьОбъект(). Отмена проведения — Записать(РежимЗаписиДокумента.ОтменаПроведения).

💡 При массовом создании документов из обработки проводите каждый документ в своей попытке, как в примере. Тогда один документ с ошибкой не остановит всю загрузку, а в сообщениях останется список проблемных строк — их удобно разобрать и провести повторно.

Чтобы документ создавался кнопкой из формы другого объекта, не пишите свою команду: отметьте основание на вкладке Ввод на основании, заполните реквизиты в ОбработкаЗаполнения, и платформа сама добавит команду «Создать на основании».

Частые вопросы

Можно ли переименовать документ, когда в базе уже есть данные?
Да. Переименование объекта метаданных данных не удаляет, но код, запросы и макеты, где упоминается старое имя, придётся поправить. Поиск по конфигурации (Ctrl+Shift+F) покажет все вхождения.
Почему новый документ не виден пользователю, хотя конфигурация обновлена?
Обычно забыты две вещи: документ не включён в подсистему или у роли пользователя нет прав на него. Проверьте вкладку «Подсистемы» объекта и права в роли.
Чем документ отличается от справочника, если оба хранят данные?
У документа есть дата, номер и проведение — он фиксирует событие во времени и меняет регистры. Справочник хранит условно-постоянную информацию: товары, контрагентов, склады.
Нужно ли пересоздавать форму после добавления реквизита?
Нет. Откройте форму и перетащите новый реквизит из вкладки «Реквизиты» в дерево элементов. Пересоздание через конструктор сотрёт ваши правки формы.
Почему движения документа задваиваются при перепроведении?
Чаще всего в свойстве «Удаление движений» стоит «Не удалять», а код не очищает наборы записей. Переключите свойство на автоматическое удаление.