Организация услуг ответственного хранения (3PL) или просто сдача складских площадей с тарификацией за объем товара — задача, с которой часто сталкиваются пользователи 1С:Управление нашей фирмой (УНФ). Типовой функционал программы отлично справляется с торговлей и производством, но специализированного биллинга складских услуг (WMS-функционала) в ней "из коробки" нет.
Рассмотрим подробно, как решить задачу расчета стоимости хранения, когда необходимо учитывать количество дней нахождения товара на складе и его объем (кубические метры).
Ситуация следующая: есть склад, предоставляющий услуги хранения. Клиент завозит товар, товар хранится определенное время, затем вывозится. Необходимо в конце месяца выставить счет клиенту, который зависит от:
Многие начинающие пользователи пытаются использовать партионный учет для решения этой задачи. Логика кажется верной: пришла партия, ушла партия, посчитали разницу дат. Однако, как выяснилось в ходе обсуждения, этот метод имеет существенные недостатки для потокового хранения:
Поэтому наиболее правильным подходом является расчет "Кубометро-дней" или "Паллето-дней" на основе остатков товаров.
Для корректного выставления счета за месяц нам не нужно отслеживать судьбу каждой конкретной коробки. Нам достаточно знать, сколько места занимал товар клиента в каждый конкретный день месяца.
Разберем математическую модель, предложенную опытными специалистами:
Пример расчета:
Если мы считаем услугу за период с 1 по 15 января, расчет будет выглядеть так:
4 * 50 = 200 кубометро-дней.5 * 100 = 500 кубометро-дней.6 * 30 = 180 кубометро-дней.Итого: 200 + 500 + 180 = 880 единиц объема к оплате. Умножаем на стоимость хранения 1 м³ в день и получаем сумму счета.
Поскольку в 1С:УНФ нет документа "Расчет услуг хранения", нам потребуется небольшая доработка или создание внешней обработки (внешнего отчета). Мы не будем снимать конфигурацию с поддержки, а используем механизм расширений или внешних печатных форм/обработок заполнения табличных частей.
Рассмотрим, откуда брать данные. В УНФ основным регистром, хранящим информацию о товарах на складах, является регистр накопления Запасы (или ЗапасыНаСкладах в зависимости от версий и настроек, но чаще мы оперируем общими остатками).
Чтобы система могла посчитать объем, в карточках номенклатуры должны быть корректно заполнены данные.
Убедимся, что для каждой номенклатуры (или характеристики) заполнен реквизит, отвечающий за объем. В типовой УНФ это может быть реализовано через дополнительные реквизиты или через использование единиц измерения, где прописан коэффициент пересчета в м³.
Нам необходимо написать запрос, который получит остатки на каждый день месяца. Получить просто "Остатки на дату" в цикле — не самый производительный метод (хотя для небольших баз рабочий). Более профессиональный подход — использовать виртуальную таблицу ОстаткиИОбороты.
Рассмотрим логику построения запроса к регистру Запасы. Нам нужно получить движения и рассчитать остаток на каждый календарный день.
// Примерная схема алгоритма для обработки заполнения табличной части
// 1. Определяем период расчета (например, НачалоМесяца и КонецМесяца)
// 2. Получаем остаток на начало периода
// 3. Получаем все обороты за период с детализацией по дням
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Календарь.ДатаКалендаря КАК Период
|ПОМЕСТИТЬ ВТ_Дни
|ИЗ
| &ТаблицаДат КАК Календарь
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ЗапасыОстаткиИОбороты.Номенклатура КАК Номенклатура,
| ЗапасыОстаткиИОбороты.Период КАК Период,
| ЗапасыОстаткиИОбороты.КоличествоКонечныйОстаток КАК Количество
|ПОМЕСТИТЬ ВТ_Движения
|ИЗ
| РегистрНакопления.Запасы.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, День, , ) КАК ЗапасыОстаткиИОбороты
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ_Дни.Период КАК День,
| ЕСТЬNULL(ВТ_Движения.Номенклатура, &ПустаяНоменклатура) КАК Номенклатура,
| ЕСТЬNULL(ВТ_Движения.Количество, 0) КАК КоличествоНаКонецДня
|ИЗ
| ВТ_Дни КАК ВТ_Дни
| ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Движения КАК ВТ_Движения
| ПО ВТ_Дни.Период = ВТ_Движения.Период";
Обратите внимание, что прямой запрос к таблице ОстаткиИОбороты с периодичностью "День" вернет только те дни, когда были движения. А нам нужны все дни, даже если товар просто лежал без движения. Поэтому алгоритм должен быть следующим:
СуммаКубов = СуммаКубов + (ТекущийОстатокШт * ОбъемЕдиницы).Важный момент, который обсуждался экспертами: как считать неполные дни? Если товар привезли утром, а увезли вечером того же дня — брать ли плату?
Существует несколько стратегий, которые нужно закрепить в договоре с клиентом и реализовать в коде:
Для большинства случаев подходит вариант "Остаток на конец дня" + отдельная услуга за ПРР (Погрузо-разгрузочные работы). ПРР оплачиваются по факту операции (документ Приходная/Расходная накладная), а хранение — за ночевку товара.
Самый удобный способ для пользователя — создать кнопку "Заполнить расчет хранения" в документе Акт выполненных работ (или Расходная накладная с типом Услуга).
Как это будет работать:
Запасы по данному контрагенту.Это решение позволяет избежать ручных подсчетов в Excel, минимизирует ошибки и сохраняет историю расчетов в 1С (в виде созданных Актов).
Для организации биллинга ответственного хранения в 1С:УНФ не обязательно покупать сложную WMS-систему. Достаточно использовать данные регистра накопления Запасы. Ключ к решению — переход от попыток учесть "партии" к математическому расчету интегрального показателя объема товара во времени.
Рекомендуем реализовать этот механизм через Расширение конфигурации, добавив команду заполнения в документы реализации. Это сохранит возможность автоматического обновления 1С:УНФ и решит задачу автоматизации расчетов.