Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to most recent #17

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
32 changes: 32 additions & 0 deletions netsuitesdk/api/employees.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from collections import OrderedDict

from netsuitesdk.internal.utils import PaginatedSearch

from .base import ApiBase
import logging

Expand All @@ -10,6 +12,36 @@ class Employees(ApiBase):
def __init__(self, ns_client):
ApiBase.__init__(self, ns_client=ns_client, type_name='Employee')

def get_all_generator(self, is_inactive=False, page_size=50, last_modified_date_query={
'search_value',
'operator',
}):
# Get Only Employee Items using SearchBooleanField
record_type_search_field = self.ns_client.SearchBooleanField(searchValue=is_inactive)

date_search = None
if 'search_value' in last_modified_date_query and 'operator' in last_modified_date_query:
if last_modified_date_query['search_value'] and last_modified_date_query['operator']:
date_search = self.ns_client.SearchDateField(
searchValue=last_modified_date_query['search_value'],
operator=last_modified_date_query['operator']
)

basic_search = self.ns_client.basic_search_factory(
type_name='Employee',
isInactive=record_type_search_field,
lastModifiedDate=date_search
)

paginated_search = PaginatedSearch(
client=self.ns_client,
type_name='Employee',
basic_search=basic_search,
pageSize=page_size
)

return self._paginated_search_generator(paginated_search=paginated_search)

def post(self, data) -> OrderedDict:
assert data['externalId'], 'missing external id'
employee = self.ns_client.Employee(externalId=data['externalId'])
Expand Down
4 changes: 3 additions & 1 deletion netsuitesdk/api/expense_reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from netsuitesdk.internal.utils import PaginatedSearch


logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -97,5 +98,6 @@ def post(self, data) -> OrderedDict:
er['entity'] = self.ns_client.RecordRef(**(data['entity']))

logger.debug('able to create er = %s', er)
res = self.ns_client.upsert(er)
res = self.ns_client.upsert(er, 'expense_report')

return self._serialize(res)
24 changes: 24 additions & 0 deletions netsuitesdk/api/items.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from .base import ApiBase
from netsuitesdk.internal.utils import PaginatedSearch
import logging

logger = logging.getLogger(__name__)

class Items(ApiBase):

def __init__(self, ns_client):
ApiBase.__init__(self, ns_client=ns_client, type_name='Item')

def get_all_generator(self, is_inactive=False):
# Get Only Active Items using SearchBooleanField
record_type_search_field = self.ns_client.SearchBooleanField(searchValue=is_inactive)
basic_search = self.ns_client.basic_search_factory('Item', isInactive=record_type_search_field)

paginated_search = PaginatedSearch(
client=self.ns_client,
type_name='Item',
basic_search=basic_search,
pageSize=20
)

return self._paginated_search_generator(paginated_search=paginated_search)
2 changes: 1 addition & 1 deletion netsuitesdk/api/journal_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def post(self, data) -> OrderedDict:
je = self._build_journal_entry_data(data)

logger.debug('able to create je = %s', je)
res = self.ns_client.upsert(je)
res = self.ns_client.upsert(je, 'journal_entry')
return self._serialize(res)

def post_batch(self, records) -> [OrderedDict]:
Expand Down
91 changes: 62 additions & 29 deletions netsuitesdk/api/vendor_bills.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import logging
from collections import OrderedDict

from netsuitesdk.internal.utils import PaginatedSearch

from .base import ApiBase
from typing import List
from collections import OrderedDict

logger = logging.getLogger(__name__)

Expand All @@ -16,7 +18,6 @@ class VendorBills(ApiBase):
'memo',
'tranDate',
'tranId',
'itemList',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the changes here are to support customFields for items. We don't use item based lines, so we're in the clear. 😄

'customFieldList'
]

Expand All @@ -27,7 +28,7 @@ class VendorBills(ApiBase):
'department',
'account',
'entity',
'subsidiary'
'subsidiary',
]

