diff --git a/corepos/db/common/__init__.py b/corepos/db/common/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/corepos/db/common/trans.py b/corepos/db/common/trans.py
new file mode 100644
index 0000000..2b4e503
--- /dev/null
+++ b/corepos/db/common/trans.py
@@ -0,0 +1,123 @@
+# -*- coding: utf-8; -*-
+################################################################################
+#
+# pyCOREPOS -- Python Interface to CORE POS
+# Copyright © 2018-2025 Lance Edgar
+#
+# This file is part of pyCOREPOS.
+#
+# pyCOREPOS 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.
+#
+# pyCOREPOS 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
+# pyCOREPOS. If not, see .
+#
+################################################################################
+"""
+Common schema for transaction data models
+"""
+
+import sqlalchemy as sa
+from sqlalchemy import orm
+from sqlalchemy.ext.declarative import declared_attr
+
+
+class TransactionDetailBase:
+ """
+ Base class for POS transaction detail models, shared by Office +
+ Lane.
+ """
+
+ # register
+ register_number = sa.Column('register_no', sa.Integer(), nullable=True)
+
+ # txn
+ transaction_id = sa.Column('trans_id', sa.Integer(), nullable=True)
+ transaction_number = sa.Column('trans_no', sa.Integer(), nullable=True)
+ transaction_type = sa.Column('trans_type', sa.String(length=1), nullable=True)
+ transaction_subtype = sa.Column('trans_subtype', sa.String(length=2), nullable=True)
+ trans_status = sa.Column(sa.String(length=1), nullable=True)
+
+ @declared_attr
+ def transaction_status(self):
+ return orm.synonym('trans_status')
+
+ # cashier
+ employee_number = sa.Column('emp_no', sa.Integer(), nullable=True)
+
+ # customer
+ card_number = sa.Column('card_no', sa.Integer(), nullable=True)
+ member_type = sa.Column('memType', sa.Integer(), nullable=True)
+ staff = sa.Column(sa.Boolean(), nullable=True)
+
+ ##############################
+ # remainder is "line item" ...
+ ##############################
+
+ upc = sa.Column(sa.String(length=13), nullable=True)
+
+ department_number = sa.Column('department', sa.Integer(), nullable=True)
+
+ description = sa.Column(sa.String(length=30), nullable=True)
+
+ quantity = sa.Column(sa.Float(), nullable=True)
+
+ scale = sa.Column(sa.Boolean(), nullable=True, default=False)
+
+ cost = sa.Column(sa.Numeric(precision=10, scale=2), nullable=True)
+
+ unitPrice = sa.Column('unitPrice', sa.Numeric(precision=10, scale=2), nullable=True)
+
+ @declared_attr
+ def unit_price(self):
+ return orm.synonym('unitPrice')
+
+ total = sa.Column(sa.Numeric(precision=10, scale=2), nullable=True)
+
+ reg_price = sa.Column('regPrice', sa.Numeric(precision=10, scale=2), nullable=True)
+
+ tax = sa.Column(sa.SmallInteger(), nullable=True)
+
+ @declared_attr
+ def tax_rate_id(self):
+ return orm.synonym('tax')
+
+ food_stamp = sa.Column('foodstamp', sa.Boolean(), nullable=True)
+
+ discount = sa.Column(sa.Numeric(precision=10, scale=2), nullable=True)
+
+ member_discount = sa.Column('memDiscount', sa.Numeric(precision=10, scale=2), nullable=True)
+
+ discountable = sa.Column(sa.Boolean(), nullable=True)
+
+ discount_type = sa.Column('discounttype', sa.Integer(), nullable=True)
+
+ voided = sa.Column(sa.Integer(), nullable=True)
+
+ percent_discount = sa.Column('percentDiscount', sa.Integer(), nullable=True)
+
+ item_quantity = sa.Column('ItemQtty', sa.Float(), nullable=True)
+
+ volume_discount_type = sa.Column('volDiscType', sa.Integer(), nullable=True)
+
+ volume = sa.Column(sa.Integer(), nullable=True)
+
+ volume_special = sa.Column('VolSpecial', sa.Numeric(precision=10, scale=2), nullable=True)
+
+ mix_match = sa.Column('mixMatch', sa.String(length=13), nullable=True)
+
+ matched = sa.Column(sa.Boolean(), nullable=True)
+
+ num_flag = sa.Column('numflag', sa.Integer(), nullable=True, default=0)
+
+ char_flag = sa.Column('charflag', sa.String(length=2), nullable=True)
+
+ def __str__(self):
+ return self.description or ''
diff --git a/corepos/db/lane_trans/__init__.py b/corepos/db/lane_trans/__init__.py
new file mode 100644
index 0000000..8e8c706
--- /dev/null
+++ b/corepos/db/lane_trans/__init__.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8; -*-
+################################################################################
+#
+# pyCOREPOS -- Python Interface to CORE POS
+# Copyright © 2018-2025 Lance Edgar
+#
+# This file is part of pyCOREPOS.
+#
+# pyCOREPOS 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.
+#
+# pyCOREPOS 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
+# pyCOREPOS. If not, see .
+#
+################################################################################
+"""
+Lane Transaction Database
+"""
+
+from sqlalchemy import orm
+
+
+Session = orm.sessionmaker()
diff --git a/corepos/db/lane_trans/model.py b/corepos/db/lane_trans/model.py
new file mode 100644
index 0000000..b656d8f
--- /dev/null
+++ b/corepos/db/lane_trans/model.py
@@ -0,0 +1,62 @@
+# -*- coding: utf-8; -*-
+################################################################################
+#
+# pyCOREPOS -- Python Interface to CORE POS
+# Copyright © 2018-2025 Lance Edgar
+#
+# This file is part of pyCOREPOS.
+#
+# pyCOREPOS 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.
+#
+# pyCOREPOS 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
+# pyCOREPOS. If not, see .
+#
+################################################################################
+"""
+Data model for CORE POS "lane_trans" DB
+"""
+
+import sqlalchemy as sa
+from sqlalchemy import orm
+
+from corepos.db.common import trans as common
+
+
+Base = orm.declarative_base()
+
+
+class DTransactionBase(common.TransactionDetailBase):
+ """
+ Base class for ``dtransactions`` and similar models.
+ """
+ pos_row_id = sa.Column(sa.Integer(), primary_key=True, nullable=False)
+
+ store_id = sa.Column(sa.Integer(), nullable=True, default=0)
+ date_time = sa.Column('datetime', sa.DateTime(), nullable=True)
+
+
+class DTransaction(DTransactionBase, Base):
+ """
+ Represents a record from ``dtransactions`` table.
+ """
+ __tablename__ = 'dtransactions'
+
+
+class LocalTempTrans(common.TransactionDetailBase, Base):
+ """
+ Represents a record from ``localtemptrans`` table.
+ """
+ __tablename__ = 'localtemptrans'
+ __table_args__ = (
+ sa.PrimaryKeyConstraint('trans_id'),
+ )
+
+ date_time = sa.Column('datetime', sa.DateTime(), nullable=True)
diff --git a/corepos/db/office_arch/model.py b/corepos/db/office_arch/model.py
index 49b0bbd..bc5838f 100644
--- a/corepos/db/office_arch/model.py
+++ b/corepos/db/office_arch/model.py
@@ -2,7 +2,7 @@
################################################################################
#
# pyCOREPOS -- Python Interface to CORE POS
-# Copyright © 2018-2024 Lance Edgar
+# Copyright © 2018-2025 Lance Edgar
#
# This file is part of pyCOREPOS.
#
@@ -24,9 +24,11 @@
CORE Office "arch" data model
"""
+import sqlalchemy as sa
from sqlalchemy import orm
-from corepos.db.office_trans.model import DTransactionBase, DLogBase
+from corepos.db.common import trans as common
+from corepos.db.office_trans.model import DTransactionBase
Base = orm.declarative_base()
@@ -34,7 +36,7 @@ Base = orm.declarative_base()
class BigArchive(DTransactionBase, Base):
"""
- Represents a record from ``bigArchive`` table.
+ Data model for ``bigArchive`` table.
"""
__tablename__ = 'bigArchive'
@@ -43,8 +45,19 @@ class BigArchive(DTransactionBase, Base):
TransactionDetail = BigArchive
+class DLogBase(common.TransactionDetailBase):
+ """
+ Base class for ``dlogBig`` and similar models.
+ """
+ store_row_id = sa.Column(sa.Integer(), primary_key=True, nullable=False)
+
+ store_id = sa.Column(sa.Integer(), nullable=True, default=0)
+ pos_row_id = sa.Column(sa.Integer(), nullable=True)
+ date_time = sa.Column('tdate', sa.DateTime(), nullable=True)
+
+
class DLogBig(DLogBase, Base):
"""
- Represents a record from ``dlogBig`` view.
+ Data model for ``dlogBig`` view.
"""
__tablename__ = 'dlogBig'
diff --git a/corepos/db/office_trans/model.py b/corepos/db/office_trans/model.py
index b4659cd..c2b0959 100644
--- a/corepos/db/office_trans/model.py
+++ b/corepos/db/office_trans/model.py
@@ -2,7 +2,7 @@
################################################################################
#
# pyCOREPOS -- Python Interface to CORE POS
-# Copyright © 2018-2024 Lance Edgar
+# Copyright © 2018-2025 Lance Edgar
#
# This file is part of pyCOREPOS.
#
@@ -26,7 +26,8 @@ CORE POS Transaction Data Model
import sqlalchemy as sa
from sqlalchemy import orm
-from sqlalchemy.ext.declarative import declared_attr
+
+from corepos.db.common import trans as common
Base = orm.declarative_base()
@@ -68,118 +69,20 @@ class EquityLiveBalance(Base):
start_date = sa.Column('startdate', sa.DateTime(), nullable=True)
-class TransactionDetailBase:
+class DTransactionBase(common.TransactionDetailBase):
"""
- Represents a POS transaction detail record.
+ Base class for ``dtransactions`` and similar models.
"""
-
- # store
store_row_id = sa.Column(sa.Integer(), primary_key=True, nullable=False)
- store_id = sa.Column(sa.Integer(), nullable=True, default=0)
- # register
- register_number = sa.Column('register_no', sa.Integer(), nullable=True)
pos_row_id = sa.Column(sa.Integer(), nullable=True)
-
- # txn
- transaction_id = sa.Column('trans_id', sa.Integer(), nullable=True)
- transaction_number = sa.Column('trans_no', sa.Integer(), nullable=True)
- transaction_type = sa.Column('trans_type', sa.String(length=1), nullable=True)
- transaction_subtype = sa.Column('trans_subtype', sa.String(length=2), nullable=True)
-
- trans_status = sa.Column(sa.String(length=1), nullable=True)
-
- @declared_attr
- def transaction_status(self):
- return orm.synonym('trans_status')
-
- # cashier
- employee_number = sa.Column('emp_no', sa.Integer(), nullable=True)
-
- # customer
- card_number = sa.Column('card_no', sa.Integer(), nullable=True)
- member_type = sa.Column('memType', sa.Integer(), nullable=True)
- staff = sa.Column(sa.Boolean(), nullable=True)
-
- ##############################
- # remainder is "line item" ...
- ##############################
-
- upc = sa.Column(sa.String(length=13), nullable=True)
-
- department_number = sa.Column('department', sa.Integer(), nullable=True)
-
- description = sa.Column(sa.String(length=30), nullable=True)
-
- quantity = sa.Column(sa.Float(), nullable=True)
-
- scale = sa.Column(sa.Boolean(), nullable=True, default=False)
-
- cost = sa.Column(sa.Numeric(precision=10, scale=2), nullable=True)
-
- unitPrice = sa.Column('unitPrice', sa.Numeric(precision=10, scale=2), nullable=True)
-
- @declared_attr
- def unit_price(self):
- return orm.synonym('unitPrice')
-
- total = sa.Column(sa.Numeric(precision=10, scale=2), nullable=True)
-
- reg_price = sa.Column('regPrice', sa.Numeric(precision=10, scale=2), nullable=True)
-
- tax = sa.Column(sa.SmallInteger(), nullable=True)
-
- @declared_attr
- def tax_rate_id(self):
- return orm.synonym('tax')
-
- food_stamp = sa.Column('foodstamp', sa.Boolean(), nullable=True)
-
- discount = sa.Column(sa.Numeric(precision=10, scale=2), nullable=True)
-
- member_discount = sa.Column('memDiscount', sa.Numeric(precision=10, scale=2), nullable=True)
-
- discountable = sa.Column(sa.Boolean(), nullable=True)
-
- discount_type = sa.Column('discounttype', sa.Integer(), nullable=True)
-
- voided = sa.Column(sa.Integer(), nullable=True)
-
- percent_discount = sa.Column('percentDiscount', sa.Integer(), nullable=True)
-
- item_quantity = sa.Column('ItemQtty', sa.Float(), nullable=True)
-
- volume_discount_type = sa.Column('volDiscType', sa.Integer(), nullable=True)
-
- volume = sa.Column(sa.Integer(), nullable=True)
-
- volume_special = sa.Column('VolSpecial', sa.Numeric(precision=10, scale=2), nullable=True)
-
- mix_match = sa.Column('mixMatch', sa.String(length=13), nullable=True)
-
- matched = sa.Column(sa.Boolean(), nullable=True)
-
- num_flag = sa.Column('numflag', sa.Integer(), nullable=True, default=0)
-
- char_flag = sa.Column('charflag', sa.String(length=2), nullable=True)
-
- def __str__(self):
- return self.description or ''
-
-
-class DTransactionBase(TransactionDetailBase):
-
+ store_id = sa.Column(sa.Integer(), nullable=True, default=0)
date_time = sa.Column('datetime', sa.DateTime(), nullable=True)
-class DLogBase(TransactionDetailBase):
-
- date_time = sa.Column('tdate', sa.DateTime(), nullable=True)
-
-
class DTransaction(DTransactionBase, Base):
"""
- Represents a record from ``dtransactions`` table.
+ Data model for ``dtransactions`` table.
"""
__tablename__ = 'dtransactions'