HomeCase studiesA Regulatory Compliance Scheduling and Equipment Register...

Case study · San Diego, United States

A Regulatory Compliance Scheduling and Equipment Register Platform

Regulated equipment inspection and compliance services — diagnostic imaging physics and radiation safety

A specialist inspection services provider is measured on one thing: nothing at a customer site goes past its due date. Doing that across thousands of individually scheduled assets, spread over hundreds of physical sites and assigned to a roster of licensed specialists, is a scheduling and record-keeping problem that spreadsheets cannot survive. Our team built the operational system of record for it — a three-level equipment register with derived compliance dates, a prioritised workload queue for every specialist, geographic radius search for field routing, print-ready compliance document generation, a full change history with one-click restore, automated scheduling outreach, and a scoped self-service portal for the provider's own customers.

Industry
Regulated equipment inspection and compliance services — diagnostic imaging physics and radiation safety
Solution
A standalone full-stack web platform with its own relational database, two separate authenticated user realms, scheduled background jobs, document generation and a small machine-readable interface. Not a client over someone else's API — the platform owns the data.
Platforms
Web & API
Stack
jQuery · Bootstrap · MySQL · Docker · Capistrano · Apache
Location
San Diego, United States · delivered remotely
Role
Engineering, with the team behind for mobile and QA

Delivered remotely for a business based in San Diego, United States. Names withheld by agreement.

Project Overview

Industry: Regulated equipment inspection and compliance services — diagnostic imaging physics and radiation safety.

Type of solution: A standalone full-stack web platform with its own relational database, two separate authenticated user realms, scheduled background jobs, document generation and a small machine-readable interface. Not a client over someone else's API — the platform owns the data.

Business context: Equipment that emits radiation is regulated equipment. It must be evaluated on a defined cycle by a qualified specialist, and the evaluation must produce a document that satisfies an inspector. Healthcare facilities outsource this to specialist providers, and those providers become responsible for a compliance calendar that spans every asset at every site they cover. Each asset has its own cycle. Each site has its own contacts. Each evaluation has to be assigned to someone licensed to perform it, and that person has to physically travel there. Miss a date and the exposure is the customer's, but the failure is the provider's.

General users: Compliance administrators managing the register, licensed field specialists working their own assigned queue, scheduling coordinators driving appointment booking, and customer-side safety officers accessing a scoped view of their own facilities.

General purpose: To turn a compliance calendar of thousands of individually scheduled assets into a system that knows what is due, who owns it, where it is, what document proves it was done, and what changed.

The Business Challenge

Compliance is a calendar problem that scales badly. Every regulated asset carries its own cycle and therefore its own next-due date. Multiply that across every unit at every site of every customer, and the arithmetic alone becomes a full-time job long before anyone actually goes and inspects anything.

Every asset runs on a different clock. Cycles range from a few months to several years depending on the equipment type and the applicable regulation. There is no single interval to apply across the estate, so the due date has to be computed and held per unit and kept correct as frequencies change.

A missed date is a regulatory event, not an administrative slip. The consequence of losing track of one unit is not an inconvenience — it is a compliance failure at the customer's facility. The system's core obligation is that nothing falls through.

Work has to reach the right qualified person. Evaluations must be performed by an appropriately licensed specialist. Assignment is therefore a first-class property of the record, not a scheduling afterthought, and each specialist needs a view of their own workload rather than a shared list everyone has to filter.

Field work is dominated by geography. Specialists travel to sites. The economics of the operation depend on grouping nearby work, which means the register has to be searchable by distance and not just by name and date.

The deliverable is a printed document. What ultimately satisfies an inspector is a site inventory record — laid out for print, carrying site and contact details, the full equipment table, and a signature block for the facility's safety officer. Producing that by hand for every site, every cycle, is enormous manual effort and a constant source of transcription error.

Nothing is defensible without a change history. Due dates and assignments get edited. When a date moves, someone eventually needs to know who moved it, what it was before, and whether it can be put back — and the answer needs to be available without opening a database.

Customers want visibility, not access. Facilities want to see what is due at their own sites without being given the provider's whole operational system, and without being able to see anything belonging to anyone else.

Reminders only work if they cause a booking. Knowing that a unit is due in six weeks achieves nothing on its own. Something has to reach the specialist and the site contact together, early enough to get a date in the diary.

