Check negative on cancellation.

- Like perform operations, cancel_operations can add/remove an account
  from negative accounts system.
- Balances checks are now performed against real_balance instead of
  balance.
  So if someone with a balance_offset go, for real, to positive land (ie even
  without taking into account the balance offset), its account is removed from
  the negative system.
- Fix bug on real_balance when negative exists but balance_offset is
  not set.

Fixes #156.
This commit is contained in:
Aurélien Delobelle 2017-04-13 15:15:59 +02:00
parent a725f8020c
commit 18425b82c2
2 changed files with 42 additions and 19 deletions

View file

@ -81,7 +81,7 @@ class Account(models.Model):
# Propriétés supplémentaires
@property
def real_balance(self):
if (hasattr(self, 'negative')):
if hasattr(self, 'negative') and self.negative.balance_offset:
return self.balance - self.negative.balance_offset
return self.balance
@ -210,6 +210,29 @@ class Account(models.Model):
def delete(self, *args, **kwargs):
pass
def check_negative(self):
if self.real_balance < 0:
if hasattr(self, 'negative') and not self.negative.start:
self.negative.start = timezone.now()
self.negative.save()
elif not hasattr(self, 'negative'):
self.negative = (
AccountNegative.objects.create(
account=self, start=timezone.now(),
)
)
elif hasattr(self, 'negative'):
# self.real_balance >= 0
balance_offset = self.negative.balance_offset
if balance_offset:
(
Account.objects
.filter(pk=self.pk)
.update(balance=F('balance')-balance_offset)
)
self.refresh_from_db()
self.negative.delete()
class UserHasAccount(Exception):
def __init__(self, trigramme):
self.trigramme = trigramme

View file

@ -1105,22 +1105,15 @@ def kpsul_perform_operations(request):
with transaction.atomic():
# If not cash account,
# saving account's balance and adding to Negative if not in
if not operationgroup.on_acc.is_cash:
Account.objects.filter(pk=operationgroup.on_acc.pk).update(
balance=F('balance') + operationgroup.amount)
operationgroup.on_acc.refresh_from_db()
if operationgroup.on_acc.balance < 0:
if hasattr(operationgroup.on_acc, 'negative'):
if not operationgroup.on_acc.negative.start:
operationgroup.on_acc.negative.start = timezone.now()
operationgroup.on_acc.negative.save()
else:
negative = AccountNegative(
account=operationgroup.on_acc, start=timezone.now())
negative.save()
elif (hasattr(operationgroup.on_acc, 'negative') and
not operationgroup.on_acc.negative.balance_offset):
operationgroup.on_acc.negative.delete()
on_acc = operationgroup.on_acc
if not on_acc.is_cash:
(
Account.objects
.filter(pk=on_acc.pk)
.update(balance=F('balance') + operationgroup.amount)
)
on_acc.refresh_from_db()
on_acc.check_negative()
# Updating checkout's balance
if to_checkout_balance:
@ -1311,8 +1304,15 @@ def kpsul_cancel_operations(request):
(Operation.objects.filter(pk__in=opes)
.update(canceled_by=canceled_by, canceled_at=canceled_at))
for account in to_accounts_balances:
Account.objects.filter(pk=account.pk).update(
balance = F('balance') + to_accounts_balances[account])
(
Account.objects
.filter(pk=account.pk)
.update(balance=F('balance') + to_accounts_balances[account])
)
if not account.is_cash:
# Should always be true, but we want to be sure
account.refresh_from_db()
account.check_negative()
for checkout in to_checkouts_balances:
Checkout.objects.filter(pk=checkout.pk).update(
balance = F('balance') + to_checkouts_balances[checkout])