dibbler/db.py

177 lines
5.4 KiB
Python
Raw Normal View History

2017-02-21 16:38:41 +01:00
from sqlalchemy import Column, Integer, String, ForeignKey, create_engine, DateTime, Boolean
2010-05-07 19:32:39 +02:00
from sqlalchemy.orm import sessionmaker, relationship, backref
from sqlalchemy.ext.declarative import declarative_base
2017-02-21 16:38:41 +01:00
from math import ceil, floor
2010-05-07 19:32:39 +02:00
import datetime
import conf
2010-05-07 19:32:39 +02:00
engine = create_engine(conf.db_url)
2010-05-07 19:32:39 +02:00
Base = declarative_base()
Session = sessionmaker(bind=engine)
2017-02-21 16:38:41 +01:00
2010-05-07 19:32:39 +02:00
class User(Base):
2015-10-03 20:41:29 +02:00
__tablename__ = 'users'
name = Column(String(10), primary_key=True)
card = Column(String(10))
rfid = Column(String(10))
credit = Column(Integer)
name_re = r"[a-z]+"
card_re = r"(([Nn][Tt][Nn][Uu])?[0-9]+)?"
rfid_re = r"[0-9]*"
2017-02-21 16:38:41 +01:00
def __init__(self, name, card, rfid=None, credit=0):
2015-10-03 20:41:29 +02:00
self.name = name
if card == '':
card = None
self.card = card
if rfid == '':
rfid = None
self.rfid = rfid
self.credit = credit
def __repr__(self):
return "<User('%s')>" % self.name
def __str__(self):
return self.name
def is_anonymous(self):
return self.card == '11122233'
2017-02-21 16:38:41 +01:00
2010-05-07 19:32:39 +02:00
class Product(Base):
2015-10-03 20:41:29 +02:00
__tablename__ = 'products'
2010-05-07 19:32:39 +02:00
product_id = Column(Integer, primary_key=True)
bar_code = Column(String(13))
2015-10-03 20:41:29 +02:00
name = Column(String(45))
price = Column(Integer)
stock = Column(Integer)
hidden = Column(Boolean, nullable=False, default=False)
2010-05-07 19:32:39 +02:00
2015-10-03 20:41:29 +02:00
bar_code_re = r"[0-9]+"
name_re = r".+"
name_length = 45
def __init__(self, bar_code, name, price, stock=0, hidden = False):
2015-10-03 20:41:29 +02:00
self.name = name
self.bar_code = bar_code
self.price = price
self.stock = stock
self.hidden = hidden
2010-05-07 19:32:39 +02:00
2015-10-03 20:41:29 +02:00
def __repr__(self):
2017-02-21 16:38:41 +01:00
return "<Product('%s', '%s', '%s', '%s', '%s')>" %\
(self.name, self.bar_code, self.price, self.stock, self.hidden)
2010-05-07 19:32:39 +02:00
2015-10-03 20:41:29 +02:00
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)
user = relationship(User, backref=backref('products', order_by=count.desc()), lazy='joined')
product = relationship(Product, backref="users", lazy='joined')
2010-05-07 19:32:39 +02:00
class PurchaseEntry(Base):
2015-10-03 20:41:29 +02:00
__tablename__ = 'purchase_entries'
id = Column(Integer, primary_key=True)
2017-02-21 16:38:41 +01:00
purchase_id = Column(Integer, ForeignKey("purchases.id"))
product_id = Column(Integer, ForeignKey("products.product_id"))
2015-10-03 20:41:29 +02:00
amount = Column(Integer)
2017-02-21 16:38:41 +01:00
product = relationship(Product, backref="purchases")
2015-10-03 20:41:29 +02:00
def __init__(self, purchase, product, amount):
self.product = product
self.product_bar_code = product.bar_code
self.purchase = purchase
self.amount = amount
2017-02-21 16:38:41 +01:00
2015-10-03 20:41:29 +02:00
def __repr__(self):
2017-02-21 16:38:41 +01:00
return "<PurchaseEntry('%s', '%s')>" % (self.product.name, self.amount)
2015-10-03 20:41:29 +02:00
2010-05-07 19:32:39 +02:00
class Transaction(Base):
2015-10-03 20:41:29 +02:00
__tablename__ = 'transactions'
2015-10-03 20:41:29 +02:00
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)
2015-10-03 20:41:29 +02:00
user = relationship(User, backref=backref('transactions', order_by=time))
def __init__(self, user, amount=0, description=None, purchase=None, penalty=1):
2015-10-03 20:41:29 +02:00
self.user = user
self.amount = amount
self.description = description
self.purchase = purchase
self.penalty = penalty
2017-02-21 16:38:41 +01:00
def perform_transaction(self, ignore_penalty=False):
2015-10-03 20:41:29 +02:00
self.time = datetime.datetime.now()
2017-02-21 16:38:41 +01:00
if not ignore_penalty:
self.amount *= self.penalty
self.user.credit -= self.amount
2010-05-07 19:32:39 +02:00
class Purchase(Base):
2015-10-03 20:41:29 +02:00
__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):
2017-02-21 16:38:41 +01:00
return "<Purchase(%d, %d, '%s')>" % (int(self.id), self.price, self.time.strftime('%c'))
2015-10-03 20:41:29 +02:00
def is_complete(self):
return len(self.transactions) > 0 and len(self.entries) > 0
2017-02-21 16:38:41 +01:00
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)))
2015-10-03 20:41:29 +02:00
2017-02-21 16:38:41 +01:00
def set_price(self, round_up=True):
2015-10-03 20:41:29 +02:00
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:
2017-02-21 16:38:41 +01:00
t.amount = self.price_per_transaction(round_up=round_up)
2015-10-03 20:41:29 +02:00
2017-02-21 16:38:41 +01:00
def perform_purchase(self, ignore_penalty=False, round_up=True):
2015-10-03 20:41:29 +02:00
self.time = datetime.datetime.now()
2017-02-21 16:38:41 +01:00
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)
2015-10-03 20:41:29 +02:00
for t in self.transactions:
t.perform_transaction()