WorkB2B Technology Sales CRM
Quote-to-cash for a technology distributor
B2B Technology Sales CRM
A production CRM that replaced spreadsheet quoting for a B2B technology distributor — with an import-duty engine that has to be right to the cent.
- Status
- In Use
- Category
- Business system
- Year
- 2026
- Role
- Designed and built end to end — schema to pixels to pentests.
Client identity withheld. Interfaces shown are recreated with representative demo data — not customer screenshots.
The problem
A B2B technology distributor quoted everything by hand across a legacy ERP and spreadsheets. Sri Lanka's import-duty regime is a multi-layer cascade that behaves differently depending on how a line item enters the country — and a manual process got it wrong often enough to cost real money. There was no live pipeline picture, no approval trail, and every quote was a small act of heroism.
Constraints
- The duty cascade changes by import route, and the engine had to match the firm's own historical paperwork exactly — close wasn't good enough
- Dual-currency quoting against a bank rate that moves during the working day
- Sales and admin roles had to be separated in the database itself, not just the interface
- One builder, a production timeline measured in weeks, and a business that couldn't stop quoting while it was built
The approach
I started from the workflow, not the feature list — sitting with how quotes actually moved from enquiry to purchase order. The duty engine came first, built against ground truth: the firm's own historical bills of quantity, reconciled line by line until every block matched to the cent. Only then did the product grow around it — pipeline, quoting, approvals, vendor POs — on one Postgres backend with row-level security, and with verification wired in as a schedule rather than a phase.
What was built
- Quote builder with dual-currency pricing and a live bank-rate bar refreshed three times daily by scheduled jobs
- Import-duty engine with universal levies and import-only layers gated per line — reconciled to the cent across fourteen real bills of quantity
- Realtime kanban pipeline, deal drawer for meetings and next steps, and a reporting dashboard with KPI charts and spreadsheet/PDF export
- Quote PDFs, vendor purchase orders and notification emails through role-authorised edge functions with idempotent logging
- Twenty-two Postgres migrations across 13+ tables, with row-level security pentested green (36/36 checks)
- ~59 unit and property tests — the duty math fuzzed across roughly forty thousand generated cases — under strict TypeScript
Contribution
Built with React 19 · TypeScript · Vite · Supabase · Postgres RLS · Edge Functions · pg_cron · Playwright · Vercel
Technical decisions
Ground truth over cleverness
The first version of the duty engine confidently applied the wrong cascade. The fix wasn't smarter code — it was treating the client's own historical paperwork as the oracle and reconciling against it line by line before building anything else.
Security as a schedule, not a phase
Row-level-security pentests and full E2E suites run as scheduled agents — nightly and weekly — so regressions surface on their own instead of waiting for a review.
Money math gets property tests
Anything that touches currency is fuzzed across generated cases, not just spot-checked. Forty thousand cases argue better than four examples.
Evidence
Outcome
- Deployed to production infrastructure and used for live quoting workflows
- The reconciliation pass surfaced a systematic overcharge (roughly a third on affected import lines) that the manual cascade had been applying
- Nightly automated E2E runs and weekly security stress-tests have run green on a schedule since mid-June
- A stripped-down fork of the same system now runs my own studio's client pipeline every day
Current status
In UseIn Use — the scheduled verification agents have run green through July; the client go-live was parked during a strategy pivot, and the internal fork runs my own studio pipeline daily.
Lessons
The hard part was never the software — it was the domain. Duty law doesn't care how clean your components are. The lesson that stuck: when a number matters commercially, the build starts at the number, and the UI earns its place around it.
Next stage
A multi-tenant direction (team knowledge sync and a retrieval-grounded assistant) is built behind a flag — it ships when the first external tenant signs, not before.