💾 Archived View for gemini.sensorstation.co › ~winduptoy › notes.accounting.gmi captured on 2024-05-10 at 10:40:40. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
2024-04-06: I'm re-publishing this from an archived copy because I was contacted by someone who said it was helpful info. Slimvoice is no longer published online as I ended up being slightly unhappy with the ergonomics of it. I'll update this guide one day when I have a better solution.
We've spent a few years perfecting a simplicity-oriented and open source accounting system to run our business. We believe it is applicable to many other small businesses and is a reliable, private, and completly free alternative to commercial products like QuickBooks. The system consists of Ledger, the open source plaintext accounting system, and Slimvoice, our home-grown order and invoicing companion.
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:
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
We follow the following basic account categories which are described in the "Structuring your Accounts" section of the Ledger documentation.
Here's an overview of all of the the accounts we've ended up with so far.
Assets Checking Cash Donations Expense Accounting Ag Education Equipment Materials Packaging Seeds Soil Test Hosting Mileage Phone Property Lease Tax Income Ag Apps Development Opening Balance Taxable:VA:Sales Tax Food General
We have our finances organized by year, so they end up oulooking like this:
. ├── 2018 [ previous years ] └── ... ├── 2019 └── ... ├── 2020 └── ... └── 2021 ├── sensorstation.txt [ main ledger file, major transactions ] ├── csa_payments.txt [ customer cash payments ] ├── csa_donations.txt [ tax-deductable food donations ] ├── csa_harvest.txt [ you can track veggies too ] ├── mileage.txt [ just mileage transactions ] ├── orders.txt [ transactions generated from Slimvoice orders, don't touch ] ├── orders [ Slimvoice order source files ] │ ├── 00001_2021-05-19_Jones │ ├── 00002_2021-05-20_Gander │ └── 00003_2021-05-21_Grilli └── receipts [ receipts to substantiate expenses ] ├── 2021-01-01_DigitalOcean.pdf ├── 2021-01-02_VA-SCC.pdf └── 2021-01-03_HomeDepot.pdf
Ledger allows you to import other files, so running it on the main `sensorstation.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.
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 payments.txt file:
2021/05/20 (1113) Assets:Checking $20.50 Customer:Amy 2021/05/20 Assets:Cash $20.50 Customer:Erin 2021/05/20 Assets:Cash $21.00 Customer:Vicki
In this example, our weekly share cost $20.00 + $0.50 sales tax for a total of $20.50.
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:
06/04 Assets:Checking $41.50 Assets:Cash
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:
; January 1 odometer: 144328 year 2021 ; Assert that all details required by the IRS are provided for every transaction ; (must use --strict flag on the command line) account Expense:Mileage assert commodity == "mi" assert amount > mi 0 assert has_meta('Depart') assert has_meta('Destination') assert has_meta('Time') assert has_meta('Purpose') tag Depart tag Destination tag Purpose tag Time bucket Vehicle:2007 Yaris apply account Expense ; Dollar equivalent per mile ; (using the --market flag on the command line will show dollar values) P 01/01 mi $0.56 ; IRS 2021 bucket Vehicle:2007 Yaris apply account Expense 05/11 Mileage (146757 mi - 146738 mi) ; Depart: 1234 Office St. ; Destination: 5678 Farm Rd. ; Time: 09:05 AM ; Purpose: Agriculture Labor 05/11 Mileage (146775 mi - 146757 mi) ; Depart: 5678 Farm Rd. ; Destination: 1234 Office St. ; Time: 2:45 PM ; Purpose: Return to office
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.
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.
year 2021 bucket Equity ; ALL UNITS IN POUNDS P 07/01 squash $2.49 ; Fresh Market organic squash P 07/01 bean $4.99 ; Kroger organic green beans P 07/22 cucumber $2.29 ; Fresh Market organic cucumber 07/08 Food Bank Donation 31 squash 07/12 Food Bank Donation 14 bean Donation 43 squash Equity 07/22 Homeless Shelter Donation 59 squash Donation 13 bean Donation 4 cucumber Equity
When a customer places an order that requires an invoice, use Slimvoice to create a new order. Slimvoice will create a plain text file with the order number. You can then fill in all the details for the customer, line items and quantities, and taxes. The final result will look something like this:
ORDER: 00012 DATE: 2021-07-31 CURRENCY: USD CATEGORY: Ag:CSA CUSTOMER: Rick Cooper ITEMS Arugula PRICE: 8.00/lb QTY: 0.5 TAXED: food Mustard Greens PRICE: 4.50/lb QTY: 1.0 TAXED: food Zucchini PRICE: 2.00/lb QTY: 4 TAXED: food Delivery PRICE: 5.00 TAXES [VA:Sales Tax:Food] TAG: food RATE: 2.5%
Slimvoice then does all the hard work of computing subtotals and taxes and places these totals into a new Ledger journal that lives beside your standard journal. You can use the Ledger `include` directive to have the Slimvoice totals imported into your primary journal. Slimvoice can also render templates from order data, making it simple to generate invoices and send them to the customer. The Slimvoice documentation provides more details on its operation.
When you use Slimvoice to process your orders, it will automatically generate appropriate balances for tax accounts in the ledger. Here's a sample snippet from an order:
ITEMS Tomato PRICE: 3.00/lb QTY: 4.5 TAXED: food TAXES [VA:Sales Tax:Food] TAG: food RATE: 2.5%
When processed by Slimvoice, it will produce the following transaction:
2021/05/19 (#100) Amy Customer:Amy $13.84 Income:CSA $-13.50 Liability:VA:Sales Tax:Food $-0.34 (Taxable:VA:Sales Tax:Food) $-13.50
Meaning:
To determine the sales tax that you collected, run this report:
ledger register --monthly --effective 'Liability:VA:Sales Tax' -f company.txt
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:
To find the total income that should be taxed, run this report, which will take into account the virtual postings mentioned above:
ledger register --monthly --effective 'Taxable' -f company.txt
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:
2022/01/05=2021/12/31 Virginia department of Taxation Liability:VA:Sales Tax:Food $21.56 Assets:Checking
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:
2022/01/05=2021/12/31 Virginia department of Taxation Liability:VA:Sales Tax:Food $21.56 Assets:Checking -$21.27 Income:VA Dealer Discount
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.
Figuring out which clients owe you a 1099, or those that have paid you $600.00 or more over the course of the year:
ledger register --group-by 'payee' --subtotal --display 'U(T)>=600' 'Income' -f company.txt
Breaking these arguments down:
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:
ledger register --group-by 'payee' --subtotal --display 'U(T)>=600' 'Expense:Contractor' -f company.txt
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:
2021/06/04 Distribution $1000.00 ; Payee: Matt Distribution $1000.00 ; Payee: Ruth Assets:Checking
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":
#!/bin/sh FILE=$1 echo -e "\n=== IRS Q1 (Jan 1 - Mar 31) ===\n" ledger balance --effective --period 'until 4/1' -f "$FILE" --no-pager echo -e "\n=== IRS Q2 (Apr 1 - May 31) ===\n" ledger balance --effective --period 'from 4/1 to 6/1' -f "$FILE" --no-pager echo -e "\n=== IRS Q3 (Jun 1 - Aug 31) ===\n" ledger balance --effective --period 'from 6/1 to 9/1' -f "$FILE" --no-pager echo -e "\n=== IRS Q4 (Sep 1 - Dec 31) ===\n" ledger balance --effective --period 'from 9/1' -f "$FILE" --no-pager echo -e "\n=== Totals ===\n" ledger balance --effective -f "$FILE" --no-pager