Merge branch 'consignes' into 'master'

Add limit for ecocup recording

See merge request !90
This commit is contained in:
Skia 2017-08-15 18:03:51 +02:00
commit 0ffd7485e3
7 changed files with 327 additions and 203 deletions

View File

@ -39,7 +39,7 @@ from accounting.models import GeneralJournal, BankAccount, ClubAccount, Operatio
from core.utils import resize_image
from club.models import Club, Membership
from subscription.models import Subscription
from counter.models import Customer, ProductType, Product, Counter
from counter.models import Customer, ProductType, Product, Counter, Selling
from com.models import Sith, Weekmail
from election.models import Election, Role, Candidature, ElectionList
from forum.models import Forum, ForumTopic
@ -340,6 +340,8 @@ Welcome to the wiki page!
c.save()
r = ProductType(name="Rechargements")
r.save()
verre = ProductType(name="Verre")
verre.save()
cotis = Product(name="Cotis 1 semestre", code="1SCOTIZ", product_type=c, purchase_price="15", selling_price="15",
special_selling_price="15", club=main_club)
cotis.save()
@ -355,6 +357,14 @@ Welcome to the wiki page!
cble = Product(name="Chimay Bleue", code="CBLE", product_type=p, purchase_price="1.50", selling_price="1.7",
special_selling_price="1.6", club=main_club)
cble.save()
cons = Product(name="Consigne Eco-cup", code="CONS", product_type=verre, purchase_price="1", selling_price="1",
special_selling_price="1", club=main_club)
cons.id = 1152
cons.save()
dcons = Product(name="Déconsigne Eco-cup", code="DECO", product_type=verre, purchase_price="-1", selling_price="-1",
special_selling_price="-1", club=main_club)
dcons.id = 1151
dcons.save()
Product(name="Corsendonk", code="CORS", product_type=p, purchase_price="1.50", selling_price="1.7",
special_selling_price="1.6", club=main_club).save()
Product(name="Carolus", code="CARO", product_type=p, purchase_price="1.50", selling_price="1.7",
@ -362,6 +372,8 @@ Welcome to the wiki page!
mde = Counter.objects.filter(name="MDE").first()
mde.products.add(barb)
mde.products.add(cble)
mde.products.add(cons)
mde.products.add(dcons)
mde.sellers.add(skia)
mde.save()
@ -473,6 +485,9 @@ Welcome to the wiki page!
start=s.subscription_start)
s.save()
Selling(label=dcons.name, product=dcons, counter=mde, unit_price=dcons.selling_price, club=main_club,
quantity=settings.SITH_ECOCUP_LIMIT + 3, seller=skia, customer=krophil.customer).save()
# Add barman to counter
c = Counter.objects.get(id=2)
c.sellers.add(User.objects.get(pk=krophil.pk))

View File

@ -37,14 +37,18 @@
<h3>{% trans %}User account{% endtrans %}</h3>
<p>{% trans %}Amount: {% endtrans %}{{ customer.amount }} €</p>
<div id="drop">
{% if customer.refillings.exists() %}
{% if customer.buyings.exists() %}
{% set bought = customer.buyings.exists() %}
{% set refilled = customer.refillings.exists() %}
{% if bought or refilled %}
{% if bought %}
<h5>{% trans %}Account buyings{% endtrans %}</h5>
{{ monthly(buyings_month) }}
{% endif %}
{% if refilled %}
<h5>{% trans %}Refillings{% endtrans %}</h5>
{{ monthly(refilling_month) }}
{% endif %}
{% endif %}
{% if customer.user.invoices.exists() %}
<h5>{% trans %}Eboutic invoices{% endtrans %}</h5>
{{ monthly(invoices_month) }}

View File

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
from django.db import migrations, models
from django.conf import settings
from core.models import User
from counter.models import Customer, Product, Selling, Counter
def balance_ecocups(apps, schema_editor):
for customer in Customer.objects.all():
customer.recorded_products = 0
for selling in customer.buyings.filter(product__id__in=[settings.SITH_ECOCUP_CONS, settings.SITH_ECOCUP_DECO]).all():
if selling.product.is_record_product:
customer.recorded_products += selling.quantity
elif selling.product.is_unrecord_product:
customer.recorded_products -= selling.quantity
if customer.recorded_products < -settings.SITH_ECOCUP_LIMIT:
qt = -(customer.recorded_products + settings.SITH_ECOCUP_LIMIT)
cons = Product.objects.get(id=settings.SITH_ECOCUP_CONS)
Selling(label=_("Ecocup regularization"), product=cons, unit_price=cons.selling_price,
club=cons.club, counter=Counter.objects.filter(name='Foyer').first(),
quantity=qt, seller=User.objects.get(id=0), customer=customer).save(allow_negative=True)
customer.recorded_products += qt
customer.save()
class Migration(migrations.Migration):
dependencies = [
('counter', '0012_auto_20170515_2202'),
]
operations = [
migrations.AddField(
model_name='customer',
name='recorded_products',
field=models.IntegerField(verbose_name='recorded items', default=0),
),
migrations.RunPython(balance_ecocups),
]

View File

