Translate datepicker and add age limit to products

This commit is contained in:
Skia 2016-08-20 02:55:48 +02:00
parent 7e90e657a7
commit 84efcd87e7
11 changed files with 119 additions and 24 deletions

View File

@ -7,6 +7,8 @@ from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.conf import settings from django.conf import settings
from django.db import transaction from django.db import transaction
from django.contrib.staticfiles.storage import staticfiles_storage
from django.utils.html import escape
from phonenumber_field.modelfields import PhoneNumberField from phonenumber_field.modelfields import PhoneNumberField
from datetime import datetime, timedelta, date from datetime import datetime, timedelta, date
@ -281,6 +283,12 @@ class User(AbstractBaseUser):
return "%s (%s)" % (self.get_full_name(), self.nick_name) return "%s (%s)" % (self.get_full_name(), self.nick_name)
return self.get_full_name() return self.get_full_name()
def get_age(self):
"""
Returns the age
"""
return timezone.now().year - self.date_of_birth.year
def email_user(self, subject, message, from_email=None, **kwargs): def email_user(self, subject, message, from_email=None, **kwargs):
""" """
Sends an email to this User. Sends an email to this User.
@ -360,9 +368,9 @@ class User(AbstractBaseUser):
<em>%s</em> <em>%s</em>
</a> </a>
""" % ( """ % (
self.profile_pict.get_download_url() if self.profile_pict else "/static/core/img/na.gif", self.profile_pict.get_download_url() if self.profile_pict else staticfiles_storage.url("core/img/na.gif"),
_("Profile"), _("Profile"),
self.get_display_name(), escape(self.get_display_name()),
) )

View File

@ -35,8 +35,4 @@ $( function() {
popup.html('<iframe src="/file/popup" width="100%" height="95%"></iframe><div id="file_id" value="null" />'); popup.html('<iframe src="/file/popup" width="100%" height="95%"></iframe><div id="file_id" value="null" />');
popup.dialog({title: $(this).text()}).dialog( "open" ); popup.dialog({title: $(this).text()}).dialog( "open" );
}); });
$('.select_date').datepicker({
changeMonth: true,
changeYear: true
});
} ); } );

View File

@ -0,0 +1,39 @@
/* French initialisation for the jQuery UI date picker plugin. */
/* Written by Keith Wood (kbwood{at}iinet.com.au),
Stéphane Nahmani (sholby@sholby.net),
Stéphane Raimbault <stephane.raimbault@gmail.com> */
( function( factory ) {
if ( typeof define === "function" && define.amd ) {
// AMD. Register as an anonymous module.
define( [ "../widgets/datepicker" ], factory );
} else {
// Browser globals
factory( jQuery.datepicker );
}
}( function( datepicker ) {
datepicker.regional.fr = {
closeText: "Fermer",
prevText: "Précédent",
nextText: "Suivant",
currentText: "Aujourd'hui",
monthNames: [ "janvier", "février", "mars", "avril", "mai", "juin",
"juillet", "août", "septembre", "octobre", "novembre", "décembre" ],
monthNamesShort: [ "janv.", "févr.", "mars", "avr.", "mai", "juin",
"juil.", "août", "sept.", "oct.", "nov.", "déc." ],
dayNames: [ "dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi" ],
dayNamesShort: [ "dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam." ],
dayNamesMin: [ "D","L","M","M","J","V","S" ],
weekHeader: "Sem.",
dateFormat: "dd/mm/yy",
firstDay: 1,
isRTL: false,
showMonthAfterYear: false,
yearSuffix: "" };
datepicker.setDefaults( datepicker.regional.fr );
return datepicker.regional.fr;
} ) );

View File

@ -69,6 +69,7 @@
{% block script %} {% block script %}
<script src="{{ static('core/js/jquery-3.1.0.min.js') }}"></script> <script src="{{ static('core/js/jquery-3.1.0.min.js') }}"></script>
<script src="{{ static('core/js/ui/jquery-ui.min.js') }}"></script> <script src="{{ static('core/js/ui/jquery-ui.min.js') }}"></script>
<script src="{{ static('core/js/ui/i18n/datepicker-fr.js') }}"></script>
<script src="{{ static('core/js/multiple-select.js') }}"></script> <script src="{{ static('core/js/multiple-select.js') }}"></script>
<script src="{{ static('ajax_select/js/ajax_select.js') }}"></script> <script src="{{ static('ajax_select/js/ajax_select.js') }}"></script>
<script src="{{ static('core/js/script.js') }}"></script> <script src="{{ static('core/js/script.js') }}"></script>
@ -85,6 +86,14 @@ $('.select_multiple').multipleSelect({
position: 'top', position: 'top',
{% endif %} {% endif %}
}); });
$('.select_date').datepicker({
changeMonth: true,
changeYear: true,
dayNamesShort: $.datepicker.regional[ "{{ request.LANGUAGE_CODE }}" ].dayNamesShort,
dayNames: $.datepicker.regional[ "{{ request.LANGUAGE_CODE }}" ].dayNames,
monthNamesShort: $.datepicker.regional[ "{{ request.LANGUAGE_CODE }}" ].monthNamesShort,
monthNames: $.datepicker.regional[ "{{ request.LANGUAGE_CODE }}" ].monthNames,
}).datepicker( $.datepicker.regional[ "{{ request.LANGUAGE_CODE }}"] );
</script> </script>
{% endblock %} {% endblock %}
</body> </body>

