diff --git a/rattail_corepos/db/alembic/versions/7fea5aebddfb_add_store_extension.py b/rattail_corepos/db/alembic/versions/7fea5aebddfb_add_store_extension.py new file mode 100644 index 0000000..7703de6 --- /dev/null +++ b/rattail_corepos/db/alembic/versions/7fea5aebddfb_add_store_extension.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8; -*- +"""add store extension + +Revision ID: 7fea5aebddfb +Revises: 130e4632a28a +Create Date: 2021-01-27 21:01:59.767884 + +""" + +from __future__ import unicode_literals + +# revision identifiers, used by Alembic. +revision = '7fea5aebddfb' +down_revision = '130e4632a28a' +branch_labels = None +depends_on = None + +from alembic import op +import sqlalchemy as sa +import rattail.db.types + + + +def upgrade(): + + # corepos_store + op.create_table('corepos_store', + sa.Column('uuid', sa.String(length=32), nullable=False), + sa.Column('corepos_id', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['uuid'], ['store.uuid'], name='corepos_store_fk_store'), + sa.PrimaryKeyConstraint('uuid') + ) + op.create_table('corepos_store_version', + sa.Column('uuid', sa.String(length=32), autoincrement=False, nullable=False), + sa.Column('corepos_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_store_version_end_transaction_id'), 'corepos_store_version', ['end_transaction_id'], unique=False) + op.create_index(op.f('ix_corepos_store_version_operation_type'), 'corepos_store_version', ['operation_type'], unique=False) + op.create_index(op.f('ix_corepos_store_version_transaction_id'), 'corepos_store_version', ['transaction_id'], unique=False) + + +def downgrade(): + + # corepos_store + op.drop_index(op.f('ix_corepos_store_version_transaction_id'), table_name='corepos_store_version') + op.drop_index(op.f('ix_corepos_store_version_operation_type'), table_name='corepos_store_version') + op.drop_index(op.f('ix_corepos_store_version_end_transaction_id'), table_name='corepos_store_version') + op.drop_table('corepos_store_version') + op.drop_table('corepos_store') diff --git a/rattail_corepos/db/model/__init__.py b/rattail_corepos/db/model/__init__.py index 2ac93f3..2dc4ee7 100644 --- a/rattail_corepos/db/model/__init__.py +++ b/rattail_corepos/db/model/__init__.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2020 Lance Edgar +# Copyright © 2010-2021 Lance Edgar # # This file is part of Rattail. # @@ -24,6 +24,7 @@ Database schema extensions for CORE-POS integration """ +from .stores import CoreStore from .people import CorePerson, CoreCustomer, CoreMember from .products import (CoreDepartment, CoreSubdepartment, CoreVendor, CoreProduct, CoreProductCost) diff --git a/rattail_corepos/db/model/stores.py b/rattail_corepos/db/model/stores.py new file mode 100644 index 0000000..63d0c4a --- /dev/null +++ b/rattail_corepos/db/model/stores.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2021 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 . +# +################################################################################ +""" +Database schema extensions for CORE-POS integration +""" + +import sqlalchemy as sa +from sqlalchemy import orm + +from rattail.db import model + + +class CoreStore(model.Base): + """ + CORE-specific extensions to :class:`rattail:rattail.db.model.Store`. + """ + __tablename__ = 'corepos_store' + __table_args__ = ( + sa.ForeignKeyConstraint(['uuid'], ['store.uuid'], + name='corepos_store_fk_store'), + ) + __versioned__ = {} + + uuid = model.uuid_column(default=None) + store = orm.relationship( + model.Store, + doc=""" + Reference to the actual store record, which this one extends. + """, + backref=orm.backref( + '_corepos', + uselist=False, + cascade='all, delete-orphan', + doc=""" + Reference to the CORE-POS extension record for this store. + """)) + + corepos_id = sa.Column(sa.Integer(), nullable=False, doc=""" + ``Stores.storeID`` value for this store, within CORE-POS. + """) + + def __str__(self): + return str(self.store) + +CoreStore.make_proxy(model.Store, '_corepos', 'corepos_id') diff --git a/rattail_corepos/importing/corepos/api.py b/rattail_corepos/importing/corepos/api.py index 0956a12..deff510 100644 --- a/rattail_corepos/importing/corepos/api.py +++ b/rattail_corepos/importing/corepos/api.py @@ -57,6 +57,7 @@ class FromCOREPOSToRattail(importing.ToRattailHandler): importers['Person'] = PersonImporter importers['CustomerPerson'] = CustomerPersonImporter importers['Member'] = MemberImporter + importers['Store'] = StoreImporter importers['Department'] = DepartmentImporter importers['Subdepartment'] = SubdepartmentImporter importers['Vendor'] = VendorImporter @@ -349,6 +350,28 @@ class CustomerPersonImporter(FromCOREPOSAPI, importing.model.CustomerPersonImpor } +class StoreImporter(FromCOREPOSAPI, corepos_importing.model.StoreImporter): + """ + Importer for store data from CORE POS API. + """ + key = 'corepos_id' + supported_fields = [ + 'corepos_id', + 'id', + 'name', + ] + + def get_host_objects(self): + return self.api.get_stores() + + def normalize_host_object(self, store): + return { + 'corepos_id': int(store['storeID']), + 'id': str(store['storeID']), + 'name': store['description'], + } + + class DepartmentImporter(FromCOREPOSAPI, corepos_importing.model.DepartmentImporter): """ Importer for department data from CORE POS API. diff --git a/rattail_corepos/importing/model.py b/rattail_corepos/importing/model.py index a2a1f0a..861574a 100644 --- a/rattail_corepos/importing/model.py +++ b/rattail_corepos/importing/model.py @@ -69,6 +69,14 @@ class MemberImporter(importing.model.MemberImporter): ] +class StoreImporter(importing.model.StoreImporter): + + extension_attr = '_corepos' + extension_fields = [ + 'corepos_id', + ] + + class DepartmentImporter(importing.model.DepartmentImporter): extension_attr = '_corepos' diff --git a/rattail_corepos/importing/versions.py b/rattail_corepos/importing/versions.py index b060d9a..f0d5d89 100644 --- a/rattail_corepos/importing/versions.py +++ b/rattail_corepos/importing/versions.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2020 Lance Edgar +# Copyright © 2010-2021 Lance Edgar # # This file is part of Rattail. # @@ -36,6 +36,7 @@ class CoreposVersionMixin(object): importers['CorePerson'] = CorePersonImporter importers['CoreCustomer'] = CoreCustomerImporter importers['CoreMember'] = CoreMemberImporter + importers['CoreStore'] = CoreStoreImporter importers['CoreDepartment'] = CoreDepartmentImporter importers['CoreSubdepartment'] = CoreSubdepartmentImporter importers['CoreVendor'] = CoreVendorImporter @@ -67,6 +68,14 @@ class CoreMemberImporter(base.VersionImporter): return model.CoreMember +class CoreStoreImporter(base.VersionImporter): + + @property + def host_model_class(self): + model = self.config.get_model() + return model.CoreStore + + class CoreDepartmentImporter(base.VersionImporter): @property