Skip to content

Manufacturing

Replacing a factory's operating system without stopping the factory

An engine reconditioning plant ran on paper forms, walking between stations and phone calls asking whether something was finished. It now runs on a system that knows where every engine is, what has to happen to it next, and which of those steps just became possible.

Client
Recotech
Sector
Manufacturing
Published

The problem

The plant had systems, and none of them agreed. The shop knew its stock, the workshop knew its jobs, accounting knew its invoices, and the only thing joining them was somebody walking across the hall to ask. Every handover was a conversation, every status was a phone call, and the answer to 'is it ready' was only ever as current as the last person who went to look.

The solution

One system covering the whole path — reception, inspection, estimate, the client's approval, the work itself, the internal courier, the warehouse, goods receipt and the accounting entries that follow — with a screen written for each job rather than one dashboard filtered thirteen ways, and notifications that replace the walk.

The architecture

The decision that made it deployable is a migration that never happened. A day-zero cutoff — a global scope of about twenty lines — draws a line at one identifier: earlier jobs stay in the database and stay visible in an archive, and are simply invisible to everyone on the floor. No data migration, no big bang, no shutting the hall.

The outcome

The plant went from roughly a hundred engines a month to roughly three hundred, on a floor where the walking and the phone calls had been the coordination.

In detail

What a factory actually runs on, before anyone writes software for it, is walking. Somebody carries a cylinder head to the next station and tells the person there what was agreed. Somebody rings the office to ask whether the client approved the estimate. Somebody writes the findings on a paper form and somebody else types them in later, from the form, mostly correctly. None of that is anybody’s fault, and all of it is invisible until you try to replace it, because none of it is written down anywhere.

The system that replaced it had to go in while the plant kept working, which turned out to be the hardest constraint and the most interesting one. One decision carries it, and it is not a feature.

It is a line drawn through the data. On the day it went live the hall already had jobs in progress, entered partially and inconsistently, and the usual options were a risky migration or a weekend shutdown. Instead the system takes a cutoff identifier and applies one global scope: anything below it exists, is queryable, stays visible in an archive for the office, and is simply not there for anyone on the floor. About twenty lines, two escape hatches for the archive views, and a rollout with no data cleanup and no stopped production.

What the system does once it is in is production planning, not ticketing. When a client accepts an estimate, the accepted lines are turned into a directed graph of operations for that job — real edges between nodes, not an ordered list. A node becomes available when its dependencies are done and when the parts it needs have arrived, which means the arrival of a part recomputes what just became possible and tells the people who can now do it. Skipping a step is a request that somebody senior approves, measurements are recorded against tolerances, and a guard caps how many operations one person can hold open at once. There are five of these state machines running at the same time — the job, the job’s transport, an individual component’s transport, the component itself, and the graph — and they synchronise through events.

The OCR is the part that looks like a gimmick and is not, because it does not produce text. The inspection form is a paper sheet, filled in by hand at the bench, and it is photographed. The model is given the numbered rows for that zone and asked only which of them are ticked and how — a tick, a dash, a number — and its answer is filtered against that list, so any row it invents is discarded and the name of the operation is taken from the local table rather than from the model. What comes out the other side is not a transcription. It is nodes in the operations graph and lines on the estimate.

The internal courier moves work between stations, and its states are not a column. They are derived from timestamps, each paired with the identifier of the person who set it, so the history is complete and cannot be rewritten after the fact. The guards are the ordinary ones written properly: you cannot deliver something you never picked up, a second scan of the same movement is refused rather than duplicated, and something sitting too long unclaimed escalates on a timer. Undo does not delete a stock movement — it writes a compensating one that points at the original.

The integration surface is where the plant’s other systems live, and it is most of the unglamorous work. Supplier catalogues arrive through six scrapers, each running as its own service rather than as a job inside the application, so one supplier changing their markup does not take the plant down with it. Goods receipt posts against the Romanian chart of accounts with legal sequential numbering. Between stations, forty-three distinct notification types replace forty-three conversations — pushed only to people who do not currently have the app open, and never between ten at night and seven in the morning.

Stack

  • Laravel 12
  • PHP 8.3
  • MySQL 8
  • React 18
  • Filament
  • Meilisearch
  • Redis

Capability

  • Custom software
  • Integrations
  • Applied AI
Work

Contact

What do you want to build?

Discuss your project