Add CustomerShopper.corepos_customer_id and refactor importers

removes phone/email support for now..also change how we handle
default/empty values for member start/end date..
This commit is contained in:
Lance Edgar 2023-06-10 14:35:08 -05:00
parent 86a8e2d241
commit 660637522d
7 changed files with 150 additions and 37 deletions

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar # Copyright © 2010-2023 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -121,7 +121,8 @@ class MemberImporter(ToCoreAPI):
# 'modified', # 'modified',
] ]
empty_date_value = '0000-00-00 00:00:00' #empty_date_value = '0000-00-00 00:00:00'
empty_date_value = '1900-01-01 00:00:00'
def get_local_objects(self, host_data=None): def get_local_objects(self, host_data=None):
return get_core_members(self.config, self.api, progress=self.progress) return get_core_members(self.config, self.api, progress=self.progress)
@ -144,14 +145,14 @@ class MemberImporter(ToCoreAPI):
if not self.customer_data_differs(local_data, host_data): if not self.customer_data_differs(local_data, host_data):
diffs.remove('customers') diffs.remove('customers')
# also the start/end dates should be looked at more closely. if they # # also the start/end dates should be looked at more closely. if they
# contain the special '__omit__' value then we won't ever count as diff # # contain the special '__omit__' value then we won't ever count as diff
if 'startDate' in self.fields and 'startDate' in diffs: # if 'startDate' in self.fields and 'startDate' in diffs:
if host_data['startDate'] == '__omit__': # if host_data['startDate'] == '__omit__':
diffs.remove('startDate') # diffs.remove('startDate')
if 'endDate' in self.fields and 'endDate' in diffs: # if 'endDate' in self.fields and 'endDate' in diffs:
if host_data['endDate'] == '__omit__': # if host_data['endDate'] == '__omit__':
diffs.remove('endDate') # diffs.remove('endDate')
return diffs return diffs
@ -220,11 +221,11 @@ class MemberImporter(ToCoreAPI):
return data return data
cardNo = data.pop('cardNo') cardNo = data.pop('cardNo')
data = dict(data) # data = dict(data)
if data.get('startDate') == '__omit__': # if data.get('startDate') == '__omit__':
data.pop('startDate') # data.pop('startDate')
if data.get('endDate') == '__omit__': # if data.get('endDate') == '__omit__':
data.pop('endDate') # data.pop('endDate')
member = self.api.set_member(cardNo, **data) member = self.api.set_member(cardNo, **data)
return member return member

View file

@ -97,9 +97,9 @@ class MemberImporter(FromRattail, corepos_importing.model.MemberImporter):
'firstName', 'firstName',
'lastName', 'lastName',
'accountHolder', 'accountHolder',
'phone', # 'phone',
'altPhone', # 'altPhone',
'email', # 'email',
] ]
def query(self): def query(self):
@ -117,23 +117,24 @@ class MemberImporter(FromRattail, corepos_importing.model.MemberImporter):
address = customer.addresses[0] if customer.addresses else None address = customer.addresses[0] if customer.addresses else None
people = [] shoppers = []
for i, person in enumerate(customer.people, 1): for shopper in customer.shoppers:
phones = person.phones person = shopper.person
phone1 = phones[0] if phones else None # phones = person.phones
phone2 = phones[1] if len(phones) > 1 else None # phone1 = phones[0] if phones else None
email = person.emails[0] if person.emails else None # phone2 = phones[1] if len(phones) > 1 else None
people.append({ # email = person.emails[0] if person.emails else None
'customerID': str(person.corepos_customer_id), shoppers.append({
'customerID': str(shopper.corepos_customer_id),
'firstName': person.first_name, 'firstName': person.first_name,
'lastName': person.last_name, 'lastName': person.last_name,
'accountHolder': i == 1, 'accountHolder': shopper.shopper_number == 1,
'phone': phone1.number if phone1 else '', # 'phone': phone1.number if phone1 else '',
'altPhone': phone2.number if phone2 else '', # 'altPhone': phone2.number if phone2 else '',
'email': email.address if email else '', # 'email': email.address if email else '',
}) })
member = customer.only_member(require=False) member = self.app.get_member(customer)
if member: if member:
if member.joined: if member.joined:
start_date = member.joined.strftime('%Y-%m-%d 00:00:00') start_date = member.joined.strftime('%Y-%m-%d 00:00:00')
@ -144,12 +145,14 @@ class MemberImporter(FromRattail, corepos_importing.model.MemberImporter):
else: else:
end_date = self.empty_date_value end_date = self.empty_date_value
else: else:
start_date = '__omit__' # start_date = '__omit__'
end_date = '__omit__' # end_date = '__omit__'
start_date = self.empty_date_value
end_date = self.empty_date_value
return { return {
'cardNo': customer.number, 'cardNo': customer.number,
'customerAccountID': customer.id, 'customerAccountID': str(customer.corepos_account_id or ''),
'addressFirstLine': address.street if address else '', 'addressFirstLine': address.street if address else '',
'addressSecondLine': address.street2 if address else '', 'addressSecondLine': address.street2 if address else '',
'city': address.city if address else '', 'city': address.city if address else '',
@ -157,7 +160,7 @@ class MemberImporter(FromRattail, corepos_importing.model.MemberImporter):
'zip': address.zipcode if address else '', 'zip': address.zipcode if address else '',
'startDate': start_date, 'startDate': start_date,
'endDate': end_date, 'endDate': end_date,
'customers': people, 'customers': shoppers,
} }

