Simple double-entry accounting system using sqloquent for data storage.
Project description
SimpleBooks
SimpleBooks is a simple accounting library that uses
sqloquent to persist data for identities,
ledgers, accounts, transactions, and entries. Included are tools for
accomplishing basic bookkeeping tasks. The basic accounting formula is this:
Assets = Liabilities + Equity
. Assets are debit-balance; liabilities and
equity are credit-balance. Every transaction must have entries that have no net
difference between the amount of credits and the amount of debits.
This is a simplification of bookchain: all cryptographic features have been removed. This may be useful in scenarios when cryptographic features cannot be supported.
Status
All initially planned features have been implemented and tested.
Open issues can be found here.
Previous changes can be found in the changelog.
The async implementation has an upstream issue from the sqloquent dependency that can be tracked here. Once that is fixed, the dependency will be updated, and this notice will be removed.
Overview
This library provides an accounting system using sqloquent for persistence,
packify for deterministic encoding, and the classic rules of double-entry
bookkeeping. The Transaction.prepare
and Transaction.validate
ensure that
the accounting rule is followed.
Class organization
Currency
represents a currency/unit of account for a Ledger
. It includes the
number of subunits to track and optionally the base for conversion to decimal
(defaults to 10), FX symbol, prefix symbol, and/or postfix symbol to be used with
the format
method (e.g. USD.format(1200)
could result in "12.00 USD",
"$12.00", or "12.00$", respectively). It also includes to_decimal
method for
formatting int amounts into Decimal
s, and get_units
method for getting a
tuple of whole units and remainders.
Identity
represents a legal person or other entity that can sign contracts
or engage in transactions. It includes the name, details, and optionally public
key bytes and private key seed bytes.
Ledger
represents a general ledger for a given Identity
using a specific
Currency
. It includes a name, a LedgerType
, the Identity
id, and the
Currency
id. LedgerType
is an enum representing the valid ledger types,
either PRESENT
or FUTURE
for cash and accrual accounting, respectively, or
for other uses the package user may define.
Account
represents an account for a given Ledger
. It includes a name, a type
(one of the AccountType
enum options), the Ledger
id, an optional locking
script for access control, and optional details.
AccountCategory
represents a category for Account
s. It includes a name, a
LedgerType
, and a destination (str description; e.g. "Balance Sheet" or
"Profit and Loss").
AccountType
is an enum representing the valid account types. The options are
DEBIT_BALANCE
, ASSET
, CONTRA_ASSET
, CREDIT_BALANCE
, LIABILITY
,
EQUITY
, CONTRA_LIABILITY
, and CONTRA_EQUITY
.
Entry
represents an entry in the general ledger for a given Account
. It
includes a type (one of the EntryType
enum options), an amount, a nonce, the
Account
id, and optional details.
EntryType
is an enum representing the valid entry types. The options are
CREDIT and DEBIT.
Transaction
represents a transaction made of Entry
s. It includes the Entry
ids, Ledger
ids, a timestamp, and the details. Each Transaction
must include
entries that balance the number of credits and debits applied to each ledger
affected by the transaction. Use Transaction.prepare
to prepare a transaction
-- it will raise validation errors if the transaction is not valid -- then call
.save()
on the result to persist it to the database. Transactions in the
database can be validated by using .validate()
, which will return True
if it
is valid and False
if it is not (it will also raise errors in some situations
that require more information about the validation failure).
Statement
represents the balances of all accounts of a Ledger
at a particular
point in time. It allows trimming/archiving of entries/txns while maintaining the
effects of those entries/txns. It can be used either to summarize just the txns
it contains or also calculate balances starting with the balances of a previous
Statement
, but the latter is the standard behavior. Also contains a height
column that is incremented with each subsequent Statement
when using the
prepare
method.
Customer
and Vendor
are provided in case they are useful in some way, but no
relations are set up for them currently. This is likely to change in a future
release.
Identity
has manyLedger
sCurrency
has manyLedger
sLedger
- Belongs to
Identity
andCurrency
- Has many
Account
s andStatement
s - Is within
Transaction
s andArchivedTransaction
s
- Belongs to
Account
- Belongs to
Ledger
andAccountCategory
- Has many
Entry
s andArchivedEntry
s
- Belongs to
AccountCategory
has manyAccount
sEntry
- Belongs to
Account
- Is within
Transaction
s
- Belongs to
Transaction
containsLedger
s andEntry
sArchivedEntry
- Is within
ArchivedTransaction
s - Belongs to
Account
- Is within
ArchivedTransaction
- Contains
ArchivedEntry
s andLedger
s - Is within
Statement
s
- Contains
Statement
- Belongs to
Ledger
- Contains
Transaction
s andArchivedTransaction
s
- Belongs to
Installation and Setup
Install with pip install simplebooks
. If you want to use the async version,
instead install with pip install simplebooks[asyncql]
.
Once installed, use the following to setup your project as appropriate:
import simplebooks
simplebooks.publish_migrations(path_to_migrations_folder)
simplebooks.automigrate(path_to_migrations_folder, db_file_path)
simplebooks.set_connection_info(db_file_path)
To use the async version:
import simplebooks
import simplebooks.asyncql
simplebooks.publish_migrations(path_to_migrations_folder)
simplebooks.automigrate(path_to_migrations_folder, db_file_path)
simplebooks.asyncql.set_connection_info(db_file_path)
The simplebooks.publish_migrations
function can be passed a callback that
takes the str model name and str migration file contents, and returns the
modified str migration file contents. This can be used to modify the migration
file contents before they are written to disk. For example, if you wanted to
modify the Account
migration file to add a unique constraint to the name
column, you could do the following:
def migration_callback(name: str, m: str) -> str:
if name == 'Account':
return m.replace("t.text('name').index()", "t.text('name').unique()")
return m
simplebooks.publish_migrations(path_to_migrations_folder, migration_callback)
More Resources
Documentation generated by autodox can be found here. Docs for the async version can be found here.
Check out the Pycelium discord server. If you experience a problem, please discuss it on the Discord server. All suggestions for improvement are also welcome, and the best place for that is also Discord. If you experience a bug and do not use Discord, open an issue on Github.
Tests
There are a total of 9 tests (4 e2e tests and 5 tests for miscellaneous
tools/features). To run them, clone the repo, set up a virtual environment
(e.g. python -m venv venv && source venv/bin/activate
), install the
dependencies with pip install -r requirements.txt
, and then run the following:
find tests -name test_*.py -print -exec python {} \;
. On Windows, the 5 test
files will have to be individually run with the following:
python tests/test_async_basic_e2e.py
python tests/test_async_statements_e2e.py
python tests/test_basic_e2e.py
python tests/test_misc.py
python tests/test_statements_e2e.py
Personal, Non-commercial Use License
Copyright (c) 2025 Jonathan Voss (k98kurz)
Permission to use, copy, modify, and/or distribute this software for any personal, non-commercial purpose is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. For other uses, contact the software author.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file simplebooks-0.3.0.tar.gz
.
File metadata
- Download URL: simplebooks-0.3.0.tar.gz
- Upload date:
- Size: 27.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.0.1 CPython/3.11.0rc1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 |
4a16608efbb5fd1c4b4dfecfcbd960812a7f81faabe7aa70dda1989bddf73a64
|
|
MD5 |
2565ed6de695ef45ccc58299703166af
|
|
BLAKE2b-256 |
0e7e2524c7ac6ccea5acccf8bc149fe30d8c558daab2a0364951deacd662d636
|
File details
Details for the file simplebooks-0.3.0-py3-none-any.whl
.
File metadata
- Download URL: simplebooks-0.3.0-py3-none-any.whl
- Upload date:
- Size: 37.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.0.1 CPython/3.11.0rc1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 |
07d655169007314d35975f537876e7359129b768b9a6d0772e3d0bb57c63303c
|
|
MD5 |
2458ba45f7d6c7d62e6a04de35ccef05
|
|
BLAKE2b-256 |
04080578e2934665bd58b1fd12067ab9c8552f1d258ca0e6a0b13540a608d67e
|