15 Commits

Author SHA1 Message Date
f10b39a3ba Update test data 2022-11-25 23:03:43 +13:00
bbd2083109 Added exception to catch rate-limiting. 2022-09-13 14:47:48 +12:00
2c6c1f6f34 v1.0.3 2022-06-26 07:57:43 +12:00
d06b7d0a76 static version 2022-05-30 15:32:58 +12:00
c92fb0d1ee Added create transfer 2022-05-30 15:21:14 +12:00
96d4523ef4 Add test to cover all lines 2022-05-27 23:13:37 +12:00
d57798a9c0 refactor a little 2022-05-27 23:11:18 +12:00
88f161082d Remove debug responses 2022-05-27 23:01:23 +12:00
e0e803f1a7 Added setuptools_scm to requirements 2022-05-27 23:00:35 +12:00
6a03577605 Added exception for AccountNotFound 2022-05-27 22:19:17 +12:00
7eaf7c99dd Added default currency_code and currency_rate 2022-05-27 21:54:08 +12:00
409ea90a4b Added test for searching account 2022-05-26 22:39:45 +12:00
d7f4e25830 Updated requirements 2022-05-16 16:05:58 +12:00
db70f981ad Updated working environment to virtualenv 2022-05-16 15:24:08 +12:00
af0c6b504f Use scm for versioning 2022-05-16 14:48:53 +12:00
19 changed files with 491 additions and 116 deletions

8
.gitignore vendored
View File