Our Approach

Model the register to match the physical reality. A three-level hierarchy — customer organisation, physical site, individual asset — reflects how the work is actually organised. Sites that carry a materials licence and run on an audit cycle rather than an equipment cycle were modelled as a one-to-one extension of a normal site, sharing address, customer linkage and lifecycle while carrying their own cycle, due date, licence reference and contact set. That avoided both a duplicated parallel table and a general site record full of columns that apply to a minority of rows.

Make the due date the axis everything turns on. Cycle and due date are held per asset and per audited site, and every other feature reads from them — dashboards, filtered search, reports, notifications and automated outreach all key off the same derived value, so there is one answer to "when is this due" rather than several.

Let the business express priority at every level it thinks in. Priority is set independently on the asset, the site and the customer, and rolled up into a single score that orders the specialist's queue. The business can say "this customer matters", "this site matters" and "this unit matters" as three separate, independently maintainable facts, without any of them overwriting the others.

Give every specialist their own queue. The dashboard is scoped to the signed-in specialist and shows what falls due inside a look-ahead window they choose, ordered by date, with the priority-weighted queue alongside it. Administrators can look into any specialist's queue. Nobody has to filter a shared list to find their own work.

Solve routing with data held locally. Rather than calling an external geocoding service at request time, coordinate reference data is shipped with the application, bulk-imported once and queried directly. Sites geocode automatically from their postal code on save, and the register supports distance search — everything within a given radius of a location — layered on top of the full structured filter set. There is no third-party latency, no quota and no runtime dependency in the routing path.

Generate the regulator-facing document from the system. The inventory workbook is constructed programmatically with real print layout: one worksheet per site, landscape page setup, margins and page breaks, a merged site information header, the equipment table, an embedded mark, a prepared-by block and a safety officer signature line. It can be downloaded or emailed as an attachment to a nominated address.

Version everything and make change reversible. Customers, sites, audited sites and equipment are all versioned. Deletions and edits can be restored from the version history in one action, and change notifications carry a direct revert link keyed on a per-record token — so a specialist who is told a unit changed can undo it straight from the email.

Automate the outreach that actually produces appointments. A nightly job finds every asset falling due exactly the configured number of days ahead for customers who have opted in, groups those assets by assigned specialist, and emails the specialist together with the site contacts — sent from the specialist's own address, so the reply lands with the person who has to attend rather than in a shared inbox.

Give customers a genuinely separate realm. The self-service portal was built as its own authentication realm with its own layout, its own controller and its own scoping, rather than by adding a customer flag to the staff user model. The two populations have different capabilities and different trust levels, and keeping them structurally separate is what allows them to stay that way.

The Solution

Structured equipment register. Customer organisations, their physical sites and the individual assets at each, with type, use category, manufacturer, model, serial and control identifiers, physical location, status and notes — the authoritative record of what exists and where.

Specialist site handling. Sites operating under a materials licence carry an extension record with their own audit cycle, audit due date, licence reference and dedicated contacts, without distorting the general site model.

Cascading lifecycle state. An asset is treated as out of scope if it, its site, or its customer is inactive — expressed once as a reusable query rule rather than as conditionals scattered through the application, so the register never disagrees with itself about what is live.

Derived compliance scheduling. Cycle frequency and next-due date held per asset and per audited site, driving every downstream view.

Personal workload dashboards. Each specialist sees what falls due within a configurable window, ordered by date, plus a separate queue ordered by the rolled-up priority score.

Geographic radius search. Find everything due within a given distance of a location, combined with the full filter set, so field visits can be grouped by proximity rather than planned by hand.

Multi-criteria register search. Filtering across customer, site, unit, type, use category, assigned specialist, due-date range and full address, with sortable paginated results and filter state preserved as users move between list, record and edit form.

Print-ready compliance documents. Site inventory workbooks generated with full page setup — per-site worksheets, landscape layout, page breaks, footers, header blocks, contact and registration details, embedded imagery and a safety officer signature line — available as a download or as an emailed attachment. A combined cross-site variant covers multi-facility reporting.

Configurable data export. Column-selectable register export for use outside the platform.

