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 core.utils import resize_image
from club.models import Club, Membership from club.models import Club, Membership
from subscription.models import Subscription 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 com.models import Sith, Weekmail
from election.models import Election, Role, Candidature, ElectionList from election.models import Election, Role, Candidature, ElectionList
from forum.models import Forum, ForumTopic from forum.models import Forum, ForumTopic
@ -340,6 +340,8 @@ Welcome to the wiki page!
c.save() c.save()
r = ProductType(name="Rechargements") r = ProductType(name="Rechargements")
r.save() 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", cotis = Product(name="Cotis 1 semestre", code="1SCOTIZ", product_type=c, purchase_price="15", selling_price="15",
special_selling_price="15", club=main_club) special_selling_price="15", club=main_club)
cotis.save() 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", 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) special_selling_price="1.6", club=main_club)
cble.save() 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", 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() 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", 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 = Counter.objects.filter(name="MDE").first()
mde.products.add(barb) mde.products.add(barb)
mde.products.add(cble) mde.products.add(cble)
mde.products.add(cons)
mde.products.add(dcons)
mde.sellers.add(skia) mde.sellers.add(skia)
mde.save() mde.save()
@ -473,6 +485,9 @@ Welcome to the wiki page!
start=s.subscription_start) start=s.subscription_start)
s.save() 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 # Add barman to counter
c = Counter.objects.get(id=2) c = Counter.objects.get(id=2)
c.sellers.add(User.objects.get(pk=krophil.pk)) c.sellers.add(User.objects.get(pk=krophil.pk))

View File

@ -37,14 +37,18 @@
<h3>{% trans %}User account{% endtrans %}</h3> <h3>{% trans %}User account{% endtrans %}</h3>
<p>{% trans %}Amount: {% endtrans %}{{ customer.amount }} €</p> <p>{% trans %}Amount: {% endtrans %}{{ customer.amount }} €</p>
<div id="drop"> <div id="drop">
{% if customer.refillings.exists() %} {% set bought = customer.buyings.exists() %}
{% if customer.buyings.exists() %} {% set refilled = customer.refillings.exists() %}
{% if bought or refilled %}
{% if bought %}
<h5>{% trans %}Account buyings{% endtrans %}</h5> <h5>{% trans %}Account buyings{% endtrans %}</h5>
{{ monthly(buyings_month) }} {{ monthly(buyings_month) }}
{% endif %} {% endif %}
{% if refilled %}
<h5>{% trans %}Refillings{% endtrans %}</h5> <h5>{% trans %}Refillings{% endtrans %}</h5>
{{ monthly(refilling_month) }} {{ monthly(refilling_month) }}
{% endif %} {% endif %}
{% endif %}
{% if customer.user.invoices.exists() %} {% if customer.user.invoices.exists() %}
<h5>{% trans %}Eboutic invoices{% endtrans %}</h5> <h5>{% trans %}Eboutic invoices{% endtrans %}</h5>
{{ monthly(invoices_month) }} {{ 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) user = models.OneToOneField(User, primary_key=True)
account_id = models.CharField(_('account id'), max_length=10, unique=True) account_id = models.CharField(_('account id'), max_length=10, unique=True)
amount = CurrencyField(_('amount')) amount = CurrencyField(_('amount'))
recorded_products = models.IntegerField(_('recorded product'), default=0)
class Meta: class Meta:
verbose_name = _('customer') verbose_name = _('customer')
@ -60,6 +61,13 @@ class Customer(models.Model):
def __str__(self): def __str__(self):
return "%s - %s" % (self.user.username, self.account_id) 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 @property
def can_buy(self): def can_buy(self):
return (self.user.subscriptions.last() and return (self.user.subscriptions.last() and
@ -72,8 +80,13 @@ class Customer(models.Model):
letter = random.choice(string.ascii_lowercase) letter = random.choice(string.ascii_lowercase)
return number + letter return number + letter
def save(self, *args, **kwargs): def save(self, allow_negative=False, is_selling=False, *args, **kwargs):
if self.amount < 0: """
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")) raise ValidationError(_("Not enough money"))
super(Customer, self).save(*args, **kwargs) super(Customer, self).save(*args, **kwargs)
@ -143,6 +156,14 @@ class Product(models.Model):
class Meta: class Meta:
verbose_name = _('product') 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): def is_owned_by(self, user):
""" """
Method to see if that object can be edited by the given 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 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: if not self.date:
self.date = timezone.now() self.date = timezone.now()
self.full_clean() self.full_clean()
if not self.is_validated: if not self.is_validated:
self.customer.amount -= self.quantity * self.unit_price 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 self.is_validated = True
u = User.objects.filter(id=self.customer.user.id).first() u = User.objects.filter(id=self.customer.user.id).first()
if u.was_subscribed: if u.was_subscribed:

View File

@ -330,6 +330,28 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
except: except:
return 0 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): def add_product(self, request, q=1, p=None):
""" """
Add a product to the basket 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 if self.customer.amount < (total + round(q * float(price), 2)): # Check for enough money
request.session['not_enough'] = True request.session['not_enough'] = True
return False 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: if product.limit_age >= 18 and not self.customer.user.date_of_birth:
request.session['no_age'] = True request.session['no_age'] = True
return False return False
@ -421,6 +446,9 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
""" Finish the click session, and validate the basket """ """ Finish the click session, and validate the basket """
with transaction.atomic(): with transaction.atomic():
request.session['last_basket'] = [] 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(): for pid, infos in request.session['basket'].items():
# This duplicates code for DB optimization (prevent to load many times the same object) # This duplicates code for DB optimization (prevent to load many times the same object)
p = Product.objects.filter(pk=pid).first() p = Product.objects.filter(pk=pid).first()
@ -428,8 +456,6 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
uprice = p.special_selling_price uprice = p.special_selling_price
else: else:
uprice = p.selling_price 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)) 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, 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) 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, 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) quantity=infos['bonus_qty'], seller=self.operator, customer=self.customer)
s.save() 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_customer'] = self.customer.user.get_display_name()
request.session['last_total'] = "%0.2f" % self.sum_basket(request) request.session['last_total'] = "%0.2f" % self.sum_basket(request)
request.session['new_customer_amount'] = str(self.customer.amount) 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'), ('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 # Defines pagination for cash summary
SITH_COUNTER_CASH_SUMMARY_LENGTH = 50 SITH_COUNTER_CASH_SUMMARY_LENGTH = 50