diff --git a/accounting/storage/__init__.py b/accounting/storage/__init__.py index 28922c8..543607a 100644 --- a/accounting/storage/__init__.py +++ b/accounting/storage/__init__.py @@ -4,8 +4,10 @@ from abc import ABCMeta, abstractmethod +from accounting.exceptions import AccountingException -class Storage(): + +class Storage: ''' ABC for accounting storage ''' @@ -38,6 +40,14 @@ class Storage(): def update_transaction(self, transaction): raise NotImplementedError + @abstractmethod + def delete_transaction(self, transaction_id): + raise NotImplementedError + @abstractmethod def reverse_transaction(self, transaction_id): raise NotImplementedError + + +class TransactionNotFound(AccountingException): + pass diff --git a/accounting/storage/ledgercli.py b/accounting/storage/ledgercli.py index bb7f3fa..9c2691f 100644 --- a/accounting/storage/ledgercli.py +++ b/accounting/storage/ledgercli.py @@ -6,13 +6,15 @@ import sys import subprocess import logging import time +import re from datetime import datetime from xml.etree import ElementTree from contextlib import contextmanager +from accounting.exceptions import AccountingException from accounting.models import Account, Transaction, Posting, Amount -from accounting.storage import Storage +from accounting.storage import Storage, TransactionNotFound _log = logging.getLogger(__name__) @@ -205,6 +207,8 @@ class Ledger(Storage): _log.debug('written to file: %s', output) + return transaction.id + def bal(self): output = self.send_command('xml') @@ -252,6 +256,16 @@ class Ledger(Storage): def get_transactions(self): return self.reg() + def get_transaction(self, transaction_id): + transactions = self.get_transactions() + + for transaction in transactions: + if transaction.id == transaction_id: + return transaction + + raise TransactionNotFound('No transaction with id %s found', + transaction_id) + def reg(self): output = self.send_command('xml') @@ -314,8 +328,111 @@ class Ledger(Storage): return entries + def delete_transaction(self, transaction_id): + ''' + Delete a transaction from the ledger file. + + This method opens the ledger file, loads all lines into memory and + looks for the transaction_id, then looks for the bounds of that + transaction in the ledger file, removes all lines within the bounds of + the transaction and removes them, then writes the lines back to the + ledger file. + + Exceptions: + + - RuntimeError: If all boundaries to the transaction are not found + - TransactionNotFound: If no such transaction_id can be found in + :data:`self.ledger_file` + ''' + f = open(self.ledger_file, 'r') + + lines = [i for i in f] + + # A mapping of line meanings and their line numbers as found by the + # following logic + semantic_lines = dict( + id_location=None, + transaction_start=None, + next_transaction_or_eof=None + ) + + for i, line in enumerate(lines): + if transaction_id in line: + semantic_lines['id_location'] = i + break + + if not semantic_lines['id_location']: + raise TransactionNotFound('No transaction with ID "%s" found') + + transaction_start_pattern = re.compile(r'^\S') + + cursor = semantic_lines['id_location'] - 1 + + # Find the first line of the transaction + while True: + if transaction_start_pattern.match(lines[cursor]): + semantic_lines['transaction_start'] = cursor + break + + cursor -= 1 + + cursor = semantic_lines['id_location'] + 1 + + # Find the last line of the transaction + while True: + try: + if transaction_start_pattern.match(lines[cursor]): + semantic_lines['next_transaction_or_eof'] = cursor + break + except IndexError: + # Set next_line_without_starting_space_or_end_of_file to + # the cursor. The cursor will be an index not included in the + # list of lines + semantic_lines['next_transaction_or_eof'] = cursor + break + + cursor += 1 + + if not all(map(lambda v: v is not None, semantic_lines.values())): + raise RuntimeError('Could not find all the values necessary for' + ' safe deletion of a transaction.') + + del_start = semantic_lines['transaction_start'] + + if len(lines) == semantic_lines['next_transaction_or_eof']: + _log.debug('There are no transactions below the transaction being' + ' deleted. The line before the first line of the' + ' transaction will be deleted.') + # Delete the preceding line to make the file + del_start -= 1 + + del lines[del_start:semantic_lines['next_transaction_or_eof']] + + with open(self.ledger_file, 'w') as f: + for line in lines: + f.write(line) + def update_transaction(self, transaction): - _log.debug('DUMMY: Updated transaction: %s', transaction) + ''' + Update a transaction in the ledger file. + + Takes a :class:`~accounting.models.Transaction` object and removes + the old transaction using :data:`transaction.id` from the passed + :class:`~accounting.models.Transaction` instance and adds + :data:`transaction` to the database. + ''' + if not transaction.id: + return AccountingException('The transaction %s has no' + ' id attribute', transaction) + + old_transaction = self.get_transaction(transaction.id) + + self.delete_transaction(transaction.id) + + self.add_transaction(transaction) + + _log.debug('Updated transaction from: %s to: %s', old_transaction, + transaction) def main(argv=None): diff --git a/accounting/web.py b/accounting/web.py index 60564e0..53d77ce 100644 --- a/accounting/web.py +++ b/accounting/web.py @@ -11,7 +11,6 @@ import logging import argparse from flask import Flask, jsonify, request -from flask.ext.sqlalchemy import SQLAlchemy from flask.ext.script import Manager from flask.ext.migrate import Migrate, MigrateCommand @@ -65,6 +64,7 @@ def transaction_get(): ''' return jsonify(transactions=storage.get_transactions()) + @app.route('/transaction/', methods=['POST']) @jsonify_exceptions def transaction_update(transaction_id=None): @@ -74,8 +74,8 @@ def transaction_update(transaction_id=None): transaction = request.json['transaction'] if transaction.id is not None and not transaction.id == transaction_id: - raise AccountingException('The transaction data has an ID attribute and' - ' it is not the same ID as in the path') + raise AccountingException('The transaction data has an ID attribute' + ' and it is not the same ID as in the path') elif transaction.id is None: transaction.id = transaction_id @@ -84,6 +84,17 @@ def transaction_update(transaction_id=None): return jsonify(status='OK') +@app.route('/transaction/', methods=['DELETE']) +@jsonify_exceptions +def transaction_delete(transaction_id=None): + if transaction_id is None: + raise AccountingException('Transaction ID cannot be None') + + storage.delete_transaction(transaction_id) + + return jsonify(status='OK') + + @app.route('/transaction', methods=['POST']) @jsonify_exceptions def transaction_post(): @@ -139,10 +150,12 @@ def transaction_post(): if not transactions: raise AccountingException('No transaction data provided') - for transaction in transactions: - storage.add_transaction(transaction) + transaction_ids = [] - return jsonify(status='OK') + for transaction in transactions: + transaction_ids.append(storage.add_transaction(transaction)) + + return jsonify(status='OK', transaction_ids=transaction_ids) def main(argv=None): diff --git a/doc/build/html/api/accounting.html b/doc/build/html/api/accounting.html index f2ac9a6..583bde1 100644 --- a/doc/build/html/api/accounting.html +++ b/doc/build/html/api/accounting.html @@ -285,6 +285,11 @@ and the Flask endpoints.

