forked from DGNum/gestioCOF
Création de K-Psul
K-Psul est l'interface pour l'équipe K-Fêt servant à effectuer des opérations sur les comtpes General : - Ajout d'un default sur le montant d'un groupe d'opérations K-Psul : - Création de l'interface pour enregistrer une opération
This commit is contained in:
parent
e9bbb35e66
commit
6be65df654
7 changed files with 526 additions and 8 deletions
|
@ -1,6 +1,7 @@
|
|||
from django import forms
|
||||
from django.contrib.auth.models import User
|
||||
from kfet.models import Account, Checkout, Article
|
||||
from django.forms import modelformset_factory
|
||||
from kfet.models import Account, Checkout, Article, OperationGroup, Operation
|
||||
from gestioncof.models import CofProfile
|
||||
|
||||
# -----
|
||||
|
@ -107,3 +108,41 @@ class ArticleForm(forms.ModelForm):
|
|||
class ArticleRestrictForm(ArticleForm):
|
||||
class Meta(ArticleForm.Meta):
|
||||
fields = ['name', 'is_sold', 'price', 'category']
|
||||
|
||||
# -----
|
||||
# K-Psul forms
|
||||
# -----
|
||||
|
||||
class KPsulOperationGroupForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = OperationGroup
|
||||
fields = ['on_acc', 'checkout']
|
||||
widgets = {
|
||||
'on_acc' : forms.HiddenInput(),
|
||||
'checkout': forms.HiddenInput(),
|
||||
}
|
||||
|
||||
class KPsulAccountForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Account
|
||||
fields = ['trigramme']
|
||||
widgets = {
|
||||
'trigramme': forms.TextInput(attrs={'autocomplete': 'off'}),
|
||||
}
|
||||
|
||||
class KPsulCheckoutForm(forms.Form):
|
||||
checkout = forms.ModelChoiceField(
|
||||
queryset=Checkout.objects.filter(is_protected=False),
|
||||
widget=forms.Select(attrs={'id':'id_checkout_select'}))
|
||||
|
||||
class KPsulOperationForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Operation
|
||||
fields = ['type', 'amount', 'is_checkout', 'article', 'article_nb']
|
||||
"""
|
||||
OperationFormSet = modelformset_factory(
|
||||
Operation,
|
||||
form = KPsulOperationForm,
|
||||
extra = 0,
|
||||
min_num = 1, validate_min = True)
|
||||
"""
|
||||
|
|
24
kfet/migrations/0009_auto_20160805_0720.py
Normal file
24
kfet/migrations/0009_auto_20160805_0720.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('kfet', '0008_auto_20160804_1736'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='operation',
|
||||
old_name='on_checkout',
|
||||
new_name='is_checkout',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='operation',
|
||||
name='article_nb',
|
||||
field=models.PositiveSmallIntegerField(default=None, null=True, blank=True),
|
||||
),
|
||||
]
|
|
@ -355,7 +355,9 @@ class OperationGroup(models.Model):
|
|||
Checkout, on_delete = models.PROTECT,
|
||||
related_name = "operations")
|
||||
at = models.DateTimeField(auto_now_add = True)
|
||||
amount = models.IntegerField()
|
||||
amount = models.DecimalField(
|
||||
max_digits = 6, decimal_places = 2,
|
||||
default = 0)
|
||||
is_cof = models.BooleanField(default = False)
|
||||
# Optional
|
||||
comment = models.CharField(
|
||||
|
@ -364,7 +366,7 @@ class OperationGroup(models.Model):
|
|||
valid_by = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
related_name = "+",
|
||||
blank = True, null = True, default = True)
|
||||
blank = True, null = True, default = None)
|
||||
|
||||
class Operation(models.Model):
|
||||
PURCHASE = 'purchase'
|
||||
|
@ -384,12 +386,14 @@ class Operation(models.Model):
|
|||
choices = TYPE_ORDER_CHOICES,
|
||||
max_length = choices_length(TYPE_ORDER_CHOICES))
|
||||
amount = models.DecimalField(max_digits = 6, decimal_places = 2)
|
||||
on_checkout = models.BooleanField(default = True)
|
||||
is_checkout = models.BooleanField(default = True)
|
||||
# Optional
|
||||
article = models.ForeignKey(
|
||||
Article, on_delete = models.PROTECT,
|
||||
related_name = "operations",
|
||||
blank = True, null = True, default = None)
|
||||
article_nb = models.PositiveSmallIntegerField(
|
||||
blank = True, null = True, default = None)
|
||||
canceled_by = models.ForeignKey(
|
||||
Account, on_delete = models.PROTECT,
|
||||
related_name = "+",
|
||||
|
@ -400,7 +404,9 @@ class Operation(models.Model):
|
|||
Account, on_delete = models.PROTECT,
|
||||
related_name = "addcosts",
|
||||
blank = True, null = True, default = None)
|
||||
addcost_amount = models.DecimalField(max_digits = 6, decimal_places = 2)
|
||||
addcost_amount = models.DecimalField(
|
||||
max_digits = 6, decimal_places = 2,
|
||||
default = 0)
|
||||
|
||||
class GlobalPermissions(models.Model):
|
||||
class Meta:
|
||||
|
|
151
kfet/static/kfet/js.cookie.js
Normal file
151
kfet/static/kfet/js.cookie.js
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*!
|
||||
* JavaScript Cookie v2.1.2
|
||||
* https://github.com/js-cookie/js-cookie
|
||||
*
|
||||
* Copyright 2006, 2015 Klaus Hartl & Fagner Brack
|
||||
* Released under the MIT license
|
||||
*/
|
||||
;(function (factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
module.exports = factory();
|
||||
} else {
|
||||
var OldCookies = window.Cookies;
|
||||
var api = window.Cookies = factory();
|
||||
api.noConflict = function () {
|
||||
window.Cookies = OldCookies;
|
||||
return api;
|
||||
};
|
||||
}
|
||||
}(function () {
|
||||
function extend () {
|
||||
var i = 0;
|
||||
var result = {};
|
||||
for (; i < arguments.length; i++) {
|
||||
var attributes = arguments[ i ];
|
||||
for (var key in attributes) {
|
||||
result[key] = attributes[key];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function init (converter) {
|
||||
function api (key, value, attributes) {
|
||||
var result;
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write
|
||||
|
||||
if (arguments.length > 1) {
|
||||
attributes = extend({
|
||||
path: '/'
|
||||
}, api.defaults, attributes);
|
||||
|
||||
if (typeof attributes.expires === 'number') {
|
||||
var expires = new Date();
|
||||
expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
|
||||
attributes.expires = expires;
|
||||
}
|
||||
|
||||
try {
|
||||
result = JSON.stringify(value);
|
||||
if (/^[\{\[]/.test(result)) {
|
||||
value = result;
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
if (!converter.write) {
|
||||
value = encodeURIComponent(String(value))
|
||||
.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
|
||||
} else {
|
||||
value = converter.write(value, key);
|
||||
}
|
||||
|
||||
key = encodeURIComponent(String(key));
|
||||
key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
|
||||
key = key.replace(/[\(\)]/g, escape);
|
||||
|
||||
return (document.cookie = [
|
||||
key, '=', value,
|
||||
attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE
|
||||
attributes.path && '; path=' + attributes.path,
|
||||
attributes.domain && '; domain=' + attributes.domain,
|
||||
attributes.secure ? '; secure' : ''
|
||||
].join(''));
|
||||
}
|
||||
|
||||
// Read
|
||||
|
||||
if (!key) {
|
||||
result = {};
|
||||
}
|
||||
|
||||
// To prevent the for loop in the first place assign an empty array
|
||||
// in case there are no cookies at all. Also prevents odd result when
|
||||
// calling "get()"
|
||||
var cookies = document.cookie ? document.cookie.split('; ') : [];
|
||||
var rdecode = /(%[0-9A-Z]{2})+/g;
|
||||
var i = 0;
|
||||
|
||||
for (; i < cookies.length; i++) {
|
||||
var parts = cookies[i].split('=');
|
||||
var cookie = parts.slice(1).join('=');
|
||||
|
||||
if (cookie.charAt(0) === '"') {
|
||||
cookie = cookie.slice(1, -1);
|
||||
}
|
||||
|
||||
try {
|
||||
var name = parts[0].replace(rdecode, decodeURIComponent);
|
||||
cookie = converter.read ?
|
||||
converter.read(cookie, name) : converter(cookie, name) ||
|
||||
cookie.replace(rdecode, decodeURIComponent);
|
||||
|
||||
if (this.json) {
|
||||
try {
|
||||
cookie = JSON.parse(cookie);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
if (key === name) {
|
||||
result = cookie;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
result[name] = cookie;
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
api.set = api;
|
||||
api.get = function (key) {
|
||||
return api(key);
|
||||
};
|
||||
api.getJSON = function () {
|
||||
return api.apply({
|
||||
json: true
|
||||
}, [].slice.call(arguments));
|
||||
};
|
||||
api.defaults = {};
|
||||
|
||||
api.remove = function (key, attributes) {
|
||||
api(key, '', extend(attributes, {
|
||||
expires: -1
|
||||
}));
|
||||
};
|
||||
|
||||
api.withConverter = init;
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
return init(function () {});
|
||||
}));
|
214
kfet/templates/kfet/kpsul.html
Normal file
214
kfet/templates/kfet/kpsul.html
Normal file
|
@ -0,0 +1,214 @@
|
|||
{% extends 'kfet/base.html' %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block extra_head %}
|
||||
<script type="text/javascript" src="{% static 'kfet/js.cookie.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}K-Psul{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% csrf_token %}
|
||||
|
||||
<form id="operationgroup_form">{{ operationgroup_form }}</form>
|
||||
|
||||
{{ trigramme_form.as_p }}
|
||||
<div id="account_data">
|
||||
<p id="account-balance"></p>
|
||||
<p id="account-name"></p>
|
||||
<p id="account-email"></p>
|
||||
<p id="account-is_cof"></p>
|
||||
<p id="account-promo"></p>
|
||||
<p id="account-is_frozen"></p>
|
||||
<p id="account-departement"></p>
|
||||
<p id="account-nickname"></p>
|
||||
</div>
|
||||
|
||||
{{ checkout_form.as_p }}
|
||||
<div id="checkout_data">
|
||||
<p id="checkout-name"></p>
|
||||
<p id="checkout-balance"></p>
|
||||
<p id="checkout-valid_from"></p>
|
||||
<p id="checkout-valid_to"></p>
|
||||
</div>
|
||||
|
||||
<form id="operation_formset">
|
||||
{{ operation_formset.as_p }}
|
||||
</form>
|
||||
|
||||
<button type="button" id="perform_operations">Valider</button>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
// -----
|
||||
// General
|
||||
// -----
|
||||
|
||||
// Retrieving csrf token
|
||||
var csrftoken = Cookies.get('csrftoken');
|
||||
// Appending csrf token to ajax post requests
|
||||
function csrfSafeMethod(method) {
|
||||
// these HTTP methods do not require CSRF protection
|
||||
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
|
||||
}
|
||||
$.ajaxSetup({
|
||||
beforeSend: function(xhr, settings) {
|
||||
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
|
||||
xhr.setRequestHeader("X-CSRFToken", csrftoken);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// -----
|
||||
// Account data management
|
||||
// -----
|
||||
|
||||
// Initializing
|
||||
var triInput = $('#id_trigramme')
|
||||
var triPattern = /^[^a-z]{3}$/
|
||||
var account_data = {}
|
||||
|
||||
// Display data
|
||||
function displayAccountData() {
|
||||
for (var elem in account_data) {
|
||||
$('#account-'+elem).text(account_data[elem]);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear data
|
||||
function resetAccountData() {
|
||||
account_data = {
|
||||
'pk' : 0,
|
||||
'name' : '',
|
||||
'email': '',
|
||||
'is_cof' : '',
|
||||
'promo' : '',
|
||||
'balance': '',
|
||||
'is_frozen' : '',
|
||||
'departement': '',
|
||||
'nickname' : '',
|
||||
}
|
||||
$('#id_on_acc').val(0);
|
||||
displayAccountData();
|
||||
}
|
||||
|
||||
// Store data
|
||||
function storeAccountData(data) {
|
||||
for (var elem in data) {
|
||||
account_data[elem] = data[elem];
|
||||
}
|
||||
$('#id_on_acc').val(account_data['pk']);
|
||||
displayAccountData();
|
||||
}
|
||||
|
||||
// Retrieve via ajax
|
||||
function retrieveAccountData(tri) {
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url : "{% url 'kfet.kpsul.account_data' %}",
|
||||
method : "POST",
|
||||
data : { trigramme: tri },
|
||||
})
|
||||
.done(function(data) { storeAccountData(data) })
|
||||
.fail(function() { resetAccountData() });
|
||||
}
|
||||
|
||||
// Event listener
|
||||
triInput.on('input', function() {
|
||||
var tri = triInput.val()
|
||||
// Checking if tri is valid to avoid sending requests
|
||||
if (tri.match(triPattern)) {
|
||||
retrieveAccountData(tri);
|
||||
} else {
|
||||
resetAccountData();
|
||||
}
|
||||
});
|
||||
|
||||
// -----
|
||||
// Checkout data management
|
||||
// -----
|
||||
|
||||
// Initializing
|
||||
var checkoutInput = $('#id_checkout_select');
|
||||
var checkout_data = {}
|
||||
|
||||
// Display data
|
||||
function displayCheckoutData() {
|
||||
for (var elem in checkout_data) {
|
||||
$('#checkout-'+elem).text(checkout_data[elem]);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear data
|
||||
function resetCheckoutData() {
|
||||
checkout_data = {
|
||||
'pk' : 0,
|
||||
'name': '',
|
||||
'balance' : '',
|
||||
'valid_from': '',
|
||||
'valid_to' : '',
|
||||
}
|
||||
$('#id_checkout').val(0);
|
||||
displayCheckoutData();
|
||||
}
|
||||
|
||||
// Store data
|
||||
function storeCheckoutData(data) {
|
||||
for (var elem in data) {
|
||||
checkout_data[elem] = data[elem];
|
||||
}
|
||||
$('#id_checkout').val(checkout_data['pk']);
|
||||
displayCheckoutData();
|
||||
}
|
||||
|
||||
// Retrieve data
|
||||
function retrieveCheckoutData(id) {
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url : "{% url 'kfet.kpsul.checkout_data' %}",
|
||||
method : "POST",
|
||||
data : { 'pk': id },
|
||||
})
|
||||
.done(function(data) { storeCheckoutData(data) })
|
||||
.fail(function() { resetCheckoutData() });
|
||||
}
|
||||
|
||||
// Event listener
|
||||
checkoutInput.on('change', function() {
|
||||
retrieveCheckoutData(checkoutInput.val());
|
||||
});
|
||||
|
||||
// -----
|
||||
// Perform operations
|
||||
// -----
|
||||
|
||||
var performButton = $('#perform_operations');
|
||||
var operationGroup = $('#operationgroup_form');
|
||||
var operations = $('#operation_formset');
|
||||
|
||||
function performOperations() {
|
||||
data = operationGroup.serialize() + '&' + operations.serialize();
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url : "{% url 'kfet.kpsul.perform_operations' %}",
|
||||
method : "POST",
|
||||
data : data,
|
||||
})
|
||||
.done(function(data) {
|
||||
console.log(data);
|
||||
})
|
||||
.always(function($xhr) {
|
||||
var data = $xhr.responseJSON;
|
||||
console.log(data);
|
||||
});
|
||||
}
|
||||
|
||||
// Event listeners
|
||||
performButton.on('click', function() {
|
||||
performOperations();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
12
kfet/urls.py
12
kfet/urls.py
|
@ -78,4 +78,16 @@ urlpatterns = [
|
|||
url('^article/(?P<pk>\d+)/edit$',
|
||||
permission_required('kfet.is_team')(views.ArticleUpdate.as_view()),
|
||||
name = 'kfet.article.update'),
|
||||
|
||||
# -----
|
||||
# K-Psul urls
|
||||
# -----
|
||||
|
||||
url('^k-psul/$', views.kpsul, name = 'kfet.kpsul'),
|
||||
url('^k-psul/account_data$', views.kpsul_account_data,
|
||||
name = 'kfet.kpsul.account_data'),
|
||||
url('^k-psul/checkout_data$', views.kpsul_checkout_data,
|
||||
name = 'kfet.kpsul.checkout_data'),
|
||||
url('^k-psul/perform_operations$', views.kpsul_perform_operations,
|
||||
name = 'kfet.kpsul.perform_operations'),
|
||||
]
|
||||
|
|
|
@ -7,11 +7,12 @@ from django.contrib import messages
|
|||
from django.contrib.messages.views import SuccessMessageMixin
|
||||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.contrib.auth.models import User
|
||||
from django.http import HttpResponse, Http404
|
||||
import json
|
||||
from django.http import HttpResponse, JsonResponse, Http404
|
||||
from django.forms import modelformset_factory
|
||||
from gestioncof.models import CofProfile, Clipper
|
||||
from kfet.models import Account, Checkout, Article
|
||||
from kfet.forms import *
|
||||
from collections import defaultdict
|
||||
|
||||
@login_required
|
||||
def home(request):
|
||||
|
@ -40,7 +41,7 @@ def account_is_validandfree_ajax(request):
|
|||
raise Http404
|
||||
trigramme = request.GET.get("trigramme")
|
||||
data = Account.is_validandfree(trigramme)
|
||||
return HttpResponse(json.dumps(data), content_type = 'application/json')
|
||||
return JsonResponse(data)
|
||||
|
||||
# Account - Create
|
||||
|
||||
|
@ -349,3 +350,74 @@ class ArticleUpdate(UpdateView):
|
|||
raise PermissionDenied
|
||||
# Updating
|
||||
return super(ArticleUpdate, self).form_valid(form)
|
||||
|
||||
# -----
|
||||
# K-Psul
|
||||
# -----
|
||||
|
||||
@permission_required('kfet.is_team')
|
||||
def kpsul(request):
|
||||
data = {}
|
||||
data['operationgroup_form'] = KPsulOperationGroupForm()
|
||||
data['trigramme_form'] = KPsulAccountForm()
|
||||
data['checkout_form'] = KPsulCheckoutForm()
|
||||
OperationFormSet = modelformset_factory(
|
||||
Operation,
|
||||
form = KPsulOperationForm,
|
||||
extra = 0,
|
||||
min_num = 1, validate_min = True)
|
||||
operation_formset = OperationFormSet(queryset=Operation.objects.none())
|
||||
data['operation_formset'] = operation_formset
|
||||
return render(request, 'kfet/kpsul.html', data)
|
||||
|
||||
@permission_required('kfet.is_team')
|
||||
def kpsul_account_data(request):
|
||||
trigramme = request.POST.get('trigramme', '')
|
||||
account = get_object_or_404(Account, trigramme=trigramme)
|
||||
data = { 'pk': account.pk, 'name': account.name, 'email': account.email,
|
||||
'is_cof': account.is_cof, 'promo': account.promo,
|
||||
'balance': account.balance, 'is_frozen': account.is_frozen,
|
||||
'departement': account.departement, 'nickname': account.nickname }
|
||||
return JsonResponse(data)
|
||||
|
||||
@permission_required('kfet.is_team')
|
||||
def kpsul_checkout_data(request):
|
||||
pk = request.POST.get('pk', 0)
|
||||
checkout = get_object_or_404(Checkout, pk=pk)
|
||||
data = { 'pk': checkout.pk, 'name': checkout.name, 'balance': checkout.balance,
|
||||
'valid_from': checkout.valid_from, 'valid_to': checkout.valid_to }
|
||||
return JsonResponse(data)
|
||||
|
||||
@permission_required('kfet.is_team')
|
||||
def kpsul_perform_operations(request):
|
||||
# Initializing
|
||||
data = defaultdict(list)
|
||||
|
||||
# Checking operationgroup data
|
||||
try:
|
||||
account_pk = request.POST.get('on_acc', 0)
|
||||
account = Account.objects.get(pk=account_pk)
|
||||
except (Account.DoesNotExist, ValueError):
|
||||
data['errors'].append('Trigramme invalide')
|
||||
try:
|
||||
checkout_pk = request.POST.get('checkout', 0)
|
||||
checkout = Checkout.objects.get(pk=checkout_pk)
|
||||
except (Checkout.DoesNotExist, ValueError):
|
||||
data['errors'].append('Caisse invalide')
|
||||
if 'errors' in data:
|
||||
return JsonResponse(data, status=400)
|
||||
|
||||
operationgroup_form = KPsulOperationGroupForm(request.POST)
|
||||
operationgroup = operationgroup_form.save(commit = False)
|
||||
operation_formset = OperationFormSet(request.POST)
|
||||
operations = operation_formset.save(commit = False)
|
||||
for operation in operations:
|
||||
operationgroup.amount += operation.amount
|
||||
operationgroup.save()
|
||||
data['operationgroup'] = operationgroup.pk
|
||||
for operation in operations:
|
||||
operation.group = operationgroup
|
||||
operation.save()
|
||||
data['operations'].append(operation.pk)
|
||||
|
||||
return JsonResponse(data)
|
||||
|
|
Loading…
Reference in a new issue