В типовых конфигурациях «1С:Предприятие» (таких как «1С:Управление торговлей», «1С:ERP» или «1С:Комплексная автоматизация») точность всех суммовых показателей и цен по умолчанию ограничена двумя знаками после запятой. Это обусловлено требованиями бухгалтерского учета, где расчеты производятся в рублях и копейках (или центах для валютного учета). Однако на практике компании часто сталкиваются с необходимостью вести учет цен с точностью до 3 или 4 знаков после запятой. Это происходит при работе с импортными поставщиками (инвойсы в евро/долларах), закупке мелкоштучного товара (метизы, крепеж) или использовании сложных систем скидок.
Попытка решить эту задачу «в лоб» — путем изменения разрядности реквизитов в метаданных конфигурации — приводит к необходимости переписывания огромного объема кода (до 80% документов товародвижения, денежных средств, отчетов и регистров накопления), снятию конфигурации с поддержки и колоссальным затратам на сопровождение. В рамках этой статьи мы детально разберем практические альтернативные варианты обхода этого ограничения, предложенные практикующими специалистами.
Прежде чем приступать к доработке программного кода, проанализируем природу возникновения дробных цен. Очень часто поставщики предоставляют накладные, в которых цена за единицу товара содержит 3 или 4 знака после запятой, но итоговая сумма строки всегда округлена до копеек (2 знака). Это происходит потому, что дробная цена получается расчетным путем (например, базовая цена за минусом сложной скидки).
Рассмотрим пример:
Поставщик отгружает 9 000 единиц товара. Базовая цена составляет 0.60 EUR. Предоставляется скидка в размере 11%. Расчетная цена со скидкой составляет 0.60 * (1 - 0.11) = 0.534 EUR. При этом итоговая сумма строки в инвойсе будет равна 9000 * 0.534 = 4806.00 EUR.
Если мы попытаемся ввести этот документ в 1С стандартными средствами, то столкнемся с проблемой: система округлит цену 0.534 до 0.53. Итоговая сумма в документе 1С пересчитается как 9000 * 0.53 = 4770.00 EUR. Возникает расхождение с инвойсом поставщика на 36.00 EUR.
Ниже мы подробно рассмотрим несколько эффективных способов решения этой проблемы.
Этот способ идеально подходит, если вам нужно сохранить типовую конфигурацию на полной поддержке и избежать рисков при обновлении. Идея заключается в реализации принципа приоритета Суммы над Ценой.
При вводе документа «Заказ поставщику» пользователи вручную указывают количество и итоговую сумму из инвойса поставщика (например, Количество = 9000, Сумма = 4806.00). Цена при этом рассчитывается системой автоматически и отображается как 0.53 (из-за округления до 2 знаков в интерфейсе). Но сумма строки остается верной и сходится с бумажным носителем.
Проблема возникает при создании документа «Поступление товаров и услуг» (Приобретение товаров и услуг) на основании заказа. Типовой механизм 1С при заполнении по умолчанию пытается пересчитать сумму по формуле Количество * Цена, из-за чего округленная цена ломает итоговую сумму.
Чтобы обойти это поведение, мы можем создать внешнюю обработку заполнения табличной части для документа поступления. Напишем алгоритм, который переносит данные из документа-основания напрямую, игнорируя стандартный пересчет от округленной цены.
Рассмотрим пример кода, который может использоваться во внешней обработке для перезаполнения сумм из документа-основания:
// Процедура переносит точные суммы из Заказа в Поступление
Процедура ЗаполнитьТабличнуюЧастьПоЗаказу(ОбъектДокумента, ДокументОснование) Экспорт
// Получаем таблицу товаров из документа-источника
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Заказ.Номенклатура КАК Номенклатура,
| Заказ.Количество КАК Количество,
| Заказ.Сумма КАК Сумма,
| Заказ.СтавкаНДС КАК СтавкаНДС,
| Заказ.СуммаНДС КАК СуммаНДС
|ИЗ
| Документ.ЗаказПоставщику.Товары КАК Заказ
|ГДЕ
| Заказ.Ссылка = &СсылкаОснование";
Запрос.УстановитьПараметр("СсылкаОснование", ДокументОснование);
ТаблицаОснования = Запрос.Выполнить().Выгрузить();
// Перезаполняем табличную часть документа поступления
Для Каждого СтрокаПриемник Из ОбъектДокумента.Товары Цикл
// Ищем соответствующую строку в заказе по номенклатуре
СтрокаИсточник = ТаблицаОснования.Найти(СтрокаПриемник.Номенклатура, "Номенклатура");
Если СтрокаИсточник <> Неопределено Тогда
// Принудительно устанавливаем точную сумму из заказа
СтрокаПриемник.Сумма = СтрокаИсточник.Сумма;
СтрокаПриемник.СуммаНДС = СтрокаИсточник.СуммаНДС;
// Рассчитываем виртуальную цену для отображения в интерфейсе
Если СтрокаПриемник.Количество <> 0 Тогда
СтрокаПриемник.Цена = СтрокаПриемник.Сумма / СтрокаПриемник.Количество;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Использование этого подхода позволяет пользователям комфортно работать: вносить количество и сумму вручную, а система сама будет подгонять цену. Итоговые проводки и взаиморасчеты при этом будут абсолютно корректными, так как в регистры пойдут правильные суммы.
Если специфика вашего учета требует обязательного указания базовой цены и последующего расчета точной стоимости, целесообразно задействовать типовой механизм скидок. Этот метод позволяет обойти ограничение разрядности цены за счет того, что скидка в 1С может рассчитываться с высокой точностью, а округление до копеек происходит только на финальном этапе расчета общей суммы строки.
Посмотрим на пример реализации:
ПроцентРучнойСкидки указываем процент скидки (например, 11%).Преимущество метода заключается в том, что вам не нужно вносить изменения в структуру регистров накопления, так как вся информация о скидках хранится в типовых реквизитах табличных частей документов.
Если вам критически важно видеть именно цену с 3 или 4 знаками после запятой во всех печатных формах, прайс-листах и интерфейсах документов, можно прибегнуть к точечной доработке справочника ТипыЦенНоменклатуры (или ПравилаКлассификацииПоставщиков в ERP) и реквизита Цена в конкретных документах.
Разберем этот процесс по шагам:
ПорядкиОкругленияОкругления). Добавим новое значение, например, ОкруглятьДо_0_001 или ОкруглятьДо_0_0001.ТипыЦенНоменклатуры для нужных категорий цен выберем созданный порядок округления.Цена табличной части Товары необходимых документов (например, «Заказ поставщику», «Поступление товаров и услуг») изменим формат отображения и точность с 15.2 на 15.4. Это позволит визуализировать дробную цену в интерфейсе.Окр(Сумма, 2).Если вы работаете на платформе «1С:Предприятие» версии **8.3.20** и новее, вам доступен наиболее технологичный способ изменения разрядности данных без снятия конфигурации с поддержки — использование определяемых типов в механизме расширений.
Проанализируем этот подход:
В современных конфигурациях 1С для описания цен и сумм используются так называемые Определяемые типы (например, ДенежнаяСуммаНеотрицательная или Цена). Платформа позволяет переопределять свойства этих типов непосредственно через расширения. Добавив определяемый тип в расширение и изменив его точность (например, установив длину 15 и точность 4), вы автоматически измените разрядность всех связанных реквизитов во всей информационной базе — во всех документах, табличных частях и регистрах.
Однако помните о подводном камне: в коде общих модулей конфигурации могут быть жестко прописаны алгоритмы округления. Чтобы перехватить их, используйте аннотации &Вместо или &После в расширении для корректировки работы функций округления.
Рассмотрим еще один излюбленный метод опытных 1С-консультантов, который не требует написания кода вообще. Если цена единицы товара слишком мала (например, 0.1234 рубля за штуку), мы можем изменить единицу измерения для ведения взаиморасчетов.
Вместо штуки (шт) заведем в справочнике «Упаковки и единицы измерения» новую единицу — например, «Тысяча штук» (тыс. шт) с коэффициентом 1000 по отношению к базовой единице. В этом случае цена за тысячу штук составит ровно 123.40 рубля. Стандартной точности двух знаков после запятой гарантированно хватит для точного отражения сумм в учете, а при делении на количество в штуках погрешность возникать не будет.
Мы рассмотрели пять различных способов решения проблемы с округлением цен до тысячных в «1С». Выбор конкретного варианта зависит от ваших технологических ограничений, версии платформы и готовности вносить изменения в конфигурацию: