Add stock 'antipurchase' for auditing
This commit is contained in:
parent
015c64a2ac
commit
8977071b3e
49
db.py
49
db.py
|
@ -1,7 +1,7 @@
|
||||||
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey, create_engine, DateTime, Boolean, or_
|
from sqlalchemy import Column, Integer, String, ForeignKey, create_engine, DateTime, Boolean
|
||||||
from sqlalchemy.orm import sessionmaker, relationship, backref
|
from sqlalchemy.orm import sessionmaker, relationship, backref
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
from math import ceil
|
from math import ceil, floor
|
||||||
import datetime
|
import datetime
|
||||||
import conf
|
import conf
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ engine = create_engine(conf.db_url)
|
||||||
Base = declarative_base()
|
Base = declarative_base()
|
||||||
Session = sessionmaker(bind=engine)
|
Session = sessionmaker(bind=engine)
|
||||||
|
|
||||||
|
|
||||||
class User(Base):
|
class User(Base):
|
||||||
__tablename__ = 'users'
|
__tablename__ = 'users'
|
||||||
name = Column(String(10), primary_key=True)
|
name = Column(String(10), primary_key=True)
|
||||||
|
@ -20,7 +21,7 @@ class User(Base):
|
||||||
card_re = r"(([Nn][Tt][Nn][Uu])?[0-9]+)?"
|
card_re = r"(([Nn][Tt][Nn][Uu])?[0-9]+)?"
|
||||||
rfid_re = r"[0-9]*"
|
rfid_re = r"[0-9]*"
|
||||||
|
|
||||||
def __init__(self, name, card, rfid, credit=0):
|
def __init__(self, name, card, rfid=None, credit=0):
|
||||||
self.name = name
|
self.name = name
|
||||||
if card == '':
|
if card == '':
|
||||||
card = None
|
card = None
|
||||||
|
@ -39,6 +40,7 @@ class User(Base):
|
||||||
def is_anonymous(self):
|
def is_anonymous(self):
|
||||||
return self.card == '11122233'
|
return self.card == '11122233'
|
||||||
|
|
||||||
|
|
||||||
class Product(Base):
|
class Product(Base):
|
||||||
__tablename__ = 'products'
|
__tablename__ = 'products'
|
||||||
|
|
||||||
|
@ -61,7 +63,8 @@ class Product(Base):
|
||||||
self.hidden = hidden
|
self.hidden = hidden
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Product('%s', '%s', '%s', '%s', '%s')>" % (self.name, self.bar_code, self.price, self.stock, self.hidden)
|
return "<Product('%s', '%s', '%s', '%s', '%s')>" %\
|
||||||
|
(self.name, self.bar_code, self.price, self.stock, self.hidden)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -91,6 +94,7 @@ class PurchaseEntry(Base):
|
||||||
self.product_bar_code = product.bar_code
|
self.product_bar_code = product.bar_code
|
||||||
self.purchase = purchase
|
self.purchase = purchase
|
||||||
self.amount = amount
|
self.amount = amount
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<PurchaseEntry('%s', '%s')>" % (self.product.name, self.amount)
|
return "<PurchaseEntry('%s', '%s')>" % (self.product.name, self.amount)
|
||||||
|
|
||||||
|
@ -115,13 +119,11 @@ class Transaction(Base):
|
||||||
self.purchase = purchase
|
self.purchase = purchase
|
||||||
self.penalty = penalty
|
self.penalty = penalty
|
||||||
|
|
||||||
def perform_transaction(self):
|
def perform_transaction(self, ignore_penalty=False):
|
||||||
self.time = datetime.datetime.now()
|
self.time = datetime.datetime.now()
|
||||||
|
if not ignore_penalty:
|
||||||
self.amount *= self.penalty
|
self.amount *= self.penalty
|
||||||
self.user.credit -= self.amount
|
self.user.credit -= self.amount
|
||||||
if self.purchase:
|
|
||||||
for entry in self.purchase.entries:
|
|
||||||
entry.product.stock -= entry.amount
|
|
||||||
|
|
||||||
|
|
||||||
class Purchase(Base):
|
class Purchase(Base):
|
||||||
|
@ -129,12 +131,8 @@ class Purchase(Base):
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
time = Column(DateTime)
|
time = Column(DateTime)
|
||||||
# user_name = Column(Integer, ForeignKey('users.name'))
|
|
||||||
price = Column(Integer)
|
price = Column(Integer)
|
||||||
# performed = Column(Boolean)
|
|
||||||
|
|
||||||
# user = relationship(User, backref=backref('purchases', order_by=id))
|
|
||||||
# users = relationship(User, secondary=purchase_user, backref='purhcases'
|
|
||||||
transactions = relationship(Transaction, order_by=Transaction.user_name, backref='purchase')
|
transactions = relationship(Transaction, order_by=Transaction.user_name, backref='purchase')
|
||||||
entries = relationship(PurchaseEntry, backref=backref("purchase"))
|
entries = relationship(PurchaseEntry, backref=backref("purchase"))
|
||||||
|
|
||||||
|
@ -142,26 +140,37 @@ class Purchase(Base):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Purchase(%d, %d, '%s')>" % (self.id, self.price, self.time.strftime('%c'))
|
return "<Purchase(%d, %d, '%s')>" % (int(self.id), self.price, self.time.strftime('%c'))
|
||||||
|
|
||||||
def is_complete(self):
|
def is_complete(self):
|
||||||
return len(self.transactions) > 0 and len(self.entries) > 0
|
return len(self.transactions) > 0 and len(self.entries) > 0
|
||||||
|
|
||||||
def price_per_transaction(self):
|
def price_per_transaction(self, round_up=True):
|
||||||
|
if round_up:
|
||||||
return int(ceil(float(self.price)/len(self.transactions)))
|
return int(ceil(float(self.price)/len(self.transactions)))
|
||||||
|
else:
|
||||||
|
return int(floor(float(self.price)/len(self.transactions)))
|
||||||
|
|
||||||
def set_price(self):
|
def set_price(self, round_up=True):
|
||||||
self.price = 0
|
self.price = 0
|
||||||
for entry in self.entries:
|
for entry in self.entries:
|
||||||
self.price += entry.amount*entry.product.price
|
self.price += entry.amount*entry.product.price
|
||||||
if len(self.transactions) > 0:
|
if len(self.transactions) > 0:
|
||||||
for t in self.transactions:
|
for t in self.transactions:
|
||||||
t.amount = self.price_per_transaction()
|
t.amount = self.price_per_transaction(round_up=round_up)
|
||||||
|
|
||||||
def perform_purchase(self):
|
def perform_purchase(self, ignore_penalty=False, round_up=True):
|
||||||
self.time = datetime.datetime.now()
|
self.time = datetime.datetime.now()
|
||||||
self.set_price()
|
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:
|
for t in self.transactions:
|
||||||
t.perform_transaction()
|
t.perform_transaction()
|
||||||
# self.user.credit -= self.price
|
|
||||||
# self.performed = True
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from math import ceil
|
from math import ceil
|
||||||
|
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
from db import Product, User, Transaction
|
from db import Product, User, Transaction, PurchaseEntry, Purchase
|
||||||
from text_interface.helpermenus import Menu
|
from text_interface.helpermenus import Menu
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,21 +48,15 @@ much money you're due in credits for the purchase when prompted.\n'''
|
||||||
# user from accidentally killing it
|
# user from accidentally killing it
|
||||||
self.exit_confirm_msg = 'Abort transaction?'
|
self.exit_confirm_msg = 'Abort transaction?'
|
||||||
else:
|
else:
|
||||||
# thing = None
|
|
||||||
|
|
||||||
if not self.complete_input():
|
if not self.complete_input():
|
||||||
if self.confirm('Not enough information entered. Abort transaction?', default=True):
|
if self.confirm('Not enough information entered. Abort transaction?', default=True):
|
||||||
return False
|
return False
|
||||||
continue
|
continue
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
# Add the thing to the pending adjustments:
|
# Add the thing to the pending adjustments:
|
||||||
self.add_thing_to_pending(thing, amount, thing_price)
|
self.add_thing_to_pending(thing, amount, thing_price)
|
||||||
|
|
||||||
if self.confirm('Do you want to change the credited amount?', default=False):
|
|
||||||
self.price = self.input_int('Total amount> ', (1, 100000), default=self.price)
|
|
||||||
|
|
||||||
self.perform_transaction()
|
self.perform_transaction()
|
||||||
|
|
||||||
def complete_input(self):
|
def complete_input(self):
|
||||||
|
@ -77,8 +71,6 @@ much money you're due in credits for the purchase when prompted.\n'''
|
||||||
print('\n%-' + str(Product.name_length - 1) + 's Amount') % "Product"
|
print('\n%-' + str(Product.name_length - 1) + 's Amount') % "Product"
|
||||||
print(6 + Product.name_length) * '-'
|
print(6 + Product.name_length) * '-'
|
||||||
if len(self.products):
|
if len(self.products):
|
||||||
# print "Products added:"
|
|
||||||
# print (6+Product.name_length)*'-'
|
|
||||||
for product in self.products.keys():
|
for product in self.products.keys():
|
||||||
print('%' + str(-Product.name_length) + 's %5i') % (product.name, self.products[product][0])
|
print('%' + str(-Product.name_length) + 's %5i') % (product.name, self.products[product][0])
|
||||||
print(6 + Product.name_length) * '-'
|
print(6 + Product.name_length) * '-'
|
||||||
|
@ -98,13 +90,9 @@ much money you're due in credits for the purchase when prompted.\n'''
|
||||||
self.products[thing] = [amount, price]
|
self.products[thing] = [amount, price]
|
||||||
|
|
||||||
def perform_transaction(self):
|
def perform_transaction(self):
|
||||||
# self.user.credit += self.price
|
|
||||||
description = self.input_str('Log message> ', length_range=(0, 50))
|
description = self.input_str('Log message> ', length_range=(0, 50))
|
||||||
if description == '':
|
if description == '':
|
||||||
description = 'Purchased products for PVVVV, adjusted credit ' + str(self.price)
|
description = 'Purchased products for PVVVV, adjusted credit ' + str(self.price)
|
||||||
transaction = Transaction(self.user, -self.price, description)
|
|
||||||
transaction.perform_transaction()
|
|
||||||
self.session.add(transaction)
|
|
||||||
for product in self.products:
|
for product in self.products:
|
||||||
value = max(product.stock, 0) * product.price + self.products[product][1]
|
value = max(product.stock, 0) * product.price + self.products[product][1]
|
||||||
old_price = product.price
|
old_price = product.price
|
||||||
|
@ -115,6 +103,15 @@ much money you're due in credits for the purchase when prompted.\n'''
|
||||||
print "New stock for %s: %d" % (product.name, product.stock), \
|
print "New stock for %s: %d" % (product.name, product.stock), \
|
||||||
("- New price: " + str(product.price) if old_price != product.price else ""), \
|
("- New price: " + str(product.price) if old_price != product.price else ""), \
|
||||||
("- Removed hidden status" if old_hidden != product.hidden else "")
|
("- Removed hidden status" if old_hidden != product.hidden else "")
|
||||||
|
|
||||||
|
purchase = Purchase()
|
||||||
|
Transaction(self.user, purchase=purchase, amount=-self.price, description=description)
|
||||||
|
for product in self.products:
|
||||||
|
PurchaseEntry(purchase, product, -self.products[product][0])
|
||||||
|
|
||||||
|
purchase.perform_soft_purchase(-self.price, round_up=False)
|
||||||
|
self.session.add(purchase)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
print "Success! Transaction performed:"
|
print "Success! Transaction performed:"
|
||||||
|
|
Loading…
Reference in New Issue