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.
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
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.
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.
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 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.
How it was delivered
| Phase | Duration |
|---|---|
| Requirements analysis and system design | 5 days |
| Backend development (bank CSV, OCR, M365, core API) | 12 days |
| Front-end development (separate application) | 8 days |
| Workflows, exports, search, and async jobs | 5 days |
| Unit testing and validation | 3 days |
| Deployment and team training | 2 days |
| Total | 35 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
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.
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.
Common
Questions
Higher upfront, usually lower over three years. ERPs bill per user and charge for bank connectors, OCR modules, and M365 add-ons. No-code platforms bill per operation. A custom application has a build cost and a hosting cost on infrastructure you already control. Where the crossover lands depends on volume — we'll model it honestly with you before you commit, and if off-the-shelf wins, we'll tell you.
This build ingests French bank CSV exports — the multi-line, semicolon-delimited format most French business accounts provide for download. It parses transaction types and payment motifs natively and auto-links lines to invoices. If you need a live PSD2 API feed instead, that is a different integration scope we can assess separately.
Good enough to eliminate re-typing, not good enough to run unsupervised — which is why the workflow keeps a human confirmation step. Mindee API v2 handles most layouts; an OpenAI-based fallback covers invoices Mindee struggles with. Extraction quality depends on layout; recurring suppliers with consistent templates get near-perfect results.
On infrastructure you choose and control — a private server or your own cloud account. We don't hold your financial data, and there are no third-party SaaS sub-processors sitting in the middle of it.
This build was 35 working days end to end. A tighter scope can be faster; more integrations or unusual data sources will be slower. We scope before quoting.
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 →
Tell us about your setup. We respond within 24 hours.
