diff --git a/bda/models.py b/bda/models.py index a405a665..df73a209 100644 --- a/bda/models.py +++ b/bda/models.py @@ -315,10 +315,11 @@ class SpectacleRevente(models.Model): # Envoie un mail aux perdants for inscrit in inscrits: if inscrit != winner: - context['acheteur'] = inscrit.user + new_context = dict(context) + new_context['acheteur'] = inscrit.user datatuple.append(( 'bda-revente-loser', - context, + new_context, settings.MAIL_DATA['revente']['FROM'], [inscrit.user.email] )) diff --git a/gestioncof/petits_cours_views.py b/gestioncof/petits_cours_views.py index 95fdf3b7..332e156c 100644 --- a/gestioncof/petits_cours_views.py +++ b/gestioncof/petits_cours_views.py @@ -215,7 +215,7 @@ def _traitement_other(request, demande, redo): proposals = proposals.items() proposed_for = proposed_for.items() return render(request, - "gestiocof/traitement_demande_petit_cours_autre_niveau.html", + "gestioncof/traitement_demande_petit_cours_autre_niveau.html", {"demande": demande, "unsatisfied": unsatisfied, "proposals": proposals, diff --git a/kfet/management/commands/createopes.py b/kfet/management/commands/createopes.py new file mode 100644 index 00000000..77663b2b --- /dev/null +++ b/kfet/management/commands/createopes.py @@ -0,0 +1,175 @@ + +""" +Crée des opérations aléatoires réparties sur une période de temps spécifiée +""" + +import random +from datetime import timedelta +from decimal import Decimal +from django.utils import timezone +from django.core.management.base import BaseCommand + +from kfet.models import (Account, Article, OperationGroup, Operation, + Checkout, Transfer, TransferGroup) + + +class Command(BaseCommand): + help = "Crée des opérations réparties uniformément sur une période de temps" + + def add_arguments(self, parser): + # Nombre d'opérations à créer + parser.add_argument('opes', type=int, + help='Number of opegroups to create') + + # Période sur laquelle créer (depuis num_days avant maintenant) + parser.add_argument('days', type=int, + help='Period in which to create opegroups') + + # Optionnel : nombre de transfert à créer (défaut 0) + parser.add_argument('--transfers', type=int, default=0, + help='Number of transfers to create (default 0)') + + + def handle(self, *args, **options): + + self.stdout.write("Génération d'opérations") + + # Output log vars + opes_created = 0 + purchases = 0 + transfers = 0 + + num_ops = options['opes'] + num_transfers = options['transfers'] + # Convert to seconds + time = options['days'] * 24 * 3600 + + checkout = Checkout.objects.first() + articles = Article.objects.all() + accounts = Account.objects.exclude(trigramme='LIQ') + liq_account = Account.objects.get(trigramme='LIQ') + try: + con_account = Account.objects.get( + cofprofile__user__first_name='Assurancetourix' + ) + except Account.DoesNotExist: + con_account = random.choice(accounts) + + for i in range(num_ops): + + # Randomly pick account + if random.random() > 0.25: + account = random.choice(accounts) + else: + account = liq_account + + # Randomly pick time + at = timezone.now() - timedelta( + seconds=random.randint(0, time)) + + # Majoration sur compte 'concert' + if random.random() < 0.2: + addcost = True + addcost_for = con_account + addcost_amount = Decimal('0.5') + else: + addcost = False + + # Initialize opegroup amount + amount = Decimal('0') + + opegroup = OperationGroup.objects.create( + on_acc=account, + checkout=checkout, + at=at, + is_cof=account.cofprofile.is_cof + ) + + # Generating operations + ope_list = [] + for j in range(random.randint(1, 4)): + # Operation type + typevar = random.random() + + # 0.1 probability to have a charge + if typevar > 0.9 and account != liq_account: + ope = Operation( + group=opegroup, + type=Operation.DEPOSIT, + is_checkout=(random.random() > 0.2), + amount=Decimal(random.randint(1, 99)/10) + ) + # 0.1 probability to have a withdrawal + elif typevar > 0.8 and account != liq_account: + ope = Operation( + group=opegroup, + type=Operation.WITHDRAW, + is_checkout=(random.random() > 0.2), + amount=-Decimal(random.randint(1, 99)/10) + ) + else: + article = random.choice(articles) + nb = random.randint(1, 5) + + ope = Operation( + group=opegroup, + type=Operation.PURCHASE, + amount=-article.price*nb, + article=article, + article_nb=nb + ) + + purchases += 1 + + if addcost: + ope.addcost_for = addcost_for + ope.addcost_amount = addcost_amount * nb + ope.amount -= ope.addcost_amount + + ope_list.append(ope) + amount += ope.amount + + Operation.objects.bulk_create(ope_list) + opes_created += len(ope_list) + opegroup.amount = amount + opegroup.save() + + # Transfer generation + for i in range(num_transfers): + + # Randomly pick time + at = timezone.now() - timedelta( + seconds=random.randint(0, time)) + + # Choose whether to have a comment + if random.random() > 0.5: + comment = "placeholder comment" + else: + comment = "" + + transfergroup = TransferGroup.objects.create( + at=at, + comment=comment, + valid_by=random.choice(accounts) + ) + + # Randomly generate transfer + transfer_list = [] + for i in range(random.randint(1, 4)): + transfer_list.append(Transfer( + group=transfergroup, + from_acc=random.choice(accounts), + to_acc=random.choice(accounts), + amount=Decimal(random.randint(1, 99)/10) + )) + + Transfer.objects.bulk_create(transfer_list) + transfers += len(transfer_list) + + self.stdout.write( + "- {:d} opérations créées dont {:d} commandes d'articles" + .format(opes_created, purchases)) + + if transfers: + self.stdout.write("- {:d} transferts créés" + .format(transfers)) diff --git a/kfet/management/commands/loadkfetdevdata.py b/kfet/management/commands/loadkfetdevdata.py index 705f6f27..7f2ec9a3 100644 --- a/kfet/management/commands/loadkfetdevdata.py +++ b/kfet/management/commands/loadkfetdevdata.py @@ -5,15 +5,15 @@ Crée des utilisateurs, des articles et des opérations aléatoires import os import random from datetime import timedelta -from decimal import Decimal from django.utils import timezone from django.contrib.auth.models import User, Group, Permission, ContentType +from django.core.management import call_command from gestioncof.management.base import MyBaseCommand from gestioncof.models import CofProfile -from kfet.models import (Account, Article, OperationGroup, Operation, - Checkout, CheckoutStatement) +from kfet.models import (Account, Checkout, CheckoutStatement, Supplier, + SupplierArticle, Article) # Où sont stockés les fichiers json DATA_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), @@ -126,65 +126,24 @@ class Command(MyBaseCommand): amount_error=0 ) + # --- + # Fournisseur + # --- + + supplier, created = Supplier.objects.get_or_create(name="Panoramix") + if created: + articles = random.sample(list(Article.objects.all()), 40) + to_create = [] + for article in articles: + to_create.append(SupplierArticle( + supplier=supplier, + article=article + )) + + SupplierArticle.objects.bulk_create(to_create) + # --- # Opérations # --- - self.stdout.write("Génération d'opérations") - - articles = Article.objects.all() - accounts = Account.objects.exclude(trigramme='LIQ') - - num_op = 100 - # Operations are put uniformly over the span of a week - past_date = 3600*24*7 - - for i in range(num_op): - if random.random() > 0.25: - account = random.choice(accounts) - else: - account = liq_account - - amount = Decimal('0') - at = timezone.now() - timedelta( - seconds=random.randint(0, past_date)) - - opegroup = OperationGroup( - on_acc=account, - checkout=checkout, - at=at, - is_cof=account.cofprofile.is_cof) - - opegroup.save() - - for j in range(random.randint(1, 4)): - typevar = random.random() - if typevar > 0.9 and account != liq_account: - ope = Operation( - group=opegroup, - type=Operation.DEPOSIT, - amount=Decimal(random.randint(1, 99)/10,) - ) - elif typevar > 0.8 and account != liq_account: - ope = Operation( - group=opegroup, - type=Operation.WITHDRAW, - amount=-Decimal(random.randint(1, 99)/10,) - ) - else: - article = random.choice(articles) - nb = random.randint(1, 5) - - ope = Operation( - group=opegroup, - type=Operation.PURCHASE, - amount=-article.price*nb, - article=article, - article_nb=nb - ) - - ope.save() - amount += ope.amount - - opegroup.amount = amount - opegroup.save() + call_command('createopes', '100', '7', '--transfers=20') diff --git a/kfet/migrations/0048_default_datetime.py b/kfet/migrations/0048_default_datetime.py new file mode 100644 index 00000000..c9bacf1e --- /dev/null +++ b/kfet/migrations/0048_default_datetime.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('kfet', '0047_auto_20170104_1528'), + ] + + operations = [ + migrations.AlterField( + model_name='operationgroup', + name='at', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + migrations.AlterField( + model_name='transfergroup', + name='at', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + ] diff --git a/kfet/models.py b/kfet/models.py index 9d4a9536..9bb4f4f1 100644 --- a/kfet/models.py +++ b/kfet/models.py @@ -466,7 +466,7 @@ class OrderArticle(models.Model): quantity_received = models.IntegerField(default = 0) class TransferGroup(models.Model): - at = models.DateTimeField(auto_now_add = True) + at = models.DateTimeField(default=timezone.now) # Optional comment = models.CharField( max_length = 255, @@ -502,7 +502,7 @@ class OperationGroup(models.Model): checkout = models.ForeignKey( Checkout, on_delete = models.PROTECT, related_name = "opesgroup") - at = models.DateTimeField(auto_now_add = True) + at = models.DateTimeField(default=timezone.now) amount = models.DecimalField( max_digits = 6, decimal_places = 2, default = 0) diff --git a/kfet/static/kfet/js/kfet.js b/kfet/static/kfet/js/kfet.js index 8236b3e9..cc369e32 100644 --- a/kfet/static/kfet/js/kfet.js +++ b/kfet/static/kfet/js/kfet.js @@ -27,6 +27,53 @@ $(document).ready(function() { } }); +/* + * Generic Websocket class and k-psul ws instanciation + */ + +class KfetWebsocket { + + static get defaults() { + return {"relative_url": "", "default_msg": {}, "handlers": []}; + } + + constructor(data) { + $.extend(this, this.constructor.defaults, data); + } + + get url() { + var websocket_protocol = window.location.protocol == 'https:' ? 'wss' : 'ws'; + var location_host = window.location.host; + var location_url = window.location.pathname.startsWith('/gestion/') ? location_host + '/gestion' : location_host; + + return websocket_protocol+"://" + location_url + this.relative_url ; + } + + add_handler(handler) { + if (!this.socket) + this.listen(); + + this.handlers.push(handler); + } + + listen() { + var that = this; + this.socket = new ReconnectingWebSocket(this.url); + + this.socket.onmessage = function(e) { + var data = $.extend({}, that.default_msg, JSON.parse(e.data)); + for (let handler of that.handlers) { + handler(data); + } + } + } +} + +var OperationWebSocket = new KfetWebsocket({ + 'relative_url': '/ws/k-fet/k-psul/', + 'default_msg': {'opegroups':[],'opes':[],'checkouts':[],'articles':[]}, +}); + function dateUTCToParis(date) { return moment.tz(date, 'UTC').tz('Europe/Paris'); } diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index 5e5ce87d..1360a4be 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -12,7 +12,6 @@ - {% endblock %} @@ -1362,15 +1361,7 @@ $(document).ready(function() { // Synchronization // ----- - websocket_msg_default = {'opegroups':[],'opes':[],'checkouts':[],'articles':[]} - - var websocket_protocol = window.location.protocol == 'https:' ? 'wss' : 'ws'; - var location_host = window.location.host; - var location_url = window.location.pathname.startsWith('/gestion/') ? location_host + '/gestion' : location_host; - socket = new ReconnectingWebSocket(websocket_protocol+"://" + location_url + "/ws/k-fet/k-psul/"); - socket.onmessage = function(e) { - data = $.extend({}, websocket_msg_default, JSON.parse(e.data)); - + OperationWebSocket.add_handler(function(data) { for (var i=0; i