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)
|
||||
"""
|
||||
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
|
||||
from corepos.db.office_op import model as corepos
|
||||
from corepos.api import CoreWebAPI
|
||||
|
||||
from rattail import importing
|
||||
|
||||
|
||||
class ToCore(importing.ToSQLAlchemy):
|
||||
class ToCoreAPI(importing.Importer):
|
||||
"""
|
||||
Base class for all CORE "operational" model importers.
|
||||
|
||||
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.)
|
||||
Base class for all CORE "operational" model importers, which use the API.
|
||||
"""
|
||||
# TODO: should we standardize on the 'id' primary key? (can we even?)
|
||||
# key = 'id'
|
||||
caches_local_data = True
|
||||
|
||||
def setup(self):
|
||||
self.establish_api()
|
||||
|
@ -54,49 +42,85 @@ class ToCore(importing.ToSQLAlchemy):
|
|||
url = self.config.require('corepos.api', 'url')
|
||||
self.api = CoreWebAPI(url)
|
||||
|
||||
# TODO: this looks an awful lot like it belongs in rattail proper
|
||||
def get_single_local_object(self, key):
|
||||
def ensure_fields(self, data):
|
||||
"""
|
||||
Fetch a particular record from CORE, via SQLAlchemy. This is used by
|
||||
the Rattail -> CORE datasync consumer.
|
||||
Ensure each of our supported fields are included in the data. This is
|
||||
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 i, field in enumerate(self.key):
|
||||
query = query.filter(getattr(self.model_class, field) == key[i])
|
||||
for field in self.fields:
|
||||
if field not in data:
|
||||
data[field] = None
|
||||
|
||||
for option in self.cache_query_options():
|
||||
query = query.options(option)
|
||||
def fix_empties(self, data, fields):
|
||||
"""
|
||||
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:
|
||||
return query.one()
|
||||
except NoResultFound:
|
||||
pass
|
||||
Main example so far, is the Vendor API, which may not return some
|
||||
fields at all (and so our value is ``None``) in some cases, but in
|
||||
other cases it *will* return a value, default of which is the empty
|
||||
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
|
||||
"""
|
||||
model_class = corepos.Vendor
|
||||
model_name = 'Vendor'
|
||||
key = 'vendorID'
|
||||
supported_fields = [
|
||||
'vendorID',
|
||||
'vendorName',
|
||||
'vendorAbbreviation',
|
||||
'shippingMarkup',
|
||||
'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.
|
||||
# we only allow "update" b/c it will use the API instead of direct DB
|
||||
allow_create = 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):
|
||||
return {
|
||||
'vendorID': str(vendor.id),
|
||||
'vendorName': vendor.name,
|
||||
'vendorAbbreviation': vendor.abbreviation,
|
||||
'discountRate': vendor.discount_rate,
|
||||
}
|
||||
data = dict(vendor)
|
||||
|
||||
# make sure all fields are present
|
||||
self.ensure_fields(data)
|
||||
|
||||
# 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):
|
||||
"""
|
||||
|
|
|
@ -30,13 +30,12 @@ from rattail import importing
|
|||
from rattail.db import model
|
||||
from rattail.util import OrderedDict
|
||||
from rattail_corepos.corepos import importing as corepos_importing
|
||||
from rattail_corepos.corepos.importing.db.corepos import ToCoreHandler
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FromRattailToCore(importing.FromRattailHandler, ToCoreHandler):
|
||||
class FromRattailToCore(importing.FromRattailHandler):
|
||||
"""
|
||||
Rattail -> CORE-POS export handler
|
||||
"""
|
||||
|
@ -67,6 +66,9 @@ class VendorImporter(FromRattail, corepos_importing.model.VendorImporter):
|
|||
'vendorName',
|
||||
'vendorAbbreviation',
|
||||
'discountRate',
|
||||
'phone',
|
||||
'fax',
|
||||
'email',
|
||||
]
|
||||
|
||||
def normalize_host_object(self, vendor):
|
||||
|
@ -75,9 +77,25 @@ class VendorImporter(FromRattail, corepos_importing.model.VendorImporter):
|
|||
vendor.uuid, vendor.id)
|
||||
return
|
||||
|
||||
return {
|
||||
data = {
|
||||
'vendorID': vendor.id,
|
||||
'vendorName': vendor.name,
|
||||
'vendorAbbreviation': vendor.abbreviation,
|
||||
'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