@ -51,6 +51,7 @@ class Customer(models.Model):
user = models.OneToOneField(User, primary_key=True)
account_id = models.CharField(_('account id'), max_length=10, unique=True)
amount = CurrencyField(_('amount'))
recorded_products = models.IntegerField(_('recorded product'), default=0)
class Meta:
verbose_name = _('customer')
@ -60,6 +61,13 @@ class Customer(models.Model):
def __str__(self):
return "%s - %s" % (self.user.username, self.account_id)
@property
def can_record(self):
return self.recorded_products > -settings.SITH_ECOCUP_LIMIT
def can_record_more(self, number):
return self.recorded_products - number >= -settings.SITH_ECOCUP_LIMIT
@property
def can_buy(self):
return (self.user.subscriptions.last() and
@ -72,8 +80,13 @@ class Customer(models.Model):
letter = random.choice(string.ascii_lowercase)
return number + letter
def save(self, *args, **kwargs):
if self.amount < 0:
def save(self, allow_negative=False, is_selling=False, *args, **kwargs):
"""
is_selling : tell if the current action is a selling
allow_negative : ignored if not a selling. Allow a selling to put the account in negative
Those two parameters avoid blocking the save method of a customer if his account is negative
"""
if self.amount < 0 and (is_selling and not allow_negative):
raise ValidationError(_("Not enough money"))
super(Customer, self).save(*args, **kwargs)
@ -143,6 +156,14 @@ class Product(models.Model):
class Meta:
verbose_name = _('product')
@property
def is_record_product(self):
return settings.SITH_ECOCUP_CONS == self.id
@property
def is_unrecord_product(self):
return settings.SITH_ECOCUP_DECO == self.id
def is_owned_by(self, user):
"""
Method to see if that object can be edited by the given user
@ -376,13 +397,16 @@ class Selling(models.Model):
html_message=message_html
)
def save(self, *args, **kwargs):
def save(self, allow_negative=False, *args, **kwargs):
"""
allow_negative : Allow this selling to use more money than available for this user
"""
if not self.date:
self.date = timezone.now()
self.full_clean()
if not self.is_validated:
self.customer.amount -= self.quantity * self.unit_price
self.customer.save()
self.customer.save(allow_negative=allow_negative, is_selling=True)
self.is_validated = True
u = User.objects.filter(id=self.customer.user.id).first()
if u.was_subscribed:

View File

@ -330,6 +330,28 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
except:
return 0
def compute_record_product(self, request, product=None):
recorded = 0
basket = request.session['basket']
if product:
if product.is_record_product:
recorded -= 1
elif product.is_unrecord_product:
recorded += 1
for p in basket:
bproduct = self.get_product(str(p))
if bproduct.is_record_product:
recorded -= basket[p]['qty']
elif bproduct.is_unrecord_product:
recorded += basket[p]['qty']
return recorded
def is_record_product_ok(self, request, product):
return self.customer.can_record_more(
self.compute_record_product(request, product))
def add_product(self, request, q=1, p=None):
"""
Add a product to the basket
@ -359,6 +381,9 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
if self.customer.amount < (total + round(q * float(price), 2)): # Check for enough money
request.session['not_enough'] = True
return False
if product.is_unrecord_product and not self.is_record_product_ok(request, product):
request.session['not_allowed'] = True
return False
if product.limit_age >= 18 and not self.customer.user.date_of_birth:
request.session['no_age'] = True
return False
@ -421,6 +446,9 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
""" Finish the click session, and validate the basket """
with transaction.atomic():
request.session['last_basket'] = []
if self.sum_basket(request) > self.customer.amount:
raise DataError(_("You have not enough money to buy all the basket"))
for pid, infos in request.session['basket'].items():
# This duplicates code for DB optimization (prevent to load many times the same object)
p = Product.objects.filter(pk=pid).first()
@ -428,8 +456,6 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
uprice = p.special_selling_price
else:
uprice = p.selling_price
if uprice * infos['qty'] > self.customer.amount:
raise DataError(_("You have not enough money to buy all the basket"))
request.session['last_basket'].append("%d x %s" % (infos['qty'] + infos['bonus_qty'], p.name))
s = Selling(label=p.name, product=p, club=p.club, counter=self.object, unit_price=uprice,
quantity=infos['qty'], seller=self.operator, customer=self.customer)
@ -438,6 +464,8 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
s = Selling(label=p.name + " (Plateau)", product=p, club=p.club, counter=self.object, unit_price=0,
quantity=infos['bonus_qty'], seller=self.operator, customer=self.customer)
s.save()
self.customer.recorded_products -= self.compute_record_product(request)
self.customer.save()
request.session['last_customer'] = self.customer.user.get_display_name()
request.session['last_total'] = "%0.2f" % self.sum_basket(request)
request.session['new_customer_amount'] = str(self.customer.amount)

File diff suppressed because it is too large Load Diff

View File

@ -397,6 +397,13 @@ SITH_COUNTER_BANK = [
('LA-POSTE', 'La Poste'),
]
SITH_ECOCUP_CONS = 1152
SITH_ECOCUP_DECO = 1151
# The limit is the maximum difference between cons and deco possible for a customer
SITH_ECOCUP_LIMIT = 3
# Defines pagination for cash summary
SITH_COUNTER_CASH_SUMMARY_LENGTH = 50