def __init__(self, ns_client):
Expand All @@ -45,34 +46,67 @@ def get_all_generator(self):
def _build_vendor_bill(self, data) -> OrderedDict:
assert data['externalId'], 'missing external id'
vb = self.ns_client.VendorBill(externalId=data['externalId'])
expense_list = []
for eod in data['expenseList']:
if 'customFieldList' in eod and eod['customFieldList']:
custom_fields = []
for field in eod['customFieldList']:
if field['type'] == 'String':
custom_fields.append(
self.ns_client.StringCustomFieldRef(
scriptId=field['scriptId'] if 'scriptId' in field else None,
internalId=field['internalId'] if 'internalId' in field else None,
value=field['value']
# If expesess are present, add them
if 'expenseList' in data and data['expenseList']:
expense_list = []
for eod in data['expenseList']:
if 'customFieldList' in eod and eod['customFieldList']:
custom_fields = []
for field in eod['customFieldList']:
if field['type'] == 'String':
custom_fields.append(
self.ns_client.StringCustomFieldRef(
scriptId=field['scriptId'] if 'scriptId' in field else None,
internalId=field['internalId'] if 'internalId' in field else None,
value=field['value']
)
)
)
elif field['type'] == 'Select':
custom_fields.append(
self.ns_client.SelectCustomFieldRef(
scriptId=field['scriptId'] if 'scriptId' in field else None,
internalId=field['internalId'] if 'internalId' in field else None,
value=self.ns_client.ListOrRecordRef(
internalId=field['value']
elif field['type'] == 'Select':
custom_fields.append(
self.ns_client.SelectCustomFieldRef(
scriptId=field['scriptId'] if 'scriptId' in field else None,
internalId=field['internalId'] if 'internalId' in field else None,
value=self.ns_client.ListOrRecordRef(
internalId=field['value']
)
)
)
)
eod['customFieldList'] = self.ns_client.CustomFieldList(custom_fields)
vbe = self.ns_client.VendorBillExpense(**eod)
expense_list.append(vbe)
eod['customFieldList'] = self.ns_client.CustomFieldList(custom_fields)
vbe = self.ns_client.VendorBillExpense(**eod)
expense_list.append(vbe)

vb['expenseList'] = self.ns_client.VendorBillExpenseList(expense=expense_list)

# If items are present, add them
if 'itemList' in data and data['itemList']:
item_list = []
for eod in data['itemList']:
if 'customFieldList' in eod and eod['customFieldList']:
custom_fields = []
for field in eod['customFieldList']:
if field['type'] == 'String':
custom_fields.append(
self.ns_client.StringCustomFieldRef(
scriptId=field['scriptId'] if 'scriptId' in field else None,
internalId=field['internalId'] if 'internalId' in field else None,
value=field['value']
)
)
elif field['type'] == 'Select':
custom_fields.append(
self.ns_client.SelectCustomFieldRef(
scriptId=field['scriptId'] if 'scriptId' in field else None,
internalId=field['internalId'] if 'internalId' in field else None,
value=self.ns_client.ListOrRecordRef(
internalId=field['value']
)
)
)
eod['customFieldList'] = self.ns_client.CustomFieldList(custom_fields)
vbe = self.ns_client.VendorBillItem(**eod)
item_list.append(vbe)

vb['expenseList'] = self.ns_client.VendorBillExpenseList(expense=expense_list)
vb['itemList']= self.ns_client.VendorBillItemList(item=item_list)

self.build_simple_fields(self.SIMPLE_FIELDS, data, vb)
self.build_record_ref_fields(self.RECORD_REF_FIELDS, data, vb)
Expand All @@ -81,9 +115,8 @@ def _build_vendor_bill(self, data) -> OrderedDict:

def post(self, data) -> OrderedDict:
vendor_bill = self._build_vendor_bill(data)

logger.debug('able to create VendorBill = %s', vendor_bill)
res = self.ns_client.upsert(vendor_bill)
res = self.ns_client.upsert(vendor_bill, 'bills')
return self._serialize(res)

def post_batch(self, records) -> [OrderedDict]:
Expand Down
2 changes: 2 additions & 0 deletions netsuitesdk/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from .api.tax_groups import TaxGroups
from .api.price_level import PriceLevel
from .api.vendor_subsidiary_relationships import VendorSubsidiaryRelationships
from .api.items import Items
from .internal.client import NetSuiteClient


Expand Down Expand Up @@ -79,3 +80,4 @@ def __init__(self, account, consumer_key, consumer_secret, token_key, token_secr
self.price_level = PriceLevel(ns_client)
self.usages = Usage(ns_client)
self.vendor_subsidiary_relationships = VendorSubsidiaryRelationships(ns_client)
self.items = Items(ns_client)
Empty file added netsuitesdk/errors/__init__.py
Empty file.
81 changes: 81 additions & 0 deletions netsuitesdk/errors/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@

error_reference = {
"expense_report": {
'category_reference_error': {
'regex': r"An error occured in a upsert request: Invalid category reference key \d+ for entity \d+",
'keys': ['expense_category', 'employee']
},
'account_reference_error': {
'regex': r"An error occured in a upsert request: Invalid account reference key \d+ for subsidiary \d+",
'keys': ['account', 'subsidiary']
},
'project_reference_error': {
'regex': r"An error occured in a upsert request: Invalid customer reference key \d+ for entity \d+",
'keys': ['customer', 'employee']
},
'location_reference_error': {
'regex': r"An error occured in a upsert request: Invalid location reference key \d+ for subsidiary \d+",
'keys': ['location', 'subsidiary']
},
'department_reference_error': {
'regex':r"An error occured in a upsert request: Invalid department reference key \d+ for subsidiary \d+" ,
'keys': ['department', 'subsidiary']
},
'currency_reference_error': {
'regex': r"An error occured in a upsert request: Invalid currency reference key \d+ for subsidiary \d+",
'keys': ['currency', 'subsidiary']
}
},
"bills": {
'bill_account_reference_error': {
'regex': r"An error occured in a upsert request: Invalid account reference key \d+ for subsidiary \d+",
'keys': ['account', 'subsidiary']
},
'location_reference_error': {
'regex': r"An error occured in a upsert request: Invalid location reference key \d+ for subsidiary \d+",
'keys': ['location', 'subsidiary']
},
'department_reference_error': {
'regex':r"An error occured in a upsert request: Invalid department reference key \d+ for subsidiary \d+" ,
'keys': ['department', 'subsidiary']
},
'currency_reference_error': {
'regex': r"An error occured in a upsert request: Invalid currency reference key \d+ for subsidiary \d+",
'keys': ['currency', 'subsidiary']
},
'vendor_reference_error': {
'regex': r"An error occured in a upsert request: Invalid entity reference key \d+ for subsidiary \d+",
'keys': ['vendor', 'subsidiary']
}
},
"journal_entry": {
'location_reference_error': {
'regex': r"An error occured in a upsert request: Invalid location reference key \d+ for subsidiary \d+",
'keys': ['location', 'subsidiary']
},
'department_reference_error': {
'regex':r"An error occured in a upsert request: Invalid department reference key \d+ for subsidiary \d+" ,
'keys': ['department', 'subsidiary']
},
'account_reference_error': {
'regex': r"An error occured in a upsert request: Invalid account reference key \d+ for subsidiary \d+",
'keys': ['account', 'subsidiary']
},
'currency_reference_error': {
'regex': r"An error occured in a upsert request: Invalid currency reference key \d+ for subsidiary \d+",
'keys': ['currency', 'subsidiary']
},
'project_reference_error': {
'regex': r"An error occured in a upsert request: Invalid customer reference key \d+ for entity \d+",
'keys': ['customer', 'employee']
},
}
}


list_of_dicts = [
['expense_category', 'employee'], ['account', 'subsidiary'],
['customer', 'employee'], ['location', 'subsidiary'],
['department', 'subsidiary'], ['currency', 'subsidiary'],
['vendor', 'subsdiary']
]
21 changes: 21 additions & 0 deletions netsuitesdk/errors/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import re
from .errors import error_reference


def replace_numbers(string , replacement1, replacement2, number1, number2):
pattern = r"\b({0}|{1})\b".format(number1, number2)
replaced_string = re.sub(pattern, lambda match: replacement1 if match.group() == str(number1) else replacement2, string)
return replaced_string


def convert_to_camelcase(word):
return ''.join(word.title().split('_'))


def export_error_matcher(string, export_type):
for _, error_data in error_reference[export_type].items():
if re.match(error_data['regex'], string):
numbers = re.findall(r'\d+', string)
return {key: int(number) for key, number in zip(error_data['keys'], numbers)}

return {}
39 changes: 39 additions & 0 deletions netsuitesdk/errors/parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from .helpers import replace_numbers, convert_to_camelcase
from .errors import list_of_dicts

class ErrorParser():

def __init__(self, get_instance):
self.get_instance = get_instance

def get_entity_values(self, error_dict):

entity_keys = list(error_dict)
object_1 = self.get_instance(convert_to_camelcase(entity_keys[0]), error_dict[entity_keys[0]])
object_2 = self.get_instance(convert_to_camelcase(entity_keys[1]), error_dict[entity_keys[1]])

if object_1 and object_2:
if entity_keys[0] == 'customer' and entity_keys[1] == 'employee':
return object_1['entityId'], object_2['entityId']

if entity_keys[1] == 'employee':
return object_1['name'], object_2['entityId']

if entity_keys[0] == 'account':
object_1 = object_1['acctName']
return object_1, object_2['name']

if entity_keys[0] == 'vendor':
return object_1['entityId'], object_2['name']

return object_1['name'], object_2['name']


def export_error_parser(self, error_dict, message):

parsed_message = message
if list(error_dict) in list_of_dicts:
object_1, object_2 = self.get_entity_values(error_dict)
entity_keys = list(error_dict)
parsed_message = replace_numbers(message, object_1, object_2, error_dict[entity_keys[0]], error_dict[entity_keys[1]])
return parsed_message
Loading