feat(usecase): Implement account Update usecase

parent 006e31b4
Pipeline #822 passed with stages
in 5 minutes and 10 seconds
......@@ -88,10 +88,10 @@ class Memory(storages.Storage):
self._accounts = {}
self._operations = {}
def register_account(self, account):
def register_account(self, account, force=False):
logger.get().info('Register new account %r', account)
logger.get().debug('%r', self._accounts)
if account.ident in self._accounts:
if not force and account.ident in self._accounts:
logger.get().error('Already registered account %s', account.ident)
raise exceptions.Conflict('Memory-Storage', account)
self._accounts[account.ident] = account
......
......@@ -27,12 +27,15 @@ class Storage(metaclass=abc.ABCMeta):
"""
@abc.abstractmethod
def register_account(self, account):
def register_account(self, account, force=False):
"""
Store a new account in repository
:param account: Account to register
:type account: ``openbudget.core.domain.accounts.Account``
:param force: Force account registering by updating all field of
account.
:type force: ``bool``
:raises openbudget.core.exceptions.Conflict: When account is already
stored in repository.
......
......@@ -327,3 +327,30 @@ class UpdateRequest(base.ValidRequest):
account['initialbalance'] = self.initialbalance
return account
class Update(base.UseCaseBase):
"""
Usecase to allow account modification
"""
@base.safe_exec
def execute(self, request):
self._log.debug('Execute update')
if not request:
return base.ResponseFailure.build_from_invalid_request(request)
self._log.debug('Update account from request %s', request)
updated_list = []
required_account = self._repo.get_account(request.ident).to_dict()
self._log.info('Found accout to update: %r', required_account)
for key, value in request.to_dict().items():
if key != 'ident':
self._log.info('Set %s with %r', key, value)
required_account[key] = value
updated_list.append(key)
self._log.debug('Force register account')
self._repo.register_account(
accounts.Account.from_dict(required_account),
force=True
)
return base.ResponseSuccess(updated_list)
......@@ -25,6 +25,30 @@ import os
import uuid
import pytest
from openbudget.core import logger
@pytest.fixture(scope='session', autouse=True)
def set_log_level(request):
"""
Configure OpenBudget Logger to display all traces
"""
if request.config.getoption('--log'):
logger.configure_logger({
'level': 'debug',
'verbose': 'true',
'color': 'true'
})
def pytest_addoption(parser):
"""
Understand `--log` option to PyTest to enable openbudget logs
"""
parser.addoption(
"--log", action='store_true'
)
@pytest.fixture
def clean_local_file():
......
......@@ -110,6 +110,19 @@ def test_accounts_registration_conflict(single_account):
single_account['memory'].register_account(single_account['account'])
def test_accounts_registration_force_update(single_account):
"""
Generate conflict when registering a new account
"""
single_account['account'].label = 'Updated Label'
single_account['memory'].register_account(
single_account['account'], force=True
)
assert single_account['memory'].get_account(
single_account['account'].ident
).label == 'Updated Label'
def test_single_operation_registering(single_account):
"""
Register a new operation and retriev it
......
......@@ -319,3 +319,80 @@ def test_account_delete_invalid_request(ucdelete):
assert not bool(response)
repo.delete_account.assert_not_called()
@pytest.fixture
def ucupdate(repo):
"""
Build a UseCase Update tight to repo
"""
ucupdate = ucaccount.Update(repo)
stored_account = mock.MagicMock()
stored_account.ident = 'MyAccount'
yield repo, ucupdate, stored_account
def test_account_update_valid_request(ucupdate):
"""
Use case to update account
"""
repo, uc_update, account = ucupdate
repo.get_account.return_value.to_dict.return_value = {
'ident': account.ident,
'label': 'foobar'
}
request = mock.MagicMock()
request.__bool__.return_value = True
request.to_dict.return_value = {
'ident': account.ident,
'label': 'new_label'
}
with mock.patch('openbudget.core.domains.accounts.Account') as mock_acc:
response = uc_update.execute(request)
repo.register_account.assert_called_with(
mock_acc.from_dict.return_value, force=True
)
mock_acc.from_dict.assert_called_with({'ident': account.ident,
'label': 'new_label'})
repo.get_account.assert_called_with(request.ident)
assert bool(response)
assert response.value == ['label']
def test_account_update_invalid_request(ucupdate):
"""
Use case to update account but with invalid request
"""
repo, uc_update, _account = ucupdate
request = mock.MagicMock()
request.__bool__.return_value = False
response = uc_update.execute(request)
assert not bool(response)
repo.register_account.assert_not_called()
repo.get_account.assert_not_called()
def test_account_not_found(ucupdate):
"""
Use case to update account on unknown request
"""
repo, uc_update, _account = ucupdate
request = mock.MagicMock()
request.__bool__.return_value = True
repo.get_account.side_effect = exceptions.ItemNotFound
response = uc_update.execute(request)
assert not bool(response)
repo.register_account.assert_not_called()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment