В типовых конфигурациях 1С, таких как ERP, Комплексная автоматизация или Управление торговлей, часто возникает ситуация, когда пользователи случайно или намеренно вводят дробное количество для товаров, которые по своей сути являются неделимыми (например, «0.5 кувалды» или «1.032 телефона»). Проблема усугубляется тем, что на уровне архитектуры платформы реквизит Количество в большинстве документов и регистров имеет тип Число(15, 3), что позволяет хранить три знака после запятой для любых позиций.
В этой статье мы подробно разберем, почему так происходит, и рассмотрим несколько способов решения этой задачи: от визуальных ограничений в форме до жесткого контроля при проведении документов. Проанализируем ситуацию и выберем оптимальный подход.
Прежде чем внедрять ограничения, выясним причину такого поведения системы. Разработчики платформы 1С придерживаются принципа универсальности. Единый регистр накопления (например, ТоварыНаСкладах) хранит данные и по весовому товару (кг), и по метражному (м), и по штучному (шт). Система не может динамически менять разрядность числа в базе данных в зависимости от выбранной номенклатуры.
Кроме того, существуют специфические бизнес-кейсы:
Однако, если в вашей учетной политике «штука» всегда означает целое число, необходимо внедрять дополнительные механизмы контроля. Рассмотрим их подробнее.
Один из самых элегантных способов — ограничить возможность ввода дробных знаков непосредственно в поле табличной части при выборе строки. Рассмотрим программный метод изменения квалификатора числа.
Для этого в событии ПриАктивизацииСтроки или в специализированном событии редактирования (например, ПриНачалеРедактирования) мы можем динамически менять описание типа для элемента управления. Разберем по шагам логику реализации:
// В обработчике события ПриНачалеРедактирования табличной части
Процедура ТоварыПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
// Проверяем, является ли единица измерения штуками
Если ТекущиеДанные.ЕдиницаИзмерения = Справочники.УпаковкиЕдиницыИзмерения.Штука Тогда
// Создаем новый квалификатор числа с нулевой точностью
КвалификаторЧисла = Новый КвалификаторыЧисла(15, 0, ДопустимыйЗнак.Любой);
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("Число"));
// Устанавливаем ограничение типа для поля ввода Количества
ОписаниеТипаЧисло = Новый ОписаниеТипов(МассивТипов, , , КвалификаторЧисла);
Элементы.ТоварыКоличество.ОграничениеТипа = ОписаниеТипаЧисло;
Иначе
// Возвращаем стандартную точность (3 знака) для остальных единиц
Элементы.ТоварыКоличество.ОграничениеТипа = ДоступныеТипыКоличества; // Заранее сохраненный тип
КонецЕсли;
КонецПроцедуры
Этот метод хорош тем, что пользователь просто не сможет физически ввести запятую или точку в поле Количество, если выбрана штучная номенклатура.
Если вы хотите позволить пользователю вводить данные, но автоматически исправлять ошибки, можно использовать округление. Рассмотрим пример кода в модуле формы документа:
Процедура ТоварыКоличествоПриИзменении(Элемент)
ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
// Проверяем условие неделимости (например, через флаг в Единице измерения или Номенклатуре)
Если НужноОкруглятьДоЦелого(ТекущаяСтрока.Номенклатура) Тогда
// Отсекаем дробную часть
ТекущаяСтрока.Количество = Цел(ТекущаяСтрока.Количество);
Если ТекущаяСтрока.Количество = 0 И ТекущаяСтрока.Количество <> 0 Тогда
Сообщить("Для данной номенклатуры разрешено только целое количество!");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важно помнить: метод Цел() просто отсекает дробную часть, а Окр() округляет по математическим правилам. В случае с товарами чаще используется именно отсечение или проверка на кратность единице.
Проблема экранных форм в том, что данные могут попасть в документ в обход ручного ввода: через загрузку из Excel, обработку «Подбор товаров» или копирование строк. Чтобы гарантированно избежать дробных штук в базе данных, проанализируем использование механизма ОбработкаПроверкиЗаполнения в модуле объекта документа.
Рассмотрим пример реализации проверки:
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
Для Каждого СтрокаТовара Из Товары Цикл
// Проверяем кратность единице
Если (СтрокаТовара.Количество % 1) <> 0 Тогда
// Проверяем, штуки ли это (логику проверки подставьте свою)
Если ЭтоШтучныйТовар(СтрокаТовара.Номенклатура) Тогда
ТекстСообщения = СтрШаблон("В строке №%1 указано дробное количество (%2) для штучного товара!",
СтрокаТовара.НомерСтроки, СтрокаТовара.Количество);
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения, ,
"Товары[" + (СтрокаТовара.НомерСтроки - 1) + "].Количество", , Отказ);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Этот метод является наиболее надежным, так как он срабатывает непосредственно перед записью или проведением документа, независимо от того, как данные попали в табличную часть.
Как отмечалось в обсуждении, иногда дробные числа появляются не из-за ошибок ввода, а из-за алгоритмов самой 1С:ERP. Например, при создании документа Отчет переработчика на основании Заказа переработчика. Если в заказе присутствуют дублирующиеся строки или сложные коэффициенты упаковок, система применяет внутренние нормы распределения, которые могут превратить «1 шт» в «0.999 шт» или «1.001 шт».
Рекомендация: Перед тем как внедрять «жесткие» запреты, проанализируйте цепочку документов. Если дроби возникают в результате расчета себестоимости или распределения затрат, запрет проведения может парализовать работу отдела закупок или производства.
Для эффективного решения проблемы «дробных штук» мы рекомендуем комбинированный подход:
Номенклатура или ЕдиницаИзмерения — «Запретить дробное количество». Это позволит системе гибко понимать, где контроль нужен, а где нет.ОграничениеТипа (как в Решении 1). Это повысит удобство работы (UX), так как пользователь сразу увидит ограничение при вводе.ПередЗаписью для проверки остатков и корректности заполнения. Это обеспечит целостность данных при загрузках из внешних систем.Таким образом, вы не только решите техническую задачу, но и сохраните гибкость системы для тех случаев, когда дробное количество действительно необходимо по условиям производства.