DynDaCo

MEP InSight — assets you own, and assets you service

Sector
Industrial engineering and service
Period
2022–present
Role
Product owner, architect and lead developer
Stack
Ruby on Rails 8.1 · PostgreSQL · ViewComponent · Kamal · LDAP · OAuth

Situation

Two kinds of organisations have the same problem from opposite sides.

A plant owns hundreds of installations and has to keep them running. What is installed where, when was it last inspected, which drawing is the current one, who signed off the last change.

A supplier has sold and installed equipment at dozens of customer sites and has to service it. The questions are identical — but the assets are not theirs, they sit on other people's premises, and everything has to be answerable per customer.

Software normally picks a side. Maintenance systems assume you own the plant and treat customers as an afterthought. Field-service systems assume you don't, and give up the engineering depth. Organisations that are both — and plenty are, running their own plant while servicing what they have sold — end up with two systems and reconcile them by hand.

MEP InSight is my answer to that, built and owned by DynDaCo and deployed for enterprise customers rather than delivered and walked away from.

What I built

One register that supports both readings, and the decision that makes it work is a small one: the asset hierarchy hangs off a company.

Functional locations describe where equipment sits, independently of whatever unit is installed there today — the standard maintenance idea, and the reason replacing a pump doesn't throw away ten years of history. Those locations form a tree, and the root of each tree is a company. Point it at your own company and you are managing your own plant. Point it at your customers and you are managing an installed base across all of them. Same screens, same permissions, same history; the only difference is whose name sits at the root.

On top of that structure:

The equipment as it really is. The control network documented as-built — devices, their types, their ports and interfaces, and the segments they sit on — so you can start at one device and walk outward to whatever it is connected to, instead of consulting a diagram that was accurate at commissioning and has been drifting ever since.

Documents that stay current. A revision-controlled vault holds drawings, manuals and configuration files, linked to the locations and devices they describe and previewable in the browser. You get the current revision by default, and the superseded ones are still there when someone asks what changed.

Inspections and history. Inspection records accumulate against locations, so an asset carries its own past — which is the whole point of the functional-location model.

The plan, without the .mpp file. Project planning used to live in MS Project files passed around by mail. InSight imports them — the whole work breakdown, its dependencies, the assignments and the resource names — and renders them as an interactive Gantt with four readings: a team's load, one project, one person, one week. A scheduler recomputes dependent dates on the same working-day arithmetic MS Project uses, so moving one task moves what follows it the way the planner expects. Leave and absences sit behind the bars, so the plan and who is actually available are one picture. Plans are editable in place, and each one is pinned to whichever side wrote its first task — so a team leaves MS Project a project at a time instead of all at once.

Automation written as text, not shipped as code. What happens when a request comes in, a status changes or someone is assigned is not compiled in; it is a small language an administrator writes in the browser. The rules read close to the sentence you would say out loud — when the assignee changes, notify whoever was just added, and tell whoever was just taken off. The server parses and validates the document as you type and underlines what it objects to, so a broken rule cannot be saved, and every evaluation — matched or rejected, and which condition rejected it — lands in a run log. The processing code itself makes no policy decisions at all: it works out which issue a message belongs to and fires an event. Whether a reply reopens a closed ticket is a rule, not a release.

The people around it. Companies, contacts and the contractors responsible for each area, with an activity feed on every record, plus full-text search across everything, exports and an audit trail.

Notifications that carry their context. Subscribe to a company, an installation or a project and you hear about changes anywhere beneath it. Delivery is set per person and per channel — in-app badge, browser toast, email — and the mail adds what a one-line alert has no room for: the trail from company down to task, and timestamps in the reader's own zone. Every headline is prefixed with the nearest thing worth naming, because there are dozens of plans holding a task called "Electrical completion"; it is composed once and read by all three surfaces, so the mail subject and the bell entry cannot drift apart.

A hierarchy, not the hierarchy. Company → location → installation → equipment is the shape a plant needs, but nothing in the core insists on it. Belonging to the tree is a declaration a model makes about itself — one line, no controller and no configuration — and everything that reads the tree follows from it: the navigator, the breadcrumbs, permissions scoped to a branch ("may edit equipment, but only under this installation"), the activity feed, subscriptions, search and the document vault. So the two deployments already carry different trees on the same frame — one descending through equipment and field devices to their wiring, the other through projects and the tasks beneath them — and a new kind of node is a declaration rather than a project.

Two enterprises, one codebase. InSight runs for two organisations with incompatible identity systems — one against corporate Active Directory, the other through OAuth. Nearly all the code lives in a shared Rails engine, with a thin host application per customer carrying only its authentication, its overrides and its deployment configuration. A change for one no longer means reasoning about its effect on the other, and onboarding a third is adding a host rather than another branch through shared code.

Outcome

The engineer who knew how it all fitted together is no longer a single point of failure, and one product serves both an owner-operator and a service organisation without either feeling like it is borrowing the other's tool.

The flexible parts all come from the same instinct: put the variation in the data model, where it costs nothing — a hierarchy that can root on a company, a tree whose kinds of node each deployment declares for itself, a shared engine with thin hosts — rather than in branching code that has to be maintained forever.

← All work