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