Skip to content

Case study · Business platform · 2026

Custom CRM & Service Platform

Clients, tickets, time, contracts, devices, and billing in one system, built because the software we could buy did not fit.

At a glanceRolling out
  • Automated tests

    2,100+
  • Devices found on first sync

    690+
  • Ticket statuses

    16
  • Roles, scoped by territory

    5

Built for E3 IT Services' own service desk, sales, and billing teams

The problem

What it was like before

A service business runs on one system more than any other: the one that holds every client, ticket, time entry, contract, and invoice. Ours was an off-the-shelf PSA, and like most off-the-shelf software it was built for an average company rather than for us. Every workflow it did not fit became a workaround, a spreadsheet, or a habit someone had to remember.

The cost landed where it matters most. Billing depended on people remembering rules the software did not enforce. Devices found by our monitoring had to be matched to clients by hand. The sales pipeline lived in a separate system again.

And every change we wanted was a feature request to a vendor with thousands of other customers and its own priorities.

Built with

TypeScriptReactAzure FunctionsAzure SQLPrismaEntra ID single sign-onMicrosoft GraphSharePointAzure Static Web AppsAzure Pipelines

The build

How it works

The short version, before the exploded view goes component by component.

We built our own: one platform for the whole client lifecycle, from first lead to final invoice. Staff sign in with the Microsoft 365 accounts they already have, and what each person sees follows their role (admin, manager, technician, dispatcher, or sales) and their territory, both driven by Entra ID groups rather than a user list kept by hand.

Tickets move through sixteen defined statuses, and time runs on a server-side timer, so an hour is never lost because a browser tab closed. Billing rules live in the API rather than in people's heads: every entry is billable, do-not-bill, or non-billable, internal work can never be billed, and an entry locks once it has been invoiced.

Contracts carry the commercial model (managed, block hours, time and materials, or project) with per-seat and per-resource pricing and margins, so what a client is owed and what they are charged come from the same record.

Devices arrive on their own. The platform discovers them from our backup monitor, our network monitor, and our remote management tool, and anything it cannot match to a client with confidence waits in a review queue that can be cleared two hundred at a time.

A sales pipeline with monthly and annual recurring value, projects and tasks, a calendar, a knowledge base backed by SharePoint, search, and reporting complete it. Existing data comes across through spreadsheet imports, an import from the previous CRM, and a read-only reconciliation against the old PSA, so the switch happens in stages rather than over one risky weekend.

It is TypeScript end to end: a React front end, an API on Azure Functions, and Azure SQL through Prisma, deployed from Azure Pipelines and covered by more than 2,100 automated tests.

End to end

One client, start to finish

A genuine sequence, which is why these are numbered: from the first conversation to the invoice, in one system rather than four.

  1. 01

    Lead and opportunity

    A prospect enters as a lead and becomes an opportunity, with its monthly and annual recurring value tracked in the pipeline.

  2. 02

    Contract

    The signed deal becomes a contract: managed, block hours, time and materials, or project, priced per seat or per resource, with the margin visible.

  3. 03

    Devices discovered

    The client's devices appear on their own from the backup monitor, the network monitor, and remote management. Anything that cannot be matched with confidence waits in a review queue rather than being guessed.

  4. 04

    Tickets

    Requests become tickets that move through sixteen defined statuses, worked by technicians who see the clients their role and territory allow.

  5. 05

    Time captured

    A server-side timer records the work, so a closed tab or a crashed laptop never loses an hour, and every entry is marked billable, do-not-bill, or non-billable.

  6. 06

    Billing enforced

    The API applies the billing rules: internal work can never be billed, and once an entry has been invoiced it locks, so a billed number cannot drift afterwards.

  7. 07

    Knowledge kept

    What was learned goes into a knowledge base backed by SharePoint, and reporting reads from the same records the work was done in.

Architecture

Every moving part

The platform pulled apart plane by plane, from what staff see down to how a change is tested and shipped.

Exploded view

Six planes, 18 components. Select a layer to open it.

  • Web application

    React + TypeScript

    Tickets, clients, contracts, devices, pipeline, projects, calendar, and reports in one interface, so nobody switches systems mid-task.

    Search

    Application logic

    Any client, ticket, device, or article, found from one box.

    Review queues

    Application logic

    Devices that could not be matched to a client wait here for a person, and can be cleared two hundred at a time.

Can we build this for you?

This platform is rolling out across E3 IT Services' own service desk, sales, and billing in stages, alongside the system it replaces. If your business has outgrown its CRM, ticketing, or job-management software, we can build the version that fits how you work, signed in with your Microsoft 365 accounts and running in your own Azure tenant, and move your data into it at a pace your team can absorb. It is a project engagement, scoped and quoted like any other build.

Free consultation

Tell us what you are stuck with.

We will tell you whether it is a build problem, a configuration problem, or something you should not spend money on at all.