from sqlalchemy import Column, Integer, String, ForeignKey, create_engine, DateTime, Boolean from sqlalchemy.orm import sessionmaker, relationship, backref from sqlalchemy.ext.declarative import declarative_base from math import ceil, floor import datetime import conf engine = create_engine(conf.db_url) Base = declarative_base() Session = sessionmaker(bind=engine) class User(Base): __tablename__ = 'users' name = Column(String(10), primary_key=True) card = Column(String(20)) rfid = Column(String(20)) credit = Column(Integer) name_re = r"[a-z]+" card_re = r"(([Nn][Tt][Nn][Uu])?[0-9]+)?" rfid_re = r"[0-9a-fA-F]*" def __init__(self, name, card, rfid=None, credit=0): self.name = name if card == '': card = None self.card = card if rfid == '': rfid = None self.rfid = rfid self.credit = credit def __repr__(self): return "" % self.name def __str__(self): return self.name def is_anonymous(self): return self.card == '11122233' class Product(Base): __tablename__ = 'products' product_id = Column(Integer, primary_key=True) bar_code = Column(String(13)) name = Column(String(45)) price = Column(Integer) stock = Column(Integer) hidden = Column(Boolean, nullable=False, default=False) bar_code_re = r"[0-9]+" name_re = r".+" name_length = 45 def __init__(self, bar_code, name, price, stock=0, hidden = False): self.name = name self.bar_code = bar_code self.price = price self.stock = stock self.hidden = hidden def __repr__(self): return "" %\ (self.name, self.bar_code, self.price, self.stock, self.hidden) def __str__(self): return self.name class UserProducts(Base): __tablename__ = 'user_products' user_name = Column(String(10), ForeignKey('users.name'), primary_key=True) product_id = Column(Integer, ForeignKey("products.product_id"), primary_key=True) count = Column(Integer) sign = Column(Integer) user = relationship(User, backref=backref('products', order_by=count.desc()), lazy='joined') product = relationship(Product, backref="users", lazy='joined') class PurchaseEntry(Base): __tablename__ = 'purchase_entries' id = Column(Integer, primary_key=True) purchase_id = Column(Integer, ForeignKey("purchases.id")) product_id = Column(Integer, ForeignKey("products.product_id")) amount = Column(Integer) product = relationship(Product, backref="purchases") def __init__(self, purchase, product, amount): self.product = product self.product_bar_code = product.bar_code self.purchase = purchase self.amount = amount def __repr__(self): return "" % (self.product.name, self.amount) class Transaction(Base): __tablename__ = 'transactions' id = Column(Integer, primary_key=True) time = Column(DateTime) user_name = Column(String(10), ForeignKey('users.name')) amount = Column(Integer) description = Column(String(50)) purchase_id = Column(Integer, ForeignKey('purchases.id')) penalty = Column(Integer) user = relationship(User, backref=backref('transactions', order_by=time)) def __init__(self, user, amount=0, description=None, purchase=None, penalty=1): self.user = user self.amount = amount self.description = description self.purchase = purchase self.penalty = penalty def perform_transaction(self, ignore_penalty=False): self.time = datetime.datetime.now() if not ignore_penalty: self.amount *= self.penalty self.user.credit -= self.amount class Purchase(Base): __tablename__ = 'purchases' id = Column(Integer, primary_key=True) time = Column(DateTime) price = Column(Integer) transactions = relationship(Transaction, order_by=Transaction.user_name, backref='purchase') entries = relationship(PurchaseEntry, backref=backref("purchase")) def __init__(self): pass def __repr__(self): return "" % (int(self.id), self.price, self.time.strftime('%c')) def is_complete(self): return len(self.transactions) > 0 and len(self.entries) > 0 def price_per_transaction(self, round_up=True): if round_up: return int(ceil(float(self.price)/len(self.transactions))) else: return int(floor(float(self.price)/len(self.transactions))) def set_price(self, round_up=True): self.price = 0 for entry in self.entries: self.price += entry.amount*entry.product.price if len(self.transactions) > 0: for t in self.transactions: t.amount = self.price_per_transaction(round_up=round_up) def perform_purchase(self, ignore_penalty=False, round_up=True): self.time = datetime.datetime.now() self.set_price(round_up=round_up) for t in self.transactions: t.perform_transaction(ignore_penalty=ignore_penalty) for entry in self.entries: entry.product.stock -= entry.amount def perform_soft_purchase(self, price, round_up=True): self.time = datetime.datetime.now() self.price = price for t in self.transactions: t.amount = self.price_per_transaction(round_up=round_up) for t in self.transactions: t.perform_transaction()