@@ -6,6 +6,14 @@ __pycache__
.coverage .coverage
coverage.xml coverage.xml
# distribution files
dist/
*egg-info/
# Ignore Scratch files # Ignore Scratch files
scratch/* scratch/*
!/scratch/README.md !/scratch/README.md
# Ignore virtualenv
.venv
venv

8
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

16
.idea/akaunting-py.iml generated Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" />
<excludeFolder url="file://$MODULE_DIR$/.pytest_cache" />
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
</module>

View File

@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

4
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (akaunting-py)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/akaunting-py.iml" filepath="$PROJECT_DIR$/.idea/akaunting-py.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -1,2 +1,4 @@
from akauntingpy.api import Client from akauntingpy.api import Client
from akauntingpy.exceptions import * from akauntingpy.exceptions import *
__version__ = '1.0.0'

View File

@@ -1,63 +1,79 @@
import requests import requests
import json gimport logging
from requests.auth import HTTPBasicAuth from requests.auth import HTTPBasicAuth
from akauntingpy import exceptions from akauntingpy import exceptions
from akauntingpy.helpers import * from akauntingpy.helpers import *
__version__ = "1.0.5"
logger = logging.getLogger(__name__)
class Client(object): class Client(object):
""" """
Akaunting interface. Akaunting interface.
""" """
def __init__( def __init__(
self, self,
url, url,
username, username,
password, password,
company_id): company_id,
ssl_verify=True,
currency_code="NZD",
currency_rate="1.0"):
""" """
Create a new instance. Create a new instance.
Args: Args:
url (str): The URL to the Akaunting api. url (str): The URL to the Akaunting api. ** required **
username (str): The username of the Akaunting credentials. username (str): The username of the Akaunting credentials. ** required **
password (str): The password of the Akaunting credentials. password (str): The password of the Akaunting credentials. ** required **
company_id (str): The company ID from Akaunting
currency_code (str): The currency code. default is NZD
currency_rate (str): The currency rate. default is "1.0"
""" """
self.url = url self.url = url
self.ssl_verify = ssl_verify
self.authentication = HTTPBasicAuth(username, password) self.authentication = HTTPBasicAuth(username, password)
self.headers = { self.headers = {
'User-Agent': 'AkauntingPy 1.0', 'User-Agent': 'AkauntingPy v' + __version__,
} }
self.company_id = company_id self.company_id = company_id
self.default_params = {'company_id': company_id} self.default_params = {'company_id': company_id}
self.currency_code = currency_code
self.currency_rate = currency_rate
def call(self, method="get", endpoint=None, def call(self, method="get", endpoint=None,
**params) -> dict(): **params) -> dict:
response = None
response = requests.request(method=method, response = requests.request(method=method,
url=self.url + "/" + endpoint, url=self.url + "/" + endpoint,
headers=self.headers, headers=self.headers,
auth=self.authentication, auth=self.authentication,
params=MergeDict(self.default_params, params) params=MergeDict(self.default_params, params),
verify=self.ssl_verify
) )
print(response)
response_ = response.json() response_ = response.json()
print(response_)
if response.status_code == 401: if response.status_code == 401:
raise exceptions.MissingPermission(response_['message']) raise exceptions.MissingPermission(response_['message'])
elif response.status_code == 422: elif response.status_code == 422:
errors = [] errors = []
for key in response_['errors']: for key in response_['errors']:
errors.append(RemoveFromString(["<strong>","</strong>"], errors.append(RemoveFromString(["<strong>", "</strong>"],
response_['errors'][key][0]) response_['errors'][key][0])
+ " (" + key + ")") + " (" + key + ")")
raise exceptions.InvalidData(response_['message'] + raise exceptions.InvalidData(response_['message'] +
"\n" + "\n" +
"\n".join(errors)) "\n".join(errors))
# elif response.status_code != 200 and response.status_code != 201: # elif response.status_code != 200 and response.status_code != 201:
# raise exceptions.Error(response_['message']) # raise exceptions.Error(response_['message'])
elif response.status_code == 429:
# We hit the maximum requests
raise exceptions.TooManyAttempts(response_['message'])
return response_ return response_
def ping(self): def ping(self):
@@ -65,30 +81,73 @@ class Client(object):
return data return data
def get_accounts(self, **params): def get_accounts(self, **params):
data = self.call(endpoint="accounts") data = self.call(endpoint="accounts", **params)
if params.get('search', False):
# Check if there is an account returned
try:
if data['meta']['pagination'].get('count') == 0:
# No account found
raise exceptions.AccountNotFound("Sorry, account not found matching search parameters: %s".format(
params.get('search')
))
except KeyError as e:
# New API 3.0
if data['meta']['total'] == 0:
raise exceptions.AccountNotFound("Sorry, account not found matching search parameters: %s".format(
params.get('search')
))
return data['data']
def get_contact(self, **params):
data = self.call(endpoint="contacts", **params)
print(data)
if params.get('search', False):
try:
# Check if there is an account returned
if data['meta']['pagination'].get('count') == 0:
# No account found
raise exceptions.AccountNotFound("Sorry, contact not found matching search parameters: %s".format(
params.get('search')
))
except KeyError as e:
# New API 3.0
if data['meta']['total'] == 0:
raise exceptions.AccountNotFound("Sorry, contact not found matching search parameters: %s".format(
params.get('search')
))
return data['data'] return data['data']
def create_transaction(self, def create_transaction(self,
type='income', # Payment method type transaction_type='income', # Payment method type
account_id=None, # Account ID to assign account_id=None, # Account ID to assign
category_id=None, # Category ID to assign number="NULL", # Transaction number
contact_id=None, # Contact ID/Client to assign category_id=None, # Category ID to assign
description=None, # Description contact_id=None, # Contact ID/Client to assign
paid_at=None, # Date of expense/transfer or income description=None, # Description
reference=None, # Reference for the payment paid_at=None, # Date of expense/transfer or income
payment_method=None, # Payment method reference=None, # Reference for the payment
currency_code=None, # Currency code payment_method=None, # Payment method
currency_rate=None, # Currency rate currency_code=None, # Currency code
amount=None, # Amount received/paid currency_rate=None, # Currency rate
**params # Any additional parameters amount=None, # Amount received/paid
): **params # Any additional parameters
):
if currency_code is None:
# Set default value from class
currency_code = self.currency_code
if currency_rate is None:
# Set default value from class
currency_rate = self.currency_rate
data = self.call(endpoint="transactions", data = self.call(endpoint="transactions",
method="POST", method="POST",
search="type:" + type, search="type:" + transaction_type,
type=type, number=number,
type=transaction_type,
account_id=account_id, account_id=account_id,
category_id=category_id, category_id=category_id,
paid_at=paid_at, paid_at=paid_at,
@@ -97,8 +156,34 @@ class Client(object):
reference=reference, reference=reference,
currency_code=currency_code, currency_code=currency_code,
currency_rate=currency_rate, currency_rate=currency_rate,
amount=amount, amount=EnsurePositiveInteger(amount),
description=description, description=description,
**params **params
) )
return data return data
def create_transfer(self,
from_account_id=None, # Account ID to create transfer from
to_account_id=None, # Account ID to create transfer to
transferred_at=None, # Date of expense/transfer or income
payment_method="Bank Transfer", # Payment method
amount=None, # Amount received/paid
**params # Any additional parameters
):
logger.info("Transfer called with parameters")
logger.info("from_account_id: %s", from_account_id)
logger.info("to_account_id: %s", to_account_id)
logger.info("transferred_at: %s", transferred_at)
logger.info("payment_method: %s", payment_method)
logger.info("amount: %s", amount)
data = self.call(endpoint="transfers",
method="POST",
from_account_id=from_account_id,
to_account_id=to_account_id,
transferred_at=transferred_at,
payment_method=payment_method,
amount=EnsurePositiveInteger(amount),
**params
)
return data

View File

@@ -18,3 +18,27 @@ class InvalidData(Error):
Args: Args:
Error (_type_): _description_ Error (_type_): _description_
""" """
class AccountNotFound(Error):
"""
Account not found
Args:
Error (_type_): _description_
"""
class ContactNotFound(Error):
"""
Account not found
Args:
Error (_type_): _description_
"""
class TooManyAttempts(Error):
"""
Too Many attempts to API
Args:
Error (_type_): _description_
"""

View File

@@ -7,3 +7,6 @@ def RemoveFromString(items, string):
for item in items: for item in items:
string = string.replace(item, '') string = string.replace(item, '')
return string return string
def EnsurePositiveInteger(number):
return float(number) if float(number) > 0 else (float(number) * -1)

View File

@@ -0,0 +1,17 @@
{
"data":{
"id":2,
"company_id":1,
"from_account":"Some Account",
"from_account_id":1,
"to_account":"Some Account New",
"to_account_id":2,
"paid_at":"2022-05-16T11:57:51+12:00",
"amount":100,
"amount_formatted":"$100.00",
"currency_code":"NZD",
"created_by":1,
"created_at":"2022-05-16T11:57:51+12:00",
"updated_at":"2022-05-16T11:57:51+12:00"
}
}

View File

@@ -0,0 +1,34 @@
{
"data":[
{
"id":2,
"company_id":1,
"name":"Some Account",
"number":"00-0000-0000000-00",
"currency_code":"NZD",
"opening_balance":0,
"opening_balance_formatted":"$0.00",
"current_balance":100,
"current_balance_formatted":"$100.00",
"bank_name":"A Bank",
"bank_phone":"None",
"bank_address":"None",
"enabled":true,
"created_by":1,
"created_at":"2022-05-13T16:16:16+12:00",
"updated_at":"2022-05-13T16:16:16+12:00"
}
],
"meta":{
"pagination":{
"total":1,
"count":1,
"per_page":25,
"current_page":1,
"total_pages":1,
"links":{
}
}
}
}

View File

@@ -0,0 +1,15 @@
{
"data":[],
"meta":{
"pagination":{
"total":0,
"count":0,
"per_page":25,
"current_page":0,
"total_pages":0,
"links":{
}
}
}
}

View File

@@ -0,0 +1,56 @@
{
"data":[
{
"id":2,
"company_id":1,
"type":"bank",
"name":"Some Account",
"number":"00-0000-0000000-00",
"currency_code":"NZD",
"opening_balance":351.17,
"opening_balance_formatted":"$351.17",
"current_balance":306.3600000000006,
"current_balance_formatted":"$306.36",
"bank_name":"None",
"bank_phone":"None",
"bank_address":"None",
"enabled":true,
"created_from":"core::ui",
"created_by":1,
"created_at":"2022-05-30T11:06:21+12:00",
"updated_at":"2022-05-30T11:10:47+12:00"
}
],
"links":{
"first":"https://someakaunting-url/api/accounts?page=1",
"last":"https://someakaunting-url/api/accounts?page=1",
"prev":"None",
"next":"None"
},
"meta":{
"current_page":1,
"from":1,
"last_page":1,
"links":[
{
"url":"None",
"label":"Previous",
"active":false
},
{
"url":"https://someakaunting-url/api/accounts?page=1",
"label":"1",
"active":true
},
{
"url":"None",
"label":"Next",
"active":false
}
],
"path":"https://someakaunting-url/api/accounts",
"per_page":100,
"to":1,
"total":1
}
}

View File

@@ -0,0 +1,13 @@
{
"data":[],
"meta":{
"total":0,
"count":0,
"per_page":100,
"current_page":0,
"total_pages":0,
"links":{
}
}
}

View File

@@ -1,2 +1,5 @@
requests >= 2.21.0 requests ~= 2.27.0
pytest requests-mock ~= 1.9.3
pytest ~= 7.1.2
pytest-cov ~= 3.0
setuptools-scm ~= 6.4.2

View File

@@ -6,22 +6,22 @@ with open('README.md', 'r') as readme:
long_description = readme.read() long_description = readme.read()
version = '0.0.1'
setup( setup(
name='akauntingpy', name='akaunting-py',
version=version, use_scm_version=True,
author='CyberCinch', author='CyberCinch',
description='Python interface to the Akaunting API.', description='Python interface to the Akaunting API.',
url='https://github.com/cybercinch/akaunting-py', url='https://github.com/cybercinch/akaunting-py',
long_description=long_description, long_description=long_description,
long_description_content_type='text/markdown', long_description_content_type='text/markdown',
license='MIT', license='MIT',
version='1.0.5',
keywords='akaunting api library', keywords='akaunting api library',
packages=find_packages(), packages=find_packages(),
install_requires=[ install_requires=[
'requests >= 2.21.0', 'requests >= 2.21.0',
'setuptools-scm >= 6.4.2'
], ],
classifiers=[ classifiers=[
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
@@ -29,8 +29,8 @@ setup(
'Operating System :: OS Independent', 'Operating System :: OS Independent',
], ],
command_options={ command_options={
'build_sphinx': { # 'build_sphinx': {
'version': ('setup.py', version), # 'version': ('setup.py', version),
}, # },
}, },
) )

View File

@@ -1,51 +1,51 @@
import sys import sys
from this import d
sys.path.insert(1, '.') sys.path.insert(1, '.')
import pytest from helpers import RetrieveJSONFromFile
import akauntingpy import akauntingpy
from akauntingpy.exceptions import * from akauntingpy.exceptions import *
from helpers import RetrieveJSONFromFile import pytest
from requests.auth import HTTPBasicAuth from requests.auth import HTTPBasicAuth
class TestAPI: class TestAPI:
@pytest.fixture() @pytest.fixture()
def setUp(self): def setUp(self):
c = akauntingpy.Client("https://akaunting.guise.net.nz/api", c = akauntingpy.Client("https://someakaunting-url/api",
"aaron@guise.net.nz", "some-emailaddress@somewhere.com",
"L3Tm31N0w", "aPassWord",
1) 1)
yield c yield c
@pytest.fixture() @pytest.fixture()
def setUpFailed(self): def setUpFailed(self):
c = akauntingpy.Client("https://akaunting.guise.net.nz/api", c = akauntingpy.Client("https://someakaunting-url/api",
"aaron@guise.net.nz", "some-emailaddress@somewhere.com",
"L3Tm31N0w1", "aWrongPassWord",
1) 1)
yield c yield c
def test_init(self, setUp): def test_init(self, setUp):
c = setUp c = setUp
assert isinstance(c, akauntingpy.Client) assert isinstance(c, akauntingpy.Client)
assert c.url == "https://akaunting.guise.net.nz/api" assert c.url == "https://someakaunting-url/api"
assert isinstance(c.authentication, HTTPBasicAuth) assert isinstance(c.authentication, HTTPBasicAuth)
def test_ping_success(self, setUp, requests_mock): def test_ping_success(self, setUp, requests_mock):
c = setUp c = setUp
requests_mock.get(c.url + '/ping', requests_mock.get(c.url + '/ping',
json=RetrieveJSONFromFile("data/pingSuccess.json"), json=RetrieveJSONFromFile("data/pingSuccess.json"),
status_code=200) status_code=200)
data = c.ping() data = c.ping()
# The returned data should have status = ok # The returned data should have status = ok
assert data['status'] == 'ok' assert data['status'] == 'ok'
def test_ping_failed(self, setUpFailed, requests_mock): def test_ping_failed(self, setUpFailed, requests_mock):
c = setUpFailed c = setUpFailed
requests_mock.get(c.url + '/ping', requests_mock.get(c.url + '/ping',
json=RetrieveJSONFromFile("data/pingFailure.json"), json=RetrieveJSONFromFile("data/pingFailure.json"),
status_code=401) status_code=401)
with pytest.raises(MissingPermission, match="Invalid credentials."): with pytest.raises(MissingPermission, match="Invalid credentials."):
data = c.ping() data = c.ping()
assert data['status_code'] == 401 assert data['status_code'] == 401
@@ -55,23 +55,49 @@ class TestAPI:
json=RetrieveJSONFromFile("data/GetAccountsList.json")) json=RetrieveJSONFromFile("data/GetAccountsList.json"))
data = c.get_accounts(params={'page': 1, 'limit': 200}) data = c.get_accounts(params={'page': 1, 'limit': 200})
def test_get_account_search_v2(self, setUp, requests_mock):
c = setUp
requests_mock.get(c.url + "/accounts?search=number%3A00-0000-0000000-00&params=page&params=limit&company_id=1",
json=RetrieveJSONFromFile("data/v2/GetAccountsSearch.json"))
data = c.get_accounts(search="number:00-0000-0000000-00", params={'page': 1, 'limit': 200})
def test_get_account_search_v3(self, setUp, requests_mock):
c = setUp
requests_mock.get(c.url + "/accounts?search=number%3A00-0000-0000000-00&params=page&params=limit&company_id=1",
json=RetrieveJSONFromFile("data/v3/GetAccountsSearch.json"))
data = c.get_accounts(search="number:00-0000-0000000-00", params={'page': 1, 'limit': 200})
def test_get_account_search_not_found_v2(self, setUp, requests_mock):
c = setUp
requests_mock.get(c.url + "/accounts?search=number%3Aarandomvalue&company_id=1",
json=RetrieveJSONFromFile("data/v2/GetAccountsSearchNotFound.json"))
with pytest.raises(AccountNotFound):
data = c.get_accounts(search="number:arandomvalue")
def test_get_account_search_not_found_v3(self, setUp, requests_mock):
c = setUp
requests_mock.get(c.url + "/accounts?search=number%3Aarandomvalue&company_id=1",
json=RetrieveJSONFromFile("data/v3/GetAccountsSearchNotFound.json"))
with pytest.raises(AccountNotFound):
data = c.get_accounts(search="number:arandomvalue")
def test_create_transaction_income_success(self, setUp, requests_mock, def test_create_transaction_income_success(self, setUp, requests_mock,
type='income', # Payment method type transaction_type='income', # Payment method type
account_id=2, # Account ID to assign account_id=2, # Account ID to assign
category_id=3, # Category ID to assign category_id=3, # Category ID to assign
contact_id=None, # Contact ID/Client to assign contact_id=None, # Contact ID/Client to assign
paid_at="2022-05-15", # Date of expense/transfer or income paid_at="2022-05-15", # Date of expense/transfer or income
reference=None, # Reference for the payment reference=None, # Reference for the payment
payment_method="bank_transfer", # Payment method payment_method="bank_transfer", # Payment method
currency_code="NZD", # Currency code currency_code="NZD", # Currency code
currency_rate=1, # Currency rate currency_rate=1, # Currency rate
amount="25.00", # Amount received/paid amount="25.00", # Amount received/paid
): ):
c = setUp c = setUp
requests_mock.post(c.url + "/transactions", requests_mock.post(c.url + "/transactions",
json=RetrieveJSONFromFile("data/CreateTransactionIncomeSuccess.json"), json=RetrieveJSONFromFile("data/CreateTransactionIncomeSuccess.json"),
status_code=201) status_code=201)
data = c.create_transaction(type=type, data = c.create_transaction(transaction_type=transaction_type,
account_id=account_id, account_id=account_id,
category_id=category_id, category_id=category_id,
paid_at=paid_at, paid_at=paid_at,
@@ -84,17 +110,43 @@ class TestAPI:
description="Some description of the transaction" description="Some description of the transaction"
) )
def test_create_transaction_income_failed(self, setUp, requests_mock, def test_create_transaction_income_default_currency_success(self, setUp, requests_mock,
contact_id=None, # Contact ID/Client to assign transaction_type='income', # Payment method type
reference=None, # Reference for the payment account_id=2, # Account ID to assign
currency_code="NZD", # Currency code category_id=3, # Category ID to assign
currency_rate=1, # Currency rate contact_id=None, # Contact ID/Client to assign
amount="25.00", # Amount received/paid paid_at="2022-05-15",
): # Date of expense/transfer or income
reference=None, # Reference for the payment
payment_method="bank_transfer", # Payment method
amount="25.00", # Amount received/paid
):
c = setUp c = setUp
requests_mock.post(c.url + "/transactions", requests_mock.post(c.url + "/transactions",
json=RetrieveJSONFromFile("data/CreateTransactionIncomeFailed.json"), json=RetrieveJSONFromFile("data/CreateTransactionIncomeSuccess.json"),
status_code=422) status_code=201)
data = c.create_transaction(transaction_type=transaction_type,
account_id=account_id,
category_id=category_id,
paid_at=paid_at,
contact_id=contact_id,
payment_method=payment_method,
reference=reference,
amount=amount,
description="Some description of the transaction"
)
def test_create_transaction_income_failed(self, setUp, requests_mock,
contact_id=None, # Contact ID/Client to assign
reference=None, # Reference for the payment
currency_code="NZD", # Currency code
currency_rate=1, # Currency rate
amount="25.00", # Amount received/paid
):
c = setUp
requests_mock.post(c.url + "/transactions",
json=RetrieveJSONFromFile("data/CreateTransactionIncomeFailed.json"),
status_code=422)
with pytest.raises(InvalidData, match="The given data was invalid.*"): with pytest.raises(InvalidData, match="The given data was invalid.*"):
data = c.create_transaction(contact_id=contact_id, data = c.create_transaction(contact_id=contact_id,
reference=reference, reference=reference,
@@ -106,10 +158,10 @@ class TestAPI:
def test_create_transaction_expense_success(self, setUp, requests_mock): def test_create_transaction_expense_success(self, setUp, requests_mock):
c = setUp c = setUp
requests_mock.post(c.url + "/transactions", requests_mock.post(c.url + "/transactions?search=type%3Aexpense&type=expense&account_id=3&category_id=4&paid_at=2022-05-16&payment_method=Bank+Transfer&currency_code=NZD&currency_rate=1&amount=100.0&description=Some+expenditures&company_id=1",
json=RetrieveJSONFromFile("data/CreateTransactionExpenseSuccess.json"), json=RetrieveJSONFromFile("data/CreateTransactionExpenseSuccess.json"),
status_code=201) status_code=201)
data = c.create_transaction(type="expense", data = c.create_transaction(transaction_type="expense",
amount=100.00, amount=100.00,
account_id=3, account_id=3,
paid_at="2022-05-16", paid_at="2022-05-16",
@@ -120,3 +172,18 @@ class TestAPI:
description="Some expenditures" description="Some expenditures"
) )
def test_create_transfer_success(self, setUp, requests_mock):
c = setUp
requests_mock.post(c.url + "/transfers",
json=RetrieveJSONFromFile("data/CreateTransferSuccess.json"),
status_code=201)
data = c.create_transfer( amount=100.00,
account_id=3,
paid_at="2022-05-16",
currency_rate=1,
currency_code="NZD",
payment_method="Bank Transfer",
category_id="4",
description="Some expenditures"
)