View file

@ -0,0 +1,51 @@
# -*- coding: utf-8; -*-
"""add CustomerShopper.corepos_customer_id
Revision ID: b025df7cf41b
Revises: ae74c537ea51
Create Date: 2023-06-10 13:24:40.735959
"""
# revision identifiers, used by Alembic.
revision = 'b025df7cf41b'
down_revision = 'ae74c537ea51'
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
import rattail.db.types
def upgrade():
# corepos_customer_shopper
op.create_table('corepos_customer_shopper',
sa.Column('uuid', sa.String(length=32), nullable=False),
sa.Column('corepos_customer_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['uuid'], ['customer_shopper.uuid'], name='corepos_customer_shopper_fk_shopper'),
sa.PrimaryKeyConstraint('uuid')
)
op.create_table('corepos_customer_shopper_version',
sa.Column('uuid', sa.String(length=32), autoincrement=False, nullable=False),
sa.Column('corepos_customer_id', sa.Integer(), autoincrement=False, nullable=True),
sa.Column('transaction_id', sa.BigInteger(), autoincrement=False, nullable=False),
sa.Column('end_transaction_id', sa.BigInteger(), nullable=True),
sa.Column('operation_type', sa.SmallInteger(), nullable=False),
sa.PrimaryKeyConstraint('uuid', 'transaction_id')
)
op.create_index(op.f('ix_corepos_customer_shopper_version_end_transaction_id'), 'corepos_customer_shopper_version', ['end_transaction_id'], unique=False)
op.create_index(op.f('ix_corepos_customer_shopper_version_operation_type'), 'corepos_customer_shopper_version', ['operation_type'], unique=False)
op.create_index(op.f('ix_corepos_customer_shopper_version_transaction_id'), 'corepos_customer_shopper_version', ['transaction_id'], unique=False)
def downgrade():
# corepos_customer_shopper
op.drop_index(op.f('ix_corepos_customer_shopper_version_transaction_id'), table_name='corepos_customer_shopper_version')
op.drop_index(op.f('ix_corepos_customer_shopper_version_operation_type'), table_name='corepos_customer_shopper_version')
op.drop_index(op.f('ix_corepos_customer_shopper_version_end_transaction_id'), table_name='corepos_customer_shopper_version')
op.drop_table('corepos_customer_shopper_version')
op.drop_table('corepos_customer_shopper')

View file

@ -91,7 +91,8 @@ class CoreCustomer(model.Base):
""")) """))
corepos_account_id = sa.Column(sa.Integer(), nullable=True, doc=""" corepos_account_id = sa.Column(sa.Integer(), nullable=True, doc="""
``Customers.customerAccountID`` value for this customer, within CORE-POS. ``CustomerAccounts.customerAccountID`` value for this customer
account, within CORE-POS.
""") """)
corepos_card_number = sa.Column(sa.Integer(), nullable=True, doc=""" corepos_card_number = sa.Column(sa.Integer(), nullable=True, doc="""
@ -105,6 +106,42 @@ CoreCustomer.make_proxy(model.Customer, '_corepos', 'corepos_account_id')
CoreCustomer.make_proxy(model.Customer, '_corepos', 'corepos_card_number') CoreCustomer.make_proxy(model.Customer, '_corepos', 'corepos_card_number')
class CoreCustomerShopper(model.Base):
"""
CORE-specific extensions to
:class:`~rattail:rattail.db.model.CustomerShopper`.
"""
__tablename__ = 'corepos_customer_shopper'
__table_args__ = (
sa.ForeignKeyConstraint(['uuid'], ['customer_shopper.uuid'],
name='corepos_customer_shopper_fk_shopper'),
)
__versioned__ = {}
uuid = model.uuid_column(default=None)
shopper = orm.relationship(
model.CustomerShopper, doc="""
Reference to the actual shopper record, which this one extends.
""",
cascade_backrefs=False,
backref=orm.backref(
'_corepos', doc="""
Reference to the CORE-POS extension record for this customer.
""",
uselist=False,
cascade='all, delete-orphan',
cascade_backrefs=False))
corepos_customer_id = sa.Column(sa.Integer(), nullable=True, doc="""
``Customers.customerID`` value for this shopper, within CORE-POS.
""")
def __str__(self):
return str(self.shopper)
CoreCustomerShopper.make_proxy(model.CustomerShopper, '_corepos', 'corepos_customer_id')
class CoreMember(model.Base): class CoreMember(model.Base):
""" """
CORE-specific extensions to :class:`rattail:rattail.db.model.Member`. CORE-specific extensions to :class:`rattail:rattail.db.model.Member`.

View file

@ -62,6 +62,14 @@ class corepos_problems_invalid_person_numbers(ProblemReportEmail):
} }
class rattail_export_corepos_updates(ImporterEmail):
"""
Sent when a Rattail -> CORE-POS API export involves data changes.
"""
handler_spec = 'rattail_corepos.corepos.office.importing.rattail:FromRattailToCore'
abstract = False
class rattail_import_corepos_api_updates(ImporterEmail): class rattail_import_corepos_api_updates(ImporterEmail):
""" """
Sent when a CORE-POS API -> Rattail import involves data changes. Sent when a CORE-POS API -> Rattail import involves data changes.