Complete change history with restore. Every change to a customer, site, audited site or asset is versioned and attributed. Deleted records can be brought back, and individual changes reversed to their prior state, from within the application.

Change notifications with one-click revert. Creation, change and deletion notifications route to the assigned specialist with operations copied, carrying a direct link that reverses the change without opening the application.

Monthly change reporting. Trailing-period views of what changed and what was deleted, per entity type, plus a monthly digest to each specialist covering only the units they own whose material fields actually changed — determined by comparing against the stored previous version rather than by timestamp.

Automated scheduling outreach. A nightly job that reaches the specialist and the site contacts together, the configured number of days before a due date, for customers who have opted into it.

Customer self-service portal. A separate authenticated realm giving each customer a dashboard of what is due at their own sites, browsing of their sites and assets, limited asset editing that notifies the assigned specialist, their own change report and their own inventory report export.

Enquiry and supplies ordering. A public enquiry form routing to customer service, and a supplies order form with volume-based pricing and tax calculation producing both an emailed order and a stored record, with an internal listing of what has been submitted.

Key Features

Three-level equipment register with a specialist site extension Customer, site and asset modelled as a hierarchy, with licensed-materials sites carried as a one-to-one extension that shares address and lifecycle while holding its own cycle, due date and contacts.

Derived compliance dates as the system's primary axis Per-asset cycles and next-due dates that every dashboard, search, report and notification reads from, so there is a single authoritative answer to what is due when.

Rolled-up three-level priority scoring Priority set independently at asset, site and customer level and summed into one score, letting the business express three separate kinds of importance without any of them overwriting another.

Per-specialist workload queues Each licensed specialist gets their own dashboard scoped to their assignments, with a configurable look-ahead window and a parallel priority-ordered queue; administrators can view any specialist's queue.

Geographic radius search with locally-held reference data Distance-based search over the register, served from coordinate data imported into the platform's own database — no runtime third-party call, no latency and no quota in the routing path.

Print-ready compliance document generation Programmatically constructed inventory workbooks with real page setup, per-site worksheets, header and contact blocks, embedded imagery and a safety officer signature line, delivered as a download or an email attachment.

Full record versioning with one-click restore Every change to a customer, site, audited site or asset versioned and attributed, with deleted records recoverable and individual changes reversible from within the application.

Revert links embedded in change notifications A per-record token generated on save lets a change notification carry a direct link that reverses the change, so correction does not require navigating the system.

Automated pre-due scheduling outreach A nightly job that reaches the assigned specialist and the site contacts together at a per-customer configured lead time, sent from the specialist's own address so replies route to the person attending.

Scoped customer self-service portal A separate authentication realm giving customers visibility of their own sites and assets, their own change history and their own report exports, structurally separated from the internal system rather than bolted onto it.

Technical Architecture

Presentation layer. Server-rendered templates across three surfaces from one codebase: the internal back office, the customer portal with its own layout and destination routing, and a public enquiry and ordering path. A small machine-readable JSON surface sits alongside the HTML views with its own token-based authentication filter.

Controller layer. Resource-oriented controllers over a shared base carrying the cross-cutting concerns — CSRF protection, the token authentication filter, per-realm sign-in and sign-out routing, shared pagination and sorting, and per-resource session state that preserves search context as users move between list, record and edit views. Authorisation is declarative, with resource loading and an ability definition rather than per-action checks.

Domain layer. Business rules held in models: cascade-aware lifecycle scopes over an explicit join, the rolled-up priority calculation, automatic geocoding on save, change-token generation on save, cycle and frequency definitions, and notification dispatch through lifecycle callbacks.

Reporting subsystem. A workbook builder that constructs print layout programmatically — page setup, margins, page breaks, merged header cells, styled blocks, embedded imagery, signature lines and per-page footers — with per-site, cross-site and generic variants, and both download and email-attachment delivery.

Scheduled work. Rake tasks registered into the system crontab at deploy time, covering the nightly pre-due scheduling outreach and the monthly specialist change digest, plus maintenance tasks for reference data import and coordinate backfill.

Data layer. A relational database holding the register hierarchy, cycles and due dates, assignment, roles, the version store and a coordinate reference table, indexed against the queries the product actually runs and evolved through several years of migrations.

