ERPNext для оптовика: закупка коробками, партии с FEFO и продажи в одной цепочке
ERPNext для оптовой торговли закрывает базовый контур: закупку, склад, партии со сроком годности, отгрузку и возвраты. Нормативные формы УПД и бухучёт остаются в 1С. Ниже сквозная цепочка оптовика, настройки партий, коробок и оценки запасов и разбор условной компании.
Какая цепочка нужна оптовику: от заявки до отгрузки в ERPNext
Оптовик зарабатывает на обороте и на точности склада: ошибка в остатке стоит срыва отгрузки, ошибка в сроке годности стоит списания партии. Поэтому первым делом я рисую с клиентом сквозную цепочку документов и только потом включаю настройки. В ERPNext она выглядит так: заявка на материалы (Material Request), заказ поставщику (Purchase Order), приёмка (Purchase Receipt), складской остаток, заказ покупателя (Sales Order), отгрузка (Delivery Note), счёт покупателю (Sales Invoice) и оплата (Payment Entry). Такой контур мы внедряем в продукте ERPNext под ключ, а регламентированный учёт остаётся в 1С.
Главная особенность, которую надо понять до первой настройки: ERPNext строго разделяет физическое движение товара и финансовые обязательства. Приёмка двигает остатки и обновляет складской регистр (Stock Ledger), а счёт поставщика (Purchase Invoice) фиксирует долг. То же самое с продажей: отгрузка списывает товар, счёт покупателю создаёт дебиторку. Для опта это удобно, потому что товар часто приходит раньше счёта, а счёт выставляется позже отгрузки. Принудить порядок можно в Buying Settings и Selling Settings: поля «Is Purchase Receipt Required for Purchase Invoice Creation?» и «Is Delivery Note Required for Sales Invoice Creation?» заставляют сначала оформлять приёмку и отгрузку, и только потом счёт.
Если вам нужна ещё и CRM-часть с воронкой и менеджерами по продажам, она вынесена в другие материалы. Я не повторяю их здесь и отсылаю к соседним кейсам: как это выглядело на другой системе, смотрите в разборах CRM и склада для оптовой компании на Odoo и SuiteCRM в оптовой торговле. Здесь мы идём по складской вертикали: закупка, партии, единицы измерения, возвраты и оценка запасов.
Что делает каждая роль, по шагам цепочки:
- Менеджер закупок создаёт заявку и заказ поставщику в коробках (единица закупки Box).
- Кладовщик оформляет приёмку: указывает партию и срок годности, склад принимает товар в штуках.
- Остаток видно по складам, партиям и срокам, ничего не переносится руками.
- Менеджер продаж оформляет заказ покупателю в штуках или в коробках, как удобно клиенту.
- Кладовщик проводит отгрузку: партии подбираются по ближайшему сроку годности.
- Бухгалтер выставляет счёт и принимает оплату; данные утверждённых счетов уходят в 1С.
Партии и сроки годности: как включить Batch и отгружать по FEFO
FEFO (First Expired, First Out) означает, что первым уходит то, что испортится раньше. Для оптовика, торгующего химией, герметиками, клеями, пищевыми добавками или косметикой, это основа учёта. В ERPNext партионный учёт включается на карточке товара (Item) флагом «Has Batch No». Дальше вы решаете, как создаются партии. Если отметить «Automatically Create New Batch», новая партия создаётся при приёмке автоматически, номер можно задать маской в поле Batch Number Series (например, «ABCD.#####»). Если нужен срок годности, включаете «Has Expiry Date» и заполняете «Shelf Life In Days».
Стратегия отгрузки задаётся не на товаре, а глобально, в Stock Settings: поле «Pick Serial / Batch Based On» принимает значения FIFO, LIFO и Expiry. Для FEFO выбираете Expiry. Рядом лежат связанные настройки: «Use Serial / Batch Fields» и «Auto Create Serial and Batch Bundle For Outward». Первая определяет, как вы вводите партии в строках документов, вторая позволяет системе создавать связку партий при проведении расходных документов самой. Как именно ведёт себя автоподбор на экране Serial and Batch Bundle в вашей версии, проверяйте на стенде, прежде чем выкладывать склад на рабочую схему: интерфейс партий менялся между v14 и v15.
Ловушек три, и все они из практики. Первая: отрицательные остатки по партиям система по умолчанию не пропускает, даже если в Stock Settings включён общий «Allow Negative Stock», поэтому приход, который опоздал с проведением, блокирует расход. В свежих сборках v15 появился отдельный флаг «Allow Negative Stock for Batch», но и он разрешает минус только из-за документов задним числом, а подсказка к нему прямо предупреждает об искажении оценки; я его не включаю. Дисциплина здесь важнее настроек: кладовщик сначала принимает, потом отгружает. Вторая: флаг «Has Batch No» нельзя менять, когда по товару уже есть проведённые документы, так что решение «партии нужны» принимается до загрузки остатков. Третья: у просроченной партии надо решить, что делать с ценой. В Selling Settings есть флаг «Set Incoming Rate as Zero for Expired Batch», и его нужно обсудить с бухгалтером до включения, а не после первого списания.
Корректировка остатков по партиям идёт документом Stock Reconciliation. В v15 партии в нём задаются через Serial and Batch Bundle, поэтому прежний путь «скачать CSV, заполнить, загрузить» для партионных позиций работает иначе, чем для обычных. Я заранее прогоняю инвентаризацию на 20–30 позициях на стенде и только потом ставлю её в регламент склада.
Закупка коробками, продажа штуками: UOM Conversion Factor
Типичная картина оптовика: поставщик отгружает коробками, паллетами или кратными упаковками, а покупатель берёт штуками. Если учитывать всё в одной единице, начинается ручной пересчёт и ошибки при инвентаризации. В ERPNext для этого есть три поля в карточке товара и таблица пересчёта. Базовая единица хранения называется «Default Unit of Measure» (stock UOM), закупочная и продажная задаются полями «Default Purchase Unit of Measure» и «Default Sales Unit of Measure». А коэффициент хранится в таблице «UOMs» (UOM Conversion Detail).
Для условной позиции «герметик в тубе, коробка 12 штук» карточка выглядит так: | Поле карточки Item | Значение | Смысл | |---|---|---| | Default Unit of Measure | Nos (штука) | единица хранения и складского регистра | | Default Purchase Unit of Measure | Box (коробка) | в заказе поставщику вводим коробки | | Default Sales Unit of Measure | Nos | продаём штуками | | UOMs: Box | Conversion Factor = 12 | 1 коробка равна 12 штукам | Коэффициент задаётся один раз. Система не даст завести коэффициент для базовой единицы, отличный от единицы: проверка в коде карточки требует равенства 1, иначе вы получите ошибку при сохранении.
В заказе поставщику вы вводите «40 коробок», а складской регистр получает 480 штук (40 × 12). Продали 150 штук, остаток 330 штук, то есть 27,5 коробки. Отчёты остатков по умолчанию показывают штуки, и это правильно, потому что склад отгружает штуками. Для коробок удобно вести отдельную строку отгрузки, когда покупатель берёт ровно коробками. Если коэффициент в карточке неточный (бывает, что поставщик меняет фасовку), в Stock Settings есть опции редактирования количества в базовой единице: «Allow to Edit Stock UOM Qty for Purchase Documents» и «Allow to Edit Stock UOM Qty for Sales Documents». Но я не рекомендую включать её без нужды: каждая ручная правка пересчёта становится потенциальной ошибкой остатка. Проще завести новую позицию или вариант с другой фасовкой.
Ещё одна проверка на стенде: если вы одновременно используете контроль бюджета и заказываете в альтернативной единице, возможны ложные срабатывания из-за пересчёта. Для оптовика это редкий случай, но я включаю его в тест-план.
Возвраты, корректировки и инвентаризация без потери остатков
Возврат от покупателя в опте происходит постоянно: бой, пересортица, неверная фасовка. И здесь в ERPNext есть тонкость, из-за которой остатки расходятся с реальностью. Есть два пути оформить возврат. Первый: из отгрузки (Delivery Note) нажать «Create → Sales Return», тогда создаётся возвратная отгрузка, которая меняет только склад. Второй: из счёта (Sales Invoice) нажать «Create → Return / Credit Note», и тогда создаётся кредит-нота с флагом «Is Return». Чтобы товар физически вернулся на склад именно через кредит-ноту, в ней нужно отметить «Update Stock».
Здесь осторожно: нельзя возвращать один и тот же товар двумя документами. Официальная документация прямо предупреждает: если возвратная отгрузка уже приняла товар, в кредит-ноте флаг «Update Stock» надо оставить выключенным, иначе остаток увеличится дважды. Я в проектах фиксирую правило в регламенте: либо возвращаем через отгрузку и кредит-нота только исправляет долг, либо один документ-кредит-нота с «Update Stock». Выбор зависит от того, кто у вас оформляет возврат, бухгалтер или кладовщик.
Инвентаризация в ERPNext делается документом Stock Reconciliation: он же вводит начальные остатки (цель «Opening Stock»). Для каждой позиции указывают склад, количество и ставку оценки (Valuation Rate), и именно ставка влияет на себестоимость, поэтому её нельзя оставлять нулевой. Начальные остатки вносят до первых регулярных операций: если оперативные документы появились раньше остатков, себестоимость искажается, и без пересчёта это не исправить.
Отдельно про даты. Документы задним числом ломают пересчёт: ERPNext поставит в фоне задачу «Repost Item Valuation», которая пересчитает последующие движения. Запрещать задним числом можно полем «Stock Frozen Upto» или «Freeze Stocks Older Than (Days)»; роль, которой разрешено править замороженные даты, задаётся полем «Role Allowed to Edit Frozen Stock». Мой регламент для оптовика: проведение задним числом больше чем на месяц не делается совсем, а пересчёты запускаются ночью, когда никто не отгружает.
Какой метод оценки запасов выбрать: FIFO или скользящая средняя
Метод оценки определяет, по какой цене товар уходит со склада, а значит, какую себестоимость вы увидите в отчёте. В Stock Settings есть поле «Default Valuation Method» с вариантами FIFO, Moving Average и LIFO, по умолчанию стоит FIFO. На карточке товара есть собственное поле «Valuation Method». Я выбираю для оптовика FIFO, когда партии различаются по цене и сроку, и Moving Average, когда товар однородный, а цена закупки плавает мелкими шагами.
Покажу на трёх приходах одного товара: 100 штук по 10 ₽, 100 штук по 12 ₽ и 100 штук по 14 ₽. Продали 150 штук после третьего прихода. Все цифры условные. | Метод | Как считает | Списано за 150 шт. | |---|---|---| | FIFO | 100 × 10 + 50 × 12 | 1 600 ₽ | | Moving Average | средняя 12 ₽ × 150 | 1 800 ₽ | Разница в 200 ₽ на одной сделке невелика, но в сумме по сотням позиций она формирует расхождение себестоимости. Документация ERPNext приводит близкий пример: после приходов 10 штук по 100 и 10 штук по 120 отгрузка 15 штук при FIFO стоит 1 600, а при Moving Average 1 650 (средняя 110). Логика та же: FIFO использует реальные слои цен, средняя сглаживает.
Теперь о том, что нельзя исправить потом. В коде карточки товара (v15) есть проверка: если по позиции есть проведённые документы, метод оценки менять нельзя, кроме перехода с FIFO на Moving Average. Обратно нельзя. Поэтому метод выбирают до загрузки остатков. Отрицательные остатки (Allow Negative Stock) ломают расчёт и FIFO, и скользящей средней, так что оставляйте этот флаг выключенным. Добавлю: и FIFO, и скользящая средняя требуют пересчёта, если вы правите прошлое, и пересчёт тяжёлый на длинной истории. Это ещё один довод держать склад в дисциплине дат.
Крепёж-Снаб: 22 рабочих места, три склада и коробки по 12 штук
Разберу условный пример. Оптовая компания «Крепёж-Снаб»: 22 рабочих места, три склада (основной оптовый, розничный и склад химии с контролем сроков), около трёх с половиной тысяч позиций. До проекта остатки вели в таблицах, а регламентированный учёт в 1С. Жалобы были типовые: коробка принимается как штука и наоборот, у герметиков и клея не видно ближайшей даты окончания срока, возвраты возвращаются на склад не всегда, и непонятно, по какой цене считать себестоимость.
План внедрения мы строили от склада. Первым шагом завели три склада и дерево номенклатуры, у позиций химии включили «Has Batch No», «Automatically Create New Batch» и «Has Expiry Date». Вторым настроили единицы измерения: коробки закупки в таблице UOMs с коэффициентами для каждой фасовки. Третьим выбрали метод оценки: FIFO для химии и Moving Average для крепежа, где цена закупки меняется мелкими шагами, при этом начальные остатки загрузили через Stock Reconciliation до первого оперативного документа. Четвёртым прописали регламент возвратов: возврат оформляет кладовщик через возвратную отгрузку, кредит-нота исправляет долг без «Update Stock».
Сроки в условном примере такие: неделя на разбор процесса и справочники, неделя на настройку и загрузку остатков, две недели пилота на складе химии, потом переключение двух остальных складов. Что видит команда после запуска: менеджер закупок вводит коробки и не пересчитывает штуки, кладовщик при отгрузке химии получает партию с ближайшей датой, возврат больше не двигает остаток дважды, а бухгалтер выгружает утверждённые счета в 1С. Я не обещаю процентов экономии: на пилоте мы смотрим на три контрольные вещи. Совпадает ли остаток с пересчётом. Нет ли партий, ушедших вне очереди. Сходится ли себестоимость партии с её закупочным слоем. Если все три совпадают, склад можно считать рабочим.
Показать, как выглядит такая цепочка на живых данных, можно на демостенде erp-demo.itfresh.ru: доступ выдаём по запросу, пароли публично не публикуем.
Что ERPNext для опта не закрывает и как это обходят
Честно перечислю границы, чтобы решение было осознанным. В ядре ERPNext нет российского регионального модуля: нет плана счетов по РСБУ, регламентированной отчётности, форматов ФНС. Формы УПД и ТОРГ-12 из коробки не поставляются, их делают как Print Format, обычно две-три базовые формы в проекте, либо формируют в 1С. Интеграции с российскими банками, онлайн-кассами, ЭДО и «Честным знаком» в базовой поставке отсутствуют, их подключают отдельной задачей.
Склад тоже не безграничен. Для партионного учёта на большом потоке важна производительность базы данных: параллельное проведение множества документов и тяжёлые отчёты вроде Stock Balance могут конфликтовать, и тогда помогает ограничение окна пересчёта в настройках Stock Reposting и ночной график. Мобильная работа кладовщика идёт через веб-интерфейс, нативного офлайн-приложения нет, а штрихкоды и терминалы сбора данных подключаются отдельной настройкой или интеграцией. Если ваш склад работает на ТСД с адресным хранением и сложной комплектацией, прочтите материал про ТСД на складе и интеграцию с 1С и честно оцените, не нужен ли вам специализированный WMS.
- Бухучёт РФ и регламентированная отчётность: остаются в 1С.
- УПД и ТОРГ-12: Print Format в проекте или формирование в 1С; детали в статье про печатные формы.
- Банки, ЭДО, онлайн-кассы, «Честный знак»: отдельные интеграции по ТЗ.
- Адресное хранение и сложная комплектация: оцените специализированный WMS.
- Дисциплина дат: минус по партиям по умолчанию заблокирован, пересчёты лучше ночью.
Частые вопросы
Подходит ли ERPNext для оптовой торговли?
Подходит для базового контура: закупка, склад, отгрузка, партии, возвраты и оценка запасов. Регламентированный учёт и нормативные формы УПД и ТОРГ-12 из коробки не поставляются: их делают отдельным Print Format или формируют в 1С. Если нужны ЭДО и онлайн-кассы, это отдельные интеграции по ТЗ.
Как в ERPNext вести партии и сроки годности?
На карточке товара включите «Has Batch No», при необходимости «Automatically Create New Batch» и «Has Expiry Date». Для отгрузки по FEFO в Stock Settings выберите «Pick Serial / Batch Based On» = Expiry. Партионные остатки корректируются документом Stock Reconciliation через Serial and Batch Bundle, поведение проверьте на стенде своей версии.
Как закупать коробками, а продавать штуками в ERPNext?
В карточке товара базовая единица хранения, например Nos, закупочная Box, а в таблице UOMs задаётся коэффициент пересчёта, скажем 12. В заказе поставщику вы вводите коробки, а складской регистр ведётся в штуках автоматически: 40 коробок превращаются в 480 штук.
Как оформить возврат от покупателя?
Из счёта нажмите «Create → Return / Credit Note». Чтобы товар вернулся на склад, отметьте «Update Stock». Но если товар уже принят возвратной отгрузкой (Delivery Note → Sales Return), флаг оставьте выключенным, иначе остаток увеличится дважды. Выберите один путь и зафиксируйте его в регламенте.
Чем ERPNext отличается от Odoo для склада небольшой компании?
ERPNext распространяется под GPLv3 и не берёт плату за пользователей, складской контур с партиями и сроками есть в базовой поставке. Odoo сильнее в экосистеме модулей и маркетплейсе, но часть функций доступна только в платной редакции Enterprise. Цены Odoo зависят от редакции и числа пользователей: проверяйте актуальный прайс на сайте вендора на день сравнения, цифры без даты несопоставимы.
Что выбрать для оценки запасов оптовику: FIFO или Moving Average?
По умолчанию стоит FIFO. Moving Average пересчитывает среднюю цену при каждом приходе, FIFO списывает по слоям цен. В карточке товара (v15) метод можно сменить с FIFO на Moving Average, но не обратно, если уже есть проведённые документы. Поэтому выбирайте метод до загрузки остатков.
Источники
- Документация ERPNext: Batch — Проверено: флаги «Has Batch No» и «Automatically Create New Batch», запрет отрицательных остатков для партионных позиций с v15. https://docs.frappe.io/erpnext/user/manual/en/batch
- Исходники ERPNext v15 и v16: Stock Settings и Item (GitHub) — Проверены поля valuation_method (FIFO, Moving Average, LIFO), pick_serial_and_batch_based_on (FIFO, LIFO, Expiry), has_batch_no, create_new_batch, has_expiry_date, shelf_life_in_days, purchase_uom, sales_uom, таблица uoms; ограничение смены метода оценки в item.py. https://github.com/frappe/erpnext/tree/version-15/erpnext/stock/doctype/stock_settings
- Документация ERPNext: Sales Return / Credit Note — Проверено: «Create → Return / Credit Note», «Is Return», «Update Stock» и предупреждение не возвращать товар двумя документами. https://docs.frappe.io/erpnext/user/manual/en/sales-return
- Документация ERPNext: Stock Reconciliation и оценка FIFO / Moving Average — Проверены Opening Stock, ставка оценки в сверке, пример FIFO 1 600 и Moving Average 1 650. https://docs.frappe.io/erpnext/user/manual/en/stock-reconciliation
- Исходники ERPNext v15: Buying Settings и Selling Settings (GitHub) — Проверены поля «Is Purchase Receipt Required for Purchase Invoice Creation?» (pr_required), «Is Delivery Note Required for Sales Invoice Creation?» (dn_required), «Set Incoming Rate as Zero for Expired Batch», а также «Allow Negative Stock for Batch» и «Role Allowed to Edit Frozen Stock» в Stock Settings. https://github.com/frappe/erpnext/blob/version-15/erpnext/selling/doctype/selling_settings/selling_settings.json












