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.
119 lines
3.9 KiB
119 lines
3.9 KiB
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 |
|
from django.conf import settings |
|
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.debit_limit is not None: |
|
debit_limit = self.account.debit_limit |
|
else: |
|
debit_limit = settings.CASHONLY_DEFAULT_DEBIT_LIMIT |
|
if self.account.credit - total_value >= 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) |
|
|
|
|
|
|