accounting.web.main(argv=None)[source]
+
+
+accounting.web.transaction_delete(transaction_id=None)
+
+
accounting.web.transaction_get()[source]
diff --git a/doc/build/html/api/accounting.storage.html b/doc/build/html/api/accounting.storage.html index c093312..8bef1d0 100644 --- a/doc/build/html/api/accounting.storage.html +++ b/doc/build/html/api/accounting.storage.html @@ -102,7 +102,19 @@ based on self.led
delete_transaction(transaction_id)
-
+

Delete a transaction from the ledger file.

+

This method opens the ledger file, loads all lines into memory and +looks for the transaction_id, then looks for the bounds of that +transaction in the ledger file, removes all lines within the bounds of +the transaction and removes them, then writes the lines back to the +ledger file.

+

Exceptions:

+
    +
  • RuntimeError: If all boundaries to the transaction are not found
  • +
  • TransactionNotFound: If no such transaction_id can be found in +self.ledger_file
  • +
+
@@ -168,7 +180,12 @@ without the prompt.

update_transaction(transaction)[source]
-
+

Update a transaction in the ledger file.

+

Takes a Transaction object and removes +the old transaction using transaction.id from the passed +Transaction instance and adds +transaction to the database.

+
@@ -190,6 +207,11 @@ without the prompt.