View File

@ -4,15 +4,8 @@
{% macro user_link_with_pict(user) -%} {% macro user_link_with_pict(user) -%}
<a href="{{ url("core:user_profile", user_id=user.id) }}" class="mini_profile_link" > <a href="{{ url("core:user_profile", user_id=user.id) }}" class="mini_profile_link" >
<span> {{ user.get_mini_item()|safe }}
{% if user.profile_pict %} </a>
<img src="{{ user.profile_pict.get_download_url() }}" alt="{% trans %}Profile{% endtrans %}" />
{% else %}
<img src="{{ static('core/img/na.gif') }}" alt="{% trans %}Profile{% endtrans %}" />
{% endif %}
</span>
<em>{{ user.get_display_name() }}</em>
</a>
{%- endmacro %} {%- endmacro %}
{% macro user_mini_profile(user) %} {% macro user_mini_profile(user) %}
@ -27,7 +20,7 @@
<p id="nickname">&laquo; {{ user.nick_name }} &raquo;</p> <p id="nickname">&laquo; {{ user.nick_name }} &raquo;</p>
{% endif %} {% endif %}
{% if user.date_of_birth %} {% if user.date_of_birth %}
<p>{% trans %}Born: {% endtrans %}{{ user.date_of_birth|date("d/m/Y") }}</p> <p>{% trans %}Born: {% endtrans %}{{ user.date_of_birth|date("d/m/Y") }} ({{ user.get_age() }})</p>
{% endif %} {% endif %}
{% if user.promo %} {% if user.promo %}
<p><img src="{{ static('core/img/promo_%02d.png' % user.promo) }}" alt="Promo {{ user.promo }}" class="promo_pict" /> <p><img src="{{ static('core/img/promo_%02d.png' % user.promo) }}" alt="Promo {{ user.promo }}" class="promo_pict" />

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('counter', '0014_auto_20160819_1650'),
]
operations = [
migrations.AddField(
model_name='product',
name='limit_age',
field=models.IntegerField(default=0, verbose_name='limit age'),
),
migrations.AddField(
model_name='product',
name='tray',
field=models.BooleanField(default=False, verbose_name='tray price'),
),
]

View File

@ -83,6 +83,8 @@ class Product(models.Model):
special_selling_price = CurrencyField(_('special selling price')) special_selling_price = CurrencyField(_('special selling price'))
icon = models.ImageField(upload_to='products', null=True, blank=True) icon = models.ImageField(upload_to='products', null=True, blank=True)
club = models.ForeignKey(Club, related_name="products") club = models.ForeignKey(Club, related_name="products")
limit_age = models.IntegerField(_('limit age'), default=0)
tray = models.BooleanField(_('tray price'), default=False)
class Meta: class Meta:
verbose_name = _('product') verbose_name = _('product')

View File

@ -43,6 +43,9 @@
{% endif %} {% endif %}
<div> <div>
<h5>{% trans %}Selling{% endtrans %}</h5> <h5>{% trans %}Selling{% endtrans %}</h5>
{% if request.session['too_young'] %}
<p><strong>{% trans %}Too young for that product{% endtrans %}</strong></p>
{% endif %}
{% if request.session['not_enough'] %} {% if request.session['not_enough'] %}
<p><strong>{% trans %}Not enough money{% endtrans %}</strong></p> <p><strong>{% trans %}Not enough money{% endtrans %}</strong></p>
{% endif %} {% endif %}

View File

@ -8,6 +8,10 @@
</form> </form>
{% endmacro %} {% endmacro %}
{% block title %}
{% trans counter_name=counter %}{{ counter_name }} counter{% endtrans %}
{% endblock %}
{% block content %} {% block content %}
<h3>{% trans counter_name=counter %}{{ counter_name }} counter{% endtrans %}</h3> <h3>{% trans counter_name=counter %}{{ counter_name }} counter{% endtrans %}</h3>

View File

