source: rattail-corepos/rattail_corepos/importing/corepos.py @ bfb6a4c

Last change on this file since bfb6a4c was bfb6a4c, checked in by Lance Edgar <ledgar@…>, 6 months ago

Tweak vendor importer per renamed attributes

  • Property mode set to 100644
File size: 5.6 KB
Line 
1# -*- coding: utf-8; -*-
2################################################################################
3#
4#  Rattail -- Retail Software Framework
5#  Copyright © 2010-2018 Lance Edgar
6#
7#  This file is part of Rattail.
8#
9#  Rattail is free software: you can redistribute it and/or modify it under the
10#  terms of the GNU General Public License as published by the Free Software
11#  Foundation, either version 3 of the License, or (at your option) any later
12#  version.
13#
14#  Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
15#  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16#  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17#  details.
18#
19#  You should have received a copy of the GNU General Public License along with
20#  Rattail.  If not, see <http://www.gnu.org/licenses/>.
21#
22################################################################################
23"""
24CORE POS -> Rattail data importing
25"""
26
27from __future__ import unicode_literals, absolute_import
28
29import decimal
30
31import six
32
33from corepos.db import model as corepos
34from corepos.db import Session as CoreSession
35
36from rattail import importing
37from rattail.gpc import GPC
38from rattail.util import OrderedDict
39
40
41class FromCOREPOSToRattail(importing.FromSQLAlchemyHandler, importing.ToRattailHandler):
42    """
43    Import handler for data coming from a CORE POS database.
44    """
45    corepos_dbkey = 'default'
46
47    @property
48    def host_title(self):
49        return "CORE POS ({})".format(self.corepos_dbkey)
50
51    def make_host_session(self):
52        return CoreSession(bind=self.config.corepos_engines[self.corepos_dbkey])
53
54    def get_importers(self):
55        importers = OrderedDict()
56        importers['Vendor'] = VendorImporter
57        importers['Department'] = DepartmentImporter
58        importers['Subdepartment'] = SubdepartmentImporter
59        importers['Product'] = ProductImporter
60        return importers
61
62
63class FromCOREPOS(importing.FromSQLAlchemy):
64    """
65    Base class for all CORE POS data importers.
66    """
67
68
69class VendorImporter(FromCOREPOS, importing.model.VendorImporter):
70    """
71    Importer for vendor data from CORE POS.
72    """
73    host_model_class = corepos.Vendor
74    key = 'id'
75    supported_fields = [
76        'id',
77        'name',
78        'abbreviation',
79        'special_discount',
80        'phone_number',
81        'fax_number',
82        'email_address',
83    ]
84
85    def normalize_host_object(self, vendor):
86
87        special_discount = None
88        if vendor.discount_rate is not None:
89            special_discount = decimal.Decimal('{:0.3f}'.format(vendor.discount_rate))
90
91        return {
92            'id': six.text_type(vendor.id),
93            'name': vendor.name,
94            'abbreviation': vendor.abbreviation,
95            'special_discount': special_discount,
96            'phone_number': vendor.phone,
97            'fax_number': vendor.fax,
98            'email_address': vendor.email,
99        }
100
101
102class DepartmentImporter(FromCOREPOS, importing.model.DepartmentImporter):
103    """
104    Importer for department data from CORE POS.
105    """
106    host_model_class = corepos.Department
107    key = 'number'
108    supported_fields = [
109        'number',
110        'name',
111    ]
112
113    def normalize_host_object(self, department):
114        return {
115            'number': department.dept_no,
116            'name': department.dept_name,
117        }
118
119
120class SubdepartmentImporter(FromCOREPOS, importing.model.SubdepartmentImporter):
121    """
122    Importer for subdepartment data from CORE POS.
123    """
124    host_model_class = corepos.Subdepartment
125    key = 'number'
126    supported_fields = [
127        'number',
128        'name',
129        'department_number',
130    ]
131
132    def normalize_host_object(self, subdepartment):
133        return {
134            'number': subdepartment.subdept_no,
135            'name': subdepartment.subdept_name,
136            'department_number': subdepartment.dept_ID,
137        }
138
139
140class ProductImporter(FromCOREPOS, importing.model.ProductImporter):
141    """
142    Importer for product data from CORE POS.
143    """
144    host_model_class = corepos.Product
145    key = 'upc'
146    supported_fields = [
147        'item_id',
148        'upc',
149        'brand_name',
150        'description',
151        'size',
152        'weighed',
153        'department_number',
154        'subdepartment_number',
155        'regular_price_price',
156        'regular_price_multiple',
157        'food_stampable',
158        'tax1',
159    ]
160
161    def normalize_host_object(self, product):
162
163        try:
164            upc = GPC(product.upc, calc_check_digit='upc')
165        except (TypeError, ValueError):
166            log.debug("CORE POS product has invalid UPC: %s", product.upc)
167            if len(self.key) == 1 and self.key[0] == 'upc':
168                return
169            upc = None
170
171        price = None
172        if product.normal_price is not None:
173            price = decimal.Decimal('{:03f}'.format(product.normal_price))
174
175        size = (product.size or '').strip() or None
176        if size == '0':    # TODO: this is only for sake of CORE sample data...
177            size = None
178
179        return {
180            'item_id': product.upc,
181            'upc': upc,
182            'brand_name': (product.brand or '').strip() or None,
183            'description': (product.description or '').strip(),
184            'size': size,
185
186            'department_number': product.dept_no or None,
187            'subdepartment_number': product.subdept or None,
188
189            'weighed': bool(product.scale),
190            'food_stampable': product.foodstamp,
191            'tax1': bool(product.tax), # TODO: is this right?
192
193            'regular_price_price': price,
194            'regular_price_multiple': 1 if price is not None else None,
195        }
Note: See TracBrowser for help on using the repository browser.