diff --git a/corepos/db/common/op.py b/corepos/db/common/op.py index 30ecc1c..7cf84fc 100644 --- a/corepos/db/common/op.py +++ b/corepos/db/common/op.py @@ -27,24 +27,6 @@ Common schema for operational data models import sqlalchemy as sa -class ParameterBase: - """ - Base class for Parameter models, shared by Office + Lane. - """ - store_id = sa.Column(sa.SmallInteger(), primary_key=True, nullable=False) - - lane_id = sa.Column(sa.SmallInteger(), primary_key=True, nullable=False) - - param_key = sa.Column(sa.String(length=100), primary_key=True, nullable=False) - - param_value = sa.Column(sa.String(length=255), nullable=True) - - is_array = sa.Column(sa.Boolean(), nullable=True) - - def __str__(self): - return f"{self.store_id}-{self.lane_id} {self.param_key}" - - class EmployeeBase: """ Base class for Employee models, shared by Office + Lane. @@ -72,102 +54,3 @@ class EmployeeBase: def __str__(self): return ' '.join([self.first_name or '', self.last_name or '']).strip() - - -class ProductBase: - """ - Base class for Product models, shared by Office + Lane. - """ - id = sa.Column(sa.Integer(), nullable=False, primary_key=True, autoincrement=True) - - upc = sa.Column(sa.String(length=13), nullable=True) - - description = sa.Column(sa.String(length=30), nullable=True) - - brand = sa.Column(sa.String(length=30), nullable=True) - - formatted_name = sa.Column(sa.String(length=30), nullable=True) - - normal_price = sa.Column(sa.Float(), nullable=True) - - price_method = sa.Column('pricemethod', sa.SmallInteger(), nullable=True) - - group_price = sa.Column('groupprice', sa.Float(), nullable=True) - - quantity = sa.Column(sa.SmallInteger(), nullable=True) - - special_price = sa.Column(sa.Float(), nullable=True) - - special_price_method = sa.Column('specialpricemethod', sa.SmallInteger(), nullable=True) - - special_group_price = sa.Column('specialgroupprice', sa.Float(), nullable=True) - - special_quantity = sa.Column('specialquantity', sa.SmallInteger(), nullable=True) - - special_limit = sa.Column(sa.SmallInteger(), nullable=True) - - start_date = sa.Column(sa.DateTime(), nullable=True) - - end_date = sa.Column(sa.DateTime(), nullable=True) - - department_number = sa.Column('department', sa.SmallInteger(), nullable=True) - - size = sa.Column(sa.String(length=9), nullable=True) - - tax_rate_id = sa.Column('tax', sa.SmallInteger(), nullable=True) - - foodstamp = sa.Column(sa.Boolean(), nullable=True) - - scale = sa.Column(sa.Boolean(), nullable=True) - - scale_price = sa.Column('scaleprice', sa.Float(), nullable=True) - - mix_match_code = sa.Column('mixmatchcode', sa.String(length=13), nullable=True) - - created = sa.Column(sa.DateTime(), nullable=True) - - modified = sa.Column(sa.DateTime(), nullable=True) - - tare_weight = sa.Column('tareweight', sa.Float(), nullable=True) - - discount = sa.Column(sa.SmallInteger(), nullable=True) - - discount_type = sa.Column('discounttype', sa.SmallInteger(), nullable=True) - - line_item_discountable = sa.Column(sa.Boolean(), nullable=True) - - unit_of_measure = sa.Column('unitofmeasure', sa.String(length=15), nullable=True) - - wicable = sa.Column(sa.SmallInteger(), nullable=True) - - quantity_enforced = sa.Column('qttyEnforced', sa.Boolean(), nullable=True) - - id_enforced = sa.Column('idEnforced', sa.SmallInteger(), nullable=True) - - cost = sa.Column(sa.Float(), nullable=True) - - special_cost = sa.Column(sa.Float(), nullable=True) - - received_cost = sa.Column(sa.Float(), nullable=True) - - in_use = sa.Column('inUse', sa.Boolean(), nullable=True) - - numflag = sa.Column(sa.Integer(), nullable=True) - - subdepartment_number = sa.Column('subdept', sa.SmallInteger(), nullable=True) - - deposit = sa.Column(sa.Float(), nullable=True) - - local = sa.Column(sa.Integer(), nullable=True, default=0) - - store_id = sa.Column(sa.SmallInteger(), nullable=True) - - default_vendor_id = sa.Column(sa.Integer(), nullable=True) - - current_origin_id = sa.Column(sa.Integer(), nullable=True) - - auto_par = sa.Column(sa.Float(), nullable=True, default=0) - - price_rule_id = sa.Column(sa.Integer(), nullable=True, default=0) - - last_sold = sa.Column(sa.DateTime(), nullable=True) diff --git a/corepos/db/common/trans.py b/corepos/db/common/trans.py index 9ec5601..2b4e503 100644 --- a/corepos/db/common/trans.py +++ b/corepos/db/common/trans.py @@ -36,21 +36,25 @@ class TransactionDetailBase: """ # register - register_no = sa.Column(sa.Integer(), nullable=True) + register_number = sa.Column('register_no', sa.Integer(), nullable=True) # txn - trans_id = sa.Column(sa.Integer(), nullable=True) - trans_no = sa.Column(sa.Integer(), nullable=True) - trans_type = sa.Column(sa.String(length=1), nullable=True) - trans_subtype = sa.Column(sa.String(length=2), nullable=True) + 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 - emp_no = sa.Column(sa.Integer(), nullable=True) + employee_number = sa.Column('emp_no', sa.Integer(), nullable=True) # customer - card_no = sa.Column(sa.Integer(), nullable=True) - memType = sa.Column(sa.Integer(), nullable=True) + 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) ############################## @@ -59,7 +63,7 @@ class TransactionDetailBase: upc = sa.Column(sa.String(length=13), nullable=True) - department = sa.Column(sa.Integer(), nullable=True) + department_number = sa.Column('department', sa.Integer(), nullable=True) description = sa.Column(sa.String(length=30), nullable=True) @@ -69,46 +73,51 @@ class TransactionDetailBase: cost = sa.Column(sa.Numeric(precision=10, scale=2), nullable=True) - unitPrice = 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) - regPrice = 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) - foodstamp = sa.Column(sa.Boolean(), 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) - memDiscount = 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) - discounttype = sa.Column(sa.Integer(), nullable=True) + discount_type = sa.Column('discounttype', sa.Integer(), nullable=True) voided = sa.Column(sa.Integer(), nullable=True) - percentDiscount = sa.Column(sa.Integer(), nullable=True) + percent_discount = sa.Column('percentDiscount', sa.Integer(), nullable=True) - ItemQtty = sa.Column(sa.Float(), nullable=True) + item_quantity = sa.Column('ItemQtty', sa.Float(), nullable=True) - volDiscType = sa.Column(sa.Integer(), nullable=True) + volume_discount_type = sa.Column('volDiscType', sa.Integer(), nullable=True) volume = sa.Column(sa.Integer(), nullable=True) - VolSpecial = sa.Column(sa.Numeric(precision=10, scale=2), nullable=True) + volume_special = sa.Column('VolSpecial', sa.Numeric(precision=10, scale=2), nullable=True) - mixMatch = sa.Column(sa.String(length=13), nullable=True) + mix_match = sa.Column('mixMatch', sa.String(length=13), nullable=True) matched = sa.Column(sa.Boolean(), nullable=True) - numflag = sa.Column(sa.Integer(), nullable=True, default=0) + num_flag = sa.Column('numflag', sa.Integer(), nullable=True, default=0) - charflag = sa.Column(sa.String(length=2), nullable=True) + char_flag = sa.Column('charflag', sa.String(length=2), nullable=True) def __str__(self): - txnid = '-'.join([str(val) for val in [self.register_no, - self.trans_no, - self.trans_id]]) - return f"{txnid} {self.description or ''}" + return self.description or '' diff --git a/corepos/db/lane_op/model.py b/corepos/db/lane_op/model.py index 456b1b8..08da4f2 100644 --- a/corepos/db/lane_op/model.py +++ b/corepos/db/lane_op/model.py @@ -33,13 +33,6 @@ from corepos.db.common import op as common Base = orm.declarative_base() -class Parameter(common.ParameterBase, Base): - """ - Data model for ``parameters`` table. - """ - __tablename__ = 'parameters' - - class Employee(common.EmployeeBase, Base): """ Data model for ``employees`` table. @@ -88,11 +81,141 @@ class Department(Base): return self.name or "" -class Product(common.ProductBase, Base): +class Product(Base): """ - Data model for ``products`` table. + Represents a product, purchased and/or sold by the organization. """ __tablename__ = 'products' + # __table_args__ = ( + # sa.ForeignKeyConstraint(['department'], ['departments.dept_no']), + # sa.ForeignKeyConstraint(['subdept'], ['subdepts.subdept_no']), + # sa.ForeignKeyConstraint(['tax'], ['taxrates.id']), + # ) + + id = sa.Column(sa.Integer(), nullable=False, + primary_key=True, autoincrement=True) + + upc = sa.Column(sa.String(length=13), nullable=True) + + description = sa.Column(sa.String(length=30), nullable=True) + + brand = sa.Column(sa.String(length=30), nullable=True) + + formatted_name = sa.Column(sa.String(length=30), nullable=True) + + normal_price = sa.Column(sa.Float(), nullable=True) + + price_method = sa.Column('pricemethod', sa.SmallInteger(), nullable=True) + + group_price = sa.Column('groupprice', sa.Float(), nullable=True) + + quantity = sa.Column(sa.SmallInteger(), nullable=True) + + special_price = sa.Column(sa.Float(), nullable=True) + + special_price_method = sa.Column('specialpricemethod', sa.SmallInteger(), nullable=True) + + special_group_price = sa.Column('specialgroupprice', sa.Float(), nullable=True) + + special_quantity = sa.Column('specialquantity', sa.SmallInteger(), nullable=True) + + special_limit = sa.Column(sa.SmallInteger(), nullable=True) + + start_date = sa.Column(sa.DateTime(), nullable=True) + + end_date = sa.Column(sa.DateTime(), nullable=True) + + department_number = sa.Column('department', sa.SmallInteger(), nullable=True) + # department = orm.relationship( + # Department, + # primaryjoin=Department.number == department_number, + # foreign_keys=[department_number], + # doc=""" + # Reference to the :class:`Department` to which the product belongs. + # """) + + size = sa.Column(sa.String(length=9), nullable=True) + + tax_rate_id = sa.Column('tax', sa.SmallInteger(), nullable=True) + # tax_rate = orm.relationship(TaxRate) + + foodstamp = sa.Column(sa.Boolean(), nullable=True) + + scale = sa.Column(sa.Boolean(), nullable=True) + + scale_price = sa.Column('scaleprice', sa.Float(), nullable=True) + + mix_match_code = sa.Column('mixmatchcode', sa.String(length=13), nullable=True) + + created = sa.Column(sa.DateTime(), nullable=True) + + modified = sa.Column(sa.DateTime(), nullable=True) + + # TODO: what to do about this 'replaces' thing? + # 'batchID'=>array('type'=>'TINYINT', 'replaces'=>'advertised'), + # batch_id = sa.Column('batchID', sa.SmallInteger(), nullable=True) + # advertised = sa.Column(sa.Boolean(), nullable=True) + + tare_weight = sa.Column('tareweight', sa.Float(), nullable=True) + + discount = sa.Column(sa.SmallInteger(), nullable=True) + + discount_type = sa.Column('discounttype', sa.SmallInteger(), nullable=True) + + line_item_discountable = sa.Column(sa.Boolean(), nullable=True) + + unit_of_measure = sa.Column('unitofmeasure', sa.String(length=15), nullable=True) + + wicable = sa.Column(sa.SmallInteger(), nullable=True) + + quantity_enforced = sa.Column('qttyEnforced', sa.Boolean(), nullable=True) + + id_enforced = sa.Column('idEnforced', sa.SmallInteger(), nullable=True) + + cost = sa.Column(sa.Float(), nullable=True) + + special_cost = sa.Column(sa.Float(), nullable=True) + + received_cost = sa.Column(sa.Float(), nullable=True) + + in_use = sa.Column('inUse', sa.Boolean(), nullable=True) + + flags = sa.Column('numflag', sa.Integer(), nullable=True) + + subdepartment_number = sa.Column('subdept', sa.SmallInteger(), nullable=True) + # subdepartment = orm.relationship( + # Subdepartment, + # primaryjoin=Subdepartment.number == subdepartment_number, + # foreign_keys=[subdepartment_number], + # doc=""" + # Reference to the :class:`Subdepartment` to which the product belongs. + # """) + + deposit = sa.Column(sa.Float(), nullable=True) + + local = sa.Column(sa.Integer(), nullable=True, + default=0) # TODO: do we want a default here? + + store_id = sa.Column(sa.SmallInteger(), nullable=True) + + default_vendor_id = sa.Column(sa.Integer(), nullable=True) + # default_vendor = orm.relationship( + # Vendor, + # primaryjoin=Vendor.id == default_vendor_id, + # foreign_keys=[default_vendor_id], + # doc=""" + # Reference to the default :class:`Vendor` from which the product is obtained. + # """) + + current_origin_id = sa.Column(sa.Integer(), nullable=True) + + auto_par = sa.Column(sa.Float(), nullable=True, + default=0) # TODO: do we want a default here? + + price_rule_id = sa.Column(sa.Integer(), nullable=True) + + # TODO: some older DB's might not have this? guess we'll see + last_sold = sa.Column(sa.DateTime(), nullable=True) class CustomerClassic(Base): diff --git a/corepos/db/office_op/model.py b/corepos/db/office_op/model.py index e374d37..67f405a 100644 --- a/corepos/db/office_op/model.py +++ b/corepos/db/office_op/model.py @@ -56,12 +56,25 @@ class StringableDateTime(sa.TypeDecorator): raise NotImplementedError -class Parameter(common.ParameterBase, Base): +class Parameter(Base): """ - Data model for ``parameters`` table. + Represents a "parameter" value. """ __tablename__ = 'parameters' + store_id = sa.Column(sa.SmallInteger(), primary_key=True, nullable=False) + + lane_id = sa.Column(sa.SmallInteger(), primary_key=True, nullable=False) + + param_key = sa.Column(sa.String(length=100), primary_key=True, nullable=False) + + param_value = sa.Column(sa.String(length=255), nullable=True) + + is_array = sa.Column(sa.Boolean(), nullable=True) + + def __str__(self): + return "{}-{} {}".format(self.store_id, self.lane_id, self.param_key) + class TableSyncRule(Base): """ @@ -536,7 +549,7 @@ class Origin(Base): return self.name or self.short_name or "" -class Product(common.ProductBase, Base): +class Product(Base): """ Represents a product, purchased and/or sold by the organization. """ @@ -547,37 +560,120 @@ class Product(common.ProductBase, Base): sa.ForeignKeyConstraint(['tax'], ['taxrates.id']), ) + id = sa.Column(sa.Integer(), primary_key=True, autoincrement=True, nullable=False) + + upc = sa.Column(sa.String(length=13), nullable=True) + + description = sa.Column(sa.String(length=30), nullable=True) + + brand = sa.Column(sa.String(length=30), nullable=True) + + formatted_name = sa.Column(sa.String(length=30), nullable=True) + + normal_price = sa.Column(sa.Float(), nullable=True) + + price_method = sa.Column('pricemethod', sa.SmallInteger(), nullable=True) + + group_price = sa.Column('groupprice', sa.Float(), nullable=True) + + quantity = sa.Column(sa.SmallInteger(), nullable=True) + + special_price = sa.Column(sa.Float(), nullable=True) + + special_price_method = sa.Column('specialpricemethod', sa.SmallInteger(), nullable=True) + + special_group_price = sa.Column('specialgroupprice', sa.Float(), nullable=True) + + special_quantity = sa.Column('specialquantity', sa.SmallInteger(), nullable=True) + + start_date = sa.Column(sa.DateTime(), nullable=True) + + end_date = sa.Column(sa.DateTime(), nullable=True) + + department_number = sa.Column('department', sa.SmallInteger(), nullable=True) department = orm.relationship( Department, - primaryjoin='Department.number == Product.department_number', - foreign_keys='Product.department_number', + primaryjoin=Department.number == department_number, + foreign_keys=[department_number], doc=""" Reference to the :class:`Department` to which the product belongs. """) + size = sa.Column(sa.String(length=9), nullable=True) + + tax_rate_id = sa.Column('tax', sa.SmallInteger(), nullable=True) tax_rate = orm.relationship(TaxRate) + foodstamp = sa.Column(sa.Boolean(), nullable=True) + + scale = sa.Column(sa.Boolean(), nullable=True) + + # TODO: yikes, did i just code this all wrong the first time? pretty sure + # this needs to change to a decimal column... + scale_price = sa.Column('scaleprice', sa.Boolean(), nullable=True) + # scale_price = sa.Column('scaleprice', sa.Numeric(precision=10, scale=2), nullable=True) + + mix_match_code = sa.Column('mixmatchcode', sa.String(length=13), nullable=True) + + created = sa.Column(StringableDateTime(), nullable=True) + + modified = sa.Column(sa.DateTime(), nullable=True) + # advertised = sa.Column(sa.Boolean(), nullable=True) + tare_weight = sa.Column('tareweight', sa.Float(), nullable=True) + + discount = sa.Column(sa.SmallInteger(), nullable=True) + + discount_type = sa.Column('discounttype', sa.SmallInteger(), nullable=True) + + line_item_discountable = sa.Column(sa.Boolean(), nullable=True) + + unit_of_measure = sa.Column('unitofmeasure', sa.String(length=15), nullable=True) + + wicable = sa.Column(sa.SmallInteger(), nullable=True) + + quantity_enforced = sa.Column('qttyEnforced', sa.Boolean(), nullable=True) + + id_enforced = sa.Column('idEnforced', sa.SmallInteger(), nullable=True) + + cost = sa.Column(sa.Float(), nullable=True) + + in_use = sa.Column('inUse', sa.Boolean(), nullable=True) + + flags = sa.Column('numflag', sa.Integer(), nullable=True) + + subdepartment_number = sa.Column('subdept', sa.SmallInteger(), nullable=True) subdepartment = orm.relationship( Subdepartment, - primaryjoin='Subdepartment.number == Product.subdepartment_number', - foreign_keys='Product.subdepartment_number', + primaryjoin=Subdepartment.number == subdepartment_number, + foreign_keys=[subdepartment_number], doc=""" Reference to the :class:`Subdepartment` to which the product belongs. """) + deposit = sa.Column(sa.Float(), nullable=True) + + local = sa.Column(sa.Integer(), nullable=True) + + store_id = sa.Column(sa.SmallInteger(), nullable=True) + + default_vendor_id = sa.Column(sa.Integer(), nullable=True) default_vendor = orm.relationship( Vendor, - primaryjoin='Vendor.id == Product.default_vendor_id', - foreign_keys='Product.default_vendor_id', + primaryjoin=Vendor.id == default_vendor_id, + foreign_keys=[default_vendor_id], doc=""" Reference to the default :class:`Vendor` from which the product is obtained. """) - # TODO: deprecate / remove this? vendor = orm.synonym('default_vendor') + current_origin_id = sa.Column(sa.Integer(), nullable=True) + + # TODO: some older DB's might not have this? guess we'll see + last_sold = sa.Column(sa.DateTime(), nullable=True) + like_code = association_proxy( '_like_code', 'like_code', creator=lambda lc: ProductLikeCode(like_code=lc),