Case study

Building IMS-BCV's invoice and accounting platform in 35 days

IMS-BCV, trading as Open-Bar runs the back office for France's first national network of independent CHR equipment installers. Member-installers, supplier invoices, and bank exports all had to reconcile in spreadsheets. We built them a self-hosted invoice and accounting system — French bank CSV parsing, dual-engine invoice OCR, Microsoft 365 integration, and structured payment reminders — that ships in 35 working days on a fixed scope.

Sector: CHR equipment installation & maintenance · federated installer networkEngagement: fixed-scope build, 35 working daysStack: NestJS · Fastify · MySQL · Meilisearch · PM2Delivery: design → build → test → deploy → training
At a glance

The project at a glance

Scope

Bank CSV parsing, dual-engine OCR, M365, dunning, accounting export, grand livre import, search, RBAC

Duration

35 working days, fixed scope and price

Stack

NestJS, Fastify, MySQL/TypeORM, Meilisearch, PM2 on a private server

Status

Live in production; team trained as part of delivery

Context

The situation

IMS-BCV, trading as Open-Bar, is France's first national network of independent professional installers specialising in tirage pression (draft and beverage dispense systems) and other bar-space equipment — coffee machines, refrigeration, back-bar equipment, and CHR (Café-Hôtellerie-Restauration) furniture. Founded in June 2015, the network federates independent member-installer businesses under a shared quality charter. National coverage; each member is its own business, not a branch of a single operator.

The system we built serves IMS-BCV's own back office — not a restaurant or bar business. Financial operations span the network's member-installers as clients and equipment suppliers such as LENNE CRÉATION as fournisseurs. Invoices, payments, and reconciliations had outgrown the tools handling them.

That created three concrete problems.

Reconciliation was retrospective. Bank exports arrived as French CSV files with multi-line entries, semicolon delimiters, and dd/MM/yyyy dates. Someone had to classify transaction types and match payment labels to invoice references by hand — work that only happened when a spreadsheet was updated, days after a payment had already landed or left.

Invoice data was re-keyed. Supplier invoices arrived as PDFs in email and on disk. Amounts, due dates, and references were typed into tracking sheets — slow, and exactly where a transposed digit goes unnoticed until month-end.

Nobody owned the follow-up calendar. Overdue client invoices had no structured reminder path tied to the ledger. Due dates, +20-day and +30-day escalations, and phone-follow-up flags lived in people's heads or separate lists — not in one system that cleared itself when a payment was recorded.

None of this was a bookkeeping failure. It was a tooling gap: a federated installer network had scaled past what spreadsheets and a generic ERP connector could honestly connect — bank exports, Outlook inboxes, SharePoint archives, and the network's actual dunning process.

Alternatives

Why not Sage, Cegid, or a no-code stack

The obvious first move is an off-the-shelf ERP or a wire-together of SaaS tools. For many finance problems that is the right answer — we build on n8n and Make for clients regularly when the fit is there. For IMS-BCV it wasn't, for reasons that apply equally to Sage-style ERPs and to Make/Airtable/Zapier.

French bank CSV parsing built in. Generic ERPs need manual mapping or paid connectors for bank feeds. IMS-BCV's exports use the French multi-line CSV format — semicolon delimiters, dd/MM/yyyy dates, transaction motifs like "DE", "POUR", "VIR RECU", and "FRAIS" that encode client vs supplier payments. This system parses that format natively and auto-links payments to invoices from the label text. No connector subscription.

Microsoft 365 without a document-management add-on. Outlook and SharePoint integration in generic ERP is limited or costly. Here, Microsoft Graph polls the network's Outlook inbox every ten minutes for invoice attachments (OAuth2 with automatic token refresh) and files processed documents to SharePoint by fiscal year and French month name — no separate DMS to maintain.

Dual-engine invoice OCR as standard. ERP OCR is usually an optional paid module. This ships Mindee API v2 as the primary engine with an OpenAI-based fallback for layouts Mindee handles poorly — multi-page PDF splitting and merging on both paths.

Dunning that matches the network's process. Generic tools offer configurable-but-rigid reminder rules. This runs scheduled checks every twelve hours: due date, +20 days, +30 days, then a phone-follow-up flag — auto-clearing once an invoice is marked paid.

Cost and control. Per-user ERP licensing vs one-time development on infrastructure the network already controls. Financial data stays on a private server under their hosting arrangement — not on a third-party SaaS retention policy.

Build

What we built

The brief was a custom web application for invoice and accounting operations — not another spreadsheet with automation bolted on. Nine modules shipped in the same 35-day engagement.

French bank statement processing

Parses French bank CSV exports — multi-line entries, semicolon delimiters, French date format (dd/MM/yyyy) — classifies transaction types, and extracts invoice references from payment labels (patterns like "DE" for client, "POUR" for supplier, "VIR RECU", "FRAIS") to auto-link payments to the correct invoice.

