Add importer, datasync for CORE-POS (API) -> Rattail
This commit is contained in:
parent
9aefbc872e
commit
ab8894ef0d
5 changed files with 250 additions and 35 deletions
202
rattail_corepos/importing/corepos/api.py
Normal file
202
rattail_corepos/importing/corepos/api.py
Normal file
|
@ -0,0 +1,202 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2020 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
CORE POS (API) -> Rattail data importing
|
||||
"""
|
||||
|
||||
import decimal
|
||||
import logging
|
||||
|
||||
from corepos.api import CoreWebAPI
|
||||
|
||||
from rattail import importing
|
||||
from rattail.gpc import GPC
|
||||
from rattail.util import OrderedDict
|
||||
from rattail_corepos import importing as corepos_importing
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FromCOREPOSToRattail(importing.ToRattailHandler):
|
||||
"""
|
||||
Import handler for data coming from a CORE POS API.
|
||||
"""
|
||||
host_title = "CORE-POS (API)"
|
||||
|
||||
def get_importers(self):
|
||||
importers = OrderedDict()
|
||||
importers['Department'] = DepartmentImporter
|
||||
importers['Subdepartment'] = SubdepartmentImporter
|
||||
importers['Vendor'] = VendorImporter
|
||||
importers['Product'] = ProductImporter
|
||||
return importers
|
||||
|
||||
|
||||
class FromCOREPOSAPI(importing.Importer):
|
||||
"""
|
||||
Base class for all CORE POS API data importers.
|
||||
"""
|
||||
|
||||
def setup(self):
|
||||
super(FromCOREPOSAPI, self).setup()
|
||||
self.establish_api()
|
||||
|
||||
def establish_api(self):
|
||||
url = self.config.require('corepos.api', 'url')
|
||||
self.api = CoreWebAPI(url)
|
||||
|
||||
|
||||
class DepartmentImporter(FromCOREPOSAPI, importing.model.DepartmentImporter):
|
||||
"""
|
||||
Importer for department data from CORE POS API.
|
||||
"""
|
||||
key = 'number'
|
||||
supported_fields = [
|
||||
'number',
|
||||
'name',
|
||||
]
|
||||
|
||||
def get_host_objects(self):
|
||||
return self.api.get_departments()
|
||||
|
||||
def normalize_host_object(self, department):
|
||||
return {
|
||||
'number': int(department['dept_no']),
|
||||
'name': department['dept_name'],
|
||||
}
|
||||
|
||||
|
||||
class SubdepartmentImporter(FromCOREPOSAPI, importing.model.SubdepartmentImporter):
|
||||
"""
|
||||
Importer for subdepartment data from CORE POS API.
|
||||
"""
|
||||
key = 'number'
|
||||
supported_fields = [
|
||||
'number',
|
||||
'name',
|
||||
'department_number',
|
||||
]
|
||||
|
||||
def get_host_objects(self):
|
||||
return self.api.get_subdepartments()
|
||||
|
||||
def normalize_host_object(self, subdepartment):
|
||||
return {
|
||||
'number': int(subdepartment['subdept_no']),
|
||||
'name': subdepartment['subdept_name'],
|
||||
'department_number': int(subdepartment['dept_ID']),
|
||||
}
|
||||
|
||||
|
||||
class VendorImporter(FromCOREPOSAPI, corepos_importing.model.VendorImporter):
|
||||
"""
|
||||
Importer for vendor data from CORE POS API.
|
||||
"""
|
||||
key = 'corepos_id'
|
||||
supported_fields = [
|
||||
'corepos_id',
|
||||
'name',
|
||||
'abbreviation',
|
||||
'special_discount',
|
||||
'phone_number',
|
||||
'fax_number',
|
||||
'email_address',
|
||||
]
|
||||
|
||||
def get_host_objects(self):
|
||||
return self.api.get_vendors()
|
||||
|
||||
def normalize_host_object(self, vendor):
|
||||
return {
|
||||
'corepos_id': int(vendor['vendorID']),
|
||||
'name': vendor['vendorName'],
|
||||
'abbreviation': vendor['vendorAbbreviation'] or None,
|
||||
'special_discount': decimal.Decimal(vendor['discountRate']),
|
||||
'phone_number': vendor.get('phone') or None,
|
||||
'fax_number': vendor.get('fax') or None,
|
||||
'email_address': vendor.get('email') or None,
|
||||
}
|
||||
|
||||
|
||||
class ProductImporter(FromCOREPOSAPI, importing.model.ProductImporter):
|
||||
"""
|
||||
Importer for product data from CORE POS API.
|
||||
"""
|
||||
key = 'item_id'
|
||||
supported_fields = [
|
||||
'item_id',
|
||||
'upc',
|
||||
'brand_name',
|
||||
'description',
|
||||
'size',
|
||||
'weighed',
|
||||
'department_number',
|
||||
'subdepartment_number',
|
||||
'regular_price_price',
|
||||
'regular_price_multiple',
|
||||
'regular_price_type',
|
||||
'food_stampable',
|
||||
'tax1',
|
||||
'tax2',
|
||||
]
|
||||
|
||||
def get_host_objects(self):
|
||||
return self.api.get_products()
|
||||
|
||||
def normalize_host_object(self, product):
|
||||
try:
|
||||
upc = GPC(product['upc'], calc_check_digit='upc')
|
||||
except (TypeError, ValueError):
|
||||
log.debug("CORE POS product has invalid UPC: %s", product['upc'])
|
||||
if len(self.key) == 1 and self.key[0] == 'upc':
|
||||
return
|
||||
upc = None
|
||||
|
||||
price = None
|
||||
if product['normal_price'] is not None:
|
||||
price = decimal.Decimal(product['normal_price'])
|
||||
|
||||
size = product.get('size', '').strip() or None
|
||||
if size == '0': # TODO: this is maybe just for sake of CORE sample data?
|
||||
size = None
|
||||
|
||||
return {
|
||||
'item_id': product['upc'],
|
||||
'upc': upc,
|
||||
'brand_name': product.get('brand') or None,
|
||||
'description': product.get('description') or '',
|
||||
'size': size,
|
||||
|
||||
'department_number': int(product['department']) or None,
|
||||
'subdepartment_number': int(product['subdept']) or None,
|
||||
|
||||
'weighed': product['scale'] == '1',
|
||||
'food_stampable': product['foodstamp'] == '1',
|
||||
'tax1': product['tax'] == '1', # TODO: is this right?
|
||||
'tax2': product['tax'] == '2', # TODO: is this right?
|
||||
|
||||
'regular_price_price': price,
|
||||
'regular_price_multiple': 1 if price is not None else None,
|
||||
'regular_price_type': self.enum.PRICE_TYPE_REGULAR if price is not None else None,
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue