Add support for phone, fax, email in Rattail -> CORE export
This commit is contained in:
parent
75ba08b9fc
commit
4180382250
|
@ -24,28 +24,16 @@
|
||||||
CORE-POS model importers (webservices API)
|
CORE-POS model importers (webservices API)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from sqlalchemy.orm.exc import NoResultFound
|
|
||||||
|
|
||||||
from corepos.db.office_op import model as corepos
|
|
||||||
from corepos.api import CoreWebAPI
|
from corepos.api import CoreWebAPI
|
||||||
|
|
||||||
from rattail import importing
|
from rattail import importing
|
||||||
|
|
||||||
|
|
||||||
class ToCore(importing.ToSQLAlchemy):
|
class ToCoreAPI(importing.Importer):
|
||||||
"""
|
"""
|
||||||
Base class for all CORE "operational" model importers.
|
Base class for all CORE "operational" model importers, which use the API.
|
||||||
|
|
||||||
Note that this class inherits from
|
|
||||||
:class:`~rattail:rattail.importing.sqlalchemy.ToSQLAlchemy` even though our
|
|
||||||
goal is to *not* write directly to the CORE DB. However, (for now)
|
|
||||||
importers will need to override methods to ensure API is used instead,
|
|
||||||
where applicable. But even once all have been refactored to write via API,
|
|
||||||
we *still* may want to keep using ``ToSQLAlchemy`` for the sake of reading
|
|
||||||
"cached local" data. (May depend on how robust the API is.)
|
|
||||||
"""
|
"""
|
||||||
# TODO: should we standardize on the 'id' primary key? (can we even?)
|
caches_local_data = True
|
||||||
# key = 'id'
|
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
self.establish_api()
|
self.establish_api()
|
||||||
|
@ -54,49 +42,85 @@ class ToCore(importing.ToSQLAlchemy):
|
||||||
url = self.config.require('corepos.api', 'url')
|
url = self.config.require('corepos.api', 'url')
|
||||||
self.api = CoreWebAPI(url)
|
self.api = CoreWebAPI(url)
|
||||||
|
|
||||||
# TODO: this looks an awful lot like it belongs in rattail proper
|
def ensure_fields(self, data):
|
||||||
def get_single_local_object(self, key):
|
|
||||||
"""
|
"""
|
||||||
Fetch a particular record from CORE, via SQLAlchemy. This is used by
|
Ensure each of our supported fields are included in the data. This is
|
||||||
the Rattail -> CORE datasync consumer.
|
to handle cases where the API does not return all fields, e.g. when
|
||||||
|
some of them are empty.
|
||||||
"""
|
"""
|
||||||
query = self.session.query(self.model_class)
|
for field in self.fields:
|
||||||
for i, field in enumerate(self.key):
|
if field not in data:
|
||||||
query = query.filter(getattr(self.model_class, field) == key[i])
|
data[field] = None
|
||||||
|
|
||||||
for option in self.cache_query_options():
|
def fix_empties(self, data, fields):
|
||||||
query = query.options(option)
|
"""
|
||||||
|
Fix "empty" values for the given set of fields. This just uses an
|
||||||
|
empty string instead of ``None`` for each, to add some consistency
|
||||||
|
where the API might lack it.
|
||||||
|
|
||||||
try:
|
Main example so far, is the Vendor API, which may not return some
|
||||||
return query.one()
|
fields at all (and so our value is ``None``) in some cases, but in
|
||||||
except NoResultFound:
|
other cases it *will* return a value, default of which is the empty
|
||||||
pass
|
string. So we want to "pretend" that we get an empty string back even
|
||||||
|
when we actually get ``None`` from it.
|
||||||
|
"""
|
||||||
|
for field in fields:
|
||||||
|
if data[field] is None:
|
||||||
|
data[field] = ''
|
||||||
|
|
||||||
|
|
||||||
class VendorImporter(ToCore):
|
class VendorImporter(ToCoreAPI):
|
||||||
"""
|
"""
|
||||||
Vendor model importer for CORE-POS
|
Vendor model importer for CORE-POS
|
||||||
"""
|
"""
|
||||||
model_class = corepos.Vendor
|
model_name = 'Vendor'
|
||||||
key = 'vendorID'
|
key = 'vendorID'
|
||||||
supported_fields = [
|
supported_fields = [
|
||||||
'vendorID',
|
'vendorID',
|
||||||
'vendorName',
|
'vendorName',
|
||||||
'vendorAbbreviation',
|
'vendorAbbreviation',
|
||||||
|
'shippingMarkup',
|
||||||
'discountRate',
|
'discountRate',
|
||||||
|
'phone',
|
||||||
|
'fax',
|
||||||
|
'email',
|
||||||
|
'website',
|
||||||
|
'address',
|
||||||
|
'city',
|
||||||
|
'state',
|
||||||
|
'zip',
|
||||||
|
'notes',
|
||||||
|
'localOriginID',
|
||||||
|
'inactive',
|
||||||
|
'orderMinimum',
|
||||||
|
'halfCases',
|
||||||
]
|
]
|
||||||
# TODO: this importer is in a bit of an experimental state at the moment.
|
# TODO: this importer is in a bit of an experimental state at the moment.
|
||||||
# we only allow "update" b/c it will use the API instead of direct DB
|
# we only allow "update" b/c it will use the API instead of direct DB
|
||||||
allow_create = False
|
allow_create = False
|
||||||
allow_delete = False
|
allow_delete = False
|
||||||
|
|
||||||
|
def get_local_objects(self, host_data=None):
|
||||||
|
return self.api.get_vendors()
|
||||||
|
|
||||||
|
def get_single_local_object(self, key):
|
||||||
|
assert len(self.key) == 1
|
||||||
|
assert self.key[0] == 'vendorID'
|
||||||
|
return self.api.get_vendor(key[0])
|
||||||
|
|
||||||
def normalize_local_object(self, vendor):
|
def normalize_local_object(self, vendor):
|
||||||
return {
|
data = dict(vendor)
|
||||||
'vendorID': str(vendor.id),
|
|
||||||
'vendorName': vendor.name,
|
# make sure all fields are present
|
||||||
'vendorAbbreviation': vendor.abbreviation,
|
self.ensure_fields(data)
|
||||||
'discountRate': vendor.discount_rate,
|
|
||||||
}
|
# fix some "empty" values
|
||||||
|
self.fix_empties(data, ['phone', 'fax', 'email'])
|
||||||
|
|
||||||
|
# convert some values to native type
|
||||||
|
data['discountRate'] = float(data['discountRate'])
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
def update_object(self, vendor, data, local_data=None):
|
def update_object(self, vendor, data, local_data=None):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -30,13 +30,12 @@ from rattail import importing
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
from rattail.util import OrderedDict
|
from rattail.util import OrderedDict
|
||||||
from rattail_corepos.corepos import importing as corepos_importing
|
from rattail_corepos.corepos import importing as corepos_importing
|
||||||
from rattail_corepos.corepos.importing.db.corepos import ToCoreHandler
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class FromRattailToCore(importing.FromRattailHandler, ToCoreHandler):
|
class FromRattailToCore(importing.FromRattailHandler):
|
||||||
"""
|
"""
|
||||||
Rattail -> CORE-POS export handler
|
Rattail -> CORE-POS export handler
|
||||||
"""
|
"""
|
||||||
|
@ -67,6 +66,9 @@ class VendorImporter(FromRattail, corepos_importing.model.VendorImporter):
|
||||||
'vendorName',
|
'vendorName',
|
||||||
'vendorAbbreviation',
|
'vendorAbbreviation',
|
||||||
'discountRate',
|
'discountRate',
|
||||||
|
'phone',
|
||||||
|
'fax',
|
||||||
|
'email',
|
||||||
]
|
]
|
||||||
|
|
||||||
def normalize_host_object(self, vendor):
|
def normalize_host_object(self, vendor):
|
||||||
|
@ -75,9 +77,25 @@ class VendorImporter(FromRattail, corepos_importing.model.VendorImporter):
|
||||||
vendor.uuid, vendor.id)
|
vendor.uuid, vendor.id)
|
||||||
return
|
return
|
||||||
|
|
||||||
return {
|
data = {
|
||||||
'vendorID': vendor.id,
|
'vendorID': vendor.id,
|
||||||
'vendorName': vendor.name,
|
'vendorName': vendor.name,
|
||||||
'vendorAbbreviation': vendor.abbreviation,
|
'vendorAbbreviation': vendor.abbreviation,
|
||||||
'discountRate': float(vendor.special_discount),
|
'discountRate': float(vendor.special_discount),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if 'phone' in self.fields:
|
||||||
|
phones = [phone for phone in vendor.phones
|
||||||
|
if phone.type == 'Voice']
|
||||||
|
data['phone'] = phones[0].number if phones else ''
|
||||||
|
|
||||||
|
if 'fax' in self.fields:
|
||||||
|
phones = [phone for phone in vendor.phones
|
||||||
|
if phone.type == 'Fax']
|
||||||
|
data['fax'] = phones[0].number if phones else ''
|
||||||
|
|
||||||
|
if 'email' in self.fields:
|
||||||
|
email = vendor.email
|
||||||
|
data['email'] = email.address if email else ''
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
Loading…
Reference in a new issue