Delivery. Multistage deployment automation covering staging and production, with server virtual host configuration generated as a deployment task, shared configuration and upload directories symlinked across releases, asset precompilation at deploy time, and continuous integration triggering deployment on build.

Flow: Back office and customer portal → Authorisation and realm-scoped controllers → Domain models with derived due dates and cascading lifecycle → Relational register with version store and coordinate reference data → Scheduled jobs for outreach and digests → Document generation and transactional email

Technology Stack

Category Technology
Language Ruby
Framework Ruby on Rails
Database MySQL, evolved through several years of migrations
Authentication Devise, configured across two independent authenticatable models
Authorisation CanCanCan with Rolify role modelling
Audit and versioning PaperTrail, with restore and change reversal
Document generation Axlsx for print-configured Excel workbooks
Geospatial Geokit for distance search over locally-held coordinate data
Bulk data loading activerecord-import with duplicate-key handling
Pagination Kaminari
Uploads and imaging CarrierWave with MiniMagick
Scheduled jobs Whenever, generating the system crontab at deploy time
Configuration Environment-based configuration management
View layer Haml templates, SCSS, Bootstrap, CoffeeScript, jQuery and jQuery UI
JSON surface Jbuilder templates with token-based authentication
Email Transactional and scheduled mail over a hosted SMTP relay
Monitoring Hosted error tracking
Deployment Capistrano multistage with RVM, Passenger under Apache, virtual host generation as a deploy task
CI Hosted continuous integration triggering deployment
Local development Docker and Docker Compose

Technical Challenges & Solutions

Challenge Our Approach
Thousands of assets each on their own compliance cycle, with a missed date carrying regulatory consequence Cycle and derived next-due date held per asset and per audited site as the platform's primary axis, with every dashboard, search, report, notification and scheduled job reading from that single value rather than recomputing it.
Sites operating on an audit cycle under a materials licence being structurally different from ordinary equipment sites Modelled as a one-to-one extension of a site, sharing address, customer linkage and lifecycle while carrying its own cycle, due date, licence reference and contact set — avoiding both a duplicated parallel table and a general site record dominated by rarely-used columns.
An asset's relevance depending on its own status, its site's status and its customer's status simultaneously A reusable, index-friendly query scope over an explicit join expressing the cascade once, so every list, report and dashboard agrees on what is in scope.
The business needing to express importance at three different levels at once Independent priority values on asset, site and customer, summed into a single rolled-up score used to order the specialist queue — three separately maintainable facts, one ordering.
Field work economics driven by travel, not by inspection time Distance-based search over the register, served from coordinate reference data bulk-imported into the platform's own database, so radius queries carry no external latency, quota or runtime dependency.
The regulator-facing deliverable being a printed, signed document rather than a screen A programmatic workbook builder controlling page setup, margins, page breaks, merged header cells, embedded imagery, footers and a safety officer signature line, with per-site, combined and generic variants and both download and email delivery.
Compliance records needing to be defensible and correctable Full versioning with attribution across every register entity, restore of deleted records and reversal of individual changes from within the application, plus a per-record token that lets a change notification email carry a direct revert link.
Reporting only material changes rather than every touch Monthly specialist digests built by comparing the current record against its stored previous version field by field, so the digest reflects what actually changed rather than what was merely saved.
Reminders that inform without producing a booking A nightly job grouping due work by assigned specialist and emailing that specialist together with the site contacts at a per-customer lead time, sent from the specialist's own address so replies reach the person attending.
Serving customers and internal staff from one application without blurring the boundary A separate authentication realm for customers with its own layout, controller, scoping and post-login destination, rather than a capability flag on the internal user model.

Security & Reliability

Two separated authentication realms. Internal staff and customer organisations authenticate against structurally distinct models with different capabilities, layouts and destinations — the boundary is enforced by the data model, not by a flag.

Role-based authorisation with referential guards. Access is governed declaratively through role assignment and an ability definition, with explicit protections against destructive operations that would break referential integrity: a category still in use cannot be removed, a specialist with assigned work cannot be removed, and an administrator cannot delete their own account.

Complete, attributed audit trail. Every change to a customer, site, audited site or asset is versioned with the acting identity recorded, giving a defensible history of who changed a compliance date or an assignment and what it was before.

