MOVGRANTO

What we don't build: a TMS, not accounting software

A SaaS scope includes what you deliberately don't build. One sentence defining BusiKM as a TMS, not accounting software, cut 14k lines of code.

Published: 7 min read

Author: Łukasz Głowacz, Full-Stack Engineer · Czytaj po polsku

Two boxes: we build transport data, we don't build ledgers, taxes and payroll.
Contents

The most important scope decision in BusiKM wasn't about any feature I built. It was about the ones I won't build. I wrote it down in one sentence in the implementation plan from August 21: BusiKM is a TMS, not accounting software. What goes into the MVP, what gets removed from the code and how I talk to customers about what the product won't do all depended on that sentence.

The temptation to build everything

BusiKM is a system for small transport companies running vans up to 3.5 t: orders, routes, invoices, costs, drivers, working time. One of the roles in the system is the accountant. Once an accountant has an account in the app, the temptation is obvious: the data is already here, so why not keep the books here too, calculate taxes and payroll, file declarations.

That's what the product looked like in the spring. In April I built a module for accounting firms: one firm served many client companies, switched between them, had its own subscription plans and a 90-day trial. The code already had a JPK_FA generator (JPK is the Polish standard audit file format for tax authorities) and a KPiR summary (KPiR is the simplified revenue and expense ledger used by small businesses). The product audit from August 20 went even further and recommended adding a JPK_PKPiR and JPK_EWP generator, plus a single "package for the accountant" button that zips up the whole month.

Each of these sounded reasonable on its own. Together they turned BusiKM into accounting software with a transport module, which is a different product with a different market and different competitors.

The boundary in one sentence

The implementation plan from August 21 opens with a guiding principle. The accountant already has a program: Insert, Comarch Optima, Symfonia or something else. From BusiKM she needs transport data in a form that's easy to load into that program. BusiKM doesn't keep books, doesn't calculate taxes, doesn't calculate payroll and doesn't file declarations. It delivers data: complete, correctly tagged for tax purposes and in a format her program accepts.

Product boundary: on the BusiKM side orders, routes, sales invoices with tags, costs, working time, days abroad, mileage log and payroll input data. On the accountant's software side KPiR, JPK declarations, payroll and depreciation. Between them an XLSX, EPP, XML or TXT file

Four decisions followed from this principle, each with a short rationale:

What we don't build Why What we deliver instead
JPK_V7M, JPK_PKPiR, JPK_EWP These are declarations to the tax office, filed by the accountant's software Data with correct tags
KPiR as a file KPiR is a ledger, kept by the accountant's software Sales and purchase registers
Payroll (ZUS, PIT, net and gross) A separate domain with its own programs Timesheet, days abroad, per diems, advances, kilometers
Depreciation and lease schedule That's fixed asset records Vehicle ownership type and the installment correctly tagged as a cost

The same principle rejected the recommendations from the previous day's audit. The JPK_PKPiR and JPK_EWP generator was dropped from the scope for good, because those are declarations. The ZIP package was dropped too, with a short rationale in the plan: the accountant downloads what she needs.

A file, not an API

The second half of this decision is about how the data gets handed over. At first glance, an API integration with accounting software looks better than a file. The research from the audit showed otherwise. In Poland the exchange standard is a file: Insert reads EPP, Comarch Optima has an API that depends on the version and on partner licenses, and Symfonia's API handles KSeF (the Polish national e-invoicing system), not the books. Building an API integration for each of them means license costs, maintenance after every update of their software and zero value for an accountant who imports a file anyway.

That's why BusiKM has file generators for three programs and, since October 3, a fourth format: a universal XLSX that can be loaded into any program, including ones I've never heard of.

What got removed from the code

A principle in a plan changes nothing as long as the code keeps doing something else. Over the following weeks it worked its way through the code step by step:

Timeline: in April the accounting firm module, on August 20 the audit recommending a JPK generator and ZIP package, on August 21 plan v5 with the guiding principle, on August 30 removal of the pilot, on September 1 removal of the accounting firm, on October 3 universal XLSX, on October 4 payroll as input data only, on October 12 JPK_V7 tags and JPK_FA(4)

A day earlier, on August 30, I removed the pilot program. The biggest change, though, was removing the accounting firm module on September 1. The PR that did it touched 194 files and deleted 14,116 lines. The models for the firm and its invitations went away, along with switching between client companies and the header that told the backend which company the firm's accountant was acting for. The accountant role stayed, but it's now tied to the client's company: one account, one company. Serving multiple companies from one accountant account is planned only after the MVP.

On October 4 the payroll summary stopped calculating contributions and tax. What's left is input data for the payroll program: working time, days abroad per country, per diems, advances and kilometers. I wrote about how I count days abroad from GPS points in the post about offline country borders.

Where the boundary is thin

It's hardest where data and taxes meet. On October 12 I added the tags on invoices needed for JPK_V7: a KSeF number or one of the markers for invoices issued outside KSeF, along with a JPK_FA(4) file compliant with the Ministry of Finance schema. It looks like accounting, but it isn't. BusiKM doesn't file the JPK_V7 declaration. It only makes sure an invoice has the full set of tags from which the accountant's program will build that declaration. JPK_FA is a file of invoices that a company hands to the tax office on request, and the invoices are created in BusiKM.

Dates sit on the same boundary. An invoice with a sale date in the wrong month ends up in the wrong declaration, which is why I wrote separately about dates calculated in Polish time in the post about date.today(). The data has to be correct, because the accountant's program trusts it.

What it costs

Cutting scope has a price. A customer looking for one program that does everything won't find it in BusiKM and will pick someone else. The separate module for accounting firms is gone even though it already worked, and today a firm can work in BusiKM only as an accountant tied to a single company. Deleting 14 thousand lines is also an admission that the spring's work went in a direction I've backed away from.

In return, the product has one clear promise: transport data reaches the accountant correct and in her format. I can check every new feature with one question: is this transport data, or is it already accounting? The same table that's in the plan is the simplest way to show a customer what they get, what their accountant still does and why that's better for both sides.

If you're building a SaaS, try writing down the boundary of your product in one sentence before you start the next feature. If you want to talk about the scope of your MVP, write to me.

Łukasz Głowacz

About the author

Łukasz Głowacz

Full-Stack Engineer · MOVGRANTO

Full-Stack Engineer at MOVGRANTO. Builds systems from architecture to production: backend, web, mobile, payments and CI/CD. Author of BusiKM, a SaaS for managing van fleets.

LinkedInGitHub

BusiKM

Fleet management for 2.5-3.5 t vans: orders, live fleet map, driver working time and costs in one place. 14 days free.

Try BusiKM ↗

Building a similar system?

We join teams as full-stack engineers or build products from scratch. Let's talk about your project.

Book a call →

Newsletter

One real architecture decision from building a production SaaS, every week.