Tutorial : creating new objects

Creating a new Book

piecash can create a new GnuCash document (a Book) from scratch through the create_book() function.

To create a in-memory sqlite3 document (useful to test piecash for instance), a simple call is enough:

In [1]: import piecash

In [2]: book = piecash.create_book()

To create a file-based sqlite3 document:

In [3]: book = piecash.create_book("example_file.gnucash")

# or equivalently (adding the overwrite=True argument to overwrite the file if it already exists)
In [4]: book = piecash.create_book(sqlite_file="example_file.gnucash", overwrite=True)

# or equivalently
In [5]: book = piecash.create_book(uri_conn="sqlite:///example_file.gnucash", overwrite=True)

and for a postgres document (needs a pacakge installable via “pip install psycopg2”):

book = piecash.create_book(uri_conn="postgres://user:passwd@localhost/example_gnucash_db")

Note

Per default, the currency of the document is the euro (EUR) but you can specify any other ISO currency through its ISO symbol:

In [6]: book = piecash.create_book(sqlite_file="example_file.gnucash",
   ...:                         currency="USD",
   ...:                         overwrite=True)
   ...: 

If the document already exists, piecash will raise an exception. You can force piecash to overwrite an existing file/database (i.e. delete it and then recreate it) by passing the overwrite=True argument:

In [1]: book = piecash.create_book(sqlite_file="example_file.gnucash", overwrite=True)

Creating a new Account

piecash can create new accounts (a piecash.core.account.Account):

In [1]: from piecash import create_book, Account

In [2]: book = create_book(currency="EUR")

# retrieve the default currency
In [3]: EUR = book.commodities.get(mnemonic="EUR")

# creating a placeholder account
In [4]: acc = Account(name="My account",
   ...:               type="ASSET",
   ...:               parent=book.root_account,
   ...:               commodity=EUR,
   ...:               placeholder=True,)
   ...: 

# creating a detailed sub-account
In [5]: subacc = Account(name="My sub account",
   ...:                  type="BANK",
   ...:                  parent=acc,
   ...:                  commodity=EUR,
   ...:                  commodity_scu=1000,
   ...:                  description="my bank account",
   ...:                  code="FR013334...",)
   ...: 

In [6]: book.save()

In [7]: book.accounts
Out[7]: [Account<My account[EUR]>, Account<My account:My sub account[EUR]>]

Creating a new Commodity

piecash can create new commodities (a piecash.core.commodity.Commodity):

In [1]: from piecash import create_book, Commodity, factories

# create a book (in memory) with some currency
In [2]: book = create_book(currency="EUR")

In [3]: print(book.commodities)
[Commodity<CURRENCY:EUR>]

# creating a new ISO currency (if not already available in s.commodities)
In [4]: USD = factories.create_currency_from_ISO("USD")

In [5]: book.add(USD) # add to session

# create a commodity (lookup on yahoo! finance, need web access)
In [6]: apple = factories.create_stock_from_symbol("AAPL")

In [7]: book.add(apple) # add to session

# creating commodities using the constructor (warning, object should be manually added to session)
# create a special "reward miles" Commodity using the constructor
In [8]: miles = Commodity(namespace="LOYALTY", mnemonic="Miles", fullname="Reward miles", fraction=1000000)

In [9]: book.add(miles) # add to session

In [10]: USD, apple, miles
Out[10]: (Commodity<CURRENCY:USD>, Commodity<NMS:AAPL>, Commodity<LOYALTY:Miles>)

Warning

The following (creation of non ISO currencies) is explicitly forbidden by the GnuCash application.

# create a bitcoin currency (warning, max 6 digits after comma, current GnuCash limitation)
In [1]: XBT = Commodity(namespace="CURRENCY", mnemonic="XBT", fullname="Bitcoin", fraction=1000000)

In [2]: book.add(XBT) # add to session

In [3]: XBT
Out[3]: Commodity<CURRENCY:XBT>

Creating a new Transaction

piecash can create new transactions (a piecash.core.transaction.Transaction):

In [1]: from piecash import create_book, Account, Transaction, Split, GncImbalanceError, factories, ledger

# create a book (in memory)
In [2]: book = create_book(currency="EUR")

# get the EUR and create the USD currencies
In [3]: c1 = book.default_currency

In [4]: c2 = factories.create_currency_from_ISO("USD")

# create two accounts
In [5]: a1 = Account("Acc 1", "ASSET", c1, parent=book.root_account)

