Skip to content
In productionSaaSFull stack

Green Compare CRM

An internal CRM for a UK business-energy and payments broker — from quote to contract to commission.

React 19 SPAIdentity providerAPI routers18 domain modulesCapability matrixJob workerTransactional outboxPostgreSQL 16RedisObject storage
Role
Project initiator, then full-stack feature developer
Team
4 engineers — XEOO team
Timeline
Jun 2026 – Ongoing
Organisation
Green Compare Ltd (XEOO team)
Code
Proprietary (employer)
Reading time
5 min

A FastAPI modular monolith with a React 19 front end, where Postgres row-level security backs every permission check. I started the repository, then shipped features across finance, telesales, renewals, dashboards and access control.

Overview

Sellers and telesales reps source businesses, admins price them across suppliers and run credit checks, signed services become contracts tracked to renewal, and finance reconciles supplier commission and rep payouts. The CRM replaces the spreadsheets that used to hold all of this.

The problem

  • A sales pipeline with many hand-offs: seller → admin pricing → credit check → signature → contract → renewal.
  • Money flows (commission, clawbacks, partial payouts) that must be exact and auditable.
  • Strict data boundaries: a rep must see only what their role and team allow — even if an API bug slips through.

Context & constraints

I created the repository with an AI-assisted first version and worked on its frontend before the team moved it to the company organisation, added CI/CD and grew it into a production system. The platform conventions — CI, deployment, security tooling and the row-level security sweep — were built by colleagues; I worked within them.

Approach

My contributions, across 38 merged pull requests:

  • Finance — rebuilt the commissions area (overview, rep payouts, statements), clawback netting and partial payouts with a partly paid status.
  • Telesales call floor — call-floor statuses and allocation, an append-only record of every dial, and two-way sync between list rows and the callbacks diary.
  • Clients & contracts — filters by seller, service and date, a card view with analytics panels for reps, and book statistics computed on the server from one shared filter definition.
  • Renewals — a re-signed meter stops being a renewal, derived at query time with no stored status that could drift.
  • Dashboards — every role board rebuilt on a 12-column grid with a shared widget kit, plus a performance board ranking sellers and telesales over five time windows with drill-down pages. In October the seller, telesales and system-admin dashboards were rebuilt again on server-side reports — earnings, win rate, a “needs you” queue, a call funnel against a daily target, revenue mix and work queues — with every figure audited against the page it links to.
  • Pipeline — a kanban board whose stage totals are counted on the server, role-aware filters, and a notification panel with deep links.
  • Tasks & clients — a board and agenda view for tasks with real completion dates, accessible client rows, and a Files tab per client with an in-app PDF and image viewer, multi-file upload and permission-checked edits.
  • Access control — renamed a role across backend, frontend, identity provider and database, including a migration that rewrote the live row-level security policies.
  • Quality — a responsive end-to-end sweep: every route × role × 8 viewports × 2 orientations.

Key capabilities

  • Quote round-trip from seller request to signed contract
  • Per-product contracts with a renewals board
  • Telesales call floor with callbacks diary
  • Commission ledger with clawbacks and partial payouts
  • Role dashboards and a performance board
  • Pipeline kanban with server-counted stage totals
  • Client files with an in-app viewer
  • Document extraction with PII redaction before any model sees the text

Architecture

  1. Interface

  2. FastAPI modular monolith

  3. Async work

  4. Data

Two layers of authorisation: an application capability matrix decides scope, and Postgres row-level security enforces it underneath. Select a component to trace its connections.

Key decisions

Challenges

Responsive layouts across seven roles

Problem. Every role sees a different set of pages, and layout bugs hid in combinations nobody tested by hand.

Solution. An end-to-end sweep renders every route for every role at 8 viewports in both orientations, failing on overflow.

Dashboard funnels reading the wrong keys

Problem. An admin funnel silently showed zeros because it read stage keys that no longer existed.

Solution. Rebuilding the dashboards on a shared widget kit with typed data sources surfaced and fixed the mismatch.

Quality & delivery

Testing

The project-wide suite holds 858 test functions as of late October 2026 (pytest with real Postgres via Testcontainers, property-based tests with Hypothesis) plus Playwright and axe-core accessibility sweeps. My pull requests added backend tests for performance boards, renewals, book statistics, role dashboards and client files.

Deployment

Six CI gates — secret scanning, backend tests, migration checks against real Postgres, frontend build, security audits and end-to-end accessibility — must pass before merge. Merging to main deploys after a fail-closed migration preflight and a database backup (pipeline built by colleagues).

Outcome

Merged pull requests
38
My contributions, Jun–Oct 2026
Domain modules
18
One FastAPI modular monolith
Roles × capabilities
7 × 17
Backed by row-level security
Test functions project-wide
858
Team total, late October 2026

The CRM runs in production for the company's sales, telesales, admin and finance teams. My finance, call-floor, renewals, pipeline, files and dashboard work is part of the daily workflow.

Lessons

  • Put the hard security boundary in the database; application checks then become a convenience, not the last line of defence.
  • State you can derive is state you never have to migrate.

Building something similar?

Tell me what you’re working on — I reply to every serious message.

Related work

HR mailboxKnowledgeCode checksLLM triagePolicyXEOO AI ControlModelsOutlookSlackAudit log
Case study
In development2026Green Compare Ltd

HR Inbox Agent

A Python agent that reads an HR mailbox through Microsoft Graph, asks a language model for a structured classification and draft reply, and lets deterministic code decide whether to send, save a draft or escalate to Slack.

  • Python
  • SQLite
  • Docker & Compose
  • LLM APIs
  • Agent guardrails & evals
  • AI gateways
  • +1
Six-step formAttributionPOST /api/leadsGET /api/addressesLead logStreet index
Completed2026Green Compare Ltd

Business Energy Quote Funnel

A zero-dependency landing page and Node server for business-energy quotes, with progressive enhancement, ad attribution, spam protection and an offline postcode-to-street index built from open data.

  • JavaScript
  • Python
  • HTML & CSS
  • Node.js