Recoverability as a first-class control. Deletions and edits are reversible from within the application, so an incorrect change to a compliance record is a correction rather than an incident.

Cross-site request forgery protection enabled application-wide.

Transport security. TLS enforced in both the production and pre-production environments.

Credential handling. Passwords stored using an adaptive hashing function; password parameters excluded from application logs; constant-time comparison on machine-interface token checks.

Environment-separated configuration. Configuration held outside the codebase and supplied per environment, with deployment automation placing it on the server rather than embedding it in releases.

Reproducible deployment. Multistage deployment automation with server configuration generated from the repository, shared state symlinked across releases, and release retention allowing rollback.

Scalability & Performance

Indexing aligned to real query patterns. Indexes on the columns the product actually filters and sorts by — assigned specialist, site linkage, use category, customer name, lifecycle flag — plus a composite index supporting coordinate lookups.

Eager loading on register queries. Site and customer associations are loaded alongside the asset set rather than per row, which matters on a register where every list view crosses all three levels of the hierarchy.

Pagination throughout, with user-controlled page size. Every list is bounded, and users who need larger pages can request them rather than the system defaulting to something unbounded.

Geographic reference data held locally. Coordinate datasets are bulk-imported once with duplicate-key handling and queried directly, so distance search is a database operation rather than a network call — no per-request latency and no external quota on the routing path.

Scheduled work moved off the request path. Outreach and digest generation run as cron-registered jobs outside peak hours, so neither the volume of due work nor mail delivery latency affects interactive response.

Asset precompilation and digesting at deploy time, with caching enabled in production.

Session-held search context. Filter state persists across navigation rather than being rebuilt and re-executed each time a user returns to a list.

Business Outcomes

  • The compliance calendar became a system rather than a spreadsheet, with every asset's next-due date derived and held in one authoritative place.
  • Every specialist works from their own queue, ordered by date and by a priority score the business controls at three levels, instead of filtering a shared list.
  • Field visits can be planned by proximity, because the register is searchable by distance as well as by name, customer and date.
  • The regulator-facing document is generated, not retyped, with print layout, site details and signature block produced directly from the register.
  • Compliance records are defensible, with a complete attributed history of who changed a date or an assignment, and what it was before.
  • Mistakes are correctable rather than permanent, with deleted records restorable and individual changes reversible — including directly from the notification that reported them.
  • Scheduling outreach happens without anyone remembering to do it, reaching the specialist and the site contact together at a lead time the customer sets.
  • Customers can answer their own questions, through a scoped portal that shows them what is due at their own facilities without exposing anything else.
  • The platform absorbed several years of continuous change, including the later addition of an entire customer-facing realm onto a system originally built as an internal tool.

Why it worked

Compliance software is unusual in that being approximately right is worse than being obviously absent. A register that is ninety-five percent accurate does not save ninety-five percent of the effort — it creates a system nobody trusts, which people then shadow with the spreadsheet they were supposed to have replaced. The engineering standard is therefore different: the derived date has to be right everywhere it appears, the definition of what is in scope has to be expressed once, and a wrong record has to be visibly wrong and recoverable rather than quietly overwritten.

Our team built to that standard. We modelled the register to match the physical reality of customer, site and asset, including the site type that genuinely does not fit the general shape, and gave it a single derived due date that every other feature reads from. We made the definition of "in scope" a reusable rule rather than a conditional repeated in twenty places. We treated the printed compliance document as a real deliverable and built it properly, with page setup and signature blocks, rather than exporting a grid and hoping. We versioned everything and made recovery a one-click action reachable from the email that reported the change. And we solved the geography with data we control, so the routing that determines the cost of the whole operation does not depend on somebody else's service being up.

Our teams work across Ruby on Rails and long-lived server-rendered platforms, multi-realm authentication and role-based authorisation, audit and versioning design, document and report generation, geospatial search, scheduled job pipelines, and the deployment automation that keeps a system like this maintainable across years rather than months.

Final Summary

A specialist inspection provider carries a compliance calendar on behalf of its customers. Every regulated asset at every site has its own cycle, its own next-due date and its own qualified specialist, and the provider's entire reputation rests on none of them being missed. Run on spreadsheets, that operation has no audit trail, no reliable due-date arithmetic, no way to route field visits efficiently and a compliance document that gets retyped every cycle.

