Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/fylein/netsuite-sdk-py

Python SDK for accessing Netsuite resources
https://github.com/fylein/netsuite-sdk-py

team-integrations

Last synced: 1 day ago
JSON representation

Python SDK for accessing Netsuite resources

Awesome Lists containing this project

README

        

# netsuite-sdk-py

Netsuite-sdk-py is a Python SDK. It uses the SOAP client library zeep(https://python-zeep.readthedocs.io/en/master/) for accessing NetSuite resources via the NetSuite SOAP web service SuiteTalk(http://www.netsuite.com/portal/platform/developer/suitetalk.shtml), but hides the complexity from the SDK user.

## Installation

$ pip install netsuitesdk

## Get Started

There are two ways to access a NetSuite account via web services:
- Use token-based auth (TBA) (within each request). This is the mechanism supported by this SDK.
- Use email, password, role and account id to login and start a session. This is not supported by this SDK

### Token-based Auth

First, setup TBA credentials using environment variables.

```
# TBA credentials
export NS_ACCOUNT=xxxx
export NS_CONSUMER_KEY=xxxx
export NS_CONSUMER_SECRET=xxxx
export NS_TOKEN_KEY=xxxx
export NS_TOKEN_SECRET=xxxx

```

The following snippet shows how to use TBA to initialize the SDK.

Note: By default the SDK implementation is using the wsdl version '2019_1', if you wish to use other than the default wsdl version, you can pass an optional wsdl_version. The wsdl_version should be in following format: 'year_version' eg. '2023_1' or '2022_2' etc.
From version 3.0.0, the default wsdl_version will be 2024_1.

```python
import os
import itertools
import json
from netsuitesdk import NetSuiteConnection

def connect_tba():
NS_ACCOUNT = os.getenv('NS_ACCOUNT')
NS_CONSUMER_KEY = os.getenv('NS_CONSUMER_KEY')
NS_CONSUMER_SECRET = os.getenv('NS_CONSUMER_SECRET')
NS_TOKEN_KEY = os.getenv('NS_TOKEN_KEY')
NS_TOKEN_SECRET = os.getenv('NS_TOKEN_SECRET')
nc = NetSuiteConnection(
account=NS_ACCOUNT,
consumer_key=NS_CONSUMER_KEY,
consumer_secret=NS_CONSUMER_SECRET,
token_key=NS_TOKEN_KEY,
token_secret=NS_TOKEN_SECRET,
#optional wsdl_version to use version other than '2019_1'
wsdl_version='2023_2'
)
return nc

nc = connect_tba()

# Use get_all methods to get all objects of certain types
currencies = nc.currencies.get_all()
locations = nc.locations.get_all()
departments = nc.departments.get_all()
classifications = nc.classifications.get_all()
subsidiaries = nc.subsidiaries.get_all()
expense_categories = nc.expense_categories.get_all()
employees = nc.employees.get_all()
all_accounts = list(itertools.islice(nc.accounts.get_all_generator(), 100))
accounts = [a for a in all_accounts if a['acctType'] == '_expense']
vendor_bills = list(itertools.islice(nc.vendor_bills.get_all_generator(), 10))
vendors = list(itertools.islice(nc.vendors.get_all_generator(), 10))
vendor_payments = nc.vendor_payments.get_all()

data = {
'accounts': accounts,
'classifications': classifications,
'departments': departments,
'locations': locations,
'currencies': currencies,
'vendors': vendors,
'vendor_bills': vendor_bills,
'subsidiaries': subsidiaries,
'expense_categories': expense_categories,
'employees': employees,
'vendor_payments': vendor_payments
}
with open('/tmp/netsuite.json', 'w') as oj:
oj.write(json.dumps(data, default=str, indent=2))

# There are also generator methods to iterate over potentially large lists
for c in nc.currencies.get_all_generator():
print(c)

# Get a specific object
nc.currencies.get(internalId='1')

# Post operation is only supported on vendor_bills, expense_reports, journal_entries and vendor_payments currently (see tests on how to construct vendor bill, expense report and journal entry)
vb = {...}
nc.vendor_bills.post(vb)

er = {...}
nc.expense_reports.post(er)

je = {...}
nc.journal_entries.post(je)

vp = {...}
nc.vendor_payments.post(vp)

### Upsert Files
file = open('receipt.pdf', 'rb').read()

created_folder = nc.folders.post(
{
"externalId": 'new-folder',
"name": 'Receipts'
}
)

uploaded_file = nc.files.post({
"externalId": "receipt 1",
"name": 'receipt.pdf',
'content': file,
'fileType': '_PDF',
"folder": {
"name": None,
"internalId": 695,
"externalId": 'new-folder',
"type": "folder"
}
}
)
```

### Remarks and possible errors regarding authentication
**Note:** NetSuite requires two-factor authentication (2FA) for
all Administrator and other highly privileged roles in all NetSuite accounts.
Instead, you can login with a non-highly privileged role or use
token based authentication (TBA) with your requests. For TBA, see below.

If login fails, a NetSuiteLoginError is thrown.

For more information about NetSuite authentication, see:
(https://docs.oracle.com/cloud/latest/netsuitecs_gs/NSATH/NSATH.pdf)

## Integration Tests

To run integration tests, you will set both login and TBA credentials for an actual Netsuite account with the right permissions.
```
# TBA credentials
export NS_ACCOUNT=xxxx
export NS_CONSUMER_KEY=xxxx
export NS_CONSUMER_SECRET=xxxx
export NS_TOKEN_KEY=xxxx
export NS_TOKEN_SECRET=xxxx

python -m pytest test/integration
```
Currently the code coverage is at 90%

To run integration tests on a newly added / modified file

```python
python -m pytest -vv test/integration/test_filename.py;

```

## Code coverage

To get code coverage report, run this command:

```python
python -m pytest --cov=netsuitesdk

Name Stmts Miss Cover
----------------------------------------------------------------------------
netsuitesdk/__init__.py 4 0 100%
netsuitesdk/api/__init__.py 0 0 100%
netsuitesdk/api/accounts.py 6 0 100%
netsuitesdk/api/adv_inter_company_journal_entries.py 7 0 100%
netsuitesdk/api/base.py 90 9 90%
netsuitesdk/api/classifications.py 6 0 100%
netsuitesdk/api/currencies.py 10 0 100%
netsuitesdk/api/custom_record_types.py 11 0 100%
netsuitesdk/api/custom_records.py 17 0 100%
netsuitesdk/api/customers.py 21 0 100%
netsuitesdk/api/departments.py 6 0 100%
netsuitesdk/api/employees.py 34 0 100%
netsuitesdk/api/expense_categories.py 6 0 100%
netsuitesdk/api/expense_reports.py 58 2 97%
netsuitesdk/api/files.py 23 0 100%
netsuitesdk/api/folders.py 17 0 100%
netsuitesdk/api/journal_entries.py 41 0 100%
netsuitesdk/api/locations.py 6 0 100%
netsuitesdk/api/price_level.py 6 0 100%
netsuitesdk/api/projects.py 6 0 100%
netsuitesdk/api/subsidiaries.py 6 0 100%
netsuitesdk/api/tax_groups.py 6 0 100%
netsuitesdk/api/tax_items.py 6 0 100%
netsuitesdk/api/vendor_bills.py 55 1 98%
netsuitesdk/api/vendor_payments.py 46 1 98%
netsuitesdk/api/vendors.py 21 0 100%
netsuitesdk/connection.py 68 0 100%
netsuitesdk/internal/__init__.py 0 0 100%
netsuitesdk/internal/client.py 305 79 74%
netsuitesdk/internal/constants.py 4 0 100%
netsuitesdk/internal/exceptions.py 16 3 81%
netsuitesdk/internal/netsuite_types.py 2 0 100%
netsuitesdk/internal/utils.py 40 4 90%
----------------------------------------------------------------------------
TOTAL 950 99 90%

```

To get an html report, run this command:

```python
python -m pytest --cov=netsuitesdk --cov-report html:cov_html
```

We want to maintain code coverage of more than 90% for this project at all times.

## Documentation
Documentation can be found in the docs/_build/html folder (open index.html) and soon in readthedocs.
For contributors: to build the documentation (cd to /docs and) run `make buildapi`
as well as `make html`

## Contributions

We are actively accepting contributions. Please mail [email protected] if you wish to collaborate on this. (Please write test cases for new additions.)