Программное создание и заполнение документа УстановкаЦенНоменклатуры в современных конфигурациях 1С (таких как «1С:Розница», «1С:Управление торговлей» или «1С:ERP») часто вызывает трудности у начинающих разработчиков. Типичная ситуация: код написан, ТЧ заполнены, но при открытии формы документа на экране отображается пустая таблица. Давайте подробно разберем, почему так происходит, как устроен этот документ изнутри и как правильно написать процедуру его заполнения «на лету» с помощью расширения.
В большинстве документов 1С структура табличной части на форме линейно соответствует структуре табличной части в базе данных. Однако документ УстановкаЦенНоменклатуры устроен гораздо сложнее. На управляемой форме пользователю отображается динамически конструируемое Дерево цен. Колонки видов цен в нем формируются «на лету» на основании данных, хранящихся в табличной части ВидыЦен.
Если вы программно заполните табличную часть Товары, указав в ней номенклатуру и цены, но при этом забудете добавить соответствующий вид цены в табличную часть ВидыЦен, система при открытии формы просто проигнорирует ваши строки. Алгоритмы формы посчитают эти данные некорректными, так как колонка для этого вида цены не должна отображаться на экране, и документ визуально окажется абсолютно пустым.
Рассмотрим код, который часто пытаются использовать разработчики:
Товары.Очистить();
Для Каждого СтрокаТаблицы из ДанныеЗаполнения.Товары Цикл
Строка = Товары.Добавить();
ЗаполнитьЗначенияСвойств(Строка, СтрокаТаблицы);
Строка.ВидЦены = ВидРозн;
Строка.Цена = СтрокаТаблицы.Цена;
Строка.ЦенаИзмененаВручную = Истина;
КонецЦикла;
В этом примере автор совершает три критические ошибки:
ВидыЦен: Платформа не понимает, какие именно колонки видов цен нужно инициализировать в экранном интерфейсе. Строки из ТЧ Товары отсекаются при конвертации данных в форму.Характеристика и Упаковка приведут к тому, что цены установятся на «пустую» аналитику. В дальнейшем продать такой товар на кассе (РМК) по розничной цене будет невозможно.Цена). Старая цена вычисляется динамически при открытии формы путем запроса к регистру сведений ЦеныНоменклатуры на дату документа.Чтобы успешно заполнить документ программно (например, при вводе на основании документа оприходования или поступления товаров), нам необходимо выполнить следующие действия:
ВидыЦен создаваемого документа.Товары и заполнить ее данными из документа-основания.ВидЦены.ЦенаИзмененаВручную = Истина. Это критически важно, чтобы при интерактивных действиях пользователя или проведении документа система не попыталась пересчитать цену по формулам, если для данного вида цен настроен автоматический расчет.Давайте напишем правильный и отказоустойчивый код для обработчика заполнения. Мы будем использовать расширение конфигурации и аннотацию &После("ОбработкаЗаполнения").
&После("ОбработкаЗаполнения")
Процедура Расш1_ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
// Проверяем, что документ заполняется на основании нужного нам объекта
// Например, на основании документа "ОприходованиеТоваров"
Если ДанныеЗаполнения <> Неопределено
И ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ОприходованиеТоваров") Тогда
// Шаг 1. Находим нужный вид цены в справочнике
ВидРозн = Справочники.ВидыЦен.НайтиПоНаименованию("Розничная цена");
Если Не ЗначениеЗаполнено(ВидРозн) Тогда
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
"Не найден вид цены с наименованием 'Розничная цена'. Заполнение прервано."
);
Возврат;
КонецЕсли;
// Шаг 2. Заполняем табличную часть "ВидыЦен"
ВидыЦен.Очистить();
НоваяСтрокаВидаЦен = ВидыЦен.Добавить();
НоваяСтрокаВидаЦен.ВидЦены = ВидРозн;
// Шаг 3. Очищаем и заполняем основную табличную часть "Товары"
Товары.Очистить();
Для Каждого СтрокаОснования Из ДанныеЗаполнения.Товары Цикл
// Проверяем, заполнена ли номенклатура в строке-источнике
Если Не ЗначениеЗаполнено(СтрокаОснования.Номенклатура) Тогда
Продолжить;
КонецЕсли;
НоваяСтрокаТовара = Товары.Добавить();
// Заполняем базовые реквизиты номенклатуры
НоваяСтрокаТовара.Номенклатура = СтрокаОснования.Номенклатура;
// Важно: переносим характеристики и упаковки для сохранения аналитики учета
Если ОбщегоНазначения.ПустаяСсылка(СтрокаОснования.Характеристика) = Ложь Тогда
НоваяСтрокаТовара.Характеристика = СтрокаОснования.Характеристика;
КонецЕсли;
Если ОбщегоНазначения.ПустаяСсылка(СтрокаОснования.Упаковка) = ... Тогда // Если упаковки используются
// НоваяСтрокаТовара.Упаковка = СтрокаОснования.Упаковка;
КонецЕсли;
// Связываем строку товара с добавленным ранее видом цены
НоваяСтрокаТовара.ВидЦены = ВидРозн;
// Устанавливаем цену из документа-основания
НоваяСтрокаТовара.Цена = СтрокаОснования.Цена;
// Взводим флаг ручного изменения цены
НоваяСтрокаТовара.ЦенаИзмененаВручную = Истина;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
В зависимости от того, на какой редакции «1С:Розница» вы работаете, программная логика может незначительно отличаться:
Для конфигурации «1С:Розница 2.3» (и «Управление торговлей 11»): Описанный выше код является классическим и наиболее стабильным. Обратите внимание, что при интерактивном открытии формы система выполнит внутренние процедуры инициализации структуры ДеревоЦен и корректно отобразит заполненные программно данные.
Для новой конфигурации «1С:Розница 3.0» (разработанной на платформе УНФ): Архитектура документов претерпела изменения. Вместо табличной части Товары там используется ТЧ Запасы. Кроме того, в Рознице 3.0 для автоматического подтягивания видов цен из документа-основания у объекта документа существует удобный встроенный метод: ДокументОбъект.ВидыЦенЗаполнятьИзОснования(). Обязательно изучите модуль менеджера этого документа перед написанием собственного кода в новых редакциях программы.
Применяя данные правила и не забывая про обязательную синхронизацию табличных частей ВидыЦен и Товары, вы избавитесь от проблемы «исчезающих» при открытии строк и обеспечите корректную запись цен номенклатуры в регистры сведений системы.