Incident Response for 50 WordPress Sites
About 30 hacked sites cleaned, locked, and watched daily
Read case studyFor a digital studio in Indonesia, I replaced its paid CRM with a self-hosted ERPNext that holds quotations, invoices, payments, and the accounting in one place, and moved eight years of client history into it, checked client by client.
A digital studio in Indonesia that builds and maintains websites for businesses. Its account managers send quotations and invoices, and a small finance team records payments, keeps the books, and reports to management.
The studio ran its sales documents on Perfex CRM:
I set up ERPNext, an open-source ERP, on the studio’s existing server, imported everything from Perfex, and switched the CRM’s address over to it.
A scope finance agreed to
Finance confirmed they needed invoicing, quotations, and accounting: a chart of accounts, journal entries, the general ledger, a balance sheet and profit and loss, and receivables aging. Projects, payroll, a payment gateway, and multi-currency stayed out of the first version.
ERPNext, configured before coded
Of the free options I compared (Odoo Community, Invoice Ninja, Dolibarr, and ERPNext), ERPNext was the only one with full double-entry accounting and nothing behind a paid edition. Custom fields, print formats, and settings came first. The little code it needed lives in one small custom app: invoicing a quotation directly marks it Ordered without a sales order, and the studio’s branding survives every update. Finance sees only the modules they use.
Eight years of data, reconciled
A Python importer reads a local copy of the Perfex database and writes through ERPNext’s API. Every record keeps its Perfex ID, so the import can stop, resume, and run again without duplicates. A reconcile step compares each client’s invoice count, totals invoiced and paid, and quotations in both systems. The final run matched 211 of 211 clients and 974 of 974 old proposals. Withheld tax posts to a prepaid tax account, and migrated invoices keep their old numbers on the PDF.
A cutover with a written way back
ERPNext ran side by side with Perfex on a shared server before the switch. The image is built on my machine and shipped over SSH, and the deploy script shows every remote command and waits for a yes. At cutover, a final dump was compared with the imported one, Perfex was stopped, and one route file pointed the address at ERPNext. The rollback was written down first, and Perfex’s files and database stay on the server as an archive.
Backups and a manual
A nightly job backs up the database and files, and the server’s weekly offsite job copies them to S3. Finance got a manual in Indonesian that covers quotations, invoices, payments with withheld tax, journal entries, reports, and corrections.
| Layer | Tool | Role |
|---|---|---|
| ERP | ERPNext v16, Frappe | Quotations, invoices, payments, and accounting |
| Custom app | Frappe app, Jinja print formats | Quotation status, branding, and the PDF documents |
| Data | MariaDB, Redis | ERPNext’s database, cache, and job queue |
| Migration | Python importer, REST API | Imports Perfex history and reconciles it per client |
| Hosting | Docker Compose, Traefik | Runs next to the server’s other apps, routed by a file |
| Backups | Cron, S3 | Nightly backups on the server, weekly copy offsite |
ERPNext took over the CRM’s address the day after the project started, and finance works in it directly.
| Before | After |
|---|---|
| A paid CRM without accounting | Open-source ERPNext with double-entry books |
| The journal kept by hand outside the CRM | Invoices and payments post to the ledger on their own |
| Eight years of history in the old tool | Clients, quotations, invoices, and payments imported |
| Ledger and reports kept outside the CRM | Ledger, balance sheet, and profit and loss in the same place |
Finance still has to confirm the final chart of accounts and decide how to close receivables from before 2024, when the old records of payments were incomplete. The full write-up, including what broke after the cutover, is in my note on replacing a paid CRM with ERPNext.
If your team needs its sales documents and books in one place, get in touch.
New websites and landing pages, maintenance, migrations, and technical SEO for businesses and agencies.
About 30 hacked sites cleaned, locked, and watched daily
Read case studySending stopped on its own, every site on a new key
Read case studyProducts and articles published without a deploy
Read case studyNo health data sent to Google, bookings measured
Read case studyThe company's main hiring platform, built in-house
Read case studyFive chat channels in one inbox on every phone
Read case studyConsent to conversion, end to end, in 2 days
Read case study8+ issues fixed in 2 days, every conversion verified
Read case studyOne event standard across every data flow
Read case studyNext step
Tell me what you have and what you need. I usually reply within one working day with how I'd approach it.