In [6]: a2 = Account("Acc 2", "ASSET", c2, parent=book.root_account)

# create a transaction from a1 to a2
In [7]: tr = Transaction(currency=c1,
   ...:                  description="transfer",
   ...:                  splits=[
   ...:                      Split(account=a1, value=-100),
   ...:                      Split(account=a2, value=100, quantity=30)
   ...:                  ])
   ...: 

In [8]: book.flush()

# ledger() returns a representation of the transaction in the ledger-cli format
In [9]: print(ledger(tr))
2017/02/15 * transfer
	Acc 1                                       -100.00 EUR
	Acc 2                                         30.00 USD @@ 100.00 EUR


# change the book to use the "trading accounts" options
In [10]: book.use_trading_accounts = True

# add a new transaction identical to the previous
In [11]: tr2 = Transaction(currency=c1,
   ....:                   description="transfer 2",
   ....:                   splits=[
   ....:                       Split(account=a1, value=-100),
   ....:                       Split(account=a2, value=100, quantity=30)
   ....:                   ])
   ....: 

In [12]: print(ledger(tr2))
2017/02/15 * transfer 2
	Acc 1                                       -100.00 EUR
	Acc 2                                         30.00 USD @@ 100.00 EUR


# when flushing, the trading accounts are created
In [13]: book.flush()

In [14]: print(ledger(tr2))
2017/02/15 * transfer 2
	Acc 1                                       -100.00 EUR
	Acc 2                                         30.00 USD @@ 100.00 EUR


# trying to create an unbalanced transaction trigger an exception
# (there is not automatic creation of an imbalance split)
In [15]: tr3 = Transaction(currency=c1,
   ....:                   description="transfer imb",
   ....:                   splits=[
   ....:                       Split(account=a1, value=-100),
   ....:                       Split(account=a2, value=90, quantity=30)
   ....:                   ])
   ....: 

In [16]: print(ledger(tr3))
2017/02/15 * transfer imb
	Acc 1                                       -100.00 EUR
	Acc 2                                         30.00 USD @@ 90.00 EUR


In [17]: try:
   ....:     book.flush()
   ....: except GncImbalanceError:
   ....:     print("Indeed, there is an imbalance !")
   ....: 

Creating new Business objects

piecash can create new ‘business’ objects (this is a work in progress).

To create a new customer (a piecash.business.person.Customer):

In [1]: from piecash import create_book, Customer, Address

# create a book (in memory)
In [2]: b = create_book(currency="EUR")

# get the currency
In [3]: eur = b.default_currency

# create a customer
In [4]: c1 = Customer(name="Mickey", currency=eur, address=Address(addr1="Sesame street 1", email="mickey@example.com"))

# the customer has not yet an ID
In [5]: c1
Out[5]: Customer<None:Mickey>

# we add it to the book
In [6]: b.add(c1)

# flush the book
In [7]: b.flush()

# the customer gets its ID
In [8]: print(c1)
Customer<None:Mickey>

# or create a customer directly in a book (by specifying the book argument)
In [9]: c2 = Customer(name="Mickey", currency=eur, address=Address(addr1="Sesame street 1", email="mickey@example.com"),
   ...:               book=b)
   ...: 

# the customer gets immediately its ID
In [10]: c2
Out[10]: Customer<000001:Mickey>

# the counter of the ID is accessible as
In [11]: b.counter_customer
Out[11]: 1

In [12]: b.save()

Similar functions are available to create new vendors (piecash.business.person.Vendor) or employees (piecash.business.person.Employee).

There is also the possibility to set taxtables for customers or vendors as:

In [1]: from piecash import Taxtable, TaxtableEntry

In [2]: from decimal import Decimal

# let us first create an account to which link a tax table entry
In [3]: acc = Account(name="MyTaxAcc", parent=b.root_account, commodity=b.currencies(mnemonic="EUR"), type="ASSET")

# then create a table with on entry (6.5% on previous account
In [4]: tt = Taxtable(name="local taxes", entries=[
   ...:     TaxtableEntry(type="percentage",
   ...:                   amount=Decimal("6.5"),
   ...:                   account=acc),
   ...: ])
   ...: 

# and finally attach it to a customer
In [5]: c2.taxtable = tt

In [6]: b.save()

In [7]: print(b.taxtables)
[TaxTable<local taxes:[u'TaxEntry<6.5 percentage in MyTaxAcc>']>]