[tests] Check transactions for errors before being added
- Added support for Exception-specific HTTP response codes for AccountinExceptions.
This commit is contained in:
parent
ef12c232ad
commit
8abbe3462f
5 changed files with 52 additions and 10 deletions
|
@ -19,7 +19,11 @@ def jsonify_exceptions(func):
|
||||||
try:
|
try:
|
||||||
return func(*args, **kw)
|
return func(*args, **kw)
|
||||||
except AccountingException as exc:
|
except AccountingException as exc:
|
||||||
return jsonify(error=exc)
|
response = jsonify(error=exc)
|
||||||
|
|
||||||
|
response.status_code = exc.http_code
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ class AccountingException(Exception):
|
||||||
Used as a base for exceptions that are returned to the caller via the
|
Used as a base for exceptions that are returned to the caller via the
|
||||||
jsonify_exceptions decorator
|
jsonify_exceptions decorator
|
||||||
'''
|
'''
|
||||||
|
http_code = 500
|
||||||
def __init__(self, message, **kw):
|
def __init__(self, message, **kw):
|
||||||
self.message = message
|
self.message = message
|
||||||
for key, value in kw.items():
|
for key, value in kw.items():
|
||||||
|
@ -14,12 +15,12 @@ class AccountingException(Exception):
|
||||||
|
|
||||||
|
|
||||||
class TransactionNotFound(AccountingException):
|
class TransactionNotFound(AccountingException):
|
||||||
pass
|
http_code = 404
|
||||||
|
|
||||||
|
|
||||||
class LedgerNotBalanced(AccountingException):
|
class LedgerNotBalanced(AccountingException):
|
||||||
pass
|
http_code = 400
|
||||||
|
|
||||||
|
|
||||||
class TransactionIDCollision(AccountingException):
|
class TransactionIDCollision(AccountingException):
|
||||||
pass
|
http_code = 400
|
||||||
|
|
|
@ -173,6 +173,18 @@ class Ledger(Storage):
|
||||||
with open(self.ledger_file, 'ab') as f:
|
with open(self.ledger_file, 'ab') as f:
|
||||||
f.write(output)
|
f.write(output)
|
||||||
|
|
||||||
|
# Check to see that no errors were introduced
|
||||||
|
try:
|
||||||
|
self.get_transactions()
|
||||||
|
except AccountingException as exc:
|
||||||
|
# TODO: Do a hard reset on the repository using Repository.reset,
|
||||||
|
# this is on hold because of
|
||||||
|
# https://github.com/libgit2/pygit2/issues/271.
|
||||||
|
# This solution will work in the meantime
|
||||||
|
self.delete_transaction(transaction.id)
|
||||||
|
setattr(exc, 'transaction', transaction)
|
||||||
|
raise exc
|
||||||
|
|
||||||
self.commit_changes('Added transaction %s' % transaction.id)
|
self.commit_changes('Added transaction %s' % transaction.id)
|
||||||
|
|
||||||
_log.info('Added transaction %s', transaction.id)
|
_log.info('Added transaction %s', transaction.id)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import copy
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
from flask import json
|
from flask import json
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ from accounting.web import app, init_ledger
|
||||||
from accounting.transport import AccountingEncoder, AccountingDecoder
|
from accounting.transport import AccountingEncoder, AccountingDecoder
|
||||||
from accounting.models import Transaction, Posting, Amount
|
from accounting.models import Transaction, Posting, Amount
|
||||||
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
#logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
|
|
||||||
class TransactionTestCase(unittest.TestCase):
|
class TransactionTestCase(unittest.TestCase):
|
||||||
|
@ -263,13 +264,36 @@ class TransactionTestCase(unittest.TestCase):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
self._post_json('/transaction', transaction)
|
response = self._post_json('/transaction', transaction, expect=400)
|
||||||
|
|
||||||
response = self._get_json('/transaction')
|
self.assertEqual(response['error']['type'], 'LedgerNotBalanced')
|
||||||
|
|
||||||
import pdb; pdb.set_trace()
|
def test_update_transaction_amounts(self):
|
||||||
|
transaction = self._add_simple_transaction()
|
||||||
|
response = self._get_json(
|
||||||
|
'/transaction/' + transaction.id)
|
||||||
|
|
||||||
def test_update_transaction_amounts(self): pass
|
transaction = response['transaction']
|
||||||
|
|
||||||
|
for posting in transaction.postings:
|
||||||
|
posting.amount.amount *= Decimal(1.50)
|
||||||
|
|
||||||
|
response = self._post_json('/transaction/' + transaction.id,
|
||||||
|
{'transaction': transaction})
|
||||||
|
|
||||||
|
self.assertEqual(response['status'], 'OK')
|
||||||
|
|
||||||
|
response = self._get_json('/transaction/' + transaction.id)
|
||||||
|
|
||||||
|
self.assertEqual(response['transaction'], transaction)
|
||||||
|
|
||||||
|
def test_delete_nonexistent_transaction(self):
|
||||||
|
response = self._open_json('DELETE', '/transaction/I-do-not-exist',
|
||||||
|
expect=404)
|
||||||
|
|
||||||
|
self.assertEqual(response['error']['type'], 'TransactionNotFound')
|
||||||
|
|
||||||
|
def test_post_transaction_with_metadata(self): pass
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -44,7 +44,8 @@ class AccountingEncoder(json.JSONEncoder):
|
||||||
elif isinstance(o, AccountingException):
|
elif isinstance(o, AccountingException):
|
||||||
return dict(
|
return dict(
|
||||||
type=o.__class__.__name__,
|
type=o.__class__.__name__,
|
||||||
message=o.message
|
message=o.message,
|
||||||
|
transaction=getattr(o, 'transaction', None)
|
||||||
)
|
)
|
||||||
|
|
||||||
return json.JSONEncoder.default(self, o)
|
return json.JSONEncoder.default(self, o)
|
||||||
|
|
Loading…
Reference in a new issue