Как ограничить ввод дробного количества для номенклатуры с единицей измерения штуки в 1С

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет IT и автоматизация бизнеса
← На главную

В типовых конфигурациях 1С, таких как ERP, Комплексная автоматизация или Управление торговлей, часто возникает ситуация, когда пользователи случайно или намеренно вводят дробное количество для товаров, которые по своей сути являются неделимыми (например, «0.5 кувалды» или «1.032 телефона»). Проблема усугубляется тем, что на уровне архитектуры платформы реквизит Количество в большинстве документов и регистров имеет тип Число(15, 3), что позволяет хранить три знака после запятой для любых позиций.

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

Почему в 1С по умолчанию разрешено дробное количество?

Прежде чем внедрять ограничения, выясним причину такого поведения системы. Разработчики платформы 1С придерживаются принципа универсальности. Единый регистр накопления (например, ТоварыНаСкладах) хранит данные и по весовому товару (кг), и по метражному (м), и по штучному (шт). Система не может динамически менять разрядность числа в базе данных в зависимости от выбранной номенклатуры.

Кроме того, существуют специфические бизнес-кейсы:

  1. Производственные нормативы: В спецификациях часто указывается количество 1.005 шт. на единицу продукции с учетом технологического брака.
  2. Разукомплектация: Когда целое изделие разбирается на части, и затраты распределяются долями.
  3. Продажа части упаковки: Например, половина буханки хлеба, которая в учете числится как «штука».

Однако, если в вашей учетной политике «штука» всегда означает целое число, необходимо внедрять дополнительные механизмы контроля. Рассмотрим их подробнее.

Решение 1. Ограничение типа данных в элементе формы

Один из самых элегантных способов — ограничить возможность ввода дробных знаков непосредственно в поле табличной части при выборе строки. Рассмотрим программный метод изменения квалификатора числа.

Для этого в событии ПриАктивизацииСтроки или в специализированном событии редактирования (например, ПриНачалеРедактирования) мы можем динамически менять описание типа для элемента управления. Разберем по шагам логику реализации:


// В обработчике события ПриНачалеРедактирования табличной части
Процедура ТоварыПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
    
    ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Проверяем, является ли единица измерения штуками
    Если ТекущиеДанные.ЕдиницаИзмерения = Справочники.УпаковкиЕдиницыИзмерения.Штука Тогда
        // Создаем новый квалификатор числа с нулевой точностью
        КвалификаторЧисла = Новый КвалификаторыЧисла(15, 0, ДопустимыйЗнак.Любой);
        МассивТипов = Новый Массив;
        МассивТипов.Добавить(Тип("Число"));
        
        // Устанавливаем ограничение типа для поля ввода Количества
        ОписаниеТипаЧисло = Новый ОписаниеТипов(МассивТипов, , , КвалификаторЧисла);
        Элементы.ТоварыКоличество.ОграничениеТипа = ОписаниеТипаЧисло;
    Иначе
        // Возвращаем стандартную точность (3 знака) для остальных единиц
        Элементы.ТоварыКоличество.ОграничениеТипа = ДоступныеТипыКоличества; // Заранее сохраненный тип
    КонецЕсли;
    
КонецПроцедуры

Этот метод хорош тем, что пользователь просто не сможет физически ввести запятую или точку в поле Количество, если выбрана штучная номенклатура.

Решение 2. Использование обработчика ПриИзменении

Если вы хотите позволить пользователю вводить данные, но автоматически исправлять ошибки, можно использовать округление. Рассмотрим пример кода в модуле формы документа:


Процедура ТоварыКоличествоПриИзменении(Элемент)
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    
    // Проверяем условие неделимости (например, через флаг в Единице измерения или Номенклатуре)
    Если НужноОкруглятьДоЦелого(ТекущаяСтрока.Номенклатура) Тогда
        // Отсекаем дробную часть
        ТекущаяСтрока.Количество = Цел(ТекущаяСтрока.Количество);
        
        Если ТекущаяСтрока.Количество = 0 И ТекущаяСтрока.Количество <> 0 Тогда
             Сообщить("Для данной номенклатуры разрешено только целое количество!");
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Важно помнить: метод Цел() просто отсекает дробную часть, а Окр() округляет по математическим правилам. В случае с товарами чаще используется именно отсечение или проверка на кратность единице.

Решение 3. Глобальный контроль через ОбработкаПроверкиЗаполнения

Проблема экранных форм в том, что данные могут попасть в документ в обход ручного ввода: через загрузку из Excel, обработку «Подбор товаров» или копирование строк. Чтобы гарантированно избежать дробных штук в базе данных, проанализируем использование механизма ОбработкаПроверкиЗаполнения в модуле объекта документа.

Рассмотрим пример реализации проверки:


Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    
    Для Каждого СтрокаТовара Из Товары Цикл
        // Проверяем кратность единице
        Если (СтрокаТовара.Количество % 1) <> 0 Тогда
            // Проверяем, штуки ли это (логику проверки подставьте свою)
            Если ЭтоШтучныйТовар(СтрокаТовара.Номенклатура) Тогда
                ТекстСообщения = СтрШаблон("В строке №%1 указано дробное количество (%2) для штучного товара!", 
                    СтрокаТовара.НомерСтроки, СтрокаТовара.Количество);
                ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения, , 
                    "Товары[" + (СтрокаТовара.НомерСтроки - 1) + "].Количество", , Отказ);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Этот метод является наиболее надежным, так как он срабатывает непосредственно перед записью или проведением документа, независимо от того, как данные попали в табличную часть.

Скрытая причина: Автоматические расчеты на основании

Как отмечалось в обсуждении, иногда дробные числа появляются не из-за ошибок ввода, а из-за алгоритмов самой 1С:ERP. Например, при создании документа Отчет переработчика на основании Заказа переработчика. Если в заказе присутствуют дублирующиеся строки или сложные коэффициенты упаковок, система применяет внутренние нормы распределения, которые могут превратить «1 шт» в «0.999 шт» или «1.001 шт».

Рекомендация: Перед тем как внедрять «жесткие» запреты, проанализируйте цепочку документов. Если дроби возникают в результате расчета себестоимости или распределения затрат, запрет проведения может парализовать работу отдела закупок или производства.

Выводы и рекомендации

Для эффективного решения проблемы «дробных штук» мы рекомендуем комбинированный подход:

  1. На уровне НСИ: Добавьте дополнительный реквизит (флаг) в карточку Номенклатура или ЕдиницаИзмерения — «Запретить дробное количество». Это позволит системе гибко понимать, где контроль нужен, а где нет.
  2. На уровне интерфейса: Используйте расширение формы, чтобы менять ОграничениеТипа (как в Решении 1). Это повысит удобство работы (UX), так как пользователь сразу увидит ограничение при вводе.
  3. На уровне бизнес-логики: Используйте подписку на событие ПередЗаписью для проверки остатков и корректности заполнения. Это обеспечит целостность данных при загрузках из внешних систем.

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

← На главную