add_transaction(transaction)
+
+
+delete_transaction(transaction_id)
+
+
get_account(*args, **kw)[source]
diff --git a/doc/build/html/genindex.html b/doc/build/html/genindex.html index 91b8612..db08df0 100644 --- a/doc/build/html/genindex.html +++ b/doc/build/html/genindex.html @@ -243,6 +243,12 @@
delete_transaction() (accounting.storage.ledgercli.Ledger method)
+
+ +
(accounting.storage.Storage method) +
+ +
dict_to_object() (accounting.transport.AccountingDecoder method)
@@ -546,16 +552,20 @@
-
transaction_get() (in module accounting.web) +
transaction_delete() (in module accounting.web)
-
transaction_post() (in module accounting.web) +
transaction_get() (in module accounting.web)
+
transaction_post() (in module accounting.web) +
+ +
transaction_update() (in module accounting.web)
diff --git a/doc/build/html/objects.inv b/doc/build/html/objects.inv index f696297..4afa717 100644 Binary files a/doc/build/html/objects.inv and b/doc/build/html/objects.inv differ diff --git a/doc/build/html/searchindex.js b/doc/build/html/searchindex.js index 120a5e2..cdcfef6 100644 --- a/doc/build/html/searchindex.js +++ b/doc/build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({objtypes:{"0":"py:module","1":"py:method","2":"py:class","3":"py:exception","4":"py:attribute","5":"py:function"},objnames:{"0":["py","module","Python module"],"1":["py","method","Python method"],"2":["py","class","Python class"],"3":["py","exception","Python exception"],"4":["py","attribute","Python attribute"],"5":["py","function","Python function"]},titles:["accounting.storage.sql package","accounting package","accounting.storage package","accounting","The Accounting API","Welcome to Accounting API’s documentation!"],envversion:43,filenames:["api/accounting.storage.sql","api/accounting","api/accounting.storage","api/modules","README","index"],terms:{"function":4,func:1,make:4,caller:1,run:[2,4],follow:4,transaction_get:1,index:[1,5],"_generate_id":1,how:4,pars:[],search:5,shell:4,on_transactions_load:1,world:1,execut:2,transaction_uuid:0,transaction_post:1,open:2,lock:2,file:[1,2],well:4,want:4,out:4,asset:[1,4],foo:1,tri:4,onc:2,which:[1,2,4],json_decod:1,net:4,user:4,need:4,builtin:[1,2],argument:2,init_ledg:1,also:4,prog:1,describ:4,servic:4,get_bal:1,simpl:4,method:[1,4],json:1,updat:4,wrap:1,name:1,print_transact:1,on_transaction_select:[],jsonencod:1,send_command:2,on_refresh_transactions_activ:[],statement:2,high:1,requir:[1,4],dict_to_object:1,report:4,sort_kei:1,have:4,recommend:2,post:[0,1],object:[1,2],generate_id:1,state:1,blah:[],head:4,webservic:1,json_encod:1,flag:4,endpoint:1,http:[],avaiabl:4,get_account:2,combin:2,amount:[0,1],none:[0,1,2],main:[1,2],type:[],abc:2,before_request:1,on_transaction_refresh_activ:1,ledger_bin:2,register_report:[],contextmanag:2,ledger_process:2,get_regist:1,virtualenvwrapp:4,argv:[1,2],clariti:[],wget:[],mkvirtualenv:4,level:1,func_or_str:1,becom:1,banner:2,from_acc:1,"try":4,end:4,accountingappl:1,kindli:1,indicate_activity_don:1,amount_id:0,went:4,reg:[1,2],paye:[0,1],uuid:0,get:[1,4],karma:[],delete_transact:2,rent:4,yield:2,x20:2,ledgercli:[],take:1,your:4,ensure_ascii:1,balance_report:[],environ:4,widget:1,usr:4,"default":1,get_transact:[0,2],rest:1,update_transact:[0,2],from:[2,4],npoacct:4,termin:4,you:4,to_acc:1,get_process:2,all:4,as_dict:0,"class":[0,1,2],see:4,output:[1,2],python:4,should:2,accountingdecod:1,list:2,subprocess:2,repositori:4,transaction_upd:1,process:2,path:[1,4],sourc:[0,1,2,4],fals:1,locked_process:2,kwarg:0,discard:2,sql:[],pip:4,site:4,evalu:2,yet:4,"return":[1,2],current:1,incom:1,page:5,write:[1,2],balanc:4,instanc:2,flask:[1,4],payload:1,sqlstorag:0,channel:4,currenc:4,decod:[],add_transact:[0,2],logic:1,context:2,check_circular:1,indent:1,linebreak:[],conserv:4,regist:4,allow_nan:1,local:4,ledger:[1,2,4],mbudd:4,read:2,parse_json:[],clone:4,handl:2,expens:4,"new":2,request:1,"catch":1,storag:[],workon:4,contextlib:2,annot:1,section:4,sudo:4,flask_sqlalchemi:0,data:[],print_balance_account:1,serv:4,read_until_prompt:2,date:[0,1],mode:2,sai:4,init_process:2,hello:1,initi:1,transactionnotfound:2,base:[0,1,2],text:2,serial:1,metadata:1,until:2,transact:[0,1,2,4],presum:2,check:[1,2,4],contain:1,usd:4,ledger_fil:[2,4],creat:2,core:4,suitabl:2,host:1,setup:[],jsonify_except:1,jsondecod:1,arg:[0,2],content:[],command:2,on_show_about_activ:1,etc:4,below:4,donor:1,self:2,virtualenv:4,donat:1,assemble_argu:2,symbol:[0,1,4],insert:4,reverse_transact:2,applic:[],add:4,on_aboutdialog_clos:[],ani:1,response_typ:1,result:2,bal:2,accountin:[],gitori:4,without:2,accountingexcept:[1,2],sinc:2,popen:2,curl:[],txt:4,transaction_id:[1,2],anoth:4,system:4,log:4,meta:0,load_ui:1,unlock:2,version:4,simple_transact:1,"true":[1,2],via:[1,4],prompt:[2,4],git:4,"__type__":1,separ:1,app:[0,2],work:4,manag:2,apt:4,irc:4,accountingencod:1,doe:4,code:4,skipkei:1,autodetect:4,when:2,would:4,purpos:4,bin:4,alreadi:2,mean:4,on_transaction_view_cursor_chang:1,python3:4,exampl:[],debug:[],stdin:2,org:4,can:4,indicate_act:1,freenod:4,on_about_dialog_respons:1,find:2,januari:4,ppa:4,set:[2,4],thi:[1,2,4]},objects:{"":{accounting:[1,0,0,"-"]},"accounting.transport":{AccountingEncoder:[1,2,1,""],AccountingDecoder:[1,2,1,""]},"accounting.storage.sql.models":{Posting:[0,2,1,""],Transaction:[0,2,1,""],Amount:[0,2,1,""]},"accounting.storage.ledgercli":{Ledger:[2,2,1,""],main:[2,5,1,""]},"accounting.gtkclient.AccountingApplication":{on_about_dialog_response:[1,1,1,""],on_transaction_view_cursor_changed:[1,1,1,""],on_transactions_loaded:[1,1,1,""],load_ui:[1,1,1,""],on_transaction_refresh_activate:[1,1,1,""],on_show_about_activate:[1,1,1,""]},"accounting.models.Transaction":{generate_id:[1,1,1,""]},accounting:{storage:[2,0,0,"-"],config:[1,0,0,"-"],decorators:[1,0,0,"-"],web:[1,0,0,"-"],models:[1,0,0,"-"],client:[1,0,0,"-"],exceptions:[1,0,0,"-"],gtkclient:[1,0,0,"-"],transport:[1,0,0,"-"]},"accounting.client":{print_transactions:[1,5,1,""],Client:[1,2,1,""],print_balance_accounts:[1,5,1,""],main:[1,5,1,""]},"accounting.decorators":{jsonify_exceptions:[1,5,1,""]},"accounting.storage.sql.models.Posting":{account:[0,4,1,""],meta:[0,4,1,""],amount:[0,4,1,""],amount_id:[0,4,1,""],transaction_uuid:[0,4,1,""],transaction:[0,4,1,""],as_dict:[0,1,1,""],id:[0,4,1,""]},"accounting.models":{Posting:[1,2,1,""],Account:[1,2,1,""],Transaction:[1,2,1,""],Amount:[1,2,1,""]},"accounting.client.Client":{simple_transaction:[1,1,1,""],post:[1,1,1,""],get:[1,1,1,""],get_register:[1,1,1,""],get_balance:[1,1,1,""]},"accounting.storage.ledgercli.Ledger":{bal:[2,1,1,""],get_process:[2,1,1,""],read_until_prompt:[2,1,1,""],get_transactions:[2,1,1,""],add_transaction:[2,1,1,""],reg:[2,1,1,""],get_transaction:[2,1,1,""],update_transaction:[2,1,1,""],locked_process:[2,1,1,""],send_command:[2,1,1,""],assemble_arguments:[2,1,1,""],delete_transaction:[2,1,1,""],init_process:[2,1,1,""]},"accounting.web":{init_ledger:[1,5,1,""],main:[1,5,1,""],transaction_get:[1,5,1,""],transaction_post:[1,5,1,""],transaction_update:[1,5,1,""],index:[1,5,1,""]},"accounting.storage.sql":{models:[0,0,0,"-"],SQLStorage:[0,2,1,""]},"accounting.storage":{Storage:[2,2,1,""],sql:[0,0,0,"-"],TransactionNotFound:[2,3,1,""],ledgercli:[2,0,0,"-"]},"accounting.storage.sql.SQLStorage":{get_transactions:[0,1,1,""],update_transaction:[0,1,1,""],add_transaction:[0,1,1,""]},"accounting.storage.Storage":{get_transaction:[2,1,1,""],get_account:[2,1,1,""],reverse_transaction:[2,1,1,""],update_transaction:[2,1,1,""],get_accounts:[2,1,1,""],get_transactions:[2,1,1,""],add_transaction:[2,1,1,""]},"accounting.storage.sql.models.Amount":{symbol:[0,4,1,""],as_dict:[0,1,1,""],id:[0,4,1,""],amount:[0,4,1,""]},"accounting.storage.sql.models.Transaction":{uuid:[0,4,1,""],as_dict:[0,1,1,""],payee:[0,4,1,""],meta:[0,4,1,""],date:[0,4,1,""],id:[0,4,1,""]},"accounting.gtkclient":{indicate_activity_done:[1,5,1,""],indicate_activity:[1,5,1,""],AccountingApplication:[1,2,1,""],main:[1,5,1,""]},"accounting.transport.AccountingDecoder":{dict_to_object:[1,1,1,""]},"accounting.transport.AccountingEncoder":{"default":[1,1,1,""]},"accounting.exceptions":{AccountingException:[1,3,1,""]}},titleterms:{sql:0,content:[0,1,2],client:[1,4],config:1,model:[0,1],api:[4,5],ledgercli:2,indic:5,account:[2,4,5,0,1,3],ubuntu:4,packag:[0,1,2],gtkclient:1,modul:[0,1,2],transport:1,usag:4,welcom:5,tabl:5,subpackag:[1,2],web:1,depend:4,decor:1,test:[],document:5,asyncio:[],develop:4,gtk:4,storag:[0,2],except:1,setup:4,instal:4,titl:[],submodul:[0,1,2]}}) \ No newline at end of file +Search.setIndex({objects:{"":{accounting:[4,0,0,"-"]},"accounting.decorators":{jsonify_exceptions:[4,5,1,""]},"accounting.gtkclient.AccountingApplication":{on_transactions_loaded:[4,1,1,""],on_transaction_refresh_activate:[4,1,1,""],on_transaction_view_cursor_changed:[4,1,1,""],load_ui:[4,1,1,""],on_show_about_activate:[4,1,1,""],on_about_dialog_response:[4,1,1,""]},"accounting.models.Transaction":{generate_id:[4,1,1,""]},"accounting.storage.ledgercli.Ledger":{get_transaction:[2,1,1,""],add_transaction:[2,1,1,""],reg:[2,1,1,""],assemble_arguments:[2,1,1,""],get_process:[2,1,1,""],send_command:[2,1,1,""],bal:[2,1,1,""],delete_transaction:[2,1,1,""],update_transaction:[2,1,1,""],read_until_prompt:[2,1,1,""],init_process:[2,1,1,""],get_transactions:[2,1,1,""],locked_process:[2,1,1,""]},"accounting.storage":{TransactionNotFound:[2,4,1,""],Storage:[2,3,1,""],ledgercli:[2,0,0,"-"],sql:[0,0,0,"-"]},accounting:{models:[4,0,0,"-"],web:[4,0,0,"-"],client:[4,0,0,"-"],decorators:[4,0,0,"-"],transport:[4,0,0,"-"],exceptions:[4,0,0,"-"],config:[4,0,0,"-"],storage:[2,0,0,"-"],gtkclient:[4,0,0,"-"]},"accounting.storage.sql":{models:[0,0,0,"-"],SQLStorage:[0,3,1,""]},"accounting.transport.AccountingEncoder":{"default":[4,1,1,""]},"accounting.storage.sql.SQLStorage":{update_transaction:[0,1,1,""],add_transaction:[0,1,1,""],get_transactions:[0,1,1,""]},"accounting.storage.sql.models.Transaction":{date:[0,2,1,""],as_dict:[0,1,1,""],id:[0,2,1,""],payee:[0,2,1,""],meta:[0,2,1,""],uuid:[0,2,1,""]},"accounting.gtkclient":{indicate_activity_done:[4,5,1,""],indicate_activity:[4,5,1,""],main:[4,5,1,""],AccountingApplication:[4,3,1,""]},"accounting.client.Client":{get_register:[4,1,1,""],simple_transaction:[4,1,1,""],post:[4,1,1,""],get_balance:[4,1,1,""],get:[4,1,1,""]},"accounting.storage.sql.models.Amount":{amount:[0,2,1,""],symbol:[0,2,1,""],as_dict:[0,1,1,""],id:[0,2,1,""]},"accounting.client":{print_transactions:[4,5,1,""],Client:[4,3,1,""],print_balance_accounts:[4,5,1,""],main:[4,5,1,""]},"accounting.web":{index:[4,5,1,""],transaction_get:[4,5,1,""],init_ledger:[4,5,1,""],main:[4,5,1,""],transaction_delete:[4,5,1,""],transaction_post:[4,5,1,""],transaction_update:[4,5,1,""]},"accounting.storage.sql.models.Posting":{meta:[0,2,1,""],as_dict:[0,1,1,""],id:[0,2,1,""],account:[0,2,1,""],transaction:[0,2,1,""],amount:[0,2,1,""],amount_id:[0,2,1,""],transaction_uuid:[0,2,1,""]},"accounting.models":{Amount:[4,3,1,""],Transaction:[4,3,1,""],Account:[4,3,1,""],Posting:[4,3,1,""]},"accounting.transport":{AccountingEncoder:[4,3,1,""],AccountingDecoder:[4,3,1,""]},"accounting.storage.sql.models":{Amount:[0,3,1,""],Transaction:[0,3,1,""],Posting:[0,3,1,""]},"accounting.storage.Storage":{get_transaction:[2,1,1,""],get_account:[2,1,1,""],reverse_transaction:[2,1,1,""],update_transaction:[2,1,1,""],get_transactions:[2,1,1,""],add_transaction:[2,1,1,""],delete_transaction:[2,1,1,""],get_accounts:[2,1,1,""]},"accounting.storage.ledgercli":{main:[2,5,1,""],Ledger:[2,3,1,""]},"accounting.exceptions":{AccountingException:[4,4,1,""]},"accounting.transport.AccountingDecoder":{dict_to_object:[4,1,1,""]}},titleterms:{titl:[],decor:4,api:[3,1],depend:3,sql:0,content:[0,4,2],gtk:3,storag:[0,2],instal:3,usag:3,welcom:1,setup:3,model:[0,4],submodul:[0,4,2],test:[],web:4,config:4,ledgercli:2,ubuntu:3,modul:[0,4,2],gtkclient:4,indic:1,tabl:1,subpackag:[4,2],client:[3,4],develop:3,transport:4,packag:[0,4,2],account:[0,1,2,3,4,5],document:1,except:4,asyncio:[]},objnames:{"0":["py","module","Python module"],"1":["py","method","Python method"],"2":["py","attribute","Python attribute"],"3":["py","class","Python class"],"4":["py","exception","Python exception"],"5":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:method","2":"py:attribute","3":"py:class","4":"py:exception","5":"py:function"},envversion:43,titles:["accounting.storage.sql package","Welcome to Accounting API’s documentation!","accounting.storage package","The Accounting API","accounting package","accounting"],filenames:["api/accounting.storage.sql","index","api/accounting.storage","README","api/accounting","api/modules"],terms:{core:3,code:3,contextlib:2,name:4,would:3,sql:[],need:3,incom:4,send_command:2,json:4,within:2,func:4,load:2,found:2,app:[0,2],stdin:2,run:[3,2],argument:2,apt:3,virtualenv:3,jsonify_except:4,yield:2,path:[3,4],parse_json:[],search:1,index:[1,4],method:[3,4,2],amount_id:0,separ:4,handl:2,"_generate_id":4,accountingdecod:4,your:3,should:2,accountingexcept:[4,2],take:[4,2],initi:4,describ:3,section:3,git:3,indicate_activity_don:4,page:1,evalu:2,databas:2,fals:4,"return":[4,2],exampl:[],regist:3,update_transact:[0,2],sort_kei:4,well:3,high:4,make:3,net:3,karma:[],process:2,ensure_ascii:4,ledgercli:[],add_transact:[0,2],version:3,remov:2,npoacct:3,linebreak:[],skipkei:4,statement:2,contextmanag:2,termin:3,simple_transact:4,get_transact:[0,2],context:2,manag:2,debug:[],mkvirtualenv:3,"class":[0,4,2],arg:[0,2],anoth:3,serial:4,balanc:3,mbudd:3,prog:4,unlock:2,instanc:2,payload:4,accountingencod:4,print_transact:4,ledger:[3,4,2],uuid:0,transaction_upd:4,usr:3,get_bal:4,etc:3,blah:[],builtin:[4,2],work:3,request:4,date:[0,4],head:3,ledger_process:2,data:[],x20:2,argv:[4,2],init_process:2,until:2,gitori:3,on_about_dialog_respons:4,logic:4,symbol:[3,0,4],get_account:2,from:[3,2],kindli:4,output:[4,2],get_process:2,jsondecod:4,sourc:[3,0,4,2],transaction_id:[4,2],webservic:4,decod:[],self:2,sudo:3,check_circular:4,current:4,onc:2,currenc:3,"default":4,mean:3,func_or_str:4,python:3,state:4,site:3,donat:4,contain:4,"try":3,environ:3,file:[4,2],usd:3,type:[],simpl:3,balance_report:[],tri:3,post:[0,4],how:3,you:3,januari:3,doe:3,flask_sqlalchemi:0,on_transaction_refresh_activ:4,base:[0,4,2],local:3,creat:2,locked_process:2,metadata:4,"function":3,amount:[0,4],irc:3,banner:2,bound:2,transaction_uuid:0,sinc:2,transaction_delet:4,ppa:3,caller:4,asset:[3,4],conserv:3,pip:3,follow:3,txt:3,annot:4,which:[3,4,2],assemble_argu:2,delet:2,shell:3,check:[3,4,2],requir:[3,4],text:2,"catch":4,insert:3,becom:4,pars:[],sai:3,from_acc:4,ledger_bin:2,discard:2,add:[3,2],on_aboutdialog_clos:[],expens:3,rest:4,recommend:2,wget:[],load_ui:4,out:3,open:2,curl:[],purpos:3,set:[3,2],response_typ:4,combin:2,abc:2,init_ledg:4,before_request:4,subprocess:2,storag:[],main:[4,2],boundari:2,without:2,old:2,avaiabl:3,thi:[3,4,2],ledger_fil:[3,2],transactionnotfound:2,meta:0,json_encod:4,suitabl:2,popen:2,flag:3,get:[3,4],via:[3,4],accountingappl:4,bal:2,generate_id:4,presum:2,pass:2,allow_nan:4,bin:3,servic:3,back:2,want:3,on_transactions_load:4,delete_transact:2,when:2,system:3,freenod:3,json_decod:4,autodetect:3,alreadi:2,list:2,print_balance_account:4,content:[],on_show_about_activ:4,on_transaction_select:[],line:2,channel:3,flask:[3,4],clone:3,to_acc:4,virtualenvwrapp:3,sqlstorag:0,on_refresh_transactions_activ:[],below:3,"__type__":4,transaction_post:4,execut:2,memori:2,applic:[],can:[3,2],serv:3,repositori:3,register_report:[],lock:2,see:3,user:3,ani:4,report:3,also:3,host:4,object:[4,2],end:3,yet:3,accountin:[],transact:[3,0,4,2],paye:[0,4],mode:2,all:[3,2],jsonencod:4,wrap:4,runtimeerror:2,clariti:[],org:3,reg:[4,2],python3:3,none:[0,4,2],command:2,went:3,read_until_prompt:2,http:[],reverse_transact:2,write:[4,2],donor:4,as_dict:0,rent:3,endpoint:4,get_regist:4,"true":[4,2],widget:4,level:4,hello:4,setup:[],have:3,look:2,world:4,foo:4,prompt:[3,2],workon:3,read:2,indicate_act:4,kwarg:0,result:2,dict_to_object:4,on_transaction_view_cursor_chang:4,"new":2,transaction_get:4,updat:[3,2],indent:4,them:2,find:2,log:3}}) \ No newline at end of file