View file

@ -136,6 +136,7 @@ class CustomerImporter(FromCOREPOSAPI, corepos_importing.model.CustomerImporter)
key = 'corepos_card_number' key = 'corepos_card_number'
supported_fields = [ supported_fields = [
'corepos_card_number', 'corepos_card_number',
'corepos_account_id',
'number', 'number',
'name', 'name',
# 'address_street', # 'address_street',
@ -171,6 +172,7 @@ class CustomerImporter(FromCOREPOSAPI, corepos_importing.model.CustomerImporter)
return { return {
'corepos_card_number': card_number, 'corepos_card_number': card_number,
'corepos_account_id': int(customer['customerAccountID']),
'number': card_number, 'number': card_number,
'name': normalize_full_name(customer['firstName'], 'name': normalize_full_name(customer['firstName'],
customer['lastName']), customer['lastName']),
@ -183,7 +185,7 @@ class CustomerImporter(FromCOREPOSAPI, corepos_importing.model.CustomerImporter)
} }
class CustomerShopperImporter(FromCOREPOSAPI, importing.model.CustomerShopperImporter): class CustomerShopperImporter(FromCOREPOSAPI, corepos_importing.model.CustomerShopperImporter):
""" """
Importer for customer shopper data from CORE POS API. Importer for customer shopper data from CORE POS API.
""" """
@ -191,6 +193,7 @@ class CustomerShopperImporter(FromCOREPOSAPI, importing.model.CustomerShopperImp
supported_fields = [ supported_fields = [
'customer_uuid', 'customer_uuid',
'shopper_number', 'shopper_number',
'corepos_customer_id',
'first_name', 'first_name',
'last_name', 'last_name',
'display_name', 'display_name',
@ -281,6 +284,7 @@ class CustomerShopperImporter(FromCOREPOSAPI, importing.model.CustomerShopperImp
data = { data = {
'customer_uuid': customer.uuid, 'customer_uuid': customer.uuid,
'shopper_number': shopper['shopper_number'], 'shopper_number': shopper['shopper_number'],
'corepos_customer_id': int(shopper['customerID']),
'first_name': shopper['firstName'], 'first_name': shopper['firstName'],
'last_name': shopper['lastName'], 'last_name': shopper['lastName'],

View file

@ -64,6 +64,15 @@ class CustomerImporter(importing.model.CustomerImporter):
} }
class CustomerShopperImporter(importing.model.CustomerShopperImporter):
extensions = {
'_corepos': [
'corepos_customer_id',
],
}
class MemberImporter(importing.model.MemberImporter): class MemberImporter(importing.model.MemberImporter):
extensions = { extensions = {