Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
third-party
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
2
Merge Requests
2
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cooperatic-foodcoops
third-party
Commits
abe34fb6
Commit
abe34fb6
authored
Mar 14, 2025
by
Yvon Kerdoncuff
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
several changes in inventaire par article app
parent
6963f5a9
Pipeline
#4179
failed with stage
Changes
6
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
80 additions
and
42 deletions
+80
-42
models.py
products/models.py
+8
-0
products.css
products/static/css/products.css
+5
-4
products_index.js
products/static/js/products_index.js
+37
-32
urls.py
products/urls.py
+1
-0
views.py
products/views.py
+25
-1
index.html
templates/products/index.html
+4
-5
No files found.
products/models.py
View file @
abe34fb6
...
...
@@ -397,6 +397,14 @@ class CagetteProducts(models.Model):
return
api
.
search_read
(
'product.product'
,
cond
,
fields
)
@staticmethod
def
get_active_products_from_name
(
name
):
api
=
OdooAPI
()
cond
=
[[
'active'
,
'='
,
True
],
[
'name'
,
'ilike'
,
name
]]
fields
=
[
'id'
,
'uom_id'
,
'name'
,
'qty_available'
,
'barcode'
,
'active'
,
'shelf_id'
,
'product_tmpl_id'
]
return
api
.
search_read
(
'product.product'
,
cond
,
fields
)
@staticmethod
def
get_vrac_products_from_cats
(
cats
,
withCandidate
=
False
,
fields
=
[]):
api
=
OdooAPI
()
cond
=
[[
'active'
,
'='
,
True
],
...
...
products/static/css/products.css
View file @
abe34fb6
.main
,
.barcode_search_area
{
.main
,
.barcode_
or_name_
search_area
{
margin-top
:
20px
;
}
#barcode_selector
{
#barcode_
or_name_
selector
{
border
:
1px
solid
#555
;
border-radius
:
15px
;
}
.stock_edit_input
{
max-width
:
5
0px
;
}
max-width
:
10
0px
;
}
\ No newline at end of file
products/static/js/products_index.js
View file @
abe34fb6
/*
* Récupération d'un produit par scan et affichage des informations du produits.
* Les informations actuellements récupérées sont :
* - Numéro de Rayon
* - Numéro de Rayon
(not anymore : too slow)
* - Stock théorique
*
* Les informations actuellement modifiables sont :
...
...
@@ -11,10 +11,11 @@
var
products
=
[],
products_table
=
null
,
search_chars
=
[];
search_history
=
[];
function
reset_focus
()
{
$
(
'#barcode_selector'
).
val
(
''
);
$
(
'#barcode_selector'
).
focus
();
$
(
'#barcode_
or_name_
selector'
).
val
(
''
);
$
(
'#barcode_
or_name_
selector'
).
focus
();
}
function
add_product
(
product
)
{
...
...
@@ -45,7 +46,6 @@ function add_product(product) {
+
display_barcode
+
'</span> </div>'
;
}
},
{
data
:
"shelf_sortorder"
,
title
:
"Rayon"
},
{
data
:
"uom_id.1"
,
title
:
"Unité de vente"
,
...
...
@@ -83,7 +83,7 @@ function add_product(product) {
.
find
(
'input'
)
.
val
();
if
(
row_data
.
uom_id
[
0
]
==
1
)
{
if
(
qty
/
parseInt
(
qty
)
!=
1
)
{
if
(
qty
!=
0
&&
qty
/
parseInt
(
qty
)
!=
1
)
{
$
.
notify
(
"Ce produit est vendu à l'unité : la valeur doit être un nombre entier !"
,
{
...
...
@@ -189,47 +189,43 @@ function update_product_stock(p_data) {
}
// Fetch a product when barcode is read
function
fetch_product
_from_bc
(
barcode
)
{
if
(
barcode
==
''
)
{
function
fetch_product
s_from_bc_or_name
(
input
)
{
if
(
input
==
''
)
{
reset_focus
();
return
0
;
}
for
(
p
of
products
)
{
if
(
p
.
barcode
==
barcode
)
{
$
.
notify
(
"Produit déjà récupéré !"
,
{
globalPosition
:
"top left"
,
className
:
"info"
}
);
if
(
search_history
.
includes
(
input
))
{
$
.
notify
(
"Recherche déjà effectuée !"
,
{
globalPosition
:
"top left"
,
className
:
"info"
}
);
reset_focus
();
reset_focus
();
return
0
;
}
return
0
;
}
else
{
search_history
.
push
(
input
)
}
$
.
ajax
({
url
:
"/products/get_product
_data?barcode="
+
barcode
,
url
:
"/products/get_product
s_data_by_barcode_or_name?input="
+
input
,
success
:
function
(
data
)
{
reset_focus
();
if
(
data
.
product
.
active
==
false
)
{
alert
(
'Ce produit est archivé !'
);
return
0
;
for
(
const
product
of
data
.
products
)
{
add_product
(
product
);
}
add_product
(
data
.
product
);
},
error
:
function
(
data
)
{
if
(
data
.
status
==
404
)
{
// Product not found (shouldn't rise)
$
.
notify
(
"Aucun produit trouvé
avec ce code barre
!"
,
"Aucun produit trouvé !"
,
{
globalPosition
:
"top left"
,
className
:
"error"
...
...
@@ -238,7 +234,7 @@ function fetch_product_from_bc(barcode) {
reset_focus
();
}
else
{
// server error
err
=
{
msg
:
"erreur serveur lors de la récupération du produit"
,
ctx
:
'fetch_product
_from_bc
'
};
err
=
{
msg
:
"erreur serveur lors de la récupération du produit"
,
ctx
:
'fetch_product
s_from_bc_or_name
'
};
if
(
typeof
data
.
responseJSON
!=
'undefined'
&&
typeof
data
.
responseJSON
.
error
!=
'undefined'
)
{
err
.
msg
+=
' : '
+
data
.
responseJSON
.
error
;
}
...
...
@@ -255,9 +251,18 @@ $(document).ready(function() {
reset_focus
();
$
(
'#button_barcode_selector'
).
on
(
'click'
,
function
()
{
bc
=
$
(
'#barcode_selector'
).
val
();
fetch_product_from_bc
(
bc
);
$
(
'#button_barcode_or_name_selector'
).
on
(
'click'
,
function
()
{
input
=
$
(
'#barcode_or_name_selector'
).
val
();
fetch_products_from_bc_or_name
(
input
);
});
// Interception de la touche "Enter" dans le champ de texte
$
(
'#barcode_or_name_selector'
).
on
(
'keypress'
,
function
(
e
)
{
if
(
e
.
which
===
13
)
{
// Si la touche pressée est "Enter" (key code 13)
e
.
preventDefault
();
// Empêche le comportement par défaut (rechargement ou soumission de formulaire)
input
=
$
(
'#barcode_or_name_selector'
).
val
();
fetch_products_from_bc_or_name
(
input
);
// Appelle la fonction de recherche
}
});
// Barcode reader: listen for 13 digits read in a very short time
...
...
@@ -271,7 +276,7 @@ $(document).ready(function() {
if
(
!
isNaN
(
barcode
))
{
search_chars
=
[];
setTimeout
(
function
()
{
fetch_product
_from_bc
(
barcode
);
fetch_product
s_from_bc_or_name
(
barcode
);
},
300
);
}
}
...
...
products/urls.py
View file @
abe34fb6
...
...
@@ -7,6 +7,7 @@ urlpatterns = [
url
(
r'^simple_list$'
,
views
.
get_simple_list
),
url
(
r'^get_product_for_order_helper$'
,
views
.
get_product_for_order_helper
),
url
(
r'^get_product_data$'
,
views
.
get_product_data
),
url
(
r'^get_products_data_by_barcode_or_name$'
,
views
.
get_products_data_by_barcode_or_name
),
url
(
r'^get_products_stdprices$'
,
views
.
get_products_stdprices
),
url
(
r'^update_product_stock$'
,
views
.
update_product_stock
),
url
(
r'^update_product_purchase_ok$'
,
views
.
update_product_purchase_ok
),
...
...
products/views.py
View file @
abe34fb6
...
...
@@ -55,6 +55,25 @@ def get_product_for_order_helper(request):
else
:
return
JsonResponse
(
res
,
safe
=
False
)
def
get_products_data_by_barcode_or_name
(
request
):
input
=
request
.
GET
[
'input'
]
# check if it is probably a barcode input
if
input
.
isdigit
()
and
len
(
input
)
>
6
:
products
=
CagetteProduct
.
get_product_from_barcode
(
input
)
# or a text input
else
:
products
=
CagetteProducts
.
get_active_products_from_name
(
input
)
#commented because too slow
#for product in products:
# add_shelf_sortorder(product)
if
not
products
:
return
JsonResponse
({
"product"
:
products
},
status
=
404
)
else
:
return
JsonResponse
({
"products"
:
products
})
def
get_product_data
(
request
):
barcode
=
request
.
GET
[
'barcode'
]
res
=
CagetteProduct
.
get_product_from_barcode
(
barcode
)
...
...
@@ -63,6 +82,12 @@ def get_product_data(request):
return
JsonResponse
({
"product"
:
res
},
status
=
404
)
p
=
res
[
0
]
add_shelf_sortorder
(
p
)
return
JsonResponse
({
"product"
:
p
})
def
add_shelf_sortorder
(
p
):
if
p
[
'shelf_id'
]
is
not
False
:
shelfs_sortorder
=
Shelfs
.
get_shelfs_sortorder
([
p
[
'shelf_id'
][
0
]])
...
...
@@ -73,7 +98,6 @@ def get_product_data(request):
else
:
p
[
'shelf_sortorder'
]
=
'X'
return
JsonResponse
({
"product"
:
p
})
def
get_products_stdprices
(
request
):
ids
=
json
.
loads
(
request
.
body
.
decode
())
...
...
templates/products/index.html
View file @
abe34fb6
...
...
@@ -15,13 +15,12 @@
{% block content %}
<div
class=
"header txtcenter"
>
<h1>
In
formations sur les produits du magasin
</h1>
<h1>
In
ventaire par produits
</h1>
</div>
<div
class=
"barcode_search_area txtcenter"
>
<p><i>
Passez un produit sous la douchette ! Si rien ne se passe, cliquez sur le champ ci-dessous puis ré-essayez.
</i></p>
<input
type=
"text"
id=
"barcode_selector"
name=
"barcode_selector"
placeholder=
"Codebarre"
>
<button
type=
"button"
class=
"btn--primary"
id=
"button_barcode_selector"
name=
"button"
>
Recherche
</button>
<div
class=
"barcode_or_name_search_area txtcenter"
>
<input
type=
"text"
id=
"barcode_or_name_selector"
name=
"barcode_or_name_selector"
placeholder=
"Nom ou codebarre"
>
<button
type=
"button"
class=
"btn--primary"
id=
"button_barcode_or_name_selector"
name=
"button"
>
Recherche
</button>
</div>
<div
class=
"main"
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment