Case 04 · furniture manufacturing · full-cycle furniture factory

The owner learns about a missed deadline at 8 a.m., not when the customer calls

Overdue-order accuracy47 false out of 503 real
“Stuck” noise90 of 114 orders8 after calibration
Response time15–40 minutes on cron1–2 seconds

Results from a specific project, not a guarantee of similar outcomes.

Context

A full-cycle furniture factory — kitchens, sliding wardrobes, walk-in closets, in a city of over a million people. Roughly 60–115 orders in production at any one time; the CRM is Bitrix24.

Orders are tracked in the “Production” smart process: every card has its own stage, its own planned installation date, its own movement history. To understand what was on fire, the owner had to log into the CRM and scan the board by hand. The problem with made-to-order furniture is that the customer pays up front, and a missed installation date is both a hit to reputation and locked-up money, because the order is occupying workshop capacity.

The CRM data, meanwhile, was incomplete and “noisy”: the opening audit found the planned installation date filled in on only 13 cards out of 114, and the board was cluttered with dozens of abandoned and test cards, some of which hadn't moved in 119–526 days. Telling a real fire from junk by eye was practically impossible. A separate pain point — two competing installation-date fields, one of which had long been unmaintained: relying on it produced 50 “overdue” orders, of which 3 were real.

Constraints

  • Data quality at the source. The planned date is filled in on 11% of cards. The system had to deliver value without requiring a CRM clean-up first — otherwise implementation would never have got off the ground
  • Legacy fields in the CRM. Two competing installation-date fields, one long unmaintained, plus 12 smart-process stages with historical junk — right down to a stage called “DELETE” and cards with “TEST” in the name
  • Telegram blocked in Russia. The Russian data center blocked api.telegram.org — the bot sat silent with timeouts even though Bitrix24 and the Anthropic API were reachable. A workaround via a proxy on Cloudflare Workers failed; the final solution was moving the server to a host where all external APIs are reachable
  • Zero external dependencies. The requirement: the code runs on any machine without pip install — Python's standard library only. That ruled out the official Anthropic and Telegram SDKs: every integration is written on urllib
  • A non-technical operator. Every implementation step — creating the server, SSH, editing configs — was performed on the factory's side by someone with no engineering background. Every action had to boil down to copying a single command

Solution

What you get

Every morning at 8:00 a digest lands in the team chat: what's on fire by deadline, what's stuck, what's ready to ship, what has turned into “backlog”. It reads from a phone in 20 seconds, sorted by severity, the most overdue at the top.

At any moment you can ask the bot an ordinary question in your own words — “how many orders are on fire?”, “what's happening with order 1042?” — and get an answer from current CRM data in a couple of seconds. Alert thresholds change right from the chat: “raise the ‘on fire’ threshold to 3 days” — the bot confirms and applies it.

How it works

The key architectural decision is two layers: deterministic code does the counting, the LLM only does the talking. Every number and every classification is computed by ordinary Python code: how many days to the deadline, how many days an order has sat at a stage, what counts as a fire. The model is not allowed anywhere near those numbers — it comes in only where a person's question needs to be understood and an answer phrased. That removes the main risk of AI reporting: the digest cannot “invent” a non-existent order or deadline.

Handling dirty data is part of the product. Analysis is preceded by a filter: cards on service stages, test records and “zombies” — anything that hasn't moved in more than 120 days — are hidden. On the first run that screened out 49 cards out of 114. Orders without a live planned date don't raise false alarms, but they don't get lost either: if such an order has been sitting still for more than 30 days, it goes into a separate “Backlog” block — not a fire, but a backlog to work through. That way the system delivers value on imperfect data and, along the way, highlights where the CRM needs filling in.

Calibration is done on live data, not on assumptions. The original thresholds from the spec (“stuck” = 3 days) fired 90 times out of 114 on the real board — pure noise; the threshold was raised to 14 days. Same with the date: comparing the two fields on a real sample showed the outdated field generating 47 false overdues against 3 real ones — it was dropped entirely.

Infrastructure: the bot lives on a VPS as a systemd service with auto-restart and holds a persistent connection to Telegram (long-polling) — answers arrive in 1–2 seconds. The same service sends the morning digest on schedule, weekdays only. The agent's entire “instruction manual” — role, thresholds, classification logic, report format — is kept in a separate document of 9 self-contained blocks: you can edit one block without touching the others and without changing the code.

Outcome

The digest and the dialogue run 24/7 with the owner's computer switched off; four people use the bot — the owner and three employees. A full export from the CRM takes 3.2 seconds. Running cost — about 600 ₽ a month for the server plus 2–10 cents per question to the model.

A separate audit finding the tool exposed: the planned installation date is filled in on only 13 orders out of 114 — automating the reporting highlighted what still needs to be filled in across the CRM.

MetricBeforeAfter
Overdue-order detection accuracy47 false positives out of 503 real overdue orders
Noise in the “stuck” block90 of 114 orders (79% of the board)8 orders after calibrating 3 → 14 days
Junk on the boardindistinguishable by eye49 of 114 cards hidden automatically
Bot response time15–40 minutes (cron)1–2 seconds (long-polling)
Availabilitywhile the PC is on24/7 on a VPS
Running cost—~600 ₽/mo + cents per question

What I'd do differently

  • Start with data reconnaissance, not the spec. The thresholds in the spec (“stuck” = 3 days) sounded reasonable but fired 90 times out of 114 on the live board — the report would have been useless from day one. Any threshold should be set after looking at the distribution of real data, not before
  • Don't trust a field by its name. “Installation date” sounded like the right field — it produced 47 false overdues. The correct one was called “Expected installation date”. Running both fields against a real sample took 10 minutes and saved the project from being completely unreliable
  • GitHub Actions is not a platform for an interactive bot. A cron every 5 minutes in practice meant delays of 15–40 minutes and skipped runs. Fine for a once-a-day report, not for a dialogue. Should have gone straight to a VPS
  • Check the host's network reachability before deploying. Everything was deployed on a Russian VPS — and only there did it emerge that the data center blocks api.telegram.org. A day lost on an attempted workaround and the move. The check would have taken 15 seconds: curl to api.telegram.org
  • The tool exposes process problems, not just automates the process. The project's main finding wasn't the code but that the installation date is filled in on 11% of orders, and some cards sit at “Ready to ship” 40+ days overdue. Automating reports is pointless if the source data isn't maintained — that was worth spelling out with the team at the start

Stack

Python · standard library onlyBitrix24 REST · smart processesAnthropic Claude APITelegram Bot API · long-pollingsystemdUbuntu VPSGit · GitHub

What it means in money

Work out the cost of a single missed deadline: the penalty, the repeat delivery, the lost repeat order. The system notices a stalled order the day it stalls — not a week later when the customer calls. If that saves even one order a month, weigh it against the implementation price and a monthly fee cheaper than one dispatcher.

Where next

People also look at

Bitrix24 · data control

The “Auditor” — data discipline in Bitrix24

manual CRM checksa daily report in Telegram

A data-quality Telegram bot for a furniture company. Every day it checks deals and records — empty fields, broken statuses, stalled stages — and sends the people responsible a report. “Dead” deals have vanished from the CRM, and the manager sees how disciplined the database is without checking by hand.

read the case study →
Prices, no call needed

Production PM pricing

150,000 – 350,000 ₽ implementation · support from 15,000 ₽/mo

Common question
Do we need to install anything on our side?
No. The system lives on a separate server and talks to your 1C and Bitrix24 through APIs with restricted permissions. Your infrastructure stays as it is.

Need time to think it over?

Take this case study as a single file — easy to forward to a colleague or bring to a meeting. The link appears instantly.

Do your orders stall silently between stages too?

Get in touch — in one conversation we'll find where the money sits in your 1C and CRM, and where to start.

I reply the same day, usually within a couple of hours.