You've already forked akaunting-py
v1.0.3
This commit is contained in:
1
.idea/akaunting-py.iml
generated
1
.idea/akaunting-py.iml
generated
@@ -4,6 +4,7 @@
|
|||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.pytest_cache" />
|
<excludeFolder url="file://$MODULE_DIR$/.pytest_cache" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from requests.auth import HTTPBasicAuth
|
|||||||
from akauntingpy import exceptions
|
from akauntingpy import exceptions
|
||||||
from akauntingpy.helpers import *
|
from akauntingpy.helpers import *
|
||||||
|
|
||||||
__version__ = "1.0.2"
|
__version__ = "1.0.3"
|
||||||
|
|
||||||
|
|
||||||
class Client(object):
|
class Client(object):
|
||||||
@@ -18,16 +18,21 @@ class Client(object):
|
|||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
company_id,
|
company_id,
|
||||||
|
ssl_verify=True,
|
||||||
currency_code="NZD",
|
currency_code="NZD",
|
||||||
currency_rate="1.0"):
|
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 v' + __version__,
|
'User-Agent': 'AkauntingPy v' + __version__,
|
||||||
@@ -44,7 +49,8 @@ class Client(object):
|
|||||||
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
|
||||||
)
|
)
|
||||||
|
|
||||||
response_ = response.json()
|
response_ = response.json()
|
||||||
@@ -73,17 +79,45 @@ class Client(object):
|
|||||||
|
|
||||||
if params.get('search', False):
|
if params.get('search', False):
|
||||||
# Check if there is an account returned
|
# Check if there is an account returned
|
||||||
if data['meta']['pagination'].get('count') == 0:
|
try:
|
||||||
# No account found
|
if data['meta']['pagination'].get('count') == 0:
|
||||||
raise exceptions.AccountNotFound("Sorry, account not found matching search parameters: %s".format(
|
# No account found
|
||||||
params.get('search')
|
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,
|
||||||
transaction_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
|
||||||
|
number="NULL", # Transaction number
|
||||||
category_id=None, # Category ID to assign
|
category_id=None, # Category ID to assign
|
||||||
contact_id=None, # Contact ID/Client to assign
|
contact_id=None, # Contact ID/Client to assign
|
||||||
description=None, # Description
|
description=None, # Description
|
||||||
@@ -106,6 +140,7 @@ class Client(object):
|
|||||||
data = self.call(endpoint="transactions",
|
data = self.call(endpoint="transactions",
|
||||||
method="POST",
|
method="POST",
|
||||||
search="type:" + transaction_type,
|
search="type:" + transaction_type,
|
||||||
|
number=number,
|
||||||
type=transaction_type,
|
type=transaction_type,
|
||||||
account_id=account_id,
|
account_id=account_id,
|
||||||
category_id=category_id,
|
category_id=category_id,
|
||||||
@@ -121,18 +156,17 @@ class Client(object):
|
|||||||
)
|
)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def create_transfer(self,
|
def create_transfer(self,
|
||||||
from_account_id=None, # Account ID to create transfer from
|
from_account_id=None, # Account ID to create transfer from
|
||||||
to_account_id=None, # Account ID to create transfer to
|
to_account_id=None, # Account ID to create transfer to
|
||||||
transferred_at=None, # Date of expense/transfer or income
|
transferred_at=None, # Date of expense/transfer or income
|
||||||
payment_method="Bank Transfer", # Payment method
|
payment_method="Bank Transfer", # Payment method
|
||||||
amount=None, # Amount received/paid
|
amount=None, # Amount received/paid
|
||||||
**params # Any additional parameters
|
**params # Any additional parameters
|
||||||
):
|
):
|
||||||
|
|
||||||
data = self.call(endpoint="transfers",
|
data = self.call(endpoint="transfers",
|
||||||
method="POST",
|
method="POST",
|
||||||
from_account_id=from_account_id,
|
from_account_id=from_account_id,
|
||||||
to_account_id=to_account_id,
|
to_account_id=to_account_id,
|
||||||
transferred_at=transferred_at,
|
transferred_at=transferred_at,
|
||||||
@@ -140,4 +174,4 @@ class Client(object):
|
|||||||
amount=EnsurePositiveInteger(amount),
|
amount=EnsurePositiveInteger(amount),
|
||||||
**params
|
**params
|
||||||
)
|
)
|
||||||
return data
|
return data
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ class AccountNotFound(Error):
|
|||||||
"""
|
"""
|
||||||
Account not found
|
Account not found
|
||||||
|
|
||||||
|
Args:
|
||||||
|
Error (_type_): _description_
|
||||||
|
"""
|
||||||
|
|
||||||
|
class ContactNotFound(Error):
|
||||||
|
"""
|
||||||
|
Account not found
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
Error (_type_): _description_
|
Error (_type_): _description_
|
||||||
"""
|
"""
|
||||||
@@ -11,24 +11,24 @@ 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):
|
||||||
@@ -55,19 +55,32 @@ 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(self, setUp, requests_mock):
|
def test_get_account_search_v2(self, setUp, requests_mock):
|
||||||
c = setUp
|
c = setUp
|
||||||
requests_mock.get(c.url + "/accounts?search=number%3A38-9011-0510023-03¶ms=page¶ms=limit&company_id=1",
|
requests_mock.get(c.url + "/accounts?search=number%3A00-0000-0000000-00¶ms=page¶ms=limit&company_id=1",
|
||||||
json=RetrieveJSONFromFile("data/GetAccountsSearch.json"))
|
json=RetrieveJSONFromFile("data/v2/GetAccountsSearch.json"))
|
||||||
data = c.get_accounts(search="number:38-9011-0510023-03", params={'page': 1, 'limit': 200})
|
data = c.get_accounts(search="number:00-0000-0000000-00", params={'page': 1, 'limit': 200})
|
||||||
|
|
||||||
def test_get_account_search_not_found(self, setUp, requests_mock):
|
def test_get_account_search_v3(self, setUp, requests_mock):
|
||||||
|
c = setUp
|
||||||
|
requests_mock.get(c.url + "/accounts?search=number%3A00-0000-0000000-00¶ms=page¶ms=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
|
c = setUp
|
||||||
requests_mock.get(c.url + "/accounts?search=number%3Aarandomvalue&company_id=1",
|
requests_mock.get(c.url + "/accounts?search=number%3Aarandomvalue&company_id=1",
|
||||||
json=RetrieveJSONFromFile("data/GetAccountsSearchNotFound.json"))
|
json=RetrieveJSONFromFile("data/v2/GetAccountsSearchNotFound.json"))
|
||||||
with pytest.raises(AccountNotFound):
|
with pytest.raises(AccountNotFound):
|
||||||
data = c.get_accounts(search="number:arandomvalue")
|
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,
|
||||||
transaction_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
|
||||||
|
|||||||
Reference in New Issue
Block a user