Don't use codes as a primary key in counter click

This commit is contained in:
Antoine Bartuccio 2024-12-20 18:34:27 +01:00
parent 60f18669c8
commit a383f3e717
3 changed files with 17 additions and 26 deletions

View File

@ -11,6 +11,7 @@ interface CounterConfig {
} }
interface Product { interface Product {
id: string;
code: string; code: string;
name: string; name: string;
price: number; price: number;
@ -56,18 +57,11 @@ exportToHtml("loadCounter", (config: CounterConfig) => {
.setAttribute(":value", "getBasketSize()"); .setAttribute(":value", "getBasketSize()");
}, },
getItemIdFromCode(code: string): string { removeFromBasket(id: string) {
return Object.keys(config.products).find( delete this.basket[id];
(key) => config.products[key].code === code,
);
}, },
removeFromBasket(code: string) { addToBasket(id: string, quantity: number): [boolean, string] {
delete this.basket[this.getItemIdFromCode(code)];
},
addToBasket(code: string, quantity: number): [boolean, string] {
const id = this.getItemIdFromCode(code);
const item: BasketItem = const item: BasketItem =
this.basket[id] || new BasketItem(config.products[id], 0); this.basket[id] || new BasketItem(config.products[id], 0);
@ -126,7 +120,7 @@ exportToHtml("loadCounter", (config: CounterConfig) => {
}); });
}, },
handleCode(event: SubmitEvent) { handleCode() {
const [quantity, code] = this.codeField.getSelectedProduct() as [ const [quantity, code] = this.codeField.getSelectedProduct() as [
number, number,
string, string,

View File

@ -63,7 +63,7 @@
{% for category in categories.keys() %} {% for category in categories.keys() %}
<optgroup label="{{ category }}"> <optgroup label="{{ category }}">
{% for product in categories[category] %} {% for product in categories[category] %}
<option value="{{ product.code }}">{{ product }}</option> <option value="{{ product.id }}">{{ product }}</option>
{% endfor %} {% endfor %}
</optgroup> </optgroup>
{% endfor %} {% endfor %}
@ -86,17 +86,17 @@
</div> </div>
<template x-for="(item, index) in Object.values(basket)"> <template x-for="(item, index) in Object.values(basket)">
<ul> <ul>
<button @click.prevent="addToBasket(item.product.code, -1)">-</button> <button @click.prevent="addToBasket(item.product.id, -1)">-</button>
<span x-text="item.quantity"></span> <span x-text="item.quantity"></span>
<button @click.prevent="addToBasket(item.product.code, 1)">+</button> <button @click.prevent="addToBasket(item.product.id, 1)">+</button>
<span x-text="item.product.name"></span> : <span x-text="item.product.name"></span> :
<span x-text="item.sum().toLocaleString(undefined, { minimumFractionDigits: 2 })">€</span> <span x-text="item.sum().toLocaleString(undefined, { minimumFractionDigits: 2 })">€</span>
<span x-cloak x-show="item.getBonusQuantity() > 0" x-text="`${item.getBonusQuantity()} x P`"></span> <span x-cloak x-show="item.getBonusQuantity() > 0" x-text="`${item.getBonusQuantity()} x P`"></span>
<button @click.prevent="removeFromBasket(item.product.code)"><i class="fa fa-trash-can delete-action"></i></button> <button @click.prevent="removeFromBasket(item.product.id)"><i class="fa fa-trash-can delete-action"></i></button>
<input type="hidden" :value="item.quantity" :id="`id_form-${index}-quantity`" :name="`form-${index}-quantity`" required readonly> <input type="hidden" :value="item.quantity" :id="`id_form-${index}-quantity`" :name="`form-${index}-quantity`" required readonly>
<input type="hidden" :value="item.product.code" :id="`id_form-${index}-code`" :name="`form-${index}-code`" required readonly> <input type="hidden" :value="item.product.id" :id="`id_form-${index}-id`" :name="`form-${index}-id`" required readonly>
</ul> </ul>
</template> </template>
@ -149,7 +149,7 @@
<div id="cat_{{ category|slugify }}"> <div id="cat_{{ category|slugify }}">
<h5>{{ category }}</h5> <h5>{{ category }}</h5>
{% for product in categories[category] -%} {% for product in categories[category] -%}
<button @click="addToBasket('{{ product.code }}', 1)"> <button @click="addToBasket('{{ product.id }}', 1)">
<strong>{{ product.name }}</strong> <strong>{{ product.name }}</strong>
{% if product.icon %} {% if product.icon %}
<img src="{{ product.icon.url }}" alt="image de {{ product.name }}"/> <img src="{{ product.icon.url }}" alt="image de {{ product.name }}"/>
@ -171,7 +171,7 @@
const products = { const products = {
{%- for p in products -%} {%- for p in products -%}
{{ p.id }}: { {{ p.id }}: {
code: "{{ p.code }}", id: "{{ p.id }}",
name: "{{ p.name }}", name: "{{ p.name }}",
price: {{ p.price }}, price: {{ p.price }},
hasTrayPrice: {{ p.tray | tojson }}, hasTrayPrice: {{ p.tray | tojson }},

View File

@ -19,8 +19,8 @@ from django.db import transaction
from django.db.models import F from django.db.models import F
from django.forms import ( from django.forms import (
BaseFormSet, BaseFormSet,
Form,
IntegerField, IntegerField,
ModelForm,
ValidationError, ValidationError,
formset_factory, formset_factory,
) )
@ -47,12 +47,9 @@ def get_operator(counter: Counter, customer: Customer) -> User:
return counter.get_random_barman() return counter.get_random_barman()
class ProductForm(ModelForm): class ProductForm(Form):
quantity = IntegerField(min_value=1) quantity = IntegerField(min_value=1)
id = IntegerField(min_value=0)
class Meta:
model = Product
fields = ["code"]
def __init__( def __init__(
self, self,
@ -75,13 +72,13 @@ class ProductForm(ModelForm):
user = self.customer.user user = self.customer.user
# We store self.product so we can use it later on the formset validation # We store self.product so we can use it later on the formset validation
self.product = self.counter.products.filter(code=cleaned_data["code"]).first() self.product = self.counter.products.filter(id=cleaned_data["id"]).first()
if self.product is None: if self.product is None:
raise ValidationError( raise ValidationError(
_( _(
"Product %(product)s doesn't exist or isn't available on this counter" "Product %(product)s doesn't exist or isn't available on this counter"
) )
% {"product": cleaned_data["code"]} % {"product": cleaned_data["id"]}
) )
# Test alcohoolic products # Test alcohoolic products