[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:
|
||||
return func(*args, **kw)
|
||||
except AccountingException as exc:
|
||||
return jsonify(error=exc)
|
||||
response = jsonify(error=exc)
|
||||
|
||||
response.status_code = exc.http_code
|
||||
|
||||
return response
|
||||
|
||||
return wrapper
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ class AccountingException(Exception):
|
|||
Used as a base for exceptions that are returned to the caller via the
|
||||
jsonify_exceptions decorator
|
||||
'''
|
||||
http_code = 500
|
||||
def __init__(self, message, **kw):
|
||||
self.message = message
|
||||
for key, value in kw.items():
|
||||
|
@ -14,12 +15,12 @@ class AccountingException(Exception):
|
|||
|
||||
|
||||
class TransactionNotFound(AccountingException):
|
||||
pass
|
||||
http_code = 404
|
||||
|
||||
|
||||
class LedgerNotBalanced(AccountingException):
|
||||
pass
|
||||
http_code = 400
|
||||
|
||||
|
||||
class TransactionIDCollision(AccountingException):
|
||||
pass
|
||||
http_code = 400
|
||||
|
|
|
@ -173,6 +173,18 @@ class Ledger(Storage):
|
|||
with open(self.ledger_file, 'ab') as f:
|
||||
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)
|
||||
|
||||
_log.info('Added transaction %s', transaction.id)
|
||||
|
|
|
@ -9,6 +9,7 @@ import copy
|
|||
import uuid
|
||||
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
from flask import json
|
||||
|
||||
|
@ -17,7 +18,7 @@ from accounting.web import app, init_ledger
|
|||
from accounting.transport import AccountingEncoder, AccountingDecoder
|
||||
from accounting.models import Transaction, Posting, Amount
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
#logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
|
||||
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__':
|
||||
|
|
|
@ -44,7 +44,8 @@ class AccountingEncoder(json.JSONEncoder):
|
|||
elif isinstance(o, AccountingException):
|
||||
return dict(
|
||||
type=o.__class__.__name__,
|
||||
message=o.message
|
||||
message=o.message,
|
||||
transaction=getattr(o, 'transaction', None)
|
||||
)
|
||||
|
||||
return json.JSONEncoder.default(self, o)
|
||||
|
|
Loading…
Reference in a new issue