Перейти к содержимому

Производство · Внутренняя система

Naryado

Мебельное производство: заявка, план цеха и отгрузка идут одним номером. Пять систем, которые уже стояли, обмениваются данными через общий контур, а не через таблицы.

Роль
Аналитика, бэкенд, интеграции
Срок
8 месяцев
Стек
Python · PostgreSQL · Redis

Что изменилось

20 минут
от подтверждения заявки до строки в плане цеха. Раньше заявка попадала туда на следующее утро.
9 → 0
точек, где одни и те же данные набирали руками во вторую систему.
0,4%
расхождение остатков на месячной инвентаризации. До перехода было от 4 до 6%.
1,5 дня
в неделю, которые уходили у двух человек на сверку перед отчётом руководству. Отчёт теперь собирается сам, из журнала.

Что не изменилось — срок производства. Он зависит от загрузки цеха и поставки плиты, а не от учёта. Контур сделал срок предсказуемым: дату отгрузки называют в день приёма заявки, и она держится. Коротким срок не стал.

Что было до

Заявку подтверждал менеджер в CRM, в таблицу «План цеха» переносил её руками он же, остатки плиты и кромки проверял склад в своей программе, документы выписывала бухгалтерия, рейс бронировал логист на портале перевозчика. Между «клиент подтвердил» и «строка в плане» проходила смена, а срочное шло по телефону мимо всех таблиц и попадало в них задним числом.

  • У одной заявки было четыре номера: в CRM, в таблице цеха, в накладной и в рейсовом листе. Чтобы сказать клиенту, где его заказ, менеджер звонил в три места.
  • Двенадцать таблиц в шести отделах и девять точек, где одни и те же данные набирали во второй раз.
  • Раз в неделю два человека полтора дня сводили цифры к отчёту для руководства и каждый раз находили расхождения — чаще всего в остатках.

Что сделали

  • Единый номер заявки: приём, план цеха и отгрузка стали одной записью с историей изменений вместо четырёх строк в четырёх местах.

  • Пять интеграций: бухгалтерия, склад, CRM, система раскроя и портал перевозчика обмениваются через очередь, каждая своим протоколом.

  • Отчётность из тех же данных: недельный отчёт руководству и утренний список расхождений собираются из журнала событий, без сверки руками.

Результат

Пять систем остались на местах, но заявка больше не переезжает между ними руками: она проходит от приёма до отгрузки одним номером, а обмен делает контур. Статус заказа виден менеджеру без звонка в цех, недельный отчёт собирается из журнала, а спор о том, чьи цифры правильные, кончился вместе с двенадцатью таблицами.

Кто заказчик

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

Заявка — это не одно изделие, а комплект: раскрой плиты, кромка, присадка, фурнитура, упаковка. В день с площадки уходит около сорока пяти отгрузок, часть из них собрана из нескольких заявок. Справочник — сорок тысяч позиций, от декоров ЛДСП до крепежа.

Задача

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

Почему нельзя было в лоб

Пять систем уже стояли, работали и принадлежали разным людям. Каждая поставила своё условие, и каждое из этих условий видно в архитектуре.

Бухгалтерия (1С)
На поддержке внешнего подрядчика, релизы раз в квартал. Доработок мы не заказывали: читаем через OData, пишем ровно один документ — реализацию по факту отгрузки.
Складская программа
Коробочная, без API. Единственный выход наружу — выгрузка CSV в общую папку раз в пятнадцать минут. Значит, остаток в контуре в худшем случае на четверть часа старше правды, и это нужно было не спрятать, а показать.
Система раскроя
Считает карты раскроя и нормы времени, трогать её никто не дал. Читаем реплику её базы, обратно не пишем ничего.
CRM отдела продаж
Отдаёт вебхуки, но позволяет править подтверждённую заявку задним числом: комплектация меняется после того, как клиент уже сказал «да». Контур обязан принимать изменение, а не считать заявку замороженной.
Портал перевозчика
SOAP, один запрос в секунду, ночные окна обслуживания. Ходить туда синхронно нельзя: рейс бронируется не в тот момент, когда логист нажал кнопку.
Справочник номенклатуры
Одна и та же плита называлась по-разному в трёх системах: артикул поставщика в закупке, внутренний код на складе, наименование в бухгалтерии. Пока их не сопоставили, любой сводный отчёт был спором о том, чьи цифры правильные.

