Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion lightspeed_api/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ def _get_wrapper(self, url, raw=False, preload_relations=[], object_class=None,

if raw:
return data[data_fieldname]
if not data:
return None
return self._unwrap_object_to_cls(data_object_class, data[data_fieldname])

def _create_forever_list(self, data, objcls, retrieval_func, search, preload_relations):
Expand Down Expand Up @@ -79,6 +81,8 @@ def __init__(self, client):
self.tags_api = TagsAPI(self)
self.customers_api = CustomersAPI(self)
self.registers_api = RegistersAPI(self)
self.workorders_api = WorkordersAPI(self)
self.vendors_api = VendorsAPI(self)

self.account_id = self.account.get_account_id()

Expand Down Expand Up @@ -126,6 +130,14 @@ def employees(self):
@property
def orders(self):
return None

@property
def vendors(self):
return self.vendors_api

@property
def workorders(self):
return self.workorders_api


class LazyLookupList:
Expand Down Expand Up @@ -157,4 +169,6 @@ def __len__(self):
from .accounts import AccountsAPI
from .tags import TagsAPI
from .customers import CustomersAPI
from .registers import RegistersAPI
from .registers import RegistersAPI
from .workorders import WorkordersAPI
from .vendors import VendorsAPI
Binary file modified lightspeed_api/api/__pycache__/__init__.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/api/__pycache__/accounts.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/api/__pycache__/customers.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/api/__pycache__/items.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/api/__pycache__/sales.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/api/__pycache__/tags.cpython-39.pyc
Binary file not shown.
12 changes: 6 additions & 6 deletions lightspeed_api/api/customers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ class CustomersAPI(BaseAPI):
}
}

def get_customer(self, CustomerID, preload_relations=[], raw=False):
url = f'Customer/{CustomerID}.json'
def get_customer(self, id, preload_relations=[], raw=False):
url = f'Customer/{id}.json'
return self._get_wrapper(url, raw=raw, preload_relations=preload_relations, object_class=Customer)

def get_customer_custom_field(self, CustomFieldID, raw=False):
url = f'Customer/CustomField/{CustomFieldID}.json'
def get_customer_custom_field(self, id, preload_relations=[], raw=False):
url = f'Customer/CustomField/{id}.json'
return self._get_wrapper(url, raw=raw, object_class=CustomerCustomField, object_field='CustomField')

def get_customer_type(self, CustomerTypeID, raw=False):
url = f'CustomerType/{CustomerTypeID}.json'
def get_customer_type(self, id, preload_relations=[], raw=False):
url = f'CustomerType/{id}.json'
return self._get_wrapper(url, raw=raw, object_class=CustomerType)
4 changes: 2 additions & 2 deletions lightspeed_api/api/sales.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

import json
from . import BaseAPI
from ..models.sale import Sale, SaleLineItem
from ..models.sale import Sale, SaleLine


class SalesAPI(BaseAPI):
Expand Down Expand Up @@ -36,7 +36,7 @@ def get_all_from_sale(self, SaleID):

return_list = []
for obj in data['SaleLine']:
return_list.append(self._unwrap_sales_object(SaleLineItem, obj))
return_list.append(self._unwrap_sales_object(SaleLine, obj))

return return_list

Expand Down
16 changes: 16 additions & 0 deletions lightspeed_api/api/vendors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

from . import BaseAPI
from ..models.vendor import *


class VendorsAPI(BaseAPI):
_all_methods = {
"": {
"url": "Vendor.json",
"class": Vendor
}
}

def get_vendor(self, id, preload_relations=[], raw=False):
url = f'Vendor/{id}.json'
return self._get_wrapper(url, raw=raw, preload_relations=preload_relations, object_class=Vendor)
40 changes: 40 additions & 0 deletions lightspeed_api/api/workorders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

from . import BaseAPI
from ..models.workorder import *


class WorkordersAPI(BaseAPI):
_all_methods = {
"": {
"url": "Workorder.json",
"class": Workorder
},
"items": {
"url": "WorkorderItem.json",
"class": WorkorderItem
},
"lines": {
"url": "WorkorderLine.json",
"class": WorkorderLine
},
"statuses": {
"url": "WorkorderStatus.json",
"class": WorkorderStatus
}
}