@ -117,6 +117,7 @@ class CounterClick(DetailView):
request.session['basket'] = {} request.session['basket'] = {}
request.session['basket_total'] = 0 request.session['basket_total'] = 0
request.session['not_enough'] = False request.session['not_enough'] = False
request.session['too_young'] = False
self.refill_form = None self.refill_form = None
ret = super(CounterClick, self).get(request, *args, **kwargs) ret = super(CounterClick, self).get(request, *args, **kwargs)
if ((self.object.type != "BAR" and not request.user.is_authenticated()) or if ((self.object.type != "BAR" and not request.user.is_authenticated()) or
@ -138,6 +139,7 @@ class CounterClick(DetailView):
request.session['basket'] = {} request.session['basket'] = {}
request.session['basket_total'] = 0 request.session['basket_total'] = 0
request.session['not_enough'] = False request.session['not_enough'] = False
request.session['too_young'] = False
if self.object.type != "BAR": if self.object.type != "BAR":
self.operator = request.user self.operator = request.user
elif self.is_barman_price(): elif self.is_barman_price():
@ -166,8 +168,11 @@ class CounterClick(DetailView):
else: else:
return False return False
def get_product(self, pid):
return Product.objects.filter(pk=int(pid)).first()
def get_price(self, pid): def get_price(self, pid):
p = Product.objects.filter(pk=pid).first() p = self.get_product(pid)
if self.is_barman_price(): if self.is_barman_price():
price = p.special_selling_price price = p.special_selling_price
else: else:
@ -181,7 +186,11 @@ class CounterClick(DetailView):
return total / 100 return total / 100
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
q is the quantity passed as integer
p is the product id, passed as an integer
"""
pid = p or request.POST['product_id'] pid = p or request.POST['product_id']
pid = str(pid) pid = str(pid)
price = self.get_price(pid) price = self.get_price(pid)
@ -189,11 +198,15 @@ class CounterClick(DetailView):
if self.customer.amount < (total + q*float(price)): if self.customer.amount < (total + q*float(price)):
request.session['not_enough'] = True request.session['not_enough'] = True
return False return False
if self.customer.user.get_age() < self.get_product(pid).limit_age:
request.session['too_young'] = True
return False
if pid in request.session['basket']: if pid in request.session['basket']:
request.session['basket'][pid]['qty'] += q request.session['basket'][pid]['qty'] += q
else: else:
request.session['basket'][pid] = {'qty': q, 'price': int(price*100)} request.session['basket'][pid] = {'qty': q, 'price': int(price*100)}
request.session['not_enough'] = False # Reset not_enough to save the session request.session['not_enough'] = False # Reset not_enough to save the session
request.session['too_young'] = False
request.session.modified = True request.session.modified = True
return True return True
@ -421,7 +434,7 @@ class ProductEditForm(forms.ModelForm):
class Meta: class Meta:
model = Product model = Product
fields = ['name', 'description', 'product_type', 'code', 'purchase_price', fields = ['name', 'description', 'product_type', 'code', 'purchase_price',
'selling_price', 'special_selling_price', 'icon', 'club'] 'selling_price', 'special_selling_price', 'icon', 'club', 'limit_age', 'tray']
counters = make_ajax_field(Product, 'counters', 'counters', show_help_text=False, label='Counters', help_text="Guy", counters = make_ajax_field(Product, 'counters', 'counters', show_help_text=False, label='Counters', help_text="Guy",
required=False) # TODO FIXME required=False) # TODO FIXME

View File

@ -452,6 +452,8 @@ def migrate_products():
selling_price=r['prix_vente_prod']/100, selling_price=r['prix_vente_prod']/100,
special_selling_price=r['prix_vente_barman_prod']/100, special_selling_price=r['prix_vente_barman_prod']/100,
club=club, club=club,
limit_age=r['mineur'] or 0,
tray=bool(r['plateau']),
) )
new.save() new.save()
except Exception as e: except Exception as e:
@ -554,7 +556,9 @@ def migrate_sellings():
) )
new.save() new.save()
except ValidationError as e: except ValidationError as e:
print(repr(e) + " for %s (%s)" % (customer, customer.user.id)) print(repr(e) + " for %s (%s), assigning to root" % (customer, customer.user.id))
new.customer = root.customer
new.save()
except Exception as e: except Exception as e:
print("FAIL to migrate selling %s: %s" % (r['id_facture'], repr(e))) print("FAIL to migrate selling %s: %s" % (r['id_facture'], repr(e)))
cur.close() cur.close()
@ -592,12 +596,12 @@ def main():
# migrate_counters() # migrate_counters()
# migrate_permanencies() # migrate_permanencies()
# migrate_typeproducts() # migrate_typeproducts()
# migrate_products() migrate_products()
# migrate_products_to_counter() migrate_products_to_counter()
# reset_customer_amount() # reset_customer_amount()
# migrate_invoices() # migrate_invoices()
migrate_refillings() # migrate_refillings()
migrate_sellings() # migrate_sellings()
reset_index('core', 'counter') reset_index('core', 'counter')
if __name__ == "__main__": if __name__ == "__main__":