Склад — учёт ТМЦ и оборудования
Склад (/admin/stock/) — универсальный учёт ТМЦ и
оборудования провайдера: от закупки до установки у клиента. Каждое перемещение —
неизменяемая запись-движение (как финансовые операции: не правим, а сторнируем),
поэтому остатки всегда сходятся, а история — доказуема. Модуль интегрирован с
нарядами монтажника, карточкой клиента и
деньгами: продажа списывает с лицевого счёта, аренда начисляется ежемесячно.
Содержание раздела
- Как устроен модуль
- Быстрый старт
- Движения и статусы единиц
- Номенклатура и остатки
- Остатки: где лежит запас и сколько он стоит
- Дефицит и список к закупке
- Карточка позиции и карточка единицы
- Приход, серийники, этикетки
- Подотчёт сотрудника
- «Я выдал»: что стало с выданным
- Журнал движений
- Инвентаризация: пересчёт и акт расхождений
- Лист пересчёта
- Что происходит при проведении
- Резерв под наряд
- Что резерв меняет в работе склада
- Перемещение между складами
- Поставщики
- Материалы в наряде монтажа
- Оборудование в карточке клиента
- Деньги: продажа и аренда
- Аналитика
- Скан-центр: операции с телефона
- Сканирование подряд и работа без связи
- Документы и интеграция с CRM
- Настройки, роли, алерты
- Несколько организаций: чьё что
- Чек-лист запуска
Приход, выдача в подотчёт, установка у клиента, возврат и инвентаризация. С озвучкой; весь текст продублирован на экране — можно смотреть и без звука.
Как устроен модуль
Ядро модели — цепочка держателей. Товар (или конкретная серийная единица) в каждый момент времени находится у одного держателя: на складе, в подотчёте сотрудника или у клиента. Перемещения между держателями фиксируются движениями:
flowchart LR
P["📦 Закупка
(накладная, поставщик)"] -->|"приход (receipt)"| W["🏬 Склад
остатки · min_stock"]
W -->|"выдача (issue)"| S["🧰 Подотчёт сотрудника
монтажник · скан"]
S -->|"установка (install)"| C["👤 Клиент
ответхранение · продажа · аренда"]
S -->|"возврат (return)"| W
C -->|"демонтаж"| W
W -->|"акт брака (defect)"| D["🗑 Брак"]
S -->|"акт брака"| D
style W fill:#e8f5e9,stroke:#43b77a
style C fill:#e7f0fb,stroke:#0d6efd
style D fill:#fdecea,stroke:#dc3545
Два типа учёта в одной модели:
- Поштучный (серийный) — роутеры, ONU, камеры: каждая единица
со своим серийником, MAC и этикеткой со штрихкодом
SU-N. Всегда видно, «где сейчас этот роутер» и вся его биография. - Количественный — кабель метрами, коннекторы, крепёж: остаток держателя считается по сумме движений, дробные количества поддерживаются.

flowchart TB
ST["📦 Склад
номенклатура · единицы · движения"]
CRM["🛠 Наряд монтажа (CRM)
кнопка «Материалы»"]
AB["👤 Карточка клиента
вкладка «Оборудование»"]
FIN["💰 Финансы
FinanceOperations"]
UU["🔁 Услуги клиента
UsersUsluga «Аренда оборудования»"]
BW["⚙️ billing_worker
ежемесячные списания"]
TG["✈️ Telegram
алерт min_stock"]
AUD["🗒 Аудит
каждое движение"]
CRM -->|"install (ref: deal#N)"| ST
AB -->|"install / демонтаж"| ST
ST -->|"продажа: −sale_price"| FIN
ST -->|"аренда: услуга rent_price/мес"| UU
UU --> BW
ST --> TG
ST --> AUD
style ST fill:#e8f5e9,stroke:#43b77a,stroke-width:2px
Быстрый старт
- Включите модуль «Склад» на
/admin/settings/modules/и тумблерSTOCK_ENABLEDв настройках (категория «Склад»). - Добавьте кладовщика в группу
storekeeper(настройкаSTOCK_KEEPER_GROUPS); монтажников — в группы изSTOCK_HOLDER_GROUPS. - Заведите категории и номенклатуру (
/admin/stock/items/) — или посмотрите на демо-данных:manage.py seed_stock_demo(удаление —--clear). - Проведите стартовую инвентаризацию: приход с типом «инвентаризация (correction)» на текущие остатки.
- Распечатайте этикетки на серийные единицы и выдайте монтажникам их текущее «железо» в подотчёт.
Движения и статусы единиц
Движение (StockMovement) — append-only запись: тип, позиция,
количество, откуда → куда, цена, документ, привязка к наряду
(ref_type/ref_id). Ошиблись — нажимаете сторно:
создаётся обратная запись, а единица возвращается к держателю-источнику.
Серийная единица (StockUnit) дополнительно несёт статус:
stateDiagram-v2
[*] --> in_stock: приход
in_stock --> issued: выдача в подотчёт
issued --> in_stock: возврат
in_stock --> installed: установка (кладовщик)
issued --> installed: установка (custody)
issued --> sold: продажа
issued --> rented: аренда
installed --> in_stock: демонтаж
rented --> in_stock: демонтаж (аренда закрывается)
issued --> defect: акт брака
in_stock --> defect: акт брака
В журнале — фильтры по типу движения и по сотруднику (показываются все движения, где он «откуда», «куда» или «кто провёл»); клик по любой фамилии в таблице подставляет её в фильтр. Колонка S/N — единая иконка штрихкода (во всех таблицах модуля): тултип показывает серийник, MAC и штрихкод, клик открывает карточку движения со всеми деталями. Даты — компактно «дд.мм.гг», полная дата в тултипе.

Номенклатура и остатки
Позиция каталога задаёт: категорию, единицу измерения, тип учёта
(поштучный/количественный), режим передачи клиенту
(ответхранение / продажа / аренда — можно переопределить при установке),
три цены (закупочная, продажи, аренды в месяц) и минимальный остаток
min_stock для алертов.
Пресеты номенклатуры: кнопка «Пресеты» на странице номенклатуры добавляет готовый набор позиций с категориями, ценами и порогами остатков — «Интернет-провайдер (ISP)», «Видеонаблюдение», «Домофония». Применение идемпотентно: существующие позиции с теми же названиями не меняются.


Остатки: где лежит запас и сколько он стоит
Страница «Остатки» отвечает на вопрос «что у нас есть» не только штуками, но и деньгами. Над таблицей — полоса распределения: сколько лежит на складе, сколько на руках у монтажников, сколько уже стоит у клиентов и сколько списано в брак. Рядом с количеством — сумма по закупочной цене, чтобы было видно, сколько денег заморожено на складе и в подотчётах.
flowchart LR
S["Склад
2445 шт · 138 751 ₽"] -->|выдача| P["Подотчёты монтажников
486 шт · 48 815 ₽"]
P -->|установка| C["У клиентов
518 шт"]
P -->|возврат| S
C -->|демонтаж| S
P -->|акт брака| D["Брак
7 шт"]
S -->|акт брака| D
Таблица сортируется кликом по любому заголовку, фильтруется по складу и категории и выгружается в CSV — ровно тот срез, который на экране. Внизу — строка итогов: сколько позиций попало в выборку и на какую сумму.

Дефицит и список к закупке
У позиции задаётся минимальный остаток. В номенклатуре рядом с остатком показывается дефицит — сколько не хватает до минимума с учётом того, что уже на руках у монтажников. Кнопка «К закупке» выгружает CSV со списком: что докупить, сколько и на какую сумму по закупочной цене — такой файл можно сразу отдать снабженцу.

Карточка позиции и карточка единицы
Чтобы посмотреть, что происходит с конкретной позицией или с конкретной единицей оборудования, никуда переходить не нужно: обе карточки открываются боковой панелью поверх текущего списка.
Карточка позиции — клик по названию позиции в остатках, номенклатуре, «Я выдал» или в модалке движения. Что показывает:
- полосу распределения остатка: сколько на складе, сколько в подотчётах у сотрудников, сколько стоит у клиентов и сколько списано в брак;
- деньги по закупочной цене — во что обходится склад и подотчёты;
- минимальный остаток и дефицит до него со ссылкой на оформление прихода;
- разбивку по складам и по держателям подотчёта;
- вкладки: Единицы (все серийники со статусом и местом), История (последние движения), У клиентов.
Карточка единицы — клик по иконке штрихкода (S/N) в любой таблице склада или ссылка из карточки позиции. Показывает, где единица сейчас (склад, сотрудник или клиент), режим передачи, цены, даты — и таймлайн владения: приход → выдача в подотчёт → передача другому сотруднику → установка клиенту → демонтаж или брак. Сторнированные события зачёркнуты.


Обе карточки уважают организацию: чужую позицию или единицу открыть нельзя (см. 10а. Несколько организаций).
Приход, серийники, этикетки
Приход оформляется накладной: номер документа, склад, позиции. Для серийных позиций серийники сканируются подряд — камерой телефона (на Android — BarcodeDetector, на iPhone — ZXing), USB-сканером или вручную. После проведения — печать этикеток:
- PNG-пачка (ZIP) — под мобильный термопринтер (Niimbot B18, 203 dpi, размер ленты из настроек, по умолчанию 40×14 мм);
- PDF-лист А4 — под обычный принтер.
На этикетке — штрихкод Code128 (или QR) со значением SU-N и серийник.
Code128 кодирует только латиницу и цифры — если значение штрихкода содержит
кириллицу, система автоматически строит QR-код (кодирует любой
текст, сканируется камерой телефона), чтобы код оставался читаемым. Во всех
таблицах модуля при наведении на иконку штрихкода всплывает
сканируемая картинка кода — сканер прикладывают прямо к экрану,
не отходя к принтеру этикеток.

Подотчёт сотрудника
Кладовщик выдаёт монтажнику оборудование по скану и расходники количеством. Выбор сотрудника — единый компонент ProfileSelect (аватар, роли, поиск). У монтажника есть свой мобильный экран «Мой подотчёт»: что на руках, возврат на склад, акт брака.


«Я выдал» (/admin/stock/issued/) — зеркальная
страница для кладовщика: все выдачи и передачи, которые он провёл, и
судьба каждой единицы — в чьём подотчёте сейчас, установлена
или в аренде у клиента (ссылка на его вкладку «Оборудование»), возвращена на
склад, списана в брак или сторнирована. В профиле сотрудника — блоки
«Мой подотчёт» (итог материальной ответственности + акт PDF, даты выдачи)
и «Я выдал».

Передача подотчёт→подотчёт: при включённой настройке сотрудники передают единицы друг другу (например, бригадир — монтажнику) без возврата на склад; движение «Перемещение» в журнале, уведомление получателю, проверка матрицы прав и лимита.
«Я выдал»: что стало с выданным
Кладовщику важно не то, что он выдал, а что с этим стало. Страница «Я выдал» показывает каждую выдачу и передачу вместе с текущей судьбой единицы, а сверху — счётчики по судьбам: сколько ещё в подотчёте, сколько уже стоит у клиентов, сколько вернулось, сколько ушло в брак и сколько сторнировано. Клик по счётчику оставляет в списке только эти строки; рядом — фильтры «кому выдал» и период.

Журнал движений
Журнал — полная история склада: приход, выдача, передача, установка, возврат, брак и сторно. Фильтры — период, организация, склад, сотрудник и тип движения; выгрузка в CSV отдаёт тот же отфильтрованный срез. Из карточки движения открываются карточка единицы и карточка позиции.

Инвентаризация: пересчёт и акт расхождений
Все цифры склада — остатки, дефицит, стоимость запаса — держатся на одном допущении: то, что в базе, лежит на полке. Проверяет это инвентаризация. Раздел Склад → Инвентаризация показывает список актов; кнопка «Начать пересчёт» открывает новый лист по выбранному складу.

Главное правило: пересчёт не правит историю. Разница оформляется отдельными движениями типа «Корректировка (инвентаризация)» со ссылкой на акт: видно, что расхождение было, когда, на сколько и кто его провёл. Приход остаётся таким, каким был.
flowchart LR
O["Открыли лист
снимок остатков склада"] --> C["Считаем полку
факт по позициям"]
O --> S["Сканируем серийники
штрихкод или s/n"]
C --> P["Проводим акт"]
S --> P
P --> M["Движения «Корректировка»
со ссылкой на акт"]
P --> L["Ненайденная единица →
статус «Недостача»"]
P --> E["Найденная лишняя →
приходуется на склад"]
Лист пересчёта
Лист запоминает учётный остаток на момент открытия — акт показывает ту цифру, от которой считали, даже если склад потом двигали. Сверху — свод: сколько позиций, сколько внесено, сколько излишков и недостач, сколько серийников найдено и во что расхождение обходится по закупочной цене.

- Факт по позициям. Вводится прямо в таблице, сохраняется само — отходить и жать «Сохранить» не нужно. Расхождение считается сразу, строка подсвечивается. Отрицательный факт не принимается: на полке не может лежать минус.
- Серийные позиции считаются сканером, а не цифрой в поле: важно не «сколько», а «какие именно». Сканировать можно ручным сканером в поле ввода или камерой телефона. Что не отсканировано — попадёт в недостачу; что нашлось, хотя числилось не здесь, — в излишки с пометкой, откуда единица.
- Фильтры «Только непосчитанные» и «Только расхождения» помогают дойти до конца по большому складу и потом быстро пересмотреть спорные строки.
- Акт CSV выгружается на любой стадии — это и есть тот документ, который подписывают.
Защита от «провёл, не считая». Если по листу не отмечена ни одна серийная единица, при проведении серийники не трогаются вовсе — иначе один клик отправил бы весь склад в недостачу. Если отсканирована меньше половины — подтверждение красное и называет цифры: сколько найдено и сколько уйдёт в недостачу. Непосчитанные позиции (пустой факт) не меняются никогда.
Что происходит при проведении
- По каждой позиции с расхождением создаётся движение «Корректировка»: на склад — если излишек, со склада — если недостача. В комментарии указано, что было по учёту и что нашли по факту.
- Ненайденная серийная единица получает статус «Недостача». Это не «Брак»: бракованная железка лежит на складе и её видно, а недостачи физически нет. Единица снимается со склада, но остаётся в базе — её история сохраняется, и если она найдётся, её можно оприходовать следующим актом.
- Лист закрывается: провести повторно нельзя, исправить — только сторно движений, как и везде на складе.
- Отменить лист можно, пока он не проведён: внесённые цифры пропадают, движений не создаётся, пересчёт можно начать заново.
На один склад одновременно открыт один лист — иначе два человека считали бы одно и то же и оба провели бы расхождение. Лист живёт в границах организации своего склада: чужие позиции в него не попадают.
Резерв под наряд
Остаток на складе перестал быть ответом на вопрос «можно ли брать»: часть запаса уже обещана конкретным адресам. Резерв — это обещание, а не движение: вещь физически лежит на складе, но считается занятой. Без него монтажник приезжал к клиенту за роутером, который час назад увезли на другой адрес — остаток был, а вещи не было.
Бронь ставится там, где о ней думают, — в наряде, в модалке «Материалы наряда». Клиент для этого не нужен: наряд уже есть, вещь нужна.

Общая картина — в разделе Склад → Резервы: что отложено, под какой наряд, к какой дате и кем. Оттуда же бронь снимается.

Что резерв меняет в работе склада
- «Свободно» = остаток − активные резервы. В остатках появилась колонка «В резерве»; подсказка на числе показывает свободный остаток.
- Выдать больше свободного нельзя. Попытка забрать чужую бронь отклоняется с цифрами: сколько свободно и сколько занято под другие наряды. Выдача по своему резерву разрешена всегда — она его и закрывает.
- Серийная единица бронируется поимённо. Другой наряд её не заберёт, даже если однотипных на складе много.
- Резерв закрывается сам, когда зарезервированное ушло по назначению — выдачей в подотчёт или списанием на клиента по тому же наряду. Частично израсходованный резерв уменьшается, а не пропадает.
- Забронированное не переезжает на другой склад: бронь привязана к складу, с которого её будут выдавать.
flowchart LR
R["Бронь под наряд
позиция или единица"] --> F["Свободно = остаток − резервы"]
F -->|"выдача по этому наряду"| C["Резерв закрыт
ушло по назначению"]
F -->|"выдача под другой наряд"| X["Отказ
«свободно N, занято M»"]
R -->|"наряд отменён"| S["Резерв снят
позиция снова свободна"]
Перемещение между складами
Переезд коробки с центрального склада в филиал — одно движение типа «Перемещение», а не списание с одного склада и приход на другой. Пара движений выглядела бы в журнале как потеря в одном месте и находка в другом, хотя это одна и та же вещь.

Кнопка «Переместить» — в разделе «Остатки». Переместить можно количеством (расходники) или по штрихкоду конкретной единицы. Не даст: на тот же склад, больше, чем лежит, забронированное под наряды и — отдельно — между складами разных организаций: передача имущества между юрлицами оформляется продажей, а не складской проводкой.
Поставщики
Поставщик — отдельный справочник, на который ссылается приход: одна карточка на фирму, вся история закупок и цен в одном месте. Отсюда ответ на вопрос «сколько у них закупили и почём брали в прошлый раз».

- На приходе поставщик выбирается из списка; кнопка + рядом заводит нового, не уходя со страницы.
- Справочник — в «Номенклатуре», кнопка «Поставщики». У каждого видны реквизиты и история: сколько поставок, на какую сумму, когда была последняя.
- Сумма закупки считается как цена × количество — по всем приходам этого поставщика.
Материалы в наряде монтажа
На карточке наряда (/admin/crm/montazh/) — строка
«Материалы: N». Модалка позволяет прямо с телефона на объекте:
- добавить оборудование из своего подотчёта (или отсканировать серийник);
- списать расходники: кабель метрами, коннекторы штуками;
- убрать ошибочное списание (сторно — единица вернётся в подотчёт);
Все списания привязываются к сделке (deal#N) и к учётке клиента.
Если у сделки ещё нет клиента — модалка подскажет сначала создать его из
карточки сделки. Настройка STOCK_REQUIRE_MATERIALS_ON_DONE включает
жёсткий режим: наряд нельзя закрыть «Выполнено», пока не указаны материалы.
Установка только «своим» клиентам: настройка
STOCK_INSTALL_REQUIRE_MONTAGE (по умолчанию выкл.) ограничивает
монтажников — установить или демонтировать оборудование клиенту можно, только
если у монтажника есть на него наряд в CRM (сделка, где он назначен монтажником
и проставлена дата монтажа — то же, что «мой наряд» на
/admin/crm/montazh/). Кладовщик, суперпользователь и менеджеры
работают без ограничения. Смена статуса единиц по-прежнему возможна только для
того, что в своём подотчёте.


Оборудование в карточке клиента
Вкладка «Оборудование» (прямая ссылка —
/admin/Abonents/<id>/equipment/): всё оборудование со склада у
клиента со статусами, история установок со сторно, ручная установка из подотчёта
и демонтаж (с вопросом «исправное или брак?»). При установке
серийной единицы её MAC/серийник автоматически подставляются в учётку клиента
(тумблер STOCK_AUTO_FILL_MAC).

Деньги: продажа и аренда
Режим передачи определяет финансовые последствия установки:
flowchart TB
I["Установка клиенту
(наряд / карточка / API)"]
I --> CU["Ответхранение
(custody)"]
I --> SA["Продажа
(sale)"]
I --> RE["Аренда
(rent)"]
CU --> CU2["Только движение и статус.
Оборудование — собственность оператора"]
SA --> SA2["FinanceOperations:
−цена продажи с лицевого счёта
метка [stock:mv:N]"]
RE --> RE2["UsersUsluga «Аренда оборудования»
цена/мес · начисления с 1-го числа
следующего месяца (billing_worker)"]
SA2 -.->|сторно| SA3["Деньги возвращаются на счёт,
операция помечается «сторно»"]
RE2 -.->|"демонтаж / сторно"| RE3["Услуга аренды выключается,
новых начислений нет"]
style SA2 fill:#fdecea,stroke:#dc3545
style RE2 fill:#fff3cd,stroke:#fd7e14
style CU2 fill:#e8f5e9,stroke:#43b77a
Аналитика
Страница /admin/stock/analytics/ (кладовщик/руководитель) — деньги
и движение ТМЦ за период (месяц/квартал/год/даты). Сверху — интерактивные
графики в стиле главного дашборда: движения по дням (стек-диаграмма
приход/выдача/установка/возврат), структура склада по категориям в рублях
(пончик), топ-5 установок за период и подотчёты сотрудников. Графики
поддерживают тёмную тему и перерисовываются при смене периода.
- KPI: стоимость склада и подотчётов по закупочной, единиц у клиентов, продажи за период, аренда (MRR) и число активных аренд, средняя себестоимость подключения, установок за период;
- Обороты по позициям: приход / выдано / установлено / возврат / брак — количеством и в рублях по закупочной;
- Подотчёты сотрудников: сколько единиц и на какую сумму на руках у каждого монтажника, с составом;
- Себестоимость подключений: по каждому наряду
(
deal#N, со ссылками на сделку и клиента) — сколько материалов и на какую сумму ушло. Сторно исключается автоматически.

Скан-центр: операции с телефона
Страница /admin/stock/scan/ (пункт меню «Скан») — максимум
автоматизации в поле: сотрудник наводит камеру телефона на этикетку (код
помещается в рамку-видоискатель с бегущей линией; можно ввести S/N вручную),
и система сама предлагает действие по статусу единицы и роли
сотрудника:
- единица на складе: кладовщик видит «Выдать сотруднику» —
селект сотрудника с аватарками, после выбора появляется необязательный
комментарий, подтверждение создаёт выдачу; остальные сотрудники
видят «Ответхранение (взять себе)» — единица уходит в их собственный
подотчёт (комментарий необязателен); выдать чужому не-кладовщик не может,
матрица
STOCK_ISSUE_RULESи лимит подотчёта действуют; - единица в моём подотчёте — вернуть на склад, оформить брак или передать коллеге (если передача разрешена настройкой; комментарий — в том же окне выбора сотрудника);
- единица у клиента — демонтаж на склад или в брак (аренда закрывается автоматически). Клиент показан отдельной строкой — ссылкой на его вкладку «Оборудование».
После выдачи или взятия на ответхранение в карточке появляется кнопка «Распечатать акт (PDF)» — открывается акт подотчёта получателя (материальная ответственность с подписями); при передаче между сотрудниками кнопку видит кладовщик. Кнопка «Вся история» выдвигает справа сайдбар со всеми событиями единицы по датам: тип операции, откуда → куда, кто провёл, комментарий; сторнированные записи перечёркнуты.
Совместимость: на Android работает нативный
BarcodeDetector; на iPhone (WebKit его не поддерживает)
автоматически подгружается декодер ZXing — сканирование доступно во всех
браузерах. После каждого действия — уведомление и журнал операций на экране;
можно сканировать следующий код без перезагрузки. USB-сканер работает как
клавиатура (ввод + Enter).

Сканирование подряд и работа без связи
Сканирование в поле рассчитано на две ситуации: серия кодов подряд и работа без связи.
- «Сканировать подряд» — камера остаётся включённой, этикетки идут потоком. Приёмка партии из сорока коробок больше не значит сорок раз открыть камеру. Повтор того же кода в течение трёх секунд не считается новым (этикетка не уезжает из кадра мгновенно), а на каждый принятый код звучит короткий сигнал — за экраном следить не нужно.
- Работа без связи. Если сети нет, действие не пропадает: оно встаёт в очередь в браузере и уходит само, как только связь появилась. Очередь переживает перезагрузку страницы и закрытие вкладки — можно спокойно спуститься в подвал, отработать и подняться.
- Индикатор «Не отправлено: N» с кнопкой «Отправить сейчас» — видно, что ещё висит. Если сервер отказал по существу (например, единицу уже забрал другой), задача снимается с очереди с пометкой в истории, а не крутится вечно; сетевые сбои повторяются с сохранением порядка.
- История сканов (последние 50 действий) тоже переживает перезагрузку: видно, что успел сделать за смену.
Что офлайн-режим не делает. Он не решает за сервер: права, организация и остаток проверяются в момент реальной отправки. Поэтому действие, отложенное в очередь, может быть отклонено позже — об этом будет запись в истории с причиной.
Документы и интеграция с CRM
Складские операции оформляются печатными документами (PDF, реквизиты организации клиента подставляются автоматически):
- Акт приёма-передачи оборудования клиенту — перечень всего переданного (S/N, режим, стоимость; аренда — ₽/мес), подписи сторон. Кнопки: вкладка «Оборудование» карточки клиента, модалка «Материалы» наряда (акт по конкретному наряду), карточка сделки CRM.
- Акт передачи ТМЦ в подотчёт — материальная ответственность сотрудника с итоговой суммой по закупочной. Кнопки: блок «Мой подотчёт» в профиле, аналитика (иконка PDF у сотрудника).
Связь с CRM: в карточке сделки (вкладка «Подключение») показываются материалы наряда — количество позиций и себестоимость по закупочной, рядом — PDF-акт. В профиле сотрудника — блоки «Мой подотчёт» (что на руках, итог ответственности, акт) и «Я выдал» (для кладовщика). Из «Остатков» число «У клиентов» открывает список клиентов со ссылками на их вкладку «Оборудование».
Настройки, роли, алерты
Схема данных модуля:
erDiagram
StockCategory ||--o{ StockItem : "категория"
StockUom ||--o{ StockItem : "ед. изм."
StockItem ||--o{ StockUnit : "серийные единицы"
StockItem ||--o{ StockMovement : "движения"
StockUnit |o--o{ StockMovement : ""
StockWarehouse |o--o{ StockMovement : "src/dst склад"
StockUnit }o--o| Abonents : "у клиента"
StockMovement }o--o| FinanceOperations : "продажа [stock:mv:N]"
StockUnit }o--o| UsersUsluga : "аренда [stock:unit:N]"
StockItem {
bool is_serialized "S-N или количеством"
string transfer_mode "custody-sale-rent"
money purchase_sale_rent "3 цены"
decimal min_stock "порог алерта"
}
StockUnit {
string serial_mac_barcode "SU-N"
string status "in_stock-issued-installed-sold-rented-defect"
}
StockMovement {
string mv_type "receipt-issue-install-return-defect-storno"
string ref "deal-manual + id"
}
| Настройка | Default | Назначение |
|---|---|---|
STOCK_ENABLED | OFF | Главный тумблер модуля |
STOCK_KEEPER_GROUPS | storekeeper, root | Кладовщики: приход, выдача, сторно чужих движений, установка прямо со склада |
STOCK_HOLDER_GROUPS | installer, … | Кому можно выдавать в подотчёт |
STOCK_BARCODE_FORMAT | code128 | Формат этикетки (code128 / qr) |
STOCK_LABEL_W_MM / H_MM | 40 × 14 | Размер этикетки под ленту принтера |
STOCK_AUTO_FILL_MAC | ON | Подставлять MAC/серийник в учётку клиента при установке |
STOCK_REQUIRE_MATERIALS_ON_DONE | OFF | Жёсткий режим: наряд не закрывается без материалов |
STOCK_ISSUE_RULES | — | Матрица «кто→кому»: JSON {"группа выдающего": ["группы получателей"]}; пусто — кладовщики выдают всем держателям |
STOCK_ALLOW_STAFF_TRANSFER | OFF | Передача подотчёт→подотчёт между сотрудниками (движение «Перемещение») |
STOCK_MAX_STAFF_COST | 0 | Лимит стоимости подотчёта, ₽ по закупочной — выдача сверх лимита блокируется |
STOCK_STALE_ISSUED_DAYS | 0 | Telegram-алерт: единица висит в подотчёте без движения дольше N дней |
STOCK_ORG_STRICT | ON | Запрет установки клиенту чужой организации (см. раздел 10а). Выключать только если у вас сознательно общий склад на несколько юрлиц |
STOCK_INSTALL_REQUIRE_MONTAGE | OFF | Монтажник ставит/демонтирует оборудование только клиентам со своим нарядом в CRM (сделка: он монтажник + дата монтажа). Кладовщик/суперюзер/менеджеры — без ограничений |
Мульти-организация: правила «чьё что» вынесены в отдельный раздел — 10а. Несколько организаций.
Алерт остатков: раз в сутки задача stock-min-alert
собирает позиции ниже min_stock и отправляет одно сообщение
в Telegram-группу оператора со ссылкой на страницу прихода.
Аудит: каждое движение пишется в журнал аудита
(STOCK_MOVEMENT) — кто, что, куда и когда переместил.
Несколько организаций: чьё что
Если в биллинге заведено больше одной организации, склад ведётся по каждой отдельно: своя номенклатура, свои склады, свои сотрудники, свои деньги. Сотрудник видит и трогает только то, что относится к доступным ему организациям.
| Объект | Кому принадлежит | Что из этого следует |
|---|---|---|
| Позиция номенклатуры | Организации (выбирается в модалке позиции) | Чужие позиции не видны в списках, поиске, аналитике и журнале |
| Склад | Организации (обязательно) | Приход и выдача идут в границах организации: склад одного юрлица не подставится под позицию другого |
| Категория | Организации или общая | «Роутеры» и «ONU/Оптика» разумно держать общими — иначе разъедутся отчёты и пресеты |
| Единица (серийник) | Наследует организацию позиции в момент прихода | Дальше не меняется: история владения не «переезжает», если позицию потом переведут в другую организацию |
| Движение | Фиксируется в момент проводки | Журнал и аналитика фильтруются по организации самого движения, а не по текущему состоянию позиции |
| Сотрудник | Организациям из профиля | Выдать и передать подотчёт можно только сотруднику своей организации |
flowchart TB
subgraph A["Организация «СмИТ»"]
A1[Склад организации А] --> A2[Позиция: ONU]
A2 --> A3[Единица SU-56]
A3 --> A4[Клиент организации А]
end
subgraph B["Организация Б"]
B1[Склад организации Б] --> B2[Позиция: ONU]
B2 --> B3[Единица SU-77]
B3 --> B4[Клиент организации Б]
end
A3 -. запрещено .-> B4
B3 -. запрещено .-> A4
Установка клиенту — только внутри своей организации.
Оборудование организации А нельзя поставить клиенту организации Б: система
ответит «Позиция принадлежит организации А, а клиент — Б». Причина не
формальная: себестоимость списывается со склада одной организации,
а операция продажи или услуга аренды создаётся у клиента — то есть
в другой организации. После такой установки не сходится ни у одной
из сторон. Правильный путь — завести позицию в организации клиента.
Ограничение снимается настройкой STOCK_ORG_STRICT = 0, если
у вас сознательно общий склад на несколько юрлиц.
Где это видно в интерфейсе. Колонка и бейдж «Орг.» в номенклатуре и на остатках; выбор организации в модалке позиции и в справочнике складов; фильтр по организации и выгрузка CSV в журнале движений. Списки организаций в этих селектах приходят с сервера уже отфильтрованными по правам сотрудника — увидеть в выпадающем списке чужую организацию нельзя.
Что проверить при запуске второй организации: завести ей свой склад (иначе приход уедет на склад по умолчанию), завести номенклатуру в её организации, проверить у сотрудников привязку к организациям в профиле — от неё зависит, кому можно выдавать подотчёт.
Чек-лист запуска
- Группа
storekeeper+ учётка кладовщика в ней. - Категории и номенклатура (типовые позиции ISP: роутеры, ONU, кабель,
коннекторы). Для знакомства —
manage.py seed_stock_demo, очистка демо —seed_stock_demo --clear. - Стартовая инвентаризация — приход «инвентаризация (correction)» на фактические остатки склада и подотчётов.
- Печать этикеток на серийные остатки.
STOCK_ENABLED = ON— с этого момента монтажники видят «Мой подотчёт», в нарядах появляются «Материалы», в карточках клиентов — вкладка «Оборудование».