Read this case study on its own page
Challenge
Manual invoicing creates friction at every step — chasing payments, reconciling the accounts, producing reports — and the errors compound: a missed reminder, a duplicate entry, no clear record of what was sent, when, and why.
Approach
A billing platform built in deliberate phases, each solid before the next was added. First the domain: optimistic concurrency and soft delete, so simultaneous edits fail safely and nothing is lost for good. Then an audit layer: every write logged, every operation carrying an idempotency key so a retry can never double-bill. Then a contract-first API with strict validation, observability with health checks and structured logging, and the automation itself — batch invoice runs, scheduled payment reminders and finance reporting. A WPF desktop application (MVVM, EF Core) gives day-to-day use without touching the API: client and invoice management, time-entry workflow, PDF invoices and estimates with brand defaults, and a light/dark theme checked for WCAG AA contrast. FreeAgent keeps payment status in sync, and local OCR handles incoming documents. Infrastructure is defined as code and deployed through a multi-environment pipeline.
Outcome
- The full billing lifecycle runs without manual chasing or re-keying
- Every write has an audit trail, which is what you want when a payment is disputed
- Reminders go out automatically when invoices fall overdue
- Accounting records stay current through the FreeAgent sync; invoices and estimates export in one action
Where judgement mattered
- Idempotent writes before features — retries are the normal case in a system that talks to an accounting API
- Phased delivery so each layer could be trusted before the next depended on it
- A desktop interface for the person doing the work, not just an API for other systems
Technology stack
C# / .NET 10 · Azure Functions · Azure SQL · WPF with EF Core · QuestPDF · FreeAgent API · Microsoft Graph · infrastructure as code · Azure DevOps CI/CD