Commit 29515baf authored by HEVELINE Thomas's avatar HEVELINE Thomas Committed by HEVELINE Thomas
Browse files

(44): delivery popup

parent d4a491da
...@@ -262,6 +262,13 @@ class Order(models.Model): ...@@ -262,6 +262,13 @@ class Order(models.Model):
except Payment.DoesNotExist: except Payment.DoesNotExist:
return False return False
@property
def mean(self) -> str:
try:
return self.payment.mean
except Payment.DoesNotExist:
return None
@property @property
def contains_cotiz(self) -> bool: def contains_cotiz(self) -> bool:
return any(i.item.is_cotiz for i in self.items.all()) return any(i.item.is_cotiz for i in self.items.all())
......
...@@ -24,41 +24,97 @@ ...@@ -24,41 +24,97 @@
} }
</script> </script>
<form> <form onchange="generateTable()">
<label for="delivered">Déjà remis</label> <label for="delivered">Déjà remis</label>
<input type="checkbox" id="delivered"> <select id="delivered"
<label for="delivery_in_progress">Distribution en cours</label> onchange="generateTable()">
<input type="checkbox" id="delivery_in_progress"> <option value="both">Tous</option>
<option value="true">Oui</option>
<option value="false">Non</option>
</select>
<label for="beeing_delivered">Distribution en cours</label>
<select id="beeing_delivered"
onchange="generateTable()">
<option value="true">Oui</option>
<option value="false">Non</option>
<option value="both">Tous</option>
</select>
<label for="hidden">Produits cachés</label>
<select id="hidden"
onchange="generateTable()">
<option value="true">Oui</option>
<option value="false">Non</option>
<option value="both">Tous</option>
</select>
<label for="paid">Payé</label>
<select id="paid"
onchange="generateTable()">
<option value="true">Oui</option>
<option value="false">Non</option>
<option value="both">Tous</option>
</select>
<label for="sort">Tri</label>
<select id="sort">
<option value="true"> --</option>
<option value="false">Personalisation</option>
<option value="both">Acheteur</option>
<option value="both">Date de commande</option>
<option value="both">Option 1</option>
<option value="both">Option 2</option>
</select>
</form> </form>
<button onclick="applyFilter()">Appliquer</button> <form onblur="generateTable()"
onkeypress="onEnter(event)">
<input placeholder="Email"
type="search"
id="emailContains">
<input placeholder="Produit"
type="search"
id="productContains">
<input placeholder="Option (valeur exacte)"
type="search"
id="optionContains">
<input placeholder="Personalisation"
type="search"
id="customizationContains">
</form>
<div id="deliveries"></div> <div id="deliveries"></div>
<script> <script>
window.addEventListener('load', function () { window.addEventListener('load', generateTable);
function onEnter(event) {
if (event.keyCode === 13) {
blur(event.target)
generateTable()
}
}
function generateTable() {
var params = new URLSearchParams(); var params = new URLSearchParams();
params.append('delivered', document.getElementById('delivered').checked); params.set('delivered', document.getElementById('delivered').value);
params.append('delivery_in_progress', document.getElementById('delivery_in_progress').checked); params.set('beeing_delivered', document.getElementById('beeing_delivered').value);
var orderedItemList = new OrderedItemList('deliveries', '/boutique/ordered_items?'+params.toString(), function() { params.set('hidden', document.getElementById('hidden').value);
function sendMail() { params.set('paid', document.getElementById('paid').value);
console.log(1) params.set('customizationContains', document.getElementById('customizationContains').value);
}; params.set('optionContains', document.getElementById('optionContains').value);
function viewProfile() { params.set('productContains', document.getElementById('productContains').value);
console.log(2) params.set('emailContains', document.getElementById('emailContains').value);
};
return [ var orderedItemList = new OrderedItemList('deliveries', '/boutique/delivery?' + params.toString());
new OrderedItemList.ItemAction('Remettre', sendMail), }
];
});
});
</script> </script>
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}
<script src="{% static 'boutique/js/deliver.js' %}"></script>
<script src="{% static 'js/json_request.js' %}"></script> <script src="{% static 'js/json_request.js' %}"></script>
<script src="{% static 'js/table_list.js' %}"></script> <script src="{% static 'js/table_list.js' %}"></script>
<script src="{% static 'js/ordered_items.js' %}"></script> <script src="{% static 'js/ordered_items.js' %}"></script>
<script src="{% static 'js/popup.js' %}"></script>
{% endblock %} {% endblock %}
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
{% load static %} {% load static %}
{% block styles %} {% block styles %}
<link rel="stylesheet" href="{% static 'boutique/css/item_manage.css' %}"/>
{% endblock %} {% endblock %}
{% block header %} {% block header %}
......
...@@ -49,7 +49,5 @@ urlpatterns = [ ...@@ -49,7 +49,5 @@ urlpatterns = [
), ),
), ),
path("delivery", views.DeliveryView.as_view(), name="delivery"), path("delivery", views.DeliveryView.as_view(), name="delivery"),
path("ordered_items", views.orderedItems, name="ordered_items"),
] ]
import json
import csv import csv
import json
from typing import Any from typing import Any
from typing import Dict from typing import Dict
from typing import Type from typing import Type
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.mixins import PermissionRequiredMixin
from django.contrib.auth.models import AnonymousUser from django.contrib.auth.models import AnonymousUser
...@@ -23,7 +22,6 @@ from django.forms import inlineformset_factory ...@@ -23,7 +22,6 @@ from django.forms import inlineformset_factory
from django.http import HttpRequest from django.http import HttpRequest
from django.http import HttpResponse from django.http import HttpResponse
from django.http import JsonResponse from django.http import JsonResponse
from django.shortcuts import render
from django.urls import reverse from django.urls import reverse
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils import timezone from django.utils import timezone
...@@ -38,6 +36,10 @@ from django.views.generic.edit import FormMixin ...@@ -38,6 +36,10 @@ from django.views.generic.edit import FormMixin
from django.views.generic.edit import ModelFormMixin from django.views.generic.edit import ModelFormMixin
import bde.models import bde.models
from lydia import APIError
from lydia import RequestState
from lydia.models import Request
from notifications.shortcuts import notify
from .forms import CategoryForm from .forms import CategoryForm
from .forms import ItemForm from .forms import ItemForm
from .forms import OrderItemForm from .forms import OrderItemForm
...@@ -47,10 +49,6 @@ from .models import Item ...@@ -47,10 +49,6 @@ from .models import Item
from .models import Order from .models import Order
from .models import OrderItem from .models import OrderItem
from .models import Payment from .models import Payment
from lydia import APIError
from lydia import RequestState
from lydia.models import Request
from notifications.shortcuts import notify
class ItemListView(ListView): class ItemListView(ListView):
...@@ -509,11 +507,63 @@ class DeliveryView(PermissionRequiredMixin, ListView): ...@@ -509,11 +507,63 @@ class DeliveryView(PermissionRequiredMixin, ListView):
def get_queryset(self) -> "QuerySet[OrderItem]": def get_queryset(self) -> "QuerySet[OrderItem]":
return OrderItem.objects.filter( return OrderItem.objects.filter(
beeing_delivered=True,
quantity_delivered__lt=F("quantity"),
order__payment__paid=True, order__payment__paid=True,
).select_related("order__user__profile", "order__user", "item") ).select_related("order__user__profile", "order__user", "item")
def boolQueryParam(self, param):
if param == 'true': return True
if param == 'false':
return False
else:
return None
def options(self, request: HttpRequest, *args: Any, **kwargs: Any) -> JsonResponse:
itemList = OrderItem.objects
delivered = self.boolQueryParam(request.GET["delivered"])
if delivered is False:
itemList = itemList.filter(quantity_delivered__lt=F("quantity"))
elif delivered is True:
itemList = itemList.filter(quantity_delivered__gte=F("quantity"))
beeing_delivered = self.boolQueryParam(request.GET["beeing_delivered"])
if beeing_delivered is not None:
itemList = itemList.filter(beeing_delivered=beeing_delivered)
paid = self.boolQueryParam(request.GET["paid"])
if paid is not None: itemList = itemList.filter(order__payment__paid=paid)
itemList = itemList.filter(Q(item__name__icontains=request.GET["productContains"])
& Q(customization__icontains=request.GET["customizationContains"]))
optionContains = request.GET["optionContains"]
print(optionContains)
if optionContains != "":
itemList = itemList.filter(Q(option__iexact=optionContains) | Q(second_option__iexact=optionContains))
orderedItems = [
{"id": orderItem.id,
"item": str(orderItem.item),
"image": str(orderItem.item.image),
"display_name": str(orderItem.order.user.profile),
"email": str(orderItem.order.user.email),
"quantity": orderItem.quantity,
"quantity_delivered": orderItem.quantity_delivered,
"option_label": orderItem.item.option_label,
"option": orderItem.option,
"second_option_label": orderItem.item.second_option_label,
"second_option": orderItem.second_option,
"customization": orderItem.customization,
"paid": orderItem.order.paid,
"ordered_date": orderItem.order.ordered_date,
"mean": orderItem.order.mean,
}
for orderItem in itemList.select_related("order__user__profile", "order__user", "item").all()
]
return JsonResponse({"orderedItems": orderedItems})
def post(self, request: HttpRequest, *args, **kwargs) -> JsonResponse: def post(self, request: HttpRequest, *args, **kwargs) -> JsonResponse:
""" """
Request content should be json Request content should be json
...@@ -543,13 +593,23 @@ class DeliveryView(PermissionRequiredMixin, ListView): ...@@ -543,13 +593,23 @@ class DeliveryView(PermissionRequiredMixin, ListView):
orderitem = queryset.get() orderitem = queryset.get()
except OrderItem.DoesNotExist: except OrderItem.DoesNotExist:
return JsonResponse( return JsonResponse(
{"status": "error", "code": 404, "message": "Commande introuvable"}, {"status": "error", "code": 404, "message": "Commande introuvable ou impayée"},
status_code=404, status=404,
) )
message = req.get("message") message = req.get("message")
if message == "deliver": if message == "deliver":
quantity = req.get("quantity") quantity = req.get("quantity")
if not orderitem.order.payment.paid:
return JsonResponse(
{
"status": "error",
"code": 400,
"message": "Cet article n'a pas été payé",
},
status=400,
)
if not isinstance(quantity, int): if not isinstance(quantity, int):
return JsonResponse( return JsonResponse(
{ {
...@@ -557,31 +617,41 @@ class DeliveryView(PermissionRequiredMixin, ListView): ...@@ -557,31 +617,41 @@ class DeliveryView(PermissionRequiredMixin, ListView):
"code": 400, "code": 400,
"message": "La quantité doit être un nombre", "message": "La quantité doit être un nombre",
}, },
status_code=400, status=400,
) )
if quantity <= 0:
if quantity == 0:
return JsonResponse(
{
"status": "info",
"code": 202,
"message": "Quantité nulle",
},
status=202,
)
if quantity > (orderitem.quantity - orderitem.quantity_delivered):
return JsonResponse( return JsonResponse(
{ {
"status": "error", "status": "error",
"code": 400, "code": 400,
"message": "La quantité doit être strictement positive", "message": "La quantité remise doit être inférieure ou égale à la quantité commandée",
}, },
status_code=400, status=400,
) )
if quantity > (orderitem.quantity - orderitem.quantity_delivered): if -quantity > orderitem.quantity_delivered:
return JsonResponse( return JsonResponse(
{ {
"status": "error", "status": "error",
"code": 400, "code": 400,
"message": "La quantité livrée doit être inférieure ou égale à la quantité commandée", "message": "La quantité reprise doit être inférieure à la quantité déjà remise",
}, },
status_code=400, status=400,
) )
orderitem.quantity_delivered += quantity orderitem.quantity_delivered += quantity
orderitem.save() orderitem.save()
notify( notify(
"Le {} vous à été livré".format(orderitem.item), "Le {} vous à été remis".format(orderitem.item),
"boutique:index", "boutique:index",
users=User.objects.filter(username=orderitem.order.user), users=User.objects.filter(username=orderitem.order.user),
) )
...@@ -589,37 +659,13 @@ class DeliveryView(PermissionRequiredMixin, ListView): ...@@ -589,37 +659,13 @@ class DeliveryView(PermissionRequiredMixin, ListView):
{ {
"status": "success", "status": "success",
"code": 200, "code": 200,
"message": f"{quantity} {orderitem.item} livrés à {orderitem.order.user.profile}", "message": f"{quantity} {orderitem.item} remis à {orderitem.order.user.profile} " +
f"({orderitem.quantity_delivered}/{orderitem.quantity} remis au total)",
"quantity_delivered": orderitem.quantity_delivered, "quantity_delivered": orderitem.quantity_delivered,
} }
) )
return JsonResponse( return JsonResponse(
{"status": "error", "code": 400, "message": "Erreur inconnue"}, {"status": "error", "code": 400, "message": "Erreur inconnue"},
status_code=400, status=400,
) )
@permission_required("permissions.default_rights")
def orderedItems(request: HttpRequest) -> HttpResponse:
if request.method == "OPTIONS":
orderedItems = [
{"id": orderItem.id,
"item": str(orderItem.item),
"image": str(orderItem.item.image),
"display_name": str(orderItem.order.user.profile),
"quantity": orderItem.quantity,
"quantity_delivered": orderItem.quantity_delivered,
"option_label": orderItem.item.option_label,
"option": orderItem.option,
"second_option_label": orderItem.item.second_option_label,
"second_option": orderItem.second_option,
"customization": orderItem.customization,
}
for orderItem in OrderItem.objects.filter(
beeing_delivered=True,
quantity_delivered__lt=F("quantity"),
order__payment__paid=True,
).select_related("order__user__profile", "order__user", "item").all()
]
return JsonResponse({"orderedItems": orderedItems})
return render(request, "", {} )
\ No newline at end of file
...@@ -26,9 +26,9 @@ SECRET_KEY = "&d3ykoj75pkdv_q^4%ens@047+qi^_^379rg#!o%zg1j=pmwi&" ...@@ -26,9 +26,9 @@ SECRET_KEY = "&d3ykoj75pkdv_q^4%ens@047+qi^_^379rg#!o%zg1j=pmwi&"
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
INTERNAL_IPS = ["127.0.0.1"] INTERNAL_IPS = ["192.168.0.181"]
ALLOWED_HOSTS: List[str] = [] ALLOWED_HOSTS: List[str] = ["192.168.0.181"]
# Application definition # Application definition
...@@ -101,8 +101,8 @@ DATABASES = { ...@@ -101,8 +101,8 @@ DATABASES = {
"default": { "default": {
"ENGINE": "django.db.backends.mysql", "ENGINE": "django.db.backends.mysql",
"NAME": "sde", "NAME": "sde",
"USER": "root", "USER": "fenwick",
"PASSWORD": "", "PASSWORD": "fenwick",
"HOST": "127.0.0.1", "HOST": "127.0.0.1",
"PORT": 3306, "PORT": 3306,
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -2,20 +2,23 @@ ...@@ -2,20 +2,23 @@
(function () { (function () {
var OrderedItemList = function (containerId, listProvider, buildCallback) { var OrderedItemList = function (containerId, listProvider) {
TableList.call(this, containerId, buildCallback); TableList.call(this, containerId);
queryJson(listProvider, {}, this.populate.bind(this)); queryJson(listProvider, {}, this.populate.bind(this));
}; };
OrderedItemList.prototype = Object.create(TableList.prototype, { OrderedItemList.prototype = Object.create(TableList.prototype, {
populate: { populate: {
value: function (json) { value: function (json) {
this.searchInput.setAttribute('placeholder', 'Acheteur')
this.elems = json['orderedItems'] this.elems = json['orderedItems']
var header = document.createElement('tr'); var header = document.createElement('tr');
header.appendChild(document.createElement('th')); header.appendChild(document.createElement('th'));
header.appendChild(document.createElement('th')).appendChild(document.createTextNode('Produit')); header.appendChild(document.createElement('th')).appendChild(document.createTextNode('Produit'));
header.appendChild(document.createElement('th')).appendChild(document.createTextNode('Client')); header.appendChild(document.createElement('th')).appendChild(document.createTextNode('Acheteur'));
header.appendChild(document.createElement('th')).appendChild(document.createTextNode('Personalisation')); header.appendChild(document.createElement('th')).appendChild(document.createTextNode('Personalisation'));
header.appendChild(document.createElement('th')).appendChild(document.createTextNode('Payement'));
header.appendChild(document.createElement('th')).appendChild(document.createTextNode('Remis')); header.appendChild(document.createElement('th')).appendChild(document.createTextNode('Remis'));
header.appendChild(document.createElement('th')); header.appendChild(document.createElement('th'));
this.header.appendChild(header); this.header.appendChild(header);
...@@ -26,17 +29,18 @@ ...@@ -26,17 +29,18 @@
var pictureContainer = document.createElement('div'); var pictureContainer = document.createElement('div');
pictureContainer.setAttribute('class', 'picture_container'); pictureContainer.setAttribute('class', 'picture_container');
pictureContainer.setAttribute('style', 'background-color: ' + item['color']); pictureContainer.appendChild(document.createElement('img'))
.setAttribute('src', '/medias/' + item['image']);
var actionContainer = document.createElement('div'); var actionContainer = document.createElement('div');
actionContainer.setAttribute('class', 'action_container'); actionContainer.setAttribute('class', 'action_container');
var customization = document.createElement('td'); let customization = document.createElement('td');
if (item['customization'] !== '') customization.appendChild(document.createElement('div')) if (item['customization'] !== '') customization.appendChild(document.createElement('div'))
.appendChild(document.createTextNode(item['customization'])); .appendChild(document.createTextNode('Personalisation : ' + item['customization']));
if (item['option_label'] !== '') customization.appendChild(document.createElement('div')) if (item['option_label'] !== '') customization.appendChild(document.createElement('div'))
.appendChild(document.createTextNode(item['option_label'] + ' : ' + item['option'])); .appendChild(document.createTextNode(item['option_label'] + ' : ' + item['option']));
if (item['seccon_option_label'] !== '') customization.appendChild(document.createElement('div')) if (item['second_option_label'] !== '') customization.appendChild(document.createElement('div'))
.appendChild(document.createTextNode( item['second_option_label'] + ' : ' + item['second_option'])); .appendChild(document.createTextNode(item['second_option_label'] + ' : ' + item['second_option']));
if (this.onElemBuild) { if (this.onElemBuild) {
...@@ -45,17 +49,57 @@ ...@@ -45,17 +49,57 @@
actionContainer.appendChild(actions[i].element); actionContainer.appendChild(actions[i].element);
} }
} }
let button = document.createElement('button');
button.addEventListener('click', deliver);
button.disabled= !item['paid'];
if(item['quantity_delivered'] >= item['quantity']) {
button.innerHTML = 'Reprendre';
button.setAttribute('class', 'red_button');
}
else{
button.innerHTML = 'Remettre';
}
actionContainer.appendChild(button);
let payement = document.createElement('td');
if (!item['paid']) {
payement.innerHTML = 'Non payé';
payement.setAttribute('style', 'color: red');
} else {
const mean = {"card": "Carte", "online": "Lydia", "cash": "Espèces", "check": "Chèque"};
const date = new Date(item['ordered_date']);
function pad(s) {
return (s < 10) ? '0' + s : s;