При разработке обработок загрузки цен из внешних источников (например, Excel) начинающие разработчики часто сталкиваются с проблемой: при попытке прямой записи в регистр сведений ЦеныНоменклатуры данные не отображаются в документе-регистраторе, а при перепроведении документа и вовсе исчезают. Разберем, почему так происходит, и как правильно реализовать программное заполнение цен в конфигурации «Управление торговлей 10.3» на обычных формах.
Рассмотрим типичную ошибку. Разработчик пытается создать набор записей регистра, установить отбор по регистратору и добавить туда строки. В 1С регистр ЦеныНоменклатуры является подчиненным регистратору. Это означает, что записи в нем полностью управляются документом (в данном случае — УстановкаЦенНоменклатуры).
Когда вы записываете данные напрямую в регистр, вы обходите логику документа. В самом документе данные хранятся в его табличных частях (например, в ТЧ Товары). Если вы не заполнили табличную часть документа, то при его открытии вы увидите пустую форму. Более того, при любом перепроведении документа система очистит старые движения в регистре и сформирует новые на основании данных из своих табличных частей. Поскольку ТЧ документа была пуста, все ваши записи, внесенные напрямую в регистр, будут удалены. Выясним, как сделать это правильно.
Основной принцип работы в типовых конфигурациях (таких как УТ 10.3): заполняем документ — проводим документ — документ сам делает записи в регистр. Проанализируем пошагово процесс программного создания или редактирования документа установки цен.
Для начала нам необходимо либо создать новый документ, либо получить объект существующего. Если у вас уже есть ссылка на документ в форме обработки, используем метод ПолучитьОбъект(). Разберем пример кода для заполнения документа:
// 1. Получаем объект документа (нового или существующего)
ОбъектДок = СсылкаНаДокумент.ПолучитьОбъект();
// 2. Очищаем старые строки, если нужно полностью перезаписать цены
ОбъектДок.Товары.Очистить();
ОбъектДок.ТипыЦен.Очистить();
// 3. Обязательно заполняем табличную часть "ТипыЦен"
// Без этого документ не поймет, по каким типам цен (Розничная, Оптовая и т.д.) идет установка
СтрокаТипаЦен = ОбъектДок.ТипыЦен.Добавить();
СтрокаТипаЦен.ТипЦен = Справочники.ТипыЦенНоменклатуры.НайтиПоНаименованию("Розничная");
// 4. Заполняем табличную часть "Товары" в цикле
НоваяСтрока = ОбъектДок.Товары.Добавить();
НоваяСтрока.Номенклатура = СсылкаНаТовар;
НоваяСтрока.ТипЦен = Справочники.ТипыЦенНоменклатуры.НайтиПоНаименованию("Розничная");
НоваяСтрока.Цена = Число(ЗначениеИзExcel);
НоваяСтрока.Валюта = Справочники.Валюты.НайтиПоКоду("643"); // Рубли
НоваяСтрока.ЕдиницаИзмерения = СсылкаНаТовар.ЕдиницаХраненияОстатков;
НоваяСтрока.Коэффициент = 1; // Критически важный реквизит!
// 5. Записываем и проводим документ
ОбъектДок.Записать(РежимЗаписиДокумента.Проведение);
Рассмотрим подробнее детали, которые часто упускают, что приводит к некорректной работе системы или ошибкам проведения.
1. Вторая табличная часть — «ТипыЦен»
В документе УстановкаЦенНоменклатуры существует скрытая или явная зависимость от ТЧ ТипыЦен. Чтобы данные корректно распределялись по колонкам в форме и правильно записывались в регистр, в этой таблице должна быть строка с соответствующим типом цен. Если вы устанавливаете цены трех видов (Закупочная, Оптовая, Розничная), в ТЧ ТипыЦен должны быть добавлены все три ссылки.
2. Единицы измерения и коэффициенты
В УТ 10.3 цена всегда привязана к единице измерения. Помимо самой единицы, в строке табличной части Товары обязательно нужно заполнять реквизит Коэффициент. Обычно он берется из справочника единиц измерения, подчиненного номенклатуре. Если оставить коэффициент равным нулю, при проведении или расчетах могут возникнуть ошибки деления на ноль или некорректные суммы в регистре.
3. Оптимизация поиска в цикле
Использование методов НайтиПоКоду() или НайтиПоНаименованию() внутри цикла загрузки (например, на 5000 строк) — это плохая практика. Каждый такой вызов создает отдельный запрос к базе данных. Проанализируем, как сделать это быстрее: рекомендуется заранее выгрузить все коды из Excel в массив, одним запросом получить соответствие «Код — Ссылка» и сохранить его в объекте Соответствие. Затем в цикле просто получать ссылку из памяти.
Посмотрим на ситуацию, когда вам нужно не перезаписать документ полностью, а только обновить цены для определенных позиций. В этом случае вместо метода Добавить() следует использовать поиск строки. Рассмотрим пример:
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Номенклатура", ИскомыйТовар);
ПараметрыОтбора.Вставить("ТипЦен", НужныйТипЦен);
НайденныеСтроки = ОбъектДок.Товары.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 0 Тогда
СтрокаТовара = НайденныеСтроки[0];
Иначе
СтрокаТовара = ОбъектДок.Товары.Добавить();
СтрокаТовара.Номенклатура = ИскомыйТовар;
СтрокаТовара.ТипЦен = НужныйТипЦен;
КонецЕсли;
СтрокаТовара.Цена = НоваяЦена;
При массовой загрузке данных (особенно если вы создаете несколько документов Установка цен номенклатуры) крайне важно использовать транзакции. Это гарантирует, что если в середине процесса произойдет ошибка, данные не запишутся частично. Используйте конструкцию НачатьТранзакцию() и ЗафиксироватьТранзакцию().
Также обратите внимание на периодичность регистра цен. Цены в 1С:УТ 10.3 действуют с точностью до секунды. Если вы загружаете цены «сегодняшним числом», убедитесь, что время документа установлено корректно. Часто удобно использовать КонецДня(ТекущаяДата()) для того, чтобы новые цены гарантированно перекрывали любые изменения, внесенные в течение дня вручную.
Подведем итог: для корректного добавления записей в регистр ЦеныНоменклатуры необходимо работать исключительно с объектом документа-регистратора, заполняя его табличные части Товары и ТипыЦен, и завершать операцию вызовом метода Записать(РежимЗаписиДокумента.Проведение). Такой подход гарантирует целостность данных и правильное отражение цен во всех отчетах и документах продажи.