mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
- REST API Example for Python Bindings #2
Enhancements include: - manipulation of transactions, splits, vendors and bills - add and edit functionality customers and invoices Author: Tom Lofts <dev@loftx.co.uk>
This commit is contained in:
@@ -1,48 +1,218 @@
|
||||
A Python based REST framework for the Gnucash accounting application
|
||||
|
||||
**Please note this is a very early work in progress and should not be run against live or production data.**
|
||||
**Please note this is a very early work in progress and should not be run
|
||||
against live or production data.**
|
||||
|
||||
This project is designed to allow other applications to easily extract (and hopefully insert and update at some point) data from Gnucash via a RESTful API.
|
||||
This project is designed to allow other applications to easily interact with
|
||||
data from Gnucash via a RESTful API.
|
||||
|
||||
The API is built on the existing Python bindings and uses Flask to serve responses in JSON.
|
||||
The API is built on the existing Python bindings and uses Flask to serve
|
||||
responses in JSON.
|
||||
|
||||
Currently only accounts, customers and invoices can be accessed via the framework
|
||||
Currently accounts, transactions, splits, customers, vendors, invoices and
|
||||
bills can be accessed to some degree via the framework:
|
||||
|
||||
Accounts: <http://localhost:5000/accounts>
|
||||
Individual accounr: <http://localhost:5000/accounts/XXXX>
|
||||
Accounts:
|
||||
|
||||
Invoices: <http://localhost:5000/invoices>
|
||||
Individual invoice: <http://localhost:5000/invoices/XXXX>
|
||||
GET request to /accounts - returns a complete list of accounts
|
||||
GET request to /accounts/<guid> - returns an individual account
|
||||
GET request to /accounts/<guid>/splits - returns splits for an individual
|
||||
account
|
||||
|
||||
Customers: <http://localhost:5000/customers>
|
||||
Individual customer: <http://localhost:5000/customers/XXXX>
|
||||
POST request to /transactions - creates a new transaction (currently with only
|
||||
two splits)
|
||||
|
||||
Invoices can be filtered via the following parameters:
|
||||
POST variables:
|
||||
currency - required - a gnucash currency code e.g. GBP
|
||||
description - required - a description for the transaction
|
||||
num - optional - a transaction number
|
||||
date_posted - required - a date formatted as YYYY-MM-DD
|
||||
splitvalue1 - required - the value of the split on splitaccount1
|
||||
splitaccount1 - required - the GUID for the 1st account on this transaction
|
||||
(can be obtained from /accounts)
|
||||
splitvalue2 - required - the value of the split on splitaccount2
|
||||
splitaccount2 - required - the GUID for the 2nd account on this transaction
|
||||
|
||||
is_active 1 or 0
|
||||
is_paid 1 or 0
|
||||
GET request to /transactions/<guid> - returns an individual transaction
|
||||
POST request to /transactions/<guid> - edits an existing transaction (accepts
|
||||
the same post variables as /transactions)
|
||||
DELETE request to /transactions/<guid> - deletes a transaction
|
||||
|
||||
e.g. <http://localhost:5000/invoices?is_active=1&is_paid=0>
|
||||
GET request to /bills - returns a list of bills
|
||||
|
||||
GET variables:
|
||||
is_paid - optional - 1 returns paid bills, 0 unpaid
|
||||
is_active - optional - 1 returns active bills, 0 inactive
|
||||
date_opened_from - optional - all transactions on and after a date formatted
|
||||
as YYYY-MM-DD
|
||||
date_opened_to - optional - all transactions up to and before a date formatted
|
||||
as YYYY-MM-DD
|
||||
|
||||
POST request to /bills - creates a new bill
|
||||
|
||||
POST variables:
|
||||
id - optional - if no id is specified the next available sequential id will be
|
||||
used
|
||||
vendor_id - required - the id of the vendor of this bill (can be obtained from
|
||||
/vendors)
|
||||
currency - required - a gnucash currency code
|
||||
date_opened - required - a date formatted as YYYY-MM-DD
|
||||
notes - optional - notes for this bill
|
||||
|
||||
GET request to /bills/<id> - returns an individual bill
|
||||
POST request to /bills/<id> - edits (and optionally posts) a bill
|
||||
|
||||
POST variables:
|
||||
vendor_id - required - the id of the vendor of this bill (can be obtained from
|
||||
/vendors)
|
||||
currency - required - a gnucash currency code
|
||||
date_opened - a date formatted as YYYY-MM-DD
|
||||
notes - optional - notes for this invoice
|
||||
posted - optional - set to 1 if marking the invoice as posted (0 or empty
|
||||
otherwise)
|
||||
posted_account_guid - required if posted = 1 - the GUID for the posted account
|
||||
posted_date - required if posted = 1 - a date formatted as YYYY-MM-DD
|
||||
due_date - required if posted = 1 - a date formatted as YYYY-MM-DD
|
||||
posted_memo - optional - a description
|
||||
posted_accumulatesplits - optional - whether to accumulate splits or not (1 for
|
||||
yes, 0 for no)
|
||||
posted_autopay - optional - whether to auto pay or not (1 for yes, 0 for no)
|
||||
|
||||
PAY request to /bills/<id> - mark a bill as paid
|
||||
|
||||
POST variables:
|
||||
|
||||
posted_account_guid - required - the GUID for the posted account
|
||||
transfer_account_guid - required - the GUID for the transfer account
|
||||
payment_date - required - a date formatted as YYYY-MM-DD
|
||||
num - optional - a number for this payment
|
||||
memo - optional - a description for this payment
|
||||
auto_pay - required - whether to auto pay or not (1 for yes, 0 for no)
|
||||
|
||||
GET request to /bills/<id>/entries - return all entries for an individual bill
|
||||
POST request to /bills/<id>/entries - adds a new entry to a bill
|
||||
|
||||
date - required - a date formatted as YYYY-MM-DD
|
||||
description - required - the description for this entry
|
||||
account_guid - required - the GUID for the required accoumt
|
||||
quantity - required - the quantity
|
||||
price - required - the price
|
||||
|
||||
GET request to /invoices - returns all invoices (accepts the same get variables
|
||||
as /bills)
|
||||
POST request to /invoices - creates a new invoice
|
||||
|
||||
POST variables:
|
||||
id - optional - if no id is specified the next available sequential id will be
|
||||
used
|
||||
customer_id - required - the id of the customer of this invoice (can be
|
||||
obtained from /customers)
|
||||
currency - required - a gnucash currency code
|
||||
date_opened - a date formatted as YYYY-MM-DD
|
||||
notes - optional - notes for this invoice
|
||||
|
||||
GET request to /invoices/<id> - returns an individual invoice
|
||||
POST request to /invoices/<id> - edits (and optionally posts) an invoice
|
||||
|
||||
POST variables:
|
||||
customer_id - required - the id of the customer of this bill (can be obtained
|
||||
from /customers)
|
||||
currency - required - a gnucash currency code
|
||||
date_opened - a date formatted as YYYY-MM-DD
|
||||
notes - optional - notes for this invoice
|
||||
posted - optional - set to 1 if marking the invoice as posted (0 or empty
|
||||
otherwise)
|
||||
posted_account_guid - required if posted = 1 - the GUID for the posted account
|
||||
posted_date - required if posted = 1 - a date formatted as YYYY-MM-DD
|
||||
due_date - required if posted = 1 - a date formatted as YYYY-MM-DD
|
||||
posted_memo - optional - a description
|
||||
posted_accumulatesplits - optional - whether to accumulate splits or not (1 for
|
||||
yes, 0 for no)
|
||||
posted_autopay - optional - whether to auto pay or not (1 for yes, 0 for no)
|
||||
|
||||
PAY request to /invoices/<id> - mark an invoice as paid (accepts the same post
|
||||
variables as /bills/<id>)
|
||||
|
||||
GET request to /invoices/<id>/entries - return all entries for an individual
|
||||
invoice
|
||||
POST request to /invoices/<id>/entries - adds a new entry to an invoice
|
||||
(accepts the same post variables as /bills/<id>/entries)
|
||||
|
||||
GET request to /entries/<guid> - returns an individual entry
|
||||
POST request to /entries/<guid> - edits an existing entry (accepts the same
|
||||
post variables as /bills/<id>/entries)
|
||||
|
||||
GET request to /customers - returns a list of customers
|
||||
POST request to /customers - creates a new customer
|
||||
|
||||
POST variables:
|
||||
id - optional - if no id is specified the next available sequential id will be
|
||||
used
|
||||
currency - required - a gnucash currency code
|
||||
name - required - the customer's name
|
||||
contact - optional - a contact for this customer
|
||||
address_line_1 - required - the first line of the customer's address
|
||||
address_line_2 - optional - the second line of the customer's address
|
||||
address_line_3 - optional - the third line of the customer's address
|
||||
address_line_4 - optional - the fourth line of the customer's address
|
||||
phone - optional - the customer's phone number
|
||||
fax - optional - the customer's fax number
|
||||
email - optional - the customer's email address
|
||||
|
||||
GET request to /customers/<id> - returns an individual customer
|
||||
POST request to /customers/<id> - edits an existing customer (accepts the same
|
||||
post variables as /customers)
|
||||
GET request to /customers/<id>/invoices - returns all invoices for a single
|
||||
customer
|
||||
|
||||
GET request to /vendors - returns a list of vendors
|
||||
POST request to /vendors - creates a new vendor
|
||||
|
||||
POST variables:
|
||||
id - optional - if no id is specified the next available sequential id will be
|
||||
used
|
||||
currency - required - a gnucash currency code
|
||||
name - required - the vendor's name
|
||||
contact - optional - a contact for this vendor
|
||||
address_line_1 - required - the first line of the vendor's address
|
||||
address_line_2 - optional - the second line of the vendor's address
|
||||
address_line_3 - optional - the third line of the vendor's address
|
||||
address_line_4 - optional - the fourth line of the vendor's address
|
||||
phone - optional - the vendor's phone number
|
||||
fax - optional - the vendor's fax number
|
||||
email - optional - the vendor's email address
|
||||
|
||||
GET request to /vendors/<id> - returns an individual vendor
|
||||
GET request to /vendors/<id>/bills - returns all bills for a single vendor
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
**As this is work in progress you'll need a knowledge of building Gnucash from source and experience with python.**
|
||||
**As this is work in progress you'll need a knowledge of building Gnucash from
|
||||
source and experience with python.**
|
||||
|
||||
Full details to be provided at a later date, but in short you'll need a copy of Gnucash built with Python bindings and the Flask module installed.
|
||||
Full details to be provided at a later date, but in short you'll need a copy of
|
||||
Gnucash built with Python bindings and the Flask module installed.
|
||||
|
||||
Rrun `python ./gnucash_rest <connection string>` to start the server on <http://localhost:5000> e.g `python ./gnucash_rest mysql://user:password@127.0.0.1/gnucash_test`
|
||||
Rrun `python ./gnucash_rest <connection string>` to start the server on
|
||||
<http://localhost:5000> e.g
|
||||
`python ./gnucash_rest mysql://user:password@127.0.0.1/gnucash_test`
|
||||
|
||||
Navigate to <http://localhost:5000/invoices> and you should get your invoices in JSON format.
|
||||
Navigate to <http://localhost:5000/invoices> and you should get your invoices
|
||||
in JSON format.
|
||||
|
||||
Files
|
||||
-----
|
||||
|
||||
`gnucash_rest.py` - The Flask app which responds to REST requests with JSON responses
|
||||
`gnucash_rest.py` - The Flask app which responds to REST requests with JSON
|
||||
responses
|
||||
|
||||
`gnucash_simple.py` - A helper file to convert Gnucash objects into dictionaries for easier conversion to JSON.
|
||||
`gnucash_simple.py` - A helper file to convert Gnucash objects into
|
||||
dictionaries for easier conversion to JSON.
|
||||
|
||||
Future
|
||||
------
|
||||
|
||||
I'm using the API already to integrate Gnucash invoices with other systems, so I'll be adding features as and when I need them. The format of the API is likely to change as development continues.
|
||||
I'm using the API already to integrate Gnucash invoices with other systems, so
|
||||
I'll be adding features as and when I need them. The format of the API is
|
||||
likely to change as development continues.
|
||||
|
||||
1900
src/optional/python-bindings/example_scripts/rest-api/gnucash_rest.py
Executable file → Normal file
1900
src/optional/python-bindings/example_scripts/rest-api/gnucash_rest.py
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,152 +1,303 @@
|
||||
'''
|
||||
|
||||
gnucash_simple.py -- A helper file to convert Gnucash objects into
|
||||
dictionaries for easier conversion to JSON
|
||||
|
||||
Copyright (C) 2013 Tom Lofts <dev@loftx.co.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, contact:
|
||||
|
||||
Free Software Foundation Voice: +1-617-542-5942
|
||||
51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
|
||||
Boston, MA 02110-1301, USA gnu@gnu.org
|
||||
|
||||
@author Tom Lofts <dev@loftx.co.uk>
|
||||
|
||||
'''
|
||||
|
||||
import gnucash
|
||||
from gnucash.gnucash_business import Entry
|
||||
from gnucash.gnucash_business import Entry, Split, Account
|
||||
|
||||
def addressToDict(address):
|
||||
if address is None:
|
||||
return None
|
||||
else:
|
||||
simple_address = {}
|
||||
simple_address['name'] = address.GetName();
|
||||
simple_address['line_1'] = address.GetAddr1();
|
||||
simple_address['line_2'] = address.GetAddr2();
|
||||
simple_address['line_3'] = address.GetAddr3();
|
||||
simple_address['line_4'] = address.GetAddr4();
|
||||
simple_address['phone'] = address.GetPhone();
|
||||
simple_address['fax'] = address.GetFax();
|
||||
simple_address['email'] = address.GetEmail();
|
||||
if address is None:
|
||||
return None
|
||||
else:
|
||||
simple_address = {}
|
||||
simple_address['name'] = address.GetName();
|
||||
simple_address['line_1'] = address.GetAddr1();
|
||||
simple_address['line_2'] = address.GetAddr2();
|
||||
simple_address['line_3'] = address.GetAddr3();
|
||||
simple_address['line_4'] = address.GetAddr4();
|
||||
simple_address['phone'] = address.GetPhone();
|
||||
simple_address['fax'] = address.GetFax();
|
||||
simple_address['email'] = address.GetEmail();
|
||||
|
||||
return simple_address
|
||||
return simple_address
|
||||
|
||||
def vendorToDict(vendor):
|
||||
|
||||
if vendor is None:
|
||||
return None
|
||||
else:
|
||||
simple_vendor = {}
|
||||
simple_vendor['name'] = vendor.GetName()
|
||||
simple_vendor['id'] = vendor.GetID()
|
||||
simple_vendor['notes'] = vendor.GetNotes()
|
||||
simple_vendor['active'] = vendor.GetActive()
|
||||
simple_vendor['currency'] = vendor.GetCurrency().get_mnemonic()
|
||||
simple_vendor['tax_table_override'] = vendor.GetTaxTableOverride()
|
||||
simple_vendor['address'] = addressToDict(vendor.GetAddr())
|
||||
simple_vendor['tax_included'] = vendor.GetTaxIncluded()
|
||||
if vendor is None:
|
||||
return None
|
||||
else:
|
||||
simple_vendor = {}
|
||||
simple_vendor['name'] = vendor.GetName()
|
||||
simple_vendor['id'] = vendor.GetID()
|
||||
simple_vendor['guid'] = vendor.GetGUID().to_string()
|
||||
simple_vendor['notes'] = vendor.GetNotes()
|
||||
simple_vendor['active'] = vendor.GetActive()
|
||||
simple_vendor['currency'] = vendor.GetCurrency().get_mnemonic()
|
||||
simple_vendor['tax_table_override'] = vendor.GetTaxTableOverride()
|
||||
simple_vendor['address'] = addressToDict(vendor.GetAddr())
|
||||
simple_vendor['tax_included'] = vendor.GetTaxIncluded()
|
||||
|
||||
return simple_vendor
|
||||
return simple_vendor
|
||||
|
||||
def customerToDict(customer):
|
||||
|
||||
if customer is None:
|
||||
return None
|
||||
else:
|
||||
simple_customer = {}
|
||||
simple_customer['name'] = customer.GetName()
|
||||
simple_customer['id'] = customer.GetID()
|
||||
simple_customer['notes'] = customer.GetNotes()
|
||||
simple_customer['active'] = customer.GetActive()
|
||||
simple_customer['discount'] = customer.GetDiscount().to_double()
|
||||
simple_customer['credit'] = customer.GetCredit().to_double()
|
||||
simple_customer['currency'] = customer.GetCurrency().get_mnemonic()
|
||||
simple_customer['tax_table_override'] = customer.GetTaxTableOverride()
|
||||
simple_customer['address'] = addressToDict(customer.GetAddr())
|
||||
simple_customer['shipping_address'] = addressToDict(customer.GetShipAddr())
|
||||
simple_customer['tax_included'] = customer.GetTaxIncluded()
|
||||
if customer is None:
|
||||
return None
|
||||
else:
|
||||
simple_customer = {}
|
||||
simple_customer['name'] = customer.GetName()
|
||||
simple_customer['id'] = customer.GetID()
|
||||
simple_customer['guid'] = customer.GetGUID().to_string()
|
||||
simple_customer['notes'] = customer.GetNotes()
|
||||
simple_customer['active'] = customer.GetActive()
|
||||
simple_customer['discount'] = customer.GetDiscount().to_double()
|
||||
simple_customer['credit'] = customer.GetCredit().to_double()
|
||||
simple_customer['currency'] = customer.GetCurrency().get_mnemonic()
|
||||
simple_customer['tax_table_override'] = customer.GetTaxTableOverride()
|
||||
simple_customer['address'] = addressToDict(customer.GetAddr())
|
||||
simple_customer['shipping_address'] = addressToDict(
|
||||
customer.GetShipAddr())
|
||||
simple_customer['tax_included'] = customer.GetTaxIncluded()
|
||||
|
||||
return simple_customer
|
||||
return simple_customer
|
||||
|
||||
def transactionToDict(transaction):
|
||||
if transaction is None:
|
||||
return None
|
||||
else:
|
||||
simple_transaction = {}
|
||||
simple_transaction['num'] = transaction.GetNum()
|
||||
simple_transaction['notes'] = transaction.GetNotes()
|
||||
simple_transaction['is_closing_txn'] = transaction.GetIsClosingTxn()
|
||||
simple_transaction['count_splits'] = transaction.CountSplits()
|
||||
simple_transaction['has_reconciled_splits'] = transaction.HasReconciledSplits()
|
||||
simple_transaction['currency'] = transaction.GetCurrency().get_mnemonic()
|
||||
simple_transaction['imbalance_value'] = transaction.GetImbalanceValue().to_double()
|
||||
simple_transaction['is_balanced'] = transaction.IsBalanced()
|
||||
simple_transaction['date'] = transaction.GetDate()
|
||||
simple_transaction['date_posted'] = transaction.RetDatePostedTS().strftime('%Y-%m-%d')
|
||||
simple_transaction['date_entered'] = transaction.RetDateEnteredTS().strftime('%Y-%m-%d')
|
||||
simple_transaction['date_due'] = transaction.RetDateDueTS().strftime('%Y-%m-%d')
|
||||
simple_transaction['void_status'] = transaction.GetVoidStatus()
|
||||
simple_transaction['void_time'] = transaction.GetVoidTime().strftime('%Y-%m-%d')
|
||||
def transactionToDict(transaction, entities):
|
||||
if transaction is None:
|
||||
return None
|
||||
else:
|
||||
simple_transaction = {}
|
||||
simple_transaction['guid'] = transaction.GetGUID().to_string()
|
||||
simple_transaction['num'] = transaction.GetNum()
|
||||
simple_transaction['notes'] = transaction.GetNotes()
|
||||
simple_transaction['is_closing_txn'] = transaction.GetIsClosingTxn()
|
||||
|
||||
if 'splits' in entities:
|
||||
simple_transaction['splits'] = []
|
||||
for split in transaction.GetSplitList():
|
||||
if type(split) != Split:
|
||||
split=Split(instance=split)
|
||||
simple_transaction['splits'].append(
|
||||
splitToDict(split, ['account']))
|
||||
|
||||
return simple_transaction
|
||||
simple_transaction['count_splits'] = transaction.CountSplits()
|
||||
simple_transaction['has_reconciled_splits'] = \
|
||||
transaction.HasReconciledSplits()
|
||||
simple_transaction['currency'] = transaction.GetCurrency(
|
||||
).get_mnemonic()
|
||||
simple_transaction['imbalance_value'] = transaction.GetImbalanceValue(
|
||||
).to_double()
|
||||
simple_transaction['is_balanced'] = transaction.IsBalanced()
|
||||
simple_transaction['date'] = transaction.GetDate()
|
||||
simple_transaction['date_posted'] = transaction.RetDatePostedTS(
|
||||
).strftime('%Y-%m-%d')
|
||||
simple_transaction['date_entered'] = transaction.RetDateEnteredTS(
|
||||
).strftime('%Y-%m-%d')
|
||||
simple_transaction['date_due'] = transaction.RetDateDueTS().strftime(
|
||||
'%Y-%m-%d')
|
||||
simple_transaction['void_status'] = transaction.GetVoidStatus()
|
||||
simple_transaction['void_time'] = transaction.GetVoidTime().strftime(
|
||||
'%Y-%m-%d')
|
||||
|
||||
simple_transaction['description'] = transaction.GetDescription()
|
||||
|
||||
return simple_transaction
|
||||
|
||||
def splitToDict(split, entities):
|
||||
if split is None:
|
||||
return None
|
||||
else:
|
||||
simple_split = {}
|
||||
simple_split['guid'] = split.GetGUID().to_string()
|
||||
if 'account' in entities:
|
||||
simple_split['account'] = accountToDict(split.GetAccount())
|
||||
if 'transaction' in entities:
|
||||
simple_split['transaction'] = transactionToDict(
|
||||
split.GetParent(), [])
|
||||
if 'other_split' in entities:
|
||||
simple_split['other_split'] = splitToDict(
|
||||
split.GetOtherSplit(), ['account'])
|
||||
simple_split['amount'] = split.GetAmount().to_double()
|
||||
simple_split['value'] = split.GetValue().to_double()
|
||||
simple_split['balance'] = split.GetBalance().to_double()
|
||||
simple_split['cleared_balance'] = split.GetClearedBalance().to_double()
|
||||
simple_split['reconciled_balance'] = split.GetReconciledBalance(
|
||||
).to_double()
|
||||
|
||||
return simple_split
|
||||
def invoiceToDict(invoice):
|
||||
|
||||
if invoice is None:
|
||||
return None
|
||||
else:
|
||||
simple_invoice = {}
|
||||
simple_invoice['id'] = invoice.GetID()
|
||||
simple_invoice['type'] = invoice.GetType()
|
||||
simple_invoice['date_opened'] = invoice.GetDateOpened().strftime('%Y-%m-%d')
|
||||
simple_invoice['date_posted'] = invoice.GetDatePosted().strftime('%Y-%m-%d')
|
||||
simple_invoice['date_due'] = invoice.GetDateDue().strftime('%Y-%m-%d')
|
||||
simple_invoice['notes'] = invoice.GetNotes()
|
||||
simple_invoice['active'] = invoice.GetActive()
|
||||
simple_invoice['currency'] = invoice.GetCurrency().get_mnemonic()
|
||||
simple_invoice['owner'] = vendorToDict(invoice.GetOwner())
|
||||
simple_invoice['owner_type'] = invoice.GetOwnerType()
|
||||
simple_invoice['billing_id'] = invoice.GetBillingID()
|
||||
simple_invoice['to_charge_amount'] = invoice.GetToChargeAmount().to_double()
|
||||
simple_invoice['total'] = invoice.GetTotal().to_double()
|
||||
simple_invoice['total_subtotal'] = invoice.GetTotalSubtotal().to_double()
|
||||
simple_invoice['total_tax'] = invoice.GetTotalTax().to_double()
|
||||
simple_invoice['entries'] = {}
|
||||
for n, entry in enumerate(invoice.GetEntries()):
|
||||
if type(entry) != Entry:
|
||||
entry=Entry(instance=entry)
|
||||
simple_invoice['entries'][n] = entryToDict(entry)
|
||||
simple_invoice['posted'] = invoice.IsPosted()
|
||||
simple_invoice['paid'] = invoice.IsPaid()
|
||||
if invoice is None:
|
||||
return None
|
||||
else:
|
||||
simple_invoice = {}
|
||||
simple_invoice['id'] = invoice.GetID()
|
||||
simple_invoice['type'] = invoice.GetType()
|
||||
simple_invoice['date_opened'] = invoice.GetDateOpened().strftime(
|
||||
'%Y-%m-%d')
|
||||
if invoice.GetDatePosted().strftime('%Y-%m-%d') == '1970-01-01':
|
||||
simple_invoice['date_posted'] = None
|
||||
else:
|
||||
simple_invoice['date_posted'] = invoice.GetDatePosted().strftime(
|
||||
'%Y-%m-%d')
|
||||
if invoice.GetDateDue().strftime('%Y-%m-%d') == '1970-01-01':
|
||||
simple_invoice['date_due'] = None
|
||||
else:
|
||||
simple_invoice['date_due'] = invoice.GetDateDue().strftime(
|
||||
'%Y-%m-%d')
|
||||
simple_invoice['notes'] = invoice.GetNotes()
|
||||
simple_invoice['active'] = invoice.GetActive()
|
||||
simple_invoice['currency'] = invoice.GetCurrency().get_mnemonic()
|
||||
simple_invoice['owner'] = vendorToDict(invoice.GetOwner())
|
||||
simple_invoice['owner_type'] = invoice.GetOwnerType()
|
||||
simple_invoice['billing_id'] = invoice.GetBillingID()
|
||||
simple_invoice['to_charge_amount'] = invoice.GetToChargeAmount().to_double()
|
||||
simple_invoice['posted_txn'] = transactionToDict(invoice.GetPostedTxn(), [])
|
||||
simple_invoice['total'] = invoice.GetTotal().to_double()
|
||||
simple_invoice['total_subtotal'] = invoice.GetTotalSubtotal(
|
||||
).to_double()
|
||||
simple_invoice['total_tax'] = invoice.GetTotalTax().to_double()
|
||||
|
||||
return simple_invoice
|
||||
simple_invoice['entries'] = []
|
||||
for n, entry in enumerate(invoice.GetEntries()):
|
||||
if type(entry) != Entry:
|
||||
entry=Entry(instance=entry)
|
||||
simple_invoice['entries'].append(entryToDict(entry))
|
||||
|
||||
simple_invoice['posted'] = invoice.IsPosted()
|
||||
simple_invoice['paid'] = invoice.IsPaid()
|
||||
|
||||
return simple_invoice
|
||||
|
||||
def billToDict(bill):
|
||||
|
||||
if bill is None:
|
||||
return None
|
||||
else:
|
||||
simple_bill = {}
|
||||
simple_bill['id'] = bill.GetID()
|
||||
simple_bill['type'] = bill.GetType()
|
||||
simple_bill['date_opened'] = bill.GetDateOpened().strftime('%Y-%m-%d')
|
||||
if bill.GetDatePosted().strftime('%Y-%m-%d') == '1970-01-01':
|
||||
simple_bill['date_posted'] = None
|
||||
else:
|
||||
simple_bill['date_posted'] = bill.GetDatePosted().strftime(
|
||||
'%Y-%m-%d')
|
||||
if bill.GetDateDue().strftime('%Y-%m-%d') == '1970-01-01':
|
||||
simple_bill['date_due'] = None
|
||||
else:
|
||||
simple_bill['date_due'] = bill.GetDateDue().strftime('%Y-%m-%d')
|
||||
simple_bill['notes'] = bill.GetNotes()
|
||||
simple_bill['active'] = bill.GetActive()
|
||||
simple_bill['currency'] = bill.GetCurrency().get_mnemonic()
|
||||
simple_bill['owner'] = vendorToDict(bill.GetOwner())
|
||||
simple_bill['owner_type'] = bill.GetOwnerType()
|
||||
simple_bill['billing_id'] = bill.GetBillingID()
|
||||
simple_bill['to_charge_amount'] = bill.GetToChargeAmount().to_double()
|
||||
simple_bill['total'] = bill.GetTotal().to_double()
|
||||
simple_bill['total_subtotal'] = bill.GetTotalSubtotal().to_double()
|
||||
simple_bill['total_tax'] = bill.GetTotalTax().to_double()
|
||||
|
||||
simple_bill['entries'] = []
|
||||
for n, entry in enumerate(bill.GetEntries()):
|
||||
if type(entry) != Entry:
|
||||
entry=Entry(instance=entry)
|
||||
simple_bill['entries'].append(entryToDict(entry))
|
||||
|
||||
simple_bill['posted'] = bill.IsPosted()
|
||||
simple_bill['paid'] = bill.IsPaid()
|
||||
|
||||
return simple_bill
|
||||
|
||||
def entryToDict(entry):
|
||||
|
||||
if entry is None:
|
||||
return None
|
||||
else:
|
||||
simple_entry = {}
|
||||
simple_entry['date'] = entry.GetDate().strftime('%Y-%m-%d')
|
||||
simple_entry['date_entered'] = entry.GetDateEntered().strftime('%Y-%m-%d')
|
||||
simple_entry['description'] = entry.GetDescription()
|
||||
simple_entry['action'] = entry.GetAction()
|
||||
simple_entry['notes'] = entry.GetNotes()
|
||||
simple_entry['quantity'] = gnucash.GncNumeric(instance=entry.GetQuantity()).to_double()
|
||||
simple_entry['inv_price'] = gnucash.GncNumeric(instance=entry.GetInvPrice()).to_double()
|
||||
simple_entry['discount'] = gnucash.GncNumeric(instance=entry.GetInvDiscount()).to_double()
|
||||
simple_entry['discounted_type'] = entry.GetInvDiscountType()
|
||||
simple_entry['discounted_how'] = entry.GetInvDiscountHow()
|
||||
simple_entry['inv_taxable'] = entry.GetInvTaxable()
|
||||
simple_entry['inv_tax_included'] = entry.GetInvTaxIncluded()
|
||||
simple_entry['inv_tax_table_override'] = entry.GetInvTaxTable()
|
||||
simple_entry['bill_price'] = gnucash.GncNumeric(instance=entry.GetBillPrice()).to_double()
|
||||
simple_entry['bill_taxable'] = entry.GetBillTaxable()
|
||||
simple_entry['bill_tax_included'] = entry.GetBillTaxIncluded()
|
||||
simple_entry['bill_tax_table'] = entry.GetBillTaxTable()
|
||||
simple_entry['billable'] = entry.GetBillable()
|
||||
simple_entry['bill_payment'] = entry.GetBillPayment()
|
||||
simple_entry['is_open'] = entry.IsOpen()
|
||||
if entry is None:
|
||||
return None
|
||||
else:
|
||||
|
||||
return simple_entry
|
||||
simple_entry = {}
|
||||
simple_entry['guid'] = entry.GetGUID().to_string()
|
||||
simple_entry['date'] = entry.GetDate().strftime('%Y-%m-%d')
|
||||
simple_entry['date_entered'] = entry.GetDateEntered().strftime(
|
||||
'%Y-%m-%d')
|
||||
simple_entry['description'] = entry.GetDescription()
|
||||
simple_entry['action'] = entry.GetAction()
|
||||
simple_entry['notes'] = entry.GetNotes()
|
||||
simple_entry['quantity'] = entry.GetQuantity().to_double()
|
||||
if entry.GetInvAccount() == None:
|
||||
simple_entry['inv_account'] = {}
|
||||
else:
|
||||
simple_entry['inv_account'] = accountToDict(entry.GetInvAccount())
|
||||
simple_entry['inv_price'] = entry.GetInvPrice().to_double()
|
||||
simple_entry['discount'] = entry.GetInvDiscount().to_double()
|
||||
simple_entry['discounted_type'] = entry.GetInvDiscountType()
|
||||
simple_entry['discounted_how'] = entry.GetInvDiscountHow()
|
||||
simple_entry['inv_taxable'] = entry.GetInvTaxable()
|
||||
simple_entry['inv_tax_included'] = entry.GetInvTaxIncluded()
|
||||
simple_entry['inv_tax_table_override'] = entry.GetInvTaxTable()
|
||||
if entry.GetBillAccount() == None:
|
||||
simple_entry['bill_account'] = {}
|
||||
else:
|
||||
simple_entry['bill_account'] = accountToDict(
|
||||
entry.GetBillAccount())
|
||||
simple_entry['bill_price'] = entry.GetBillPrice().to_double()
|
||||
simple_entry['bill_taxable'] = entry.GetBillTaxable()
|
||||
simple_entry['bill_tax_included'] = entry.GetBillTaxIncluded()
|
||||
simple_entry['bill_tax_table'] = entry.GetBillTaxTable()
|
||||
simple_entry['billable'] = entry.GetBillable()
|
||||
simple_entry['bill_payment'] = entry.GetBillPayment()
|
||||
simple_entry['is_open'] = entry.IsOpen()
|
||||
|
||||
return simple_entry
|
||||
|
||||
|
||||
def accountToDict(account):
|
||||
|
||||
if account is None:
|
||||
return None
|
||||
else:
|
||||
simple_account = {}
|
||||
simple_account['name'] = account.GetName()
|
||||
simple_account['guid'] = account.GetGUID().to_string()
|
||||
simple_account['subaccounts'] = []
|
||||
for n, subaccount in enumerate(account.get_children_sorted()):
|
||||
simple_account['subaccounts'].append(accountToDict(subaccount))
|
||||
commod_table = account.get_book().get_table()
|
||||
gbp = commod_table.lookup('CURRENCY', 'GBP')
|
||||
|
||||
return simple_account
|
||||
if account is None:
|
||||
return None
|
||||
else:
|
||||
simple_account = {}
|
||||
simple_account['name'] = account.GetName()
|
||||
simple_account['type_id'] = account.GetType()
|
||||
simple_account['description'] = account.GetDescription()
|
||||
simple_account['guid'] = account.GetGUID().to_string()
|
||||
if account.GetCommodity() == None:
|
||||
simple_account['currency'] = ''
|
||||
else:
|
||||
simple_account['currency'] = account.GetCommodity().get_mnemonic()
|
||||
simple_account['subaccounts'] = []
|
||||
for n, subaccount in enumerate(account.get_children_sorted()):
|
||||
simple_account['subaccounts'].append(accountToDict(subaccount))
|
||||
|
||||
simple_account['balance'] = account.GetBalance().to_double()
|
||||
simple_account['balance_gbp'] = account.GetBalanceInCurrency(
|
||||
gbp, True).to_double()
|
||||
simple_account['placeholder'] = account.GetPlaceholder()
|
||||
|
||||
return simple_account
|
||||
|
||||
@@ -35,7 +35,7 @@ from function_class import \
|
||||
|
||||
from gnucash_core import \
|
||||
GnuCashCoreClass, GncNumeric, GncCommodity, Transaction, \
|
||||
Split, Book, GncLot, Account
|
||||
Split, Book, GncLot, Account, GUID
|
||||
|
||||
from gnucash_core_c import GNC_OWNER_CUSTOMER, GNC_OWNER_JOB, \
|
||||
GNC_OWNER_EMPLOYEE, GNC_OWNER_VENDOR, \
|
||||
@@ -217,8 +217,7 @@ class Entry(GnuCashCoreClass):
|
||||
if invoice != None:
|
||||
invoice.AddEntry(self)
|
||||
else:
|
||||
|
||||
GnuCashCoreClass.__init__(self, instance=instance)
|
||||
GnuCashCoreClass.__init__(self, instance=instance)
|
||||
|
||||
def test_type(self, invoice):
|
||||
if invoice.GetTypeString() == "Invoice" and self.GetInvoice() == None:
|
||||
@@ -226,11 +225,11 @@ class Entry(GnuCashCoreClass):
|
||||
if invoice.GetTypeString() == "Bill" and self.GetBill() == None:
|
||||
raise Exception("Entry type error. Check that Entry type matches Bill.")
|
||||
|
||||
|
||||
# Owner
|
||||
GnuCashBusinessEntity.add_methods_with_prefix('gncOwner')
|
||||
|
||||
owner_dict = {
|
||||
'GetGUID' : GUID,
|
||||
'GetCustomer' : Customer,
|
||||
'GetVendor' : Vendor,
|
||||
'GetEmployee' : Employee,
|
||||
@@ -249,6 +248,7 @@ methods_return_instance_lists(
|
||||
|
||||
# Customer
|
||||
Customer.add_constructor_and_methods_with_prefix('gncCustomer', 'Create')
|
||||
Customer.add_method('gncOwnerApplyPayment', 'ApplyPayment')
|
||||
|
||||
customer_dict = {
|
||||
'GetAddr' : Address,
|
||||
@@ -326,6 +326,8 @@ Invoice.add_constructor_and_methods_with_prefix('gncInvoice', 'Create')
|
||||
methods_return_instance_lists(
|
||||
Invoice, { 'GetEntries': Entry })
|
||||
|
||||
Invoice.add_method('gncInvoiceRemoveEntry', 'RemoveEntry')
|
||||
|
||||
# Bill
|
||||
Bill.add_methods_with_prefix('gncBill')
|
||||
|
||||
@@ -351,7 +353,11 @@ Invoice.decorate_functions(
|
||||
# Entry
|
||||
Entry.add_constructor_and_methods_with_prefix('gncEntry', 'Create')
|
||||
|
||||
Entry.add_method('gncEntryGetGUID', 'GetGUID')
|
||||
Entry.add_method('gncEntryDestroy', 'Destroy')
|
||||
|
||||
entry_dict = {
|
||||
'GetGUID' : GUID,
|
||||
'GetQuantity': GncNumeric,
|
||||
'GetInvAccount': Account,
|
||||
'GetInvPrice': GncNumeric,
|
||||
|
||||
@@ -124,23 +124,23 @@
|
||||
PyObject * swig_wrapper_object;
|
||||
if (owner_type == GNC_OWNER_CUSTOMER ){
|
||||
swig_wrapper_object = SWIG_NewPointerObj(
|
||||
gncOwnerGetCustomer($1), $descriptor(GncCustomer *), 0);
|
||||
gncOwnerGetCustomer($1), $descriptor(GncCustomer *), 0);
|
||||
}
|
||||
else if (owner_type == GNC_OWNER_JOB){
|
||||
swig_wrapper_object = SWIG_NewPointerObj(
|
||||
gncOwnerGetJob($1), $descriptor(GncJob *), 0);
|
||||
gncOwnerGetJob($1), $descriptor(GncJob *), 0);
|
||||
}
|
||||
else if (owner_type == GNC_OWNER_VENDOR){
|
||||
swig_wrapper_object = SWIG_NewPointerObj(
|
||||
gncOwnerGetVendor($1), $descriptor(GncVendor *), 0);
|
||||
gncOwnerGetVendor($1), $descriptor(GncVendor *), 0);
|
||||
}
|
||||
else if (owner_type == GNC_OWNER_EMPLOYEE){
|
||||
swig_wrapper_object = SWIG_NewPointerObj(
|
||||
gncOwnerGetEmployee($1), $descriptor(GncEmployee *), 0);
|
||||
gncOwnerGetEmployee($1), $descriptor(GncEmployee *), 0);
|
||||
}
|
||||
else {
|
||||
swig_wrapper_object = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
Py_INCREF(Py_None);
|
||||
}
|
||||
PyTuple_SetItem(owner_tuple, 1, swig_wrapper_object);
|
||||
$result = owner_tuple;
|
||||
@@ -175,10 +175,10 @@
|
||||
$1 = temp_owner;
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(
|
||||
PyExc_ValueError,
|
||||
"Python object passed to function with GncOwner * argument "
|
||||
"couldn't be converted back to pointer of that type");
|
||||
PyErr_SetString(
|
||||
PyExc_ValueError,
|
||||
"Python object passed to function with GncOwner * argument "
|
||||
"couldn't be converted back to pointer of that type");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -187,6 +187,7 @@
|
||||
gncOwnerFree($1);
|
||||
}
|
||||
|
||||
static const GncGUID * gncEntryGetGUID(GncEntry *x);
|
||||
|
||||
%include <gnc-lot.h>
|
||||
|
||||
|
||||
@@ -40,8 +40,9 @@ from gnucash_core_c import gncInvoiceLookup, gncInvoiceGetInvoiceFromTxn, \
|
||||
gncInvoiceGetInvoiceFromLot, gncEntryLookup, gncInvoiceLookup, \
|
||||
gncCustomerLookup, gncVendorLookup, gncJobLookup, gncEmployeeLookup, \
|
||||
gncTaxTableLookup, gncTaxTableLookupByName, gnc_search_invoice_on_id, \
|
||||
gnc_search_customer_on_id, gnc_search_bill_on_id , gnc_search_vendor_on_id, \
|
||||
gncInvoiceNextID, gncCustomerNextID, gncTaxTableGetTables, gncVendorNextID
|
||||
gnc_search_customer_on_id, gnc_search_bill_on_id , \
|
||||
gnc_search_vendor_on_id, gncInvoiceNextID, gncCustomerNextID, \
|
||||
gncVendorNextID, gncTaxTableGetTables
|
||||
|
||||
class GnuCashCoreClass(ClassFromFunctions):
|
||||
_module = gnucash_core_c
|
||||
@@ -176,7 +177,7 @@ class Book(GnuCashCoreClass):
|
||||
gncInvoiceLookup, Invoice, guid.get_instance() )
|
||||
|
||||
def EntryLookup(self, guid):
|
||||
from gnucash_business import Entr
|
||||
from gnucash_business import Entry
|
||||
return self.do_lookup_create_oo_instance(
|
||||
gncEntryLookup, Entry, guid.get_instance() )
|
||||
|
||||
@@ -214,7 +215,7 @@ class Book(GnuCashCoreClass):
|
||||
from gnucash_business import TaxTable
|
||||
return [ TaxTable(instance=item) for item in gncTaxTableGetTables(self.instance) ]
|
||||
|
||||
def BillLoookupByID(self, id):
|
||||
def BillLookupByID(self, id):
|
||||
from gnucash_business import Bill
|
||||
return self.do_lookup_create_oo_instance(
|
||||
gnc_search_bill_on_id, Bill, id)
|
||||
@@ -249,7 +250,7 @@ class Book(GnuCashCoreClass):
|
||||
''' Return the next Customer ID. '''
|
||||
from gnucash.gnucash_core_c import gncCustomerNextID
|
||||
return gncCustomerNextID(self.get_instance())
|
||||
|
||||
|
||||
def VendorNextID(self):
|
||||
''' Return the next Vendor ID. '''
|
||||
from gnucash.gnucash_core_c import gncVendorNextID
|
||||
@@ -581,6 +582,9 @@ methods_return_instance(GncLot, gnclot_dict)
|
||||
Transaction.add_methods_with_prefix('xaccTrans')
|
||||
Transaction.add_method('gncTransGetGUID', 'GetGUID');
|
||||
|
||||
Transaction.add_method('xaccTransGetDescription', 'GetDescription')
|
||||
Transaction.add_method('xaccTransDestroy', 'Destroy')
|
||||
|
||||
trans_dict = {
|
||||
'GetSplit': Split,
|
||||
'FindSplitByAccount': Split,
|
||||
@@ -606,6 +610,7 @@ Transaction.decorate_functions(
|
||||
# Split
|
||||
Split.add_methods_with_prefix('xaccSplit')
|
||||
Split.add_method('gncSplitGetGUID', 'GetGUID');
|
||||
Split.add_method('xaccSplitDestroy', 'Destroy')
|
||||
|
||||
split_dict = {
|
||||
'GetBook': Book,
|
||||
@@ -634,6 +639,7 @@ Split.parent = property( Split.GetParent, Split.SetParent )
|
||||
Account.add_methods_with_prefix('xaccAccount')
|
||||
Account.add_methods_with_prefix('gnc_account_')
|
||||
Account.add_method('gncAccountGetGUID', 'GetGUID');
|
||||
Account.add_method('xaccAccountGetPlaceholder', 'GetPlaceholder')
|
||||
|
||||
account_dict = {
|
||||
'get_book' : Book,
|
||||
@@ -734,19 +740,36 @@ Query.add_method('qof_query_search_for', 'search_for')
|
||||
Query.add_method('qof_query_run', 'run')
|
||||
Query.add_method('qof_query_add_term', 'add_term')
|
||||
Query.add_method('qof_query_add_boolean_match', 'add_boolean_match')
|
||||
Query.add_method('qof_query_add_guid_list_match', 'add_guid_list_match')
|
||||
Query.add_method('qof_query_add_guid_match', 'add_guid_match')
|
||||
Query.add_method('qof_query_destroy', 'destroy')
|
||||
|
||||
class QueryStringPredicate(GnuCashCoreClass):
|
||||
pass
|
||||
|
||||
QueryStringPredicate.add_constructor_and_methods_with_prefix('qof_query_', 'string_predicate')
|
||||
QueryStringPredicate.add_constructor_and_methods_with_prefix(
|
||||
'qof_query_','string_predicate')
|
||||
|
||||
class QueryBooleanPredicate(GnuCashCoreClass):
|
||||
pass
|
||||
|
||||
QueryBooleanPredicate.add_constructor_and_methods_with_prefix('qof_query_', 'boolean_predicate')
|
||||
QueryBooleanPredicate.add_constructor_and_methods_with_prefix(
|
||||
'qof_query_', 'boolean_predicate')
|
||||
|
||||
class QueryInt32Predicate(GnuCashCoreClass):
|
||||
pass
|
||||
|
||||
QueryInt32Predicate.add_constructor_and_methods_with_prefix('qof_query_', 'int32_predicate')
|
||||
QueryInt32Predicate.add_constructor_and_methods_with_prefix(
|
||||
'qof_query_', 'int32_predicate')
|
||||
|
||||
class QueryDatePredicate(GnuCashCoreClass):
|
||||
pass
|
||||
|
||||
QueryDatePredicate.add_constructor_and_methods_with_prefix(
|
||||
'qof_query_', 'date_predicate')
|
||||
|
||||
class QueryGuidPredicate(GnuCashCoreClass):
|
||||
pass
|
||||
|
||||
QueryGuidPredicate.add_constructor_and_methods_with_prefix(
|
||||
'qof_query_', 'guid_predicate')
|
||||
|
||||
Reference in New Issue
Block a user