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

(44): delivery popup

parent d4a491da
...@@ -72,9 +72,9 @@ class Item(models.Model): ...@@ -72,9 +72,9 @@ class Item(models.Model):
@property @property
def customizable(self) -> bool: def customizable(self) -> bool:
return ( return (
(self.customization is True) (self.customization is True)
or (self.option != "") or (self.option != "")
or (self.second_option != "") or (self.second_option != "")
) )
@property @property
...@@ -159,12 +159,12 @@ class Item(models.Model): ...@@ -159,12 +159,12 @@ class Item(models.Model):
return static("images/default_product.png") return static("images/default_product.png")
def add_to_order( def add_to_order(
self, self,
order: "Order", order: "Order",
quantity: int = 1, quantity: int = 1,
customization: str = "", customization: str = "",
option: str = "", option: str = "",
second_option: str = "", second_option: str = "",
) -> "OrderItem": ) -> "OrderItem":
oi, created = None, False oi, created = None, False
if self.customizable: if self.customizable:
...@@ -196,7 +196,7 @@ class Item(models.Model): ...@@ -196,7 +196,7 @@ class Item(models.Model):
if not oi.is_pack_item: if not oi.is_pack_item:
break break
if ( 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 ): # The preceding queries in the try-except block were empty or they
# ended on a pack_item # ended on a pack_item
oi = OrderItem.objects.create( oi = OrderItem.objects.create(
...@@ -218,12 +218,12 @@ class Item(models.Model): ...@@ -218,12 +218,12 @@ class Item(models.Model):
return oi return oi
def add_to_user( def add_to_user(
self, self,
user, user,
quantity: int = 1, quantity: int = 1,
customization: str = "", customization: str = "",
option: str = "", option: str = "",
second_option: str = "", second_option: str = "",
) -> "OrderItem": ) -> "OrderItem":
if self.hidden or self.end_date < timezone.now(): if self.hidden or self.end_date < timezone.now():
raise ValidationError( raise ValidationError(
...@@ -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())
...@@ -315,10 +322,10 @@ class OrderItemManager(models.Manager): ...@@ -315,10 +322,10 @@ class OrderItemManager(models.Manager):
def get_ordered_quantity(self, item: "Item", user) -> int: def get_ordered_quantity(self, item: "Item", user) -> int:
"""Get the total quantity ever ordered/in order by that user""" """Get the total quantity ever ordered/in order by that user"""
return ( return (
self.filter(item=item, order__user=user, order__rejected=False).aggregate( self.filter(item=item, order__user=user, order__rejected=False).aggregate(
quantity=Sum("quantity") quantity=Sum("quantity")
)["quantity"] )["quantity"]
or 0 or 0
) )
...@@ -446,7 +453,7 @@ class OrderItem(models.Model): ...@@ -446,7 +453,7 @@ class OrderItem(models.Model):
) )
def delete( def delete(
self, *args, override_pack=False, **kwargs self, *args, override_pack=False, **kwargs
) -> Tuple[int, Dict[str, int]]: ) -> Tuple[int, Dict[str, int]]:
deleted = 0 deleted = 0
which: typing.Counter[str] = Counter() which: typing.Counter[str] = Counter()
...@@ -476,7 +483,7 @@ class OrderItem(models.Model): ...@@ -476,7 +483,7 @@ class OrderItem(models.Model):
@receiver(pre_save, sender=OrderItem) @receiver(pre_save, sender=OrderItem)
@receiver(pre_delete, sender=OrderItem) @receiver(pre_delete, sender=OrderItem)
def orderitem_price_computing( def orderitem_price_computing(
sender: Type[OrderItem], instance: OrderItem, **kwargs sender: Type[OrderItem], instance: OrderItem, **kwargs
) -> None: ) -> None:
if kwargs.get("raw", False): if kwargs.get("raw", False):
return return
...@@ -488,9 +495,9 @@ def orderitem_price_computing( ...@@ -488,9 +495,9 @@ def orderitem_price_computing(
@receiver(pre_delete, sender=OrderItem) @receiver(pre_delete, sender=OrderItem)
@receiver(pre_delete, sender=Order) @receiver(pre_delete, sender=Order)
def no_delete_for_ordered( def no_delete_for_ordered(
sender: Union[Type[Order], Type[OrderItem]], sender: Union[Type[Order], Type[OrderItem]],
instance: Union[Order, OrderItem], instance: Union[Order, OrderItem],
**kwargs, **kwargs,
) -> None: ) -> None:
if instance.ordered: if instance.ordered:
raise ValueError("Deletion of ordered instances is not allowed") raise ValueError("Deletion of ordered instances is not allowed")
...@@ -498,7 +505,7 @@ def no_delete_for_ordered( ...@@ -498,7 +505,7 @@ def no_delete_for_ordered(
@receiver(pre_save, sender=lydiaRequest) @receiver(pre_save, sender=lydiaRequest)
def mark_payment_as_paid( def mark_payment_as_paid(
sender: Type[lydiaRequest], instance: lydiaRequest, **kwargs sender: Type[lydiaRequest], instance: lydiaRequest, **kwargs
) -> None: ) -> None:
if kwargs.get("raw", False): if kwargs.get("raw", False):
return return
......
...@@ -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"),
] ]
This diff is collapsed.
...@@ -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;
}
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 = document.createElement('tr');
pictureContainer.appendChild(document.createElement('td')).appendChild(document.createElement('img')) item.element.setAttribute('data-id', item['id']);
.setAttribute('src', '/medias/' + item['image']); item.element.setAttribute('data-item', item['item']);
item.element.appendChild(pictureContainer); item.element.setAttribute('data-quantity_ordered', item['quantity']);
item.element.appendChild(document.createElement('td')).appendChild(document.createTextNode(item['item'])); item.element.setAttribute('data-quantity_delivered', item['quantity_delivered']);
item.element.appendChild(document.createElement('td')).appendChild(document.createTextNode(item['display_name'])); item.element.setAttribute('data-quantity_delivered', item['quantity_delivered']);
item.element.appendChild(document.createElement('td')).appendChild(customization); item.element.setAttribute('data-display_name', item['display_name']);
item.element.appendChild(document.createElement('td')).appendChild(document.createTextNode(item['quantity_delivered'] + ' / ' + item['quantity'])); item.element.setAttribute('data-paid', item['paid']);
item.element.appendChild(document.createElement('td')).appendChild(pictureContainer);
item.element.appendChild(document.createElement('td')).innerHTML = item['item'];
item.element.appendChild(buyer);
item.element.appendChild(customization);
item.element.appendChild(payement);
item.element.appendChild(document.createElement('td')).innerHTML = item['quantity_delivered'] + ' / ' + item['quantity'];
item.element.appendChild(document.createElement('td')).appendChild(actionContainer); item.element.appendChild(document.createElement('td')).appendChild(actionContainer);
this.body.appendChild(item.element); this.body.appendChild(item.element);
} }
...@@ -87,3 +131,29 @@ ...@@ -87,3 +131,29 @@
window.OrderedItemList.ItemAction = Action; window.OrderedItemList.ItemAction = Action;
})(); })();
function deliver(event) {
let tr = event.target.closest('tr')
let item = {
"id": tr.dataset.id,
"item": tr.dataset.item,
"quantity_ordered": tr.dataset.quantity_ordered,
"quantity_delivered": tr.dataset.quantity_delivered,
"display_name": tr.dataset.display_name
}
let deliverPopup = new DeliverPopup(item, function (id, quantity) {
queryJson(document.location, {
"message": "deliver",
"id": id,
"quantity": parseInt(quantity)
}, function (data) {
add_message(data.status, data.message);
if (data.code === 200) {
generateTable();
}
}, "POST");
})
deliverPopup.pop();
}
\ No newline at end of file
...@@ -89,6 +89,78 @@ SelectionPopup.prototype = Object.create(Popup.prototype, {}); ...@@ -89,6 +89,78 @@ SelectionPopup.prototype = Object.create(Popup.prototype, {});
SelectionPopup.prototype.constructor = SelectionPopup; SelectionPopup.prototype.constructor = SelectionPopup;
/*
* Selection popup
*
* Open a pupop with the given choices and call the callback with the selected
* one as it's first argument. choises is an array with a key as the choice
* name and the value as the choice displayed
*/
function DeliverPopup(item, callback) {
Popup.call(this, 'Remettre un article');
this.baseClass = 'selection_popup';
this.callback = callback;
let max = parseInt(item['quantity_ordered']) - parseInt(item["quantity_delivered"]);
let body = document.createElement("div")
body.innerHTML =
"<h4> Article : <i>" + item['item'] + "</i><br> Acheteur : <i>" + item["display_name"] + " </i></h4>" +
"<span> Quantité commandée : " + item["quantity_ordered"] +
"<br>Déjà remis : " + item["quantity_delivered"] +
"<br>Reste à remettre : " + max +
"<br><br></span>" +
"<label for='quantity_to_deliver'>Quantité à remettre :</label> "
let form = document.createElement('form')
let quantityInput = document.createElement('input')
quantityInput.setAttribute('id', 'quantity_to_deliver')
quantityInput.setAttribute('type', 'number');
quantityInput.setAttribute('max', max);
quantityInput.value = max;
quantityInput.setAttribute('min', parseInt(-item['quantity_delivered']));
quantityInput.setAttribute('step', 1);
quantityInput.setAttribute('style', 'font-size: larger');
quantityInput.addEventListener('change', is_valid)
quantityInput = body.appendChild(quantityInput);
this.main.appendChild(body);
let button = document.createElement('button');
button.setAttribute('type', 'button');
let warning = document.createElement('h4');
warning.innerHTML='Quantité négative : vous reprenez l\'article'
warning.setAttribute('style', 'color: red');
this.main.appendChild(warning);
this.main.appendChild(button);
is_valid();
function is_valid() {
let quantity = quantityInput.value;
button.disabled = (parseInt(quantity) === 0 |
quantity > item['quantity_ordered'] - item['quantity_delivered'] |
-quantity > item['quantity_delivered']);
quantityInput.value < 0 ? button.innerHTML= 'Reprendre' : button.innerHTML = 'Remettre';
quantityInput.value < 0 ? warning.hidden= false: warning.hidden= true;
}
button.addEventListener('click', function (event) {
this.callback(item['id'], quantityInput.value);
this.close();
}.bind(this));
}
DeliverPopup.prototype = Object.create(Popup.prototype, {});
DeliverPopup.prototype.constructor = DeliverPopup;
/* /*
* Customization popup