def get_workorder(self, id, preload_relations=[], raw=False):
url = f'Workorder/{id}.json'
return self._get_wrapper(url, raw=raw, preload_relations=preload_relations, object_class=Workorder)

def get_workorder_item(self, id, preload_relations=[], raw=False):
url = f'WorkorderItem/{id}.json'
return self._get_wrapper(url, raw=raw, object_class=WorkorderItem) #, object_field='CustomField')

def get_workorder_line(self, id, preload_relations=[], raw=False):
url = f'WorkorderLine/{id}.json'
return self._get_wrapper(url, raw=raw, object_class=WorkorderLine)

def get_workorder_status(self, id, preload_relations=[], raw=False):
url = f'WorkorderStatus/{id}.json'
return self._get_wrapper(url, raw=raw, object_class=WorkorderStatus)
2 changes: 0 additions & 2 deletions lightspeed_api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ def get_authorization_token(self, code):
r = s.post(self.token_url, data=payload)
json = r.json()

print(json)
self.bearer_token = json["access_token"]
self.session.headers.update({'Authorization': 'Bearer ' + self.bearer_token})

Expand All @@ -75,7 +74,6 @@ def get_token(self):
:return:
"""
if datetime.datetime.now() > self.token_expire_time:

s = requests.Session()

try:
Expand Down
80 changes: 53 additions & 27 deletions lightspeed_api/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@

# Lazy-loaded
API_MODULES = None
API_MODELS = None


def _get_model_class(class_name):
global API_MODELS
if not API_MODELS:
API_MODELS = __import__('lightspeed_api').models
return getattr(API_MODELS, class_name)


class BaseObject:
Expand All @@ -27,10 +35,14 @@ def __init__(self, obj=None, api=None):
if _id == 0:
data = None
else:
# TODO: figure out how this is going to work, want it to replace the value with the object when done.
data = LazyLookupObject(_id, api, _class, self, term)
else:
data = convert_to_type(ls_info['type'], obj[ls_info['ls_field']])
obj_data = BaseObject._parse_field_parts(ls_info['ls_field'], obj, True)
if obj_data is None:
raise KeyError() # triggers the relationships part below
if 'ls_secondary_field' in ls_info:
obj_data = obj_data[ls_info['ls_secondary_field']]
data = convert_to_type(ls_info['type'], obj_data)

if 'convert_class' in ls_info:
data = ls_info['convert_class'](data)
Expand All @@ -45,10 +57,10 @@ def __init__(self, obj=None, api=None):
_data_list.append(ls_info['convert_class'](d))
data_list = _data_list

if data_list:
setattr(self, term, data_list)
else:
if not data_list and "relationships" in ls_info:
setattr(self, term, LazyLookupAttributes(self.id, api, self._get_function, ls_info))
else:
setattr(self, term, data_list)
except KeyError as ex:
if not ('optional' in ls_info and ls_info['optional']):
raise ex
Expand All @@ -64,56 +76,63 @@ def __init__(self, obj=None, api=None):
# Only dealing with combined fields now
if "combine" not in ls_info:
continue

values = []
for attr in ls_info['combine']:
values.append(getattr(self, attr))

setattr(self, term, " ".join(values))

# Run the "cleanup" function if specified.
# Used to make some last-minute queries/adjustments if needed.
_cleanup = getattr(self, 'cleanup', None)
if _cleanup and callable(_cleanup):
_cleanup()

else:
for term in self._object_attributes:
ls_info = self._object_attributes[term]
data = None

if "multifield" in ls_info and ls_info['multifield']:
data = []

data = ls_info.get('default', data)
setattr(self, term, data)

@staticmethod
def _parse_multifield(ls_info, obj, api):
data_list = []
parts = ls_info['ls_field'].split('.')
def _parse_field_parts(ls_field, obj, notlist=False):
parts = ls_field.split('.')
downstream_obj = obj
for p in parts:
# This happens when there is no data - a list/dict becomes an empty string.
# If so, we'll exit out and assume there is no data.
if type(downstream_obj) == str or p not in downstream_obj:
downstream_obj = []
downstream_obj = [] if not notlist else None
break
downstream_obj = downstream_obj[p]

return downstream_obj

@staticmethod
def _parse_multifield(ls_info, obj, api):
data_list = []
downstream_obj = BaseObject._parse_field_parts(ls_info['ls_field'], obj)

second_field = None
if 'ls_secondary_field' in ls_info:
second_field = ls_info['ls_secondary_field']

# Only a single element in the "list"
if type(downstream_obj) == dict:
downstream_obj = [downstream_obj]

for item in downstream_obj:
if second_field:
data = convert_to_type(ls_info['type'], item[second_field])
elif issubclass(ls_info['type'], BaseObject):
data = ls_info['type'](item, api)
elif type(ls_info['type']) == str: # Means it's an object/class
_class = _get_model_class(ls_info['type'])
data = _class(item, api)
else:
raise Exception("Unexpected combination - multifield item, no ls_secondary_field or typecasting")
data_list.append(data)
Expand All @@ -129,7 +148,7 @@ def json(self, dump=True):
if "combine" in ls_info:
continue

field = ls_info['ls_field']
field = ls_info.get('ls_field', ls_info.get('ls_field_id', None))
_obj = obj
if len(field.split(".")) > 1:
fields = field.split(".")
Expand Down Expand Up @@ -178,24 +197,29 @@ def set_api(self, api):
self.api = api

def save(self):
print(self.json())
if self.id:
url = getattr(self, '_update_url')
url = getattr(self, '_update_url', None)
if url:
self.api.request('PUT', url % self.id, self.json())
else:
raise Exception('No _update_url attribute associated to this class - failing!')
raise Exception("Unable to save changes of this object type - API doesn't handle it.")
else:
url = getattr(self, '_create_url')
url = getattr(self, '_create_url', None)
if url:
response = self.api.request('POST', url, self.json())
else:
raise Exception('No _create_url attribute associated to this class - failing!')
raise Exception("Unable to create objects of this type - API doesn't handle it.")

if not response:
raise Exception("No object returned from Lightspeed - invalid object creation attempted.")

response.pop('@attributes')
key = list(response.keys())[0]
self.id = response[key][self._object_attributes['id']['ls_field']]

def delete(self):
raise Exception("Cannot delete this object type - API doesn't handle it.")

def __eq__(self, item):
if type(item) in [type(self), LazyLookupObject]:
if 'id' not in self._object_attributes or not getattr(item, 'id', None):
Expand All @@ -209,7 +233,7 @@ class LazyLookupObject:
def __init__(self, id, client, class_obj, parent_obj, parent_field):
self.id = id
self._client = client
self._class_obj = class_obj
self._class_obj = _get_model_class(class_obj)
self._parent_obj = parent_obj
self._parent_field = parent_field
self._was_loaded = False
Expand Down Expand Up @@ -237,15 +261,15 @@ def __getattr__(self, attr):
if attr != '_was_loaded':
if '_was_loaded' in self.__dict__ and not self.__dict__['_was_loaded']:
self._load()
return getattr(self._parent_obj, attr)
return getattr(getattr(self._parent_obj, self._parent_field), attr)

return self.__dict__[attr]

def __setattr__(self, attr, val):
if attr != '_was_loaded':
if '_was_loaded' in self.__dict__ and not self.__dict__['_was_loaded']:
self._load()
return setattr(self._parent_obj, attr, val)
return setattr(getattr(self._parent_obj, self._parent_field), attr, val)

return super().__setattr__(attr, val)

Expand Down Expand Up @@ -333,6 +357,7 @@ def __eq__(self, item):
# Done after declaring the above class
from .catalog import *
from .category import *
from .contact import *
from .credit_account import *
from .credit_card import *
from .customer import *
Expand All @@ -357,4 +382,5 @@ def __eq__(self, item):
from .shop import *
from .tag import *
from .tax import *
from .vendor import *
from .workorder import *
Binary file modified lightspeed_api/models/__pycache__/__init__.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/catalog.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/category.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/credit_account.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/credit_card.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/customer.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/discount.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/employee.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/image.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/industry.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/inventory.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/item.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/locale.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/manufacturer.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/note.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/options.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/order.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/payment_type.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/price_level.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/register.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/sale.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/serialized.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/session.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/shipping.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/shop.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/tag.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/tax.cpython-39.pyc
Binary file not shown.
Binary file modified lightspeed_api/models/__pycache__/workorder.cpython-39.pyc
Binary file not shown.
Loading