Dual-engine invoice OCR

Mindee API v2 as the primary OCR engine (enqueue-and-poll pattern), with an OpenAI-based fallback for invoice layouts Mindee does not handle well. Multi-page PDF splitting and merging on both paths.

Microsoft 365 native integration

Polls the network's Outlook inbox every ten minutes for invoice attachments (OAuth2 with automatic token refresh via Microsoft Graph), and uploads processed documents to SharePoint organised by fiscal year and French month-name folders — no separate document-management system to maintain.

Structured payment collection workflow

Scheduled checks every twelve hours for overdue invoices, with reminders at the due date, +20 days, and +30 days, escalating automatically to a phone-follow-up flag after 30 days. Auto-clears reminders once an invoice is marked paid.

Accounting export

Generates Excel exports formatted for the network's external accounting software, applying client code prefixes and payment-type codes (cheque/cash/transfer) automatically, and tracking what has already been exported so nothing is sent twice.

General ledger (grand livre) import

Imports client general ledger Excel files, creating or updating client and invoice records and reconciling them against existing transactions.

Network-wide search

Meilisearch-backed search across clients, invoices, suppliers, transactions, and expenses in one query — full-text and typo-tolerant, including fuzzy matching on invoice numbers. Separate indexes per entity with hourly full resync and real-time incremental updates.

Role-based access control

Module-level, granular CRUD permissions (create/read/update/delete per module), so different roles across the network's back office see only what is relevant to them.

Async processing for heavy jobs

Long-running work — ledger imports, invoice OCR batches — is queued and processed in the background with status tracking and completion notifications, so large file uploads do not time out the request.

Architecture

Architecture and security

Backend: NestJS 11, TypeScript 5.7, Fastify 5 (via @nestjs/platform-fastify, with 50MB multipart upload support for invoice PDFs). Database: MySQL via TypeORM 0.3, schema managed externally (synchronize: false). Auth: JWT with bcrypt and a custom AuthMiddleware. Search: Meilisearch with separate indexes per entity. Deployment: PM2 cluster mode (three instances), production bound to 127.0.0.1. A separate frontend application consumes the backend's REST API.

Data lives on a private server, so financial records stay under the client's control. This is the same class of custom web app work we deliver when operations have outgrown plugins and spreadsheets.

The design is deliberately modular: bank CSV ingestion, invoice OCR, Microsoft 365 sync, dunning, exports, and search are separate concerns talking through defined interfaces. Access is role-based at module level; notification and reminder logic is tied to invoice state rather than a separate alerting product.

Delivery

How it was delivered

PhaseDuration
Requirements analysis and system design5 days
Backend development (bank CSV, OCR, M365, core API)12 days
Front-end development (separate application)8 days
Workflows, exports, search, and async jobs5 days
Unit testing and validation3 days
Deployment and team training2 days
Total35 working days

Fixed scope, fixed price, staged payments. Training was part of the build rather than an afterthought — an internal tool nobody has been walked through is a spreadsheet with extra steps. Handover included role setup, reminder configuration, and a short runbook for the two most common exception paths (unmatched bank line and supplier invoice mismatch).

Results

Results

This section is qualitative client feedback, not a metrics dashboard. IMS-BCV confirmed outcomes in ongoing use rather than audited before-and-after figures. Unlike case studies on this site where hard numbers are available — the Meca Express ROAS engagement, for example — there are no hour counts, percentages, or user totals for this build, and we are not inventing them.

Three things the client called out specifically. The general ledger (grand livre) import and reconciliation works exactly as they wanted — client records line up against bank and invoice data the way their back office expected. The automated payment reminder workflow (relance automatique) reliably catches every member who has not paid by the due date, with escalating follow-up through the reminder schedule built into the platform; they described it as working perfectly. Overall, the network gained time and finance operations are organized where they were previously fragmented across spreadsheets, manual exports, and ad hoc follow-up.

That feedback is steady-state — ongoing use since go-live, not a fixed measurement window. No client quote is published for this page.

Roadmap

What the architecture unlocks next

Because the modules are separable, the platform grows without a rebuild. On the table: deeper supplier and partner management, additional business processes brought into the same system, an advanced reporting module with custom KPIs, integrations with CRM or invoicing tools, and contract management. Each of these is an addition to an existing codebase rather than a new tool with a new login and a new data silo. The network can prioritise by operational pain, not by what an ERP vendor ships next quarter.

FAQ

Common
Questions

Have a process that's outgrown its spreadsheet?

Book a short scoping conversation. We will tell you whether a custom build, an ERP, a no-code stack, or neither is the right next step.

Not ready to write it all out? Book a 15-minute discovery call →

Start the conversation →
Get Your Free Audit

Tell us about your setup. We respond within 24 hours.