В практике автоматизации производственных предприятий часто встречается задача, называемая Catch Weight или двойной мерный учет. Типичный пример — учет шкур крупного рогатого скота (КРС), мясных туш или кабельной продукции. Проблема заключается в том, что штуки и килограммы в таких товарах не связаны жестким коэффициентом. Шкура может подсыхать, теряя в весе, но оставаясь одной штукой. При реализации клиент может заказать 10 штук, но цена и списание будут зависеть от их фактического веса на момент отгрузки.
В рамках данной статьи мы подробно разберем, как спроектировать архитектуру системы для решения этой задачи в «самописной» конфигурации или при доработке типовых решений 1С.
Проанализируем самый распространенный подход: создание двух параллельных количественных показателей в системе. Это наиболее гибкий метод, который позволяет видеть остатки одновременно в двух единицах.
Рассмотрим структуру РегистрНакопления (например, «ТоварыНаСкладах»). Вместо одного ресурса Количество, мы добавим два:
КоличествоШт (Тип: Число 15, 3) — для учета физических единиц.КоличествоКг (Тип: Число 15, 3) — для учета фактической массы.При таком подходе в документах («Приходная накладная», «Требование-накладная», «Реализация товаров») пользователь должен будет заполнять оба поля вручную. Однако здесь возникает серьезная проблема «брошенных хвостов». Представьте ситуацию: по документам вы списали 10 шкур общим весом 100 кг, но из-за погрешностей взвешивания на остатке в регистре осталось 0 штук и 0.5 кг. Чтобы этого избежать, необходимо внедрить специальную логику в процедуру проведения документов расхода.
Разберем пример кода для модуля набора записей регистра:
Процедура ПередЗаписью(Отказ, Замещение)
// Алгоритм автоматической зачистки "весовых хвостов"
Если ЭтотОбъект.Количество() > 0 Тогда
Для Каждого Запись Из ЭтотОбъект Цикл
Если Запись.ВидДвижения = ВидДвиженияНакопления.Расход Тогда
// Проверяем текущий остаток в базе по данной номенклатуре и складу
ОстатокШт = ПолучитьОстатокШт(Запись.Номенклатура, Запись.Склад);
// Если списываем последние штуки, принудительно обнуляем вес
Если Запись.КоличествоШт >= ОстатокШт Тогда
Запись.КоличествоКг = ПолучитьОстатокКг(Запись.Номенклатура, Запись.Склад);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Рассмотрим альтернативный метод, который предложили участники обсуждения: учет через «доли» партии. Этот способ минимизирует риск возникновения расхождений в учете. Суть его заключается в том, что каждая поступившая партия (или даже единица товара) фиксируется как объект, имеющий начальный вес и начальное количество.
Посмотрим, как это работает на примере шкур: Приходит партия из 3 штук весом 100 кг. Мы записываем это в регистр. Когда мы списываем 1 штуку, система рассчитывает, что это 1/3 от партии, и автоматически предлагает списать 33.33 кг. Если фактический вес другой (например, 35 кг), мы разрешаем пользователю скорректировать вес, но система всегда контролирует долю списания.
Этот метод хорош тем, что он автоматически закрывает остатки. Если вы списали 3/3 партии, то и штуки, и килограммы гарантированно обнулятся.
Проанализируем ситуацию, когда каждая единица продукции уникальна и имеет высокую стоимость (например, элитная кожа). В этом случае наиболее правильным будет использование механизма Характеристики или Серии.
Выясним преимущества этого метода:
Для реализации этого в «самописке» нам потребуется РегистрСведений, где будет храниться актуальный вес для каждой конкретной единицы (серии/характеристики). При каждой технологической операции (усушка, обработка) мы создаем запись в этот регистр, корректируя вес, но не меняя количество в основном регистре остатков.
Важным аспектом является изменение веса без изменения количества штук. Проанализируем, как отразить «усушку» шкур. Для этого в системе должен существовать документ «Акт перевеса» или «Регистрация естественной убыли».
Этот документ должен делать движения только по ресурсу КоличествоКг в регистре накопления. Рассмотрим, как это повлияет на себестоимость: если количество штук не меняется, а вес уменьшается, то стоимость одного килограмма продукции при расчете себестоимости будет автоматически расти. Это корректно отражает экономическую суть процесса: по мере высыхания шкура становится дороже в пересчете на вес.
При использовании двух независимых измерений возрастает риск ошибок ввода. Программисту необходимо предусмотреть механизмы защиты. Разберем создание «коридора допустимых значений».
В справочнике Номенклатура добавим два реквизита: МинимальныйВесЕдиницы и МаксимальныйВесЕдиницы. В модуле проведения документов будем использовать следующий алгоритм проверки:
СреднийВес = ?(Строка.КоличествоШт = 0, 0, Строка.КоличествоКг / Строка.КоличествоШт);
Если СреднийВес < Строка.Номенклатура.МинимальныйВесЕдиницы
Или СреднийВес > Строка.Номенклатура.МаксимальныйВесЕдиницы Тогда
Сообщить("Внимание: Вес шкуры выходит за рамки биологической нормы!");
// Опционально: Отказ = Истина;
КонецЕсли;
Такой подход позволит отсечь грубые ошибки операторов (например, когда вместо 20 кг случайно вводят 200 кг).
Для реализации качественного учета в двух независимых единицах в 1С мы рекомендуем сочетать первый метод (два ресурса в регистре) с обязательным внедрением механизмов «зачистки хвостов» и контроля среднего веса. Если же бизнес-процесс позволяет, использование уникальных характеристик для каждой единицы продукции будет самым точным, хоть и наиболее трудозатратным способом учета.
Не забывайте, что отчетность по таким регистрам должна строиться с использованием обоих ресурсов, чтобы пользователь в любой момент мог видеть как количественный, так и весовой баланс склада.