Skip to content

Commit

Permalink
updated readme for #80
Browse files Browse the repository at this point in the history
  • Loading branch information
epogrebnyak committed Aug 19, 2024
1 parent 4675955 commit 659d381
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 70 deletions.
75 changes: 33 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,44 @@
> [!NOTE]
> Current point of work is [issue #80](https://github.com/epogrebnyak/abacus/issues/80):
> - [x] main type of entry is multiple entry
> - [x] closing of accounts in one function
> - [ ] complete list of assumptions in docs
> - [ ] profit tax
Whole program signature is:

`Chart -> Ledger -> list[MultipleEntry] -> Ledger -> (list[MultipleEntry], IncomeStatement, Ledger)`

A minimal example:
A new minimal example:

```python
from playground import *
from playground.ui import Book

# Start company
book = Book(company_name="Pied Piper")

# Create chart of accounts
chart = Chart(
assets=[Account("cash"), Account("ar")],
capital=[Account("equity")],
liabilities=[Account("ap")],
income=[Account("sales", contra_accounts=["refunds"])],
expenses=[Account("salaries")],
)

# Create ledger from chart
ledger = Ledger.new(chart)

# Define double or multiple entries and post them to ledger
entries = [
DoubleEntry("cash", "equity", 100),
Entry("Sold $200 worth of goods with a 10% refund and 50% prepayment")
.debit("cash", 90)
.debit("ar", 90)
.debit("refunds", 20)
.credit("sales", 200),
MultipleEntry.new(DebitEntry("salaries", 250), CreditEntry("ap", 250)),
]
ledger.post_many(entries)

# Close ledger at accounting period end
closing_entries, ledger, income_summary = ledger.close(chart)

# Show income statement data
print(income_summary.dict())

# Show account balances data for balance sheet statement
print(ledger.balances())
book.add_assets("cash", "inventory", "ar")
book.add_capital("equity")
book.add_income("sales", offsets=["refunds"])
book.add_expense("cogs")
book.add_liability("dividend")
book.set_retained_earnings("re")

# Open ledger and post entries
book.open()
book.entry("Shareholder investment").amount(300).debit("cash").credit("equity").commit()
book.entry("Bought inventory").amount(200).debit("inventory").credit("cash").commit()
book.entry("Invoiced sales").debit("ar", 380).debit("refunds", 20).credit("sales", 400).commit()
book.entry("Shippled goods").amount(200).debit("cogs").credit("inventory").commit()

# Close ledger at period end and make post-close entries
book.close()
book.entry("Accrue dividend").amount(90).debit("re").credit("dividend").commit()

# Show reports
print(book.balance_sheet.json())
print(book.income_statement.json())
```

Result:

```
{"assets": {"cash": 100, "inventory": 0, "ar": 380}, "capital": {"equity": 300, "re": 90}, "liabilities": {"dividend": 90}}
{"income": {"sales": 380}, "expenses": {"cogs": 200}}
```

# abacus

Expand All @@ -57,7 +48,7 @@ print(ledger.balances())
A minimal yet valid double-entry accounting system in Python.

> [!TIP]
> Check out a brand new Streamlit demo for double-entry accounting at https://abacus.streamlit.app/
> Check out a brand new Streamlit demo for double-entry accounting at https://abacus.streamlit.app/
## Documentation

Expand Down
5 changes: 2 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

# Minimal yet valid double-entry accounting system in Python and command line

`abacus` is an Python package and a command line tool for accounting calculations.
There is also a [web interface demonstration](https://abacus.streamlit.app/).

`abacus` is an Python package and a command line tool for accounting calculations.
There is also a [web interface demonstration](https://abacus.streamlit.app/).

With `abacus` you can perform a complete accounting cycle
from a chart of accounts to financial reports.
Expand Down
1 change: 1 addition & 0 deletions docs0/accounting.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
[Expanded accounting equation][eq] is a good basis for an accounting system[^1][^2]:

[^1]: As mentioned by [@mafm, author of ledger.py](https://github.com/mafm/ledger.py/blob/master/doc/Ledger.md#debits-and-credits-etc)[^1]:

[^2]: Also some students indicate expanded accounting equation [makes learning a bit smoother](https://www.reddit.com/r/Accounting/comments/137e3lz/i_plan_on_pursuing_a_bachelors_in_accounting_soon/jitcu6g/?context=3).

```
Expand Down
24 changes: 13 additions & 11 deletions playground/example_ui.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
from ui import Book

book = Book("Duffin Mills")
book.add_asset(["cash", "inventory"])
book.add_asset("cash")
book.add_asset("inventory")
book.add_asset("ar", title="Accounts receivable")
book.add_capital("equity", offsets=["buyback"])
book.add_capital("equity", offsets=["ts"])
book.set_title("ts", "Treasury shares")
book.add_income("sales", offsets=["refunds", "cashback"])
book.add_expense(["cogs", "salaries", "cit"])
book.add_liability(["vat", "dividend", "cit_due"])
book.add_expense("cogs", title="Cost of goods sold")
book.add_expense("salaries")
book.add_expense("cit", title="Income tax")
book.add_liability("vat", title="VAT payable")
book.add_liability("dividend")
book.add_liability("cit_due", title="Income tax payable")
book.set_retained_earnings("re")
book.set_income_summary_account("_isa")
book.set_title("cit", "Income tax")
book.set_title("cit_due", "Income tax payable")
book.set_title("cogs", "Cost of goods sold")
book.set_title("vat", "VAT payable")
book.open()
# fmt: off
book.entry("Shareholder investment").amount(1500).debit("cash").credit("equity").commit()
book.entry("Bought inventory (no VAT)").amount(1000).debit("inventory").credit("cash").commit()
book.entry("Invoice with VAT").debit("ar", 1200).credit("sales", 1000).credit("vat", 200).commit()
book.entry("Invoice with 20% VAT").debit("ar", 1200).credit("sales", 1000).credit("vat", 200).commit()
book.entry("Registered costs").amount(600).debit("cogs").credit("inventory").commit()
book.entry("Accepted payment").amount(900).credit("ar").debit("cash").commit()
book.entry("Made refund").amount(50).debit("refunds").credit("ar").commit()
book.entry("Made cashback").amount(50).debit("cashback").credit("cash").commit()
book.entry("Paid salaries").amount(150).credit("cash").debit("salaries").commit()
assert book.proxy_net_earnings == 150
book.entry("Accrue corporate income tax").amount(30).credit("cit_due").debit("cit").commit()
book.entry("Accrue corporate income tax 20%").amount(30).credit("cit_due").debit("cit").commit()
book.close()
book.entry("Bought back shares").amount(30).debit("buyback").credit("cash").commit()
book.entry("Bought back shares").amount(30).debit("ts").credit("cash").commit()
book.entry("Announced dividend").amount(60).debit("re").credit("dividend").commit()
book.entry("Pay corporate income tax").amount(30).debit("cit_due").credit("cash").commit()
# fmt: on
Expand Down
39 changes: 29 additions & 10 deletions playground/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from pydantic import BaseModel

from core import (
from .core import (
T5,
AbacusError,
Account,
Expand Down Expand Up @@ -110,38 +110,57 @@ def set_title(self, account_name: str, title: str):
def _add(
self,
t5: str,
account_name: str | list[str],
account_name: str ,
title: str | None,
offsets: list[str] | None,
):
if isinstance(account_name, list) and (offsets or title):
raise AbacusError("Cannot offset or set title to many accounts.")
if isinstance(account_name, list):
for name in account_name:
self._add(t5, name, title, offsets)
return self
offsets = offsets or []
account = Account(account_name, offsets)
attr = t5_to_attr(t5)
getattr(self.chart, attr).append(account)
# not implemented: title not used
title # not implemented: title not used
return self

def add_asset(self, account, *, title=None, offsets=None):
return self._add(T5.Asset, account, title, offsets)


def add_assets(self, *account_names):
for name in account_names:
self.add_asset(name)
return self

def add_liability(self, account, *, title=None, offsets=None):
return self._add(T5.Liability, account, title, offsets)

def add_liabilities(self, *account_names):
for name in account_names:
self.add_liability(name)
return self

def add_capital(self, account, *, title=None, offsets=None):
return self._add(T5.Capital, account, title, offsets)

def add_capitals(self, *account_names):
for name in account_names:
self.add_capital(name)
return self

def add_income(self, account, *, title=None, offsets=None):
return self._add(T5.Income, account, title, offsets)

def add_incomes(self, *account_names):
for name in account_names:
self.add_income(name)
return self

def add_expense(self, account, *, title=None, offsets=None):
return self._add(T5.Expense, account, title, offsets)

def add_expenses(self, *account_names):
for name in account_names:
self.add_expense(name)
return self

def set_income_summary_account(self, account_name: str):
self.chart.income_summary_account = account_name
return self
Expand Down
27 changes: 27 additions & 0 deletions readme.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from playground.ui import Book

# Start company
book = Book(company_name="Pied Piper")

# Create chart of accounts
book.add_assets("cash", "inventory", "ar")
book.add_capital("equity")
book.add_income("sales", offsets=["refunds"])
book.add_expense("cogs")
book.add_liability("dividend")
book.set_retained_earnings("re")

# Open ledger and post entries
book.open()
book.entry("Shareholder investment").amount(300).debit("cash").credit("equity").commit()
book.entry("Bought inventory").amount(200).debit("inventory").credit("cash").commit()
book.entry("Invoiced sales").debit("ar", 380).debit("refunds", 20).credit("sales", 400).commit()
book.entry("Shippled goods").amount(200).debit("cogs").credit("inventory").commit()

# Close ledger and make post-close entries
book.close()
book.entry("Accrue dividend").amount(90).debit("re").credit("dividend").commit()

# Show reports
print(book.balance_sheet.json())
print(book.income_statement.json())
8 changes: 4 additions & 4 deletions todo.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
CONSIDER:

- reflex and nicegui vs streamlit
- guide for transactions (do this next scenario)
- guide for transactions (do this next scenario)
- what makes a 1.0.0?

REFACTOR:

- [ ] remove null account and make everything a compound entry
- [ ] combine uncore.py + experimental.py
- [ ] consider roles of Chart and UserChart
- [ ] executable examples with elmsript/pydiode like in rust docs
- [ ] executable examples with elmsript/pydiode like in rust docs

DOCS/PROSE:

- [ ] _How to build your own accounting system?_ piece for docs and dev.to
- [ ] pure.py
- [ ] mailing list
- [ ] 'tutorial' in r/Python
- [ ] mailing list
- [ ] 'tutorial' in r/Python
- [ ] restore changelog
- [ ] more software reviews - akaunting

Expand Down

0 comments on commit 659d381

Please sign in to comment.