You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
3.7 KiB
115 lines
3.7 KiB
7 years ago
|
from cashonly.core.models import Account, Transaction, SalesLogEntry, Product
|
||
|
from django.core.files import File
|
||
|
from django.contrib.auth.models import User
|
||
|
from django.utils.translation import ugettext_noop
|
||
|
from django.db.models.signals import pre_save, post_save, pre_delete
|
||
|
from django.dispatch import receiver
|
||
|
from django.db import transaction
|
||
|
import PIL.Image
|
||
|
import io
|
||
|
|
||
|
|
||
|
class AccountManager:
|
||
|
def __init__(self, account):
|
||
|
self.account = account
|
||
|
|
||
|
@transaction.atomic
|
||
|
def add_transaction(self, amount, subject, description):
|
||
|
self.account.refresh_from_db()
|
||
|
self.account.credit = self.account.credit + amount
|
||
|
self.account.save()
|
||
|
|
||
|
Transaction.objects.create(account=self.account, subject=subject,
|
||
|
amount=amount, description=description)
|
||
|
|
||
|
def change_credit(self, amount, operator, comment=None):
|
||
|
if amount > 0:
|
||
|
subject = ugettext_noop('Deposit')
|
||
|
elif amount < 0:
|
||
|
subject = ugettext_noop('Payout')
|
||
|
else:
|
||
|
raise ValueError('Amount must not be zero.')
|
||
|
|
||
|
desc = ugettext_noop('Authorized by %(first)s %(last)s') % \
|
||
|
{'first': operator.first_name, 'last': operator.last_name}
|
||
|
if comment is not None and len(comment) > 0:
|
||
|
desc += ' (%s)' % (comment)
|
||
|
|
||
|
self.add_transaction(amount, subject, desc)
|
||
|
|
||
|
@transaction.atomic
|
||
|
def buy_products(self, products):
|
||
|
if min(products.values()) <= 0:
|
||
|
raise ValueError('Non-positive amount in products dict.')
|
||
|
|
||
|
total_value = sum(map(lambda p: p.price * products[p],
|
||
|
products.keys()))
|
||
|
if self.account.credit - total_value >= self.account.debit_limit * -1:
|
||
|
desc = ''
|
||
|
for product in products.keys():
|
||
|
if not product.active:
|
||
|
raise ValueError('Trying to buy a disabled product.')
|
||
|
amount = products[product]
|
||
|
desc += '%d x %s\n' % (amount, product.name)
|
||
|
|
||
|
SalesLogEntry.objects.create(
|
||
|
account=self.account,
|
||
|
product=product,
|
||
|
count=amount,
|
||
|
unit_price=product.price
|
||
|
)
|
||
|
|
||
|
self.add_transaction(-total_value, ugettext_noop('Purchase'), desc)
|
||
|
return True
|
||
|
else:
|
||
|
return False
|
||
|
|
||
|
def buy_product(self, product, amount):
|
||
|
return self.buy_products({product: amount})
|
||
|
|
||
|
def set_pin(self, pin):
|
||
|
self.account.pin = pin
|
||
|
self.account.save()
|
||
|
|
||
|
def clear_pin(self):
|
||
|
self.set_pin('')
|
||
|
|
||
|
def check_pin(self, pin):
|
||
|
return self.account.pin == pin
|
||
|
|
||
|
|
||
|
@receiver(post_save, sender=User)
|
||
|
def user_post_save_handler(sender, instance, created, **kwargs):
|
||
|
# TODO: add possibility to disable this via settings variable
|
||
|
if created:
|
||
|
Account.objects.create(user=instance)
|
||
|
|
||
|
|
||
|
@receiver(pre_delete, sender=SalesLogEntry)
|
||
|
def logentry_pre_delete_handler(sender, instance, **kwargs):
|
||
|
accmgr = AccountManager(instance.account)
|
||
|
accmgr.add_transaction(
|
||
|
instance.unit_price * instance.count,
|
||
|
ugettext_noop('Cancellation'),
|
||
|
'%d x %s' % (instance.count, instance.product.name)
|
||
|
)
|
||
|
|
||
|
|
||
|
@receiver(pre_save, sender=Product)
|
||
|
def product_post_save_handler(sender, instance, **kwargs):
|
||
|
# FIXME
|
||
|
img = instance.image
|
||
|
if img:
|
||
|
scaledFile = io.StringIO()
|
||
|
img.open(mode='r')
|
||
|
with img:
|
||
|
scaled = PIL.Image.open(img)
|
||
|
thumbnail_size = getattr(settings, 'THUMBNAIL_SIZE', (150, 150))
|
||
|
scaled.thumbnail(thumbnail_size, PIL.Image.ANTIALIAS)
|
||
|
scaled.save(scaledFile, 'PNG')
|
||
|
scaledFile.seek(0)
|
||
|
|
||
|
instance.image_thumbnail.save(img.url, File(scaledFile), save=False)
|
||
|
|
||
|
|