Commit 818438a9 authored by MOREAU Ulysse's avatar MOREAU Ulysse
Browse files

Merge branch 'feat/44-delivery-improvement' into 'master'

Feat/44 delivery improvement

See merge request !60
parents 8b33a983 0d6ffd87
......@@ -101,8 +101,8 @@ class SellForm(forms.Form):
mean = forms.ChoiceField(choices=settings.PAYMENT_MEANS)
customization = forms.CharField(label="Perso", required=False)
option = forms.ChoiceField(label="Option 1", required=False)
second_option = forms.ChoiceField(label="Option 2", required=False)
option = forms.CharField(label="Option 1", required=False)
second_option = forms.CharField(label="Option 2", required=False)
def __init__(self, *args, instance: Optional[OrderItem] = None, **kwargs) -> None:
# adds `instance` parameter to emulate ModelForm interface
......@@ -113,11 +113,14 @@ class SellForm(forms.Form):
user = self.cleaned_data["user"]
mean: str = self.cleaned_data["mean"]
quantity: int = self.cleaned_data["quantity"]
customization: str = self.cleaned_data["customization"]
option: str = self.cleaned_data["option"]
second_option: str = self.cleaned_data["second_option"]
with transaction.atomic():
order = Order.objects.create(user=user, ordered=True)
Payment.objects.create(mean=mean, paid=True, order=order)
order_item = item.add_to_order(order, quantity)
order_item = item.add_to_order(order, quantity, customization, option, second_option)
order.compute_price()
order.save()
order.post_payment()
......
......@@ -159,12 +159,12 @@ class Item(models.Model):
return static("images/default_product.png")
def add_to_order(
self,
order: "Order",
quantity: int = 1,
customization: str = "",
option: str = "",
second_option: str = "",
self,
order: "Order",
quantity: int = 1,
customization: str = "",
option: str = "",
second_option: str = "",
) -> "OrderItem":
oi, created = None, False
if self.customizable:
......@@ -196,7 +196,7 @@ class Item(models.Model):
if not oi.is_pack_item:
break
if (
oi is None or oi.is_pack_item
oi is None or oi.is_pack_item
): # The preceding queries in the try-except block were empty or they
# ended on a pack_item
oi = OrderItem.objects.create(
......@@ -218,12 +218,12 @@ class Item(models.Model):
return oi
def add_to_user(
self,
user,
quantity: int = 1,
customization: str = "",
option: str = "",
second_option: str = "",
self,
user,
quantity: int = 1,
customization: str = "",
option: str = "",
second_option: str = "",
) -> "OrderItem":
if self.hidden or self.end_date < timezone.now():
raise ValidationError(
......@@ -262,6 +262,13 @@ class Order(models.Model):
except Payment.DoesNotExist:
return False
@property
def mean(self) -> str:
try:
return self.payment.mean
except Payment.DoesNotExist:
return 'None'
@property
def contains_cotiz(self) -> bool:
return any(i.item.is_cotiz for i in self.items.all())
......@@ -446,7 +453,7 @@ class OrderItem(models.Model):
)
def delete(
self, *args, override_pack=False, **kwargs
self, *args, override_pack=False, **kwargs
) -> Tuple[int, Dict[str, int]]:
deleted = 0
which: typing.Counter[str] = Counter()
......@@ -476,7 +483,7 @@ class OrderItem(models.Model):
@receiver(pre_save, sender=OrderItem)
@receiver(pre_delete, sender=OrderItem)
def orderitem_price_computing(
sender: Type[OrderItem], instance: OrderItem, **kwargs
sender: Type[OrderItem], instance: OrderItem, **kwargs
) -> None:
if kwargs.get("raw", False):
return
......@@ -488,9 +495,9 @@ def orderitem_price_computing(
@receiver(pre_delete, sender=OrderItem)
@receiver(pre_delete, sender=Order)
def no_delete_for_ordered(
sender: Union[Type[Order], Type[OrderItem]],
instance: Union[Order, OrderItem],
**kwargs,
sender: Union[Type[Order], Type[OrderItem]],
instance: Union[Order, OrderItem],
**kwargs,
) -> None:
if instance.ordered:
raise ValueError("Deletion of ordered instances is not allowed")
......@@ -498,7 +505,7 @@ def no_delete_for_ordered(
@receiver(pre_save, sender=lydiaRequest)
def mark_payment_as_paid(
sender: Type[lydiaRequest], instance: lydiaRequest, **kwargs
sender: Type[lydiaRequest], instance: lydiaRequest, **kwargs
) -> None:
if kwargs.get("raw", False):
return
......
......@@ -4,9 +4,12 @@ window.addEventListener("load", function (e) {
let button = begin_delivery[i];
let id = button.closest("article").dataset.id;
button.addEventListener("click", function() {
let cb = function(data){
button.addEventListener("click", function () {
let cb = function (data) {
add_message(data["status"], data["data"]);
setTimeout(function () {
document.location.reload()
}, 2000)
};
queryJson(document.location, {
......@@ -17,57 +20,192 @@ window.addEventListener("load", function (e) {
}
});
window.addEventListener("load", function (e) {
let stop_delivery = document.getElementsByClassName("stop-delivery")
for (let i = stop_delivery.length - 1; i >= 0; i--) {
let button = stop_delivery[i];
let id = button.closest("article").dataset.id;
button.addEventListener("click", function () {
let cb = function (data) {
add_message(data["status"], data["data"]);
setTimeout(function () {
document.location.reload()
}, 2000)
};
queryJson(document.location, {
message: "stop-delivery",
id: id,
}, cb, "POST");
});
}
});
window.addEventListener("load", function (e) {
let see_orders = document.getElementsByClassName("see-orders")
for (let i = see_orders.length - 1; i >= 0; i--) {
let button = see_orders[i];
let id = button.closest("article").dataset.id;
button.addEventListener("click", function() {
let cb = function(data){
button.addEventListener("click", function () {
let popup = new Popup("Commandes de " + button.closest("article").querySelector("h2").innerText);
let orders = data["data"];
let table = document.createElement('table');
table.insertAdjacentHTML("beforeend", "<tr><th>Utilisateur</th><th>Personnalisation</th><th>Opt 1</th><th>Opt 2</th><th>Payé</th><th>Quantité</th></tr>");
for (let i = orders.length - 1; i >= 0; i--) {
let order = orders[i];
let line = document.createElement("tr")
let li = document.createElement('li');
let c1 = document.createElement("td")
let c2 = document.createElement("td")
let c3 = document.createElement("td")
let c4 = document.createElement("td")
let c5 = document.createElement("td")
let c6 = document.createElement("td")
c1.appendChild(document.createTextNode(order.user))
c2.appendChild(document.createTextNode(order.customization))
c3.appendChild(document.createTextNode(order.option))
c4.appendChild(document.createTextNode(order.second_option))
c5.appendChild(document.createTextNode(order.paid))
c6.appendChild(document.createTextNode(order.quantity))
line.appendChild(c1)
line.appendChild(c2)
line.appendChild(c3)
line.appendChild(c4)
line.appendChild(c5)
line.appendChild(c6)
table.appendChild(line);
}
popup.main.appendChild(table);
orders = document.createElement('div');
orders.setAttribute('id', 'orders')
popup.pop();
popup.main.appendChild(orders)
new SeeOrdersList('orders', document.location, id);
};
queryJson(document.location, {
message: "see-orders",
id: id,
}, cb, "POST");
});
}
});
(function () {
var SeeOrdersList = function (containerId, listProvider, id) {
TableList.call(this, containerId);
queryJson(listProvider, {
message: "see-orders",
id: id,
}, this.populate.bind(this),
'POST');
};
SeeOrdersList.prototype = Object.create(TableList.prototype, {
populate: {
value: function (json) {
this.searchInput.setAttribute('placeholder', 'Acheteur')
this.elems = json['data']
var header = document.createElement('tr');
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('Payement'));
header.appendChild(document.createElement('th')).appendChild(document.createTextNode('Remis'));
header.appendChild(document.createElement('th'));
this.header.appendChild(header);
for (var i in this.elems) {
var item = this.elems[i];
let customization = document.createElement('td');
if (item['customization'] !== '') customization.appendChild(document.createElement('div'))
.appendChild(document.createTextNode('Personalisation : ' + item['customization']));
if (item['option_label'] !== '') customization.appendChild(document.createElement('div'))
.appendChild(document.createTextNode(item['option_label'] + ' : ' + item['option']));
if (item['second_option_label'] !== '') customization.appendChild(document.createElement('div'))
.appendChild(document.createTextNode(item['second_option_label'] + ' : ' + item['second_option']));
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;
}
payement.innerHTML = (mean[item['mean']] ? mean[item['mean']] : item['mean'])
+ '<br>'
+ [pad(date.getDate()), pad(date.getMonth() + 1), date.getFullYear()].join('/');
}
let buyer = document.createElement('td');
buyer.innerHTML = (item['display_name'] === item['email'] ? item['display_name'] : item['display_name'] + '<br>' + item['email'])
item.element = document.createElement('tr');
item.element.setAttribute('data-id', item['id']);
item.element.setAttribute('data-quantity_ordered', item['quantity']);
item.element.setAttribute('data-quantity_delivered', item['quantity_delivered']);
item.element.setAttribute('data-display_name', item['display_name']);
item.element.setAttribute('data-paid', item['paid']);
item.element.appendChild(buyer);
item.element.appendChild(customization);
item.element.appendChild(payement);
item.element.appendChild(document.createElement('td')).innerHTML = item['quantity_delivered'] + ' / ' + item['quantity'];
this.body.appendChild(item.element);
}
this.matchingElems = this.elems;
console.log(this.matchingElems);
this.matchingElems.sort(function (a, b) {
var nameA = a['display_name'].toLowerCase();
var nameB = b['display_name'].toLowerCase();
if (nameA > nameB) return 1;
else if (nameA < nameB) return -1;
else return 0;
});
this.render();
},
},
match: {
value: function (item) {
var match = false;
var regex = this.cachedSearchRegex;
match |= regex.test(item['display_name']);
return match;
},
},
});
window.SeeOrdersList = SeeOrdersList;
window.SeeOrdersList.ItemAction = Action;
})();
function sell(event) {
const item = event.target.closest('article');
const item_id = item.dataset.pk;
let data = {
"item": item_id,
"user": 0,
"quantity": 1,
"mean": null,
"customization": '',
"option": '',
"second_option": ''
};
let customization_popup = new CustomizationPopup("Options et personalisation", item, function (quantity, customization, option, second_option) {
data.quantity = quantity;
data.customization = customization;
data.option = option;
data.second_option = second_option;
mean_popup.pop();
});
let mean_popup = new SelectionPopup(
"Moyen de paiement",
{"card": "Carte", "online": "Lydia", "cash": "Espèces", "check": "Chèque"},
function (mean) {
data.mean = mean;
console.log(data);
queryJson("/boutique/item/sell", data, function (response) {
add_message(response["status"], response["message"]);
}, "PUT");
});
let user_popup = new UserSelectionPopup("Client", function (uid, dname) {
console.log(uid);
data.user = uid;
customization_popup.pop();
});
user_popup.pop();
};
\ No newline at end of file
window.addEventListener("load", function() {
const list = document.querySelector(".item-sell-list");
window.addEventListener("load", function () {
const list = document.querySelector(".item-sell-list");
const items = list.getElementsByTagName('li');
const items = list.getElementsByTagName('li');
for (var i = items.length - 1; i >= 0; i--) {
const item = items[i];
const item_id = item.dataset.pk;
for (var i = items.length - 1; i >= 0; i--) {
const item = items[i];
const item_id = item.dataset.pk;
console.log(item.dataset);
const button = item.lastElementChild;
button.addEventListener("click", function () {
let data = {
"item": item_id,
"user": 0,
"quantity": 1,
"mean": null,
"customization": '',
"option": '',
"second_option": ''
};
const button = item.lastElementChild;
button.addEventListener("click", function() {
let user_id = 0;
let customization_popup = new CustomizationPopup("Options et personalisation", item, function (quantity, customization, option, second_option) {
data.quantity = quantity;
data.customization = customization;
data.option = option;
data.second_option = second_option;
mean_popup.pop();
let mean_popup = new SelectionPopup(
"Moyen de paiement",
{"card": "Carte", "online": "Lydia", "cash": "Espèces", "check": "Chèque"},
function(mean) {
const data = {
"item": item_id,
"user": user_id,
"quantity": 1,
"mean": mean
};
queryJson("", data, function(response) {
add_message(response["status"], response["message"]);
}, "PUT");
});
});
let user_popup = new UserSelectionPopup("Client", function (uid) {
user_id = uid;
mean_popup.pop();
});
user_popup.pop();
});
}
let mean_popup = new SelectionPopup(
"Moyen de paiement",
{"card": "Carte", "online": "Lydia", "cash": "Espèces", "check": "Chèque"},
function (mean) {
data.mean = mean;
console.log(data);
queryJson("", data, function (response) {
add_message(response["status"], response["message"]);
}, "PUT");
});
list.style.removeProperty("display");
let user_popup = new UserSelectionPopup("Client", function (uid, dname) {
console.log(uid);
data.user = uid;
customization_popup.pop();
});
user_popup.pop();
});
}
list.style.removeProperty("display");
});
......@@ -11,36 +11,111 @@
{% endblock %}
{% block main %}
<h1>Livraison</h1>
<table id="deliveries">
<tr>
<th>Produit</th>
<th>Client</th>
<th>Commandé</th>
<th>Livré</th>
<th></th>
</tr>
{% for orderitem in object_list %}
<tr data-id="{{ orderitem.id }}">
<td>{{ orderitem.item }}</td>
<td>{{ orderitem.order.user.profile }}</td>
<td class="quantity_ordered">{{ orderitem.quantity }}</td>
<td class="quantity_delivered">{{ orderitem.quantity_delivered }}</td>
<td><button>Livrer</button></td>
</tr>
{% empty %}
<tr>
<td colspan="5">
Aucun produit en cours de livraison, allez sur la page
d'administration pour lancer une livraison.
</td>
</tr>
{% endfor %}
</table>
<div class="delivery">
<h1>Livraison</h1>
<script>
var url = new URL(window.location.href);
function applyFilter() {
url.searchParams.set('delivered', document.getElementById('delivered').checked);
url.searchParams.set('delivery_in_progress', document.getElementById('delivery_in_progress').checked);
window.location.href = url
}
</script>
<form onchange="generateTable()">
<label for="delivered">Déjà remis :</label>
<select id="delivered"
onchange="generateTable()">
<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 selected 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="none"> --</option>
<option value="false">Personalisation</option>
<option value="both">Acheteur</option>
<option value="date">Date de commande</option>
<option value="option">Option 1</option>
<option value="second_option">Option 2</option>
</select>
</form>
<form onblur="generateTable()"
onkeypress="onEnter(event)">
<input placeholder="Produit"
type="search"
id="productContains">
<input placeholder="Email"
type="search"
id="emailContains">
<input placeholder="Option (valeur exacte)"
type="search"
id="optionContains">
<input placeholder="Personalisation"
type="search"
id="customizationContains">
</form>
<div id="deliveries"></div>
<script>
window.addEventListener('load', generateTable);
function onEnter(event) {
if (event.keyCode === 13) {
blur(event.target)
generateTable()
}
}
function generateTable() {
var params = new URLSearchParams();
params.set('delivered', document.getElementById('delivered').value);
params.set('beeing_delivered', document.getElementById('beeing_delivered').value);
params.set('hidden', document.getElementById('hidden').value);
params.set('paid', document.getElementById('paid').value);
params.set('customizationContains', document.getElementById('customizationContains').value);
params.set('optionContains', document.getElementById('optionContains').value);
params.set('productContains', document.getElementById('productContains').value);
params.set('emailContains', document.getElementById('emailContains').value);
var orderedItemList = new OrderedItemList('deliveries', '/boutique/delivery?' + params.toString());