💾 Archived View for gemini.sensorstation.co › ~winduptoy › notes.accounting.gmi captured on 2024-07-08 at 23:40:53. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2024-05-10)
-=-=-=-=-=-=-
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:
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 Design 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 ├── business.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 ] └── 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 (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.
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:
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
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.
07/01 Farmers Market Retail:Food -1 "rosemary salt" @ $5.00 Retail:Food -2 "black eyed peas 8oz" @ $5.00 Retail:General -1 "herbal smudge" @ $5.00 Retail:General -3 "quail egg art" @ $15.00 Retail:General -1 "pot echinacea" @ $5.00 Retail:General -1 "pot basil" @ $5.00 Retail:General -2 "pot butterfly weed" @ $5.00 Assets:Cash $85.00 = $204.00
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.
; Retail food sales tax @ 1% = /^Retail:Food/ Income:Ag:Food (roundto(b / 1.01, 2)) (Taxable:VA:Sales Tax:Food) (roundto(b / 1.01, 2)) Liability:VA:Sales Tax:Food (roundto(b - (b / 1.01), 2)) $account (b * -1) ; make it balance ; Retail general sales tax @ 5.3% = /^Retail:General/ Income:Ag:General (roundto(b / 1.053, 2)) (Taxable:VA:Sales Tax:General) (roundto(b / 1.053, 2)) Liability:VA:Sales Tax:General (roundto(b - (b / 1.053), 2)) $account (b * -1) ; make it balance
This will insert additional virtual postings into the transaction so that this:
07/01 Farmers Market Retail:Food -1 "rosemary salt" @ $5.00 Assets:Cash $5.00
Becomes this:
07/01 Farmers Market Retail:Food -1 "rosemary salt" @ $5.00 Income:Ag:Food $-4.95 (Taxable:VA:Sales Tax:Food) $-4.95 Liability:VA:Sales Tax:Food $-0.05 Retail:Food $5.00 Assets:Cash $5.00
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