Our team built the system of record that replaced it. A three-level register of customers, sites and assets — including a properly modelled extension for sites that run on an audit cycle under a materials licence — with cycle and derived next-due date as the single axis every dashboard, search, report and job reads from. Priority set independently at asset, site and customer level and rolled up into one score that orders each specialist's personal queue. Distance search served from coordinate data held in the platform's own database, so field visits can be grouped by proximity without a runtime dependency on anyone else's service. Print-ready inventory workbooks generated with real page layout and a safety officer signature block, delivered as a download or an attachment.

Around that sit the controls a compliance system needs: complete attributed versioning across every register entity, restore of deleted records and reversal of individual changes, revert links carried in the notification emails themselves, monthly digests that report what materially changed rather than what was merely saved, and automated pre-due outreach that reaches the specialist and the site contact together at a lead time each customer sets. A separate authentication realm gives customers visibility of their own facilities without access to anything else. Delivered as a full-stack web platform that has absorbed several years of continuous change, it turned a calendar nobody could see into a system that knows what is due, who owns it, where it is, and what changed.

01 — Questions

asked about this kind of project

How do you build software for a compliance operation?

Start from the observation that a compliance register which is approximately right is worse than none at all, because people stop trusting it and quietly rebuild the spreadsheet alongside it. That changes the engineering priorities: the derived date must be correct everywhere it is displayed, the definition of what counts as in-scope must be expressed once rather than reimplemented per screen, and any record that is wrong must be visibly wrong and recoverable. Get those three right and the rest of the product is ordinary work.

How should due dates be modelled in a scheduling platform?

As a derived value held on the record and treated as the system's primary axis, with every dashboard, filter, report, notification and background job reading it rather than recomputing it independently. The failure mode to avoid is three different parts of the application each calculating what is due and disagreeing, which is exactly the situation that erodes trust in the system.

How do you handle an entity that is mostly like another but not quite?

Neither by duplicating it into a parallel table nor by adding a wall of nullable columns to the general record. A one-to-one extension is usually the right answer: the shared properties — address, ownership, lifecycle — stay on the base record, and the specialist properties live on an extension that only exists where it applies. Reporting and search then stay coherent instead of forking.

Why hold geographic reference data locally instead of calling a geocoding service?

Because when distance search is central to how work gets planned, it should not depend on a third party being available, fast, or within quota. Importing coordinate reference data once and querying it directly makes radius search a plain database operation, with no per-request latency, no rate limit and no external failure mode in a path the operation's economics depend on.

How much does audit trail design matter?

In a compliance system it is a core feature, not infrastructure. When a due date or an assignment changes, someone will eventually need to know who changed it, what it was before, and whether it can be restored — and they need to answer that from the application rather than from a database backup. Building versioning in from the start, with attribution and a restore path, is far cheaper than reconstructing history afterwards.

Should a notification just inform, or should it let the user act?

Act, wherever the action is unambiguous. A "this record changed" email that requires the recipient to log in, navigate to the record and work out what to do will frequently be ignored. The same email carrying a direct link that reverses the change turns a notification into a correction mechanism, and the token-keyed link that makes it possible costs almost nothing to build.

How do you add a customer-facing portal to an internal system safely?

As a separate authentication realm with its own model, layout, controllers and scoping — not as a capability flag on the internal user account. The two populations have fundamentally different trust levels, and a structural separation is what keeps them separated as the application grows. The critical discipline is that every lookup in the customer realm must be scoped through the signed-in customer's own relationships, never by identifier alone.

What makes a system like this survive for years?

Keeping the rules in one place. Systems that erode are the ones where the same business rule — what counts as active, when something is due, who can see what — gets reimplemented slightly differently in each new screen. This platform absorbed several years of change, including an entire additional user-facing realm, because the core rules stayed centralised in the domain model rather than spreading into the controllers.

03 — Similar project?

describe what is different about yours

Build yours.

Tell me what exists, what you need and the deadline. Fixed price for a defined scope, or hourly from $10 with a written estimate first.

Ahmedabad, India · IST (UTC+5:30) · --:-- IST · Mon–Fri 09:00–18:00 IST · US & EU overlap daily

No newsletter, no CRM. Just a reply.