Accounting
I've spent a few years perfecting a simplicity-oriented and open source accounting system to run my business. I believe it is applicable to many other small businesses and is a reliable, private, and completly free alternative to commercial products like QuickBooks. All you need is Ledger, the open source plaintext accounting system.
Ledger may seem overwhelming at first but it's not hard to get the hang of it; the simplicity, power, and flexibility far outweighs anything like QuickBooks. An overview of plain text accounting will help you understand its advantages.
Understanding the basics of Ledger is critical to understanding this guide. Ledger's documentation is excellent, so make sure you understand the following sections:
- 1.1 Fat-free Accounting
- 2. Ledger Tutorial
- 3. Principles of Accounting with Ledger
- 4. Keeping a Journal (safe to skip anything about trading stock and price histories)
It doesn't require any programming experience, but familiarity with a text editor and the command line are necessary.
A Beginner's Guide to the Command Line
The basics
We follow the following basic account categories which are described in the "Structuring your Accounts" section of the Ledger documentation.
- Expenses can be broken down into education, seeds, packaging, hosting, accounting services, and whatever level of granularity you believe is right for you. We use "Expense:Materials:*" categories for consumable expenses, like seeds, compost, and other amendments. We use "Expense:Equipment:*" categories to help keep track of items that qualify for local business property taxes, like machinery and tools.
- Assets simply describes our cash on hand and checking account.
- Income can be broken down by any level of granularity that you prefer. We have "Income:Development" for programming work, "Income:CSA" for our committed farm customers, and "Income:Wholesale" for our bulk customers.
- We use a "Liabilities:Sales Tax" category for sales tax that we collect on behalf of the state, that we then owe at the end of the month.
Here's an overview of all of the the accounts we've ended up with so far.
Other details
- See section 4.2 "Starting up" in the Ledger documentation for an explanation of how to handle your opening balances.
- See section 3.3.1 "Tracking reimbursable expenses" to understand how reimbursements work, as you may eventually need to track that.
File organization
We have our finances organized by year, so they end up oulooking like this:
Ledger allows you to import other files (with `include file.txt`), so running it on the main `business.txt` file will include all details about payments, donations, mileage, and orders. You can structure this however you like, this is just how we do it.
Payments
If you sell at a market to customers on the street, you may be able to total up your cash for the day and make a single ledger entry for your income. We operate our CSA on a share-commitment model in which customers come to pick up produce every week and are committed for the whole season. Customers don't always have exact change, so we need to keep track of balances and credits available to each customer.
To make collecting payments easy, we created a separate file in our accounting folder for customer payments and used Ledger's `include` command to import it into our main ledger.
Here's a snippet from our csa_payments.txt file:
In this example, our weekly share cost $20.00 + $0.50 sales tax for a total of $20.50.
- Amy wrote a check for the exact amount. We deposited it immediately via our bank's mobile app. We recorded the check number in case of a discrepancy with the bank.
- Erin paid exact cash.
- Vicki didn't have change so she paid with bills and told us to put the credit on her account.
Assuming you've created transactions for Amy, Erin, and Vicki's orders (see above), Ledger will compute Amy and Erin to have a balance of $0.00 and Vicki will have a balance of $-0.50, meaning you owe her $0.50.
In our model, we will return any unspent credit to each customer at the end of the year. Notice that our customer accounts are not categorized under "Income:Customer:...". This unspent credit of Vicki's does not count towards our taxable income, as we are simply holding it for Vicki temporarily. Check with your accountant and local laws to determine if this is appropriate for your case.
When we make a trip to the bank to deposit our cash, we can record the deposit like so:
Mileage
We want to use the IRS's standard deduction for personal vehicle use. According to IRS rules, you must provide records that substantiate the date, odometer begin and end readings, depature location, destination, and business purpose of each trip. As we file taxes quarterly, we need to report this with our income and expenses.
https://www.irs.gov/publications/p463
Note that not all trips can be deducted as business trips. Make sure you understand the tax laws and discuss it with your accountant.
First we added a new file to our accounting folder with the name of the vehicle, and used the `include` command to import it into our main ledger. Having one file per vehicle can make it easier to quickly enter odometer readings if you're doing it daily.
Here's a snippet from our mileage_yaris.txt file:
- Note the January 1 odometer reading comment at the top. The IRS might request this information.
- The `bucket` command specifies the default account to balance against so that we don't have to re-type it with every transaction. This applies to every transaction in the file.
- The `apply account` command simply sets the root account of all accounts following in the file (so that we don't have to type "Expense:Mileage")
- The metadata values for "Depart" and "Destination" are included with each transaction.
- Time and business purpose are listed in the transaction's description.
Ledger can keep track of any unit; this account posting uses miles as the unit instead of dollars. You can do math within the account posting as long as the expression is wrapped in parentheses. This way you can record begin and end odometer readings as `(end - begin)` and let Ledger do the math for you when you balance. Mileage can now be queried just like any other Ledger transaction in order to get the appropriate report for your taxing authority. If you want to figure out the dollar-equivalent per mile, use the `--market` flag when invoking Ledger and it will automatically convert miles to dollars at the rate you have specified.
Non-cash donations
As with mileage, you can also track non-cash donations for tax deduction purposes. It's as simple as giving each commodity a value, and then using the `--market` flag to compute the total value of all donations.
Sales Tax
We collect cash when at the farmers market and to make things easy, we price our stuff so that things round to the whole dollar when tax is included. The formula to figure this out is `DESIRED_TOTAL / (TAX_RATE + 1) = ORIGINAL_PRICE`. For example, if we want to sell 8oz of black eyed peas for $5.00, then to calculate the original price at a sales tax rate of 1% you'd do `$5.00 / (1.01) = $4.95`. The remaining $0.05 is the sales tax to collect. Depending on your state, you're legally required to list the product for "$4.95" and not "$5.00 including tax."
This system isn't perfect because we're charging sales tax on the individual items rather than the transaction total which will cause rounding errors, but at least we're getting close here. Also notice that $5.00 / 1.01 actually equals $4.950495. You will report your collected tax to the state as a monthly or quarterly total, and there will also be more rounding descrepancies there too as described below.
Here's an example transaction for a day at the farmers market in which we sold $85.00 of goods.
As with mileage described above, we can use any commodity or unit for the posting. Our quantities of goods sold are negative because we're exchaning these items and receiving positive cash. Using the @ symobl, we can indicate the grand total sale price of each item including tax. This transaction will balance because, regardless of what is taxed or not, we now have an additional $85.00 cash in our possession.
Notice the `= $204.00` at the end of the Assets:Cash posting. That's a quick sanity check verify that we now have a total of $204.00 in our cash envelope total. You can even leave out the $85.00 and just write `= $204.00` so that you only have to count the total cash in your envelope without having to add up your sales manually. If the cash doesn't match, your ledger won't balance and will throw an error.
The state of Virginia taxes food at a different rate than other items, so that's why things are categorized separately for Retail:Food and Retail:General. At the top of the file, add these "Automated Postings" which will create additional postings based on the regex after the = symbol.
This will insert additional virtual postings into the transaction so that this:
Becomes this:
Meaning:
- We sold 1 rosemary salt and exchanged that for $5.00 cash from the customer
- $4.95 of that should be classified as income
- That $4.95 should be reported to the state as part of our gross retail sales (virtual posting in parentheses, more on this below)
- $0.05 was added to our sales tax liability
- $5.00 cash is now in our assets
Paying
To determine the sales tax that you collected, run this report:
The first number will be the tax owed (assuming you haven't paid it yet), and the second number will be a running total, which is irrelevant to this situation.
Breaking these arguments down:
- group the transactions by month
- use the "effective date" so that the payments appear with their appropriate collection month (see below)
- change 'Liability:VA:Sales Tax' to any appropriate account filter for your situation
To find the total income that should be taxed, run this report, which will take into account the virtual postings mentioned above:
When making a payment on January 5th for December's taxes, be sure to set the "effective date" to the previous year so that you can verify that all taxes are paid up. The same applies for each month (e.g. paying June's taxes in July). For example:
A small wrinkle in this situation is rounding errors and discounts. For example, if you collect 2.5% sales tax on an order with a subtotal of $10.79, you would collect $0.26975, which rounds to $0.27. This rounding error will accumulate on every order. So if, for example, you have made a total of $859.04 of sales in a given month, 2.5% of that is $21.48 (what the state will calculate that you owe), but you will have found that you have collected something like $21.56. That's $0.08 that you've overcollected, and since everything must balance in ledger, it needs to be accounted for somehow.
In our case, the state of Virginia also gives an extra "dealer discount" of some very small percentage for those who pay on time. So in the above example, the state calculates that we owe $21.48 in taxes minus their $0.21 dealer discount for a total of $21.27 owed. Since we actually collected $21.56 from customers over the course of the month, we'll just lump our $0.08 overcollection in with the $0.21 dealer discount and just classify this as extra income.
This is how the transaction posting from above should now look to account for all of this:
The first line in the transaction states that we are removing $21.56 from our sales tax liability. The second line states that $21.27 of that is coming out of our checking account (what we paid to the state). The third line indicates that the remainder, the dealer discount plus our overcollection, gets categorized as income; since ledger forces each transaction to balance, the math is done for us when we leave out the amount on this line.
1099s
Figuring out which clients owe you a 1099, or those that have paid you $600.00 or more over the course of the year:
Breaking these arguments down:
- grouping the transactions by payee
- compute the final subtotal for each payee, as we don't care about individual transactions in this report
- display only totals [T] that are greater than or equal to 600 (remember that incomes are negative in ledger, so we use [U(T)] to take the absolute value)
- filter to show only transactions from 'Income' and children accounts (unrelated to the previous --display argument)
If you have any contractors, you can also see which contractors to whom you owe a 1099 by running the same report on the relevant 'Expense' accounts:
Distributions
If your business is set up like a pass-through entity so that you pay yourself via distributions rather than an official payroll process, you can record your distributions like so:
Estimated Quarterly Tax
If you live in a sane country and need to pay quarterly tax estimates, you can probably use Ledger's `--quarterly` option. If you live in the United States, the IRS has shifted quarters around to fudge the books, and now we all have to live with it. This simple shell script divides the report into four "magic IRS quarters":