Refactor the Rattail <-> CORE product importers

this should allow for more seamless "dual authority" mode
This commit is contained in:
Lance Edgar 2020-08-20 20:00:13 -05:00
parent de628b387a
commit d3e2619944
2 changed files with 83 additions and 12 deletions

View file

@ -286,13 +286,18 @@ class ProductImporter(FromRattail, corepos_importing.model.ProductImporter):
'scale', 'scale',
] ]
def query(self):
query = super(ProductImporter, self).query()
return query.filter(model.Product.item_id != None)
def normalize_host_object(self, product): def normalize_host_object(self, product):
upc = product.item_id
if not upc and product.upc:
upc = str(product.upc)[:-1]
if not upc:
log.warning("skipping product %s with unknown upc: %s",
product.uuid, product)
return
return { return {
'upc': product.item_id, '_product': product,
'upc': upc,
'brand': product.brand.name if product.brand else '', 'brand': product.brand.name if product.brand else '',
'description': product.description or '', 'description': product.description or '',
'size': product.size or '', 'size': product.size or '',
@ -301,3 +306,25 @@ class ProductImporter(FromRattail, corepos_importing.model.ProductImporter):
'foodstamp': '1' if product.food_stampable else '0', 'foodstamp': '1' if product.food_stampable else '0',
'scale': '1' if product.weighed else '0', 'scale': '1' if product.weighed else '0',
} }
def create_object(self, key, data):
# must be sure not to pass the original Product instance, or else the
# API call will try to serialize and submit it
product = data.pop('_product')
corepos_product = super(ProductImporter, self).create_object(key, data)
if corepos_product:
# update our Rattail Product with the CORE ID
product.corepos_id = int(corepos_product['id'])
return corepos_product
def update_object(self, corepos_product, data, local_data=None):
# must be sure not to pass the original Product instance, or else the
# API call will try to serialize and submit it
product = data.pop('_product', None)
corepos_product = super(ProductImporter, self).update_object(corepos_product, data, local_data)
return corepos_product

View file

@ -29,7 +29,6 @@ import decimal
import logging import logging
from sqlalchemy import orm from sqlalchemy import orm
from sqlalchemy.orm.exc import NoResultFound
from corepos.api import CoreWebAPI from corepos.api import CoreWebAPI
@ -37,6 +36,7 @@ from rattail import importing
from rattail.gpc import GPC from rattail.gpc import GPC
from rattail.util import OrderedDict from rattail.util import OrderedDict
from rattail.time import localtime, make_utc from rattail.time import localtime, make_utc
from rattail.core import get_uuid
from rattail.db.util import normalize_full_name from rattail.db.util import normalize_full_name
from rattail_corepos import importing as corepos_importing from rattail_corepos import importing as corepos_importing
from rattail_corepos.corepos.util import get_core_members from rattail_corepos.corepos.util import get_core_members
@ -223,7 +223,7 @@ class PersonImporter(FromCOREPOSAPI, corepos_importing.model.PersonImporter):
return self.session.query(model.Customer)\ return self.session.query(model.Customer)\
.filter(model.Customer.id == id)\ .filter(model.Customer.id == id)\
.one() .one()
except NoResultFound: except orm.exc.NoResultFound:
pass pass
def normalize_host_object(self, person): def normalize_host_object(self, person):
@ -311,7 +311,7 @@ class CustomerPersonImporter(FromCOREPOSAPI, importing.model.CustomerPersonImpor
.join(model.CoreCustomer)\ .join(model.CoreCustomer)\
.filter(model.CoreCustomer.corepos_account_id == account_id)\ .filter(model.CoreCustomer.corepos_account_id == account_id)\
.one() .one()
except NoResultFound: except orm.exc.NoResultFound:
pass pass
def get_person(self, corepos_customer_id): def get_person(self, corepos_customer_id):
@ -324,7 +324,7 @@ class CustomerPersonImporter(FromCOREPOSAPI, importing.model.CustomerPersonImpor
.join(model.CorePerson)\ .join(model.CorePerson)\
.filter(model.CorePerson.corepos_customer_id == corepos_customer_id)\ .filter(model.CorePerson.corepos_customer_id == corepos_customer_id)\
.one() .one()
except NoResultFound: except orm.exc.NoResultFound:
pass pass
def normalize_host_object(self, cp): def normalize_host_object(self, cp):
@ -432,8 +432,9 @@ class ProductImporter(FromCOREPOSAPI, corepos_importing.model.ProductImporter):
""" """
Importer for product data from CORE POS API. Importer for product data from CORE POS API.
""" """
key = 'corepos_id' key = 'uuid'
supported_fields = [ supported_fields = [
'uuid',
'corepos_id', 'corepos_id',
'item_id', 'item_id',
'upc', 'upc',
@ -451,9 +452,51 @@ class ProductImporter(FromCOREPOSAPI, corepos_importing.model.ProductImporter):
# 'tax2', # 'tax2',
] ]
def setup(self):
super(ProductImporter, self).setup()
model = self.config.get_model()
query = self.session.query(model.Product)\
.join(model.CoreProduct)\
.filter(model.CoreProduct.corepos_id != None)\
.options(orm.joinedload(model.Product._corepos))
self.core_existing = self.cache_model(model.Product, key='corepos_id',
query=query)
def get_host_objects(self): def get_host_objects(self):
return self.api.get_products() return self.api.get_products()
def identify_product(self, corepos_product):
model = self.config.get_model()
corepos_id = int(corepos_product['id'])
if hasattr(self, 'core_existing'):
product = self.core_existing.get(corepos_id)
if product:
return product
else:
try:
return self.session.query(model.Product)\
.join(model.CoreProduct)\
.filter(model.CoreProduct.corepos_id == corepos_id)\
.one()
except orm.exc.NoResultFound:
pass
# at this point we'll search by `Product.item_id` instead
return self.session.query(model.Product)\
.outerjoin(model.CoreProduct)\
.filter(model.CoreProduct.corepos_id == None)\
.filter(model.Product.item_id == corepos_product['upc'])\
.first()
def identify_product_uuid(self, corepos_product):
product = self.identify_product(corepos_product)
if product:
return product.uuid
return get_uuid()
def normalize_host_object(self, product): def normalize_host_object(self, product):
try: try:
upc = GPC(product['upc'], calc_check_digit='upc') upc = GPC(product['upc'], calc_check_digit='upc')
@ -472,10 +515,11 @@ class ProductImporter(FromCOREPOSAPI, corepos_importing.model.ProductImporter):
subdepartment_number = int(product['subdept']) or None subdepartment_number = int(product['subdept']) or None
price = None price = None
if product['normal_price'] is not None: if product.get('normal_price') is not None:
price = decimal.Decimal(product['normal_price']) price = decimal.Decimal(product['normal_price'])
return { return {
'uuid': self.identify_product_uuid(product),
'corepos_id': int(product['id']), 'corepos_id': int(product['id']),
'item_id': product['upc'], 'item_id': product['upc'],
'upc': upc, 'upc': upc,
@ -570,7 +614,7 @@ class MemberImporter(FromCOREPOSAPI, corepos_importing.model.MemberImporter):
return self.session.query(model.Customer)\ return self.session.query(model.Customer)\
.filter(model.Customer.number == number)\ .filter(model.Customer.number == number)\
.one() .one()
except NoResultFound: except orm.exc.NoResultFound:
pass pass
def normalize_host_object(self, member): def normalize_host_object(self, member):