Как шла работа

  1. 01

    Разбор

    1 месяц

    Двадцать три интервью, от менеджера до кладовщика, и путь заявки, нарисованный на стене. Там и посчитали двенадцать таблиц, девять точек двойного ввода и четыре номера у одной заявки. Итог этапа — не техзадание, а решение не заменять пять систем.

  2. 02

    Ядро учёта

    1,5 месяца

    Модель заявки, плана и отгрузки, единый номер, таблица соответствий с внешними идентификаторами, журнал событий. Только PostgreSQL, без интеграций: контур сначала научился жить сам, на данных, введённых руками.

  3. 03

    Интеграции

    2 месяца

    Пять подключений и сопоставление номенклатуры. По артикулу автоматически сошлись 86% позиций; оставшиеся 5 600 три недели разбирали два человека со стороны заказчика — по правилу и списку исключений.

  4. 04

    План цеха и отгрузка

    1,5 месяца

    Очередь по участкам, комплектность заявки, отгрузка, собранная из нескольких заявок, бронь рейса. Здесь же появились статусы, которые видит менеджер, — то, ради чего всё и затевалось.

  5. 05

    Параллельная работа и переход

    2 месяца

    Шесть недель контур и таблицы вели одно и то же одновременно, расхождения разбирали каждое утро. Таблицы выключали по одной; последними ушли цеховая и логистическая.

Технические решения

Три вещи в стеке, и у каждой здесь одна работа: Python разговаривает с чужими системами, PostgreSQL хранит данные и отвечает за их согласованность, Redis держит обмен асинхронным.

  • Один номер вместо четырёх

    Заявка, план и отгрузка — записи одной базы, связанные внешними ключами и меняющиеся в одной транзакции: отгрузка не может уехать по заявке, которой нет в плане. Идентификаторы пяти систем лежат рядом, в таблице соответствий, — это она позволяет ответить, какой документ в 1С стоит за строкой цеха.

  • Журнал вместо текущего состояния

    Каждое изменение — событие в append-only таблице PostgreSQL: кто, когда, из какой системы и что было до. Партиции по месяцам. Отсюда два ответа, которых раньше не было: почему цифра именно такая и в какой момент она разошлась.

  • Пять интеграций — пять разных способов

    OData у бухгалтерии, вебхуки у CRM, CSV из общей папки у склада, реплика базы у раскроя, SOAP у перевозчика. Python здесь выбран ровно за то, за что его обычно и берут в интеграции: разобрать чужой формат и заговорить на чужом протоколе — библиотечная работа, своим кодом описываются только правила.

  • Очередь, а не прямые вызовы

    Обмен идёт через Redis: у каждой системы свой поток и своя скорость, повтор — с растущим отступом, ключ события живёт двое суток, поэтому повторная доставка не создаёт вторую отгрузку. Там же ограничение частоты для портала перевозчика и для 1С: обе ложатся, если ходить чаще, чем они просили. И там же кэш справочника на сорок тысяч позиций — склад отдаёт его файлом, читать файл на каждый экран бессмысленно.

  • Расхождения не прячем

    Остаток подписан временем последней выгрузки со склада — до пятнадцати минут назад, и это видно. Всё, что не сошлось при обмене, не исправляется молча, а падает в отдельный список: его разбирает планировщик утром. За первые полгода список ни разу не был пуст, и для контура, сшитого из пяти чужих систем, это нормальное состояние, а не поломка.

Что осталось за рамками

Часть работы сознательно не входила в контур, часть отложена до данных, которых пока нет.

  • Интерфейсы. Их собирал фронтенд-разработчик заказчика поверх нашего API: на нас были модель данных, сервис и пять интеграций.

  • Планирование загрузки станков. Контур показывает очередь по участкам, но не расставляет её: для этого нужны фактические времена операций хотя бы за год, а они копятся только с запуска.

  • Отметка операций на рабочих местах. Участок пока отмечает выполнение с планшета мастера, терминалы у станков — следующий этап.

  • Закупки и снабжение. Остались в бухгалтерии и в почте: втягивать их в контур до того, как он устоится на заявках, никто не хотел.

Сейчас в работе: срок по факту вместо норм — считаем по журналу за первый год — и перенос недельного отчёта в самообслуживание, чтобы за ним не приходили к нам.

Контакты

Пришлите описание задачи

Ответ с объёмом работ, сроками и оценкой бюджета придёт в течение 24 часов.

Первый звонок — 30 минут, без обязательств с вашей стороны.