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
0
Merge Requests
0
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
Alexis AOUN
third-party
Commits
9279aa72
Commit
9279aa72
authored
May 28, 2021
by
Damien Moulard
Committed by
Alexis Aoun
Jul 06, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
select products & generate inventory
parent
618415fb
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
272 additions
and
57 deletions
+272
-57
models.py
inventory/models.py
+36
-18
custom_lists.js
inventory/static/js/custom_lists.js
+16
-2
views.py
inventory/views.py
+16
-2
oders_helper_style.css
orders/static/css/oders_helper_style.css
+25
-3
orders_helper.js
orders/static/js/orders_helper.js
+165
-31
custom_lists.html
templates/inventory/custom_lists.html
+1
-1
helper.html
templates/orders/helper.html
+13
-0
No files found.
inventory/models.py
View file @
9279aa72
...
...
@@ -52,7 +52,7 @@ class CagetteInventory(models.Model):
file_data
=
json
.
load
(
json_file
)
date_time
=
datetime
.
fromtimestamp
(
int
(
filename
))
d
=
date_time
.
strftime
(
"
%
m/
%
d
/
%
Y,
%
H:
%
M"
)
d
=
date_time
.
strftime
(
"
%
d/
%
m
/
%
Y,
%
H:
%
M"
)
file_data
[
'id'
]
=
int
(
filename
)
file_data
[
'datetime_created'
]
=
d
...
...
@@ -113,7 +113,7 @@ class CagetteInventory(models.Model):
return
file_data
[
'inventory_status'
]
@staticmethod
def
create_custom_inv_file
(
line_ids
,
line_type
):
def
create_custom_inv_file
(
line_ids
,
line_type
,
default_partners_id
=
[]
):
res
=
{}
try
:
...
...
@@ -127,36 +127,54 @@ class CagetteInventory(models.Model):
api
=
OdooAPI
()
ids
=
[]
order
=
[
''
,
''
]
user
=
partner
=
''
fields
=
[
'create_uid'
,
'product_id'
,
'partner_id'
]
cond
=
[[
'id'
,
'in'
,
line_ids
]]
if
(
line_type
==
'cpo'
):
model
=
'computed.purchase.order.line'
fields
+=
[
'computed_purchase_order_id'
]
user
=
''
partners
=
[]
if
len
(
default_partners_id
)
>
0
:
f
=
[
'name'
]
c
=
[[
'id'
,
'in'
,
default_partners_id
]]
partners_name
=
api
.
search_read
(
'res.partner'
,
c
,
f
)
for
p
in
partners_name
:
partners
.
append
(
p
[
'name'
])
if
line_type
==
'product_templates'
:
fields
=
[
'id'
]
cond
=
[[
'product_tmpl_id'
,
'in'
,
line_ids
]]
model
=
'product.product'
user
=
"api"
else
:
model
=
'purchase.order.line'
fields
+=
[
'order_id'
]
fields
=
[
'create_uid'
,
'product_id'
,
'partner_id'
]
cond
=
[[
'id'
,
'in'
,
line_ids
]]
if
(
line_type
==
'cpo'
):
model
=
'computed.purchase.order.line'
fields
+=
[
'computed_purchase_order_id'
]
else
:
model
=
'purchase.order.line'
fields
+=
[
'order_id'
]
lines
=
api
.
search_read
(
model
,
cond
,
fields
)
if
len
(
lines
)
==
len
(
line_ids
):
for
l
in
lines
:
ids
.
append
(
l
[
'product_id'
][
0
])
user
=
l
[
'create_uid'
][
1
]
if
(
line_type
==
'cpo'
):
order
=
l
[
'computed_purchase_order_id'
]
if
line_type
==
'product_templates'
:
ids
.
append
(
l
[
'id'
])
else
:
order
=
l
[
'order_id'
]
partner
=
l
[
'partner_id'
][
1
]
ids
.
append
(
l
[
'product_id'
][
0
])
user
=
l
[
'create_uid'
][
1
]
if
(
line_type
==
'cpo'
):
order
=
l
[
'computed_purchase_order_id'
]
else
:
order
=
l
[
'order_id'
]
partners
.
append
(
l
[
'partner_id'
][
1
])
if
(
line_type
==
'cpo'
):
# partner_id isn't defined
f
=
[
'partner_id'
]
c
=
[[
'id'
,
'='
,
int
(
order
[
0
])]]
cpo
=
api
.
search_read
(
'computed.purchase.order'
,
c
,
f
)
if
len
(
cpo
)
>
0
:
partner
=
cpo
[
0
][
'partner_id'
][
1
]
partner
s
.
append
(
cpo
[
0
][
'partner_id'
][
1
])
file_data
=
{
'order'
:
order
[
1
],
'user'
:
user
,
'partner
'
:
partner
,
'partner
s'
:
partners
,
'inventory_status'
:
''
,
'products'
:
ids
}
...
...
inventory/static/js/custom_lists.js
View file @
9279aa72
...
...
@@ -4,6 +4,13 @@ var shelfs_table = null,
function
init_datatable
()
{
// For a smooth migration...
for
(
const
i
in
lists
)
{
if
((
'partners'
in
lists
[
i
])
===
false
)
{
lists
[
i
][
'partners'
]
=
[
lists
[
i
][
'partner'
]]
}
}
return
$
(
'#lists'
).
DataTable
({
data
:
lists
,
// data passed at page loading
rowId
:
'id'
,
...
...
@@ -17,8 +24,15 @@ function init_datatable() {
}
},
{
data
:
"partner"
,
title
:
"Fournisseur"
data
:
"partners"
,
title
:
"Fournisseur(s)"
,
render
:
function
(
data
)
{
res
=
""
;
for
(
const
i
in
data
)
{
res
+=
`
${
data
[
i
]}
<br/>`
;
}
return
res
;
}
},
{
data
:
"order"
,
...
...
inventory/views.py
View file @
9279aa72
...
...
@@ -43,7 +43,6 @@ def custom_list_inventory(request, id):
products
=
CagetteInventory
.
get_custom_list_products
(
id
)
if
'error'
in
products
:
print
(
products
)
products
[
'data'
]
=
[]
context
=
{
'title'
:
'Inventaire'
,
...
...
@@ -112,10 +111,25 @@ def do_custom_list_inventory(request):
def
generate_inventory_list
(
request
):
"""Responding to Odoo ajax call (no csrf)."""
res
=
{}
default_partners_id
=
[]
try
:
lines
=
json
.
loads
(
request
.
POST
.
get
(
'lines'
))
ltype
=
request
.
POST
.
get
(
'type'
)
res
=
CagetteInventory
.
create_custom_inv_file
(
lines
,
ltype
)
except
Exception
as
e
:
try
:
# POST.get() returns None when request from django
data
=
json
.
loads
(
request
.
body
.
decode
())
lines
=
data
[
"lines"
]
ltype
=
data
[
"type"
]
if
"partners_id"
in
data
:
default_partners_id
=
data
[
"partners_id"
]
except
Exception
as
ee
:
res
[
'error'
]
=
str
(
ee
)
coop_looger
.
error
(
"generate_inventory_list :
%
s"
,
str
(
e
))
return
JsonResponse
(
res
,
status
=
500
)
try
:
res
=
CagetteInventory
.
create_custom_inv_file
(
lines
,
ltype
,
default_partners_id
)
except
Exception
as
e
:
res
[
'error'
]
=
str
(
e
)
coop_looger
.
error
(
"generate_inventory_list :
%
s"
,
str
(
e
))
...
...
orders/static/css/oders_helper_style.css
View file @
9279aa72
.page_body
{
position
:
relative
;
}
#form_container
{
margin-top
:
30px
;
}
...
...
@@ -7,7 +11,7 @@
}
#products_table_filter
input
{
height
:
5
0px
;
height
:
4
0px
;
}
#supplier_input
{
...
...
@@ -29,6 +33,21 @@
font-weight
:
bold
;
}
#table_header_select_all
{
display
:
flex
;
align-content
:
center
;
justify-content
:
center
;
flex-wrap
:
wrap
;
}
#table_header_select_all
input
{
margin-left
:
5px
;
}
.select_product_cb
{
cursor
:
pointer
;
}
#suppliers_container
{
display
:
flex
;
justify-content
:
center
;
...
...
@@ -56,5 +75,8 @@
cursor
:
pointer
;
}
#actions_buttons_area
{
position
:
absolute
;
top
:
0
;
right
:
0
;
}
orders/static/js/orders_helper.js
View file @
9279aa72
var
suppliers_list
=
[],
products_table
=
null
,
products
=
[]
selected_suppliers
=
[],
products
=
[];
/* CALLS TO SERVER */
selected_rows
=
[];
/**
* Add a supplier to the selected suppliers list.
...
...
@@ -69,13 +67,34 @@ function add_supplier() {
}
/**
* Remove a supplier from the selected list & its associated products
*
* @param {int} supplier_id
*/
function
remove_supplier
(
supplier_id
)
{
// Remove from suppliers list
selected_suppliers
=
selected_suppliers
.
filter
(
supplier
=>
supplier
.
id
!=
supplier_id
);
// Remove the supplier from the products suppliers list
for
(
const
i
in
products
)
{
products
[
i
].
suppliers
=
products
[
i
].
suppliers
.
filter
(
supplier
=>
supplier
.
id
!=
supplier_id
);
}
// Remove products only associated to this product
products
=
products
.
filter
(
product
=>
product
.
suppliers
.
length
>
0
);
update_display
();
}
/**
* Send to server the association product-supplier
*
* @param {object} product
* @param {object} supplier
* @param {node} cell product's row in datatable
*/
function
save_supplier_product_association
(
product
,
supplier
,
cell
)
{
function
save_supplier_product_association
(
product
,
supplier
,
cell
)
{
openModal
();
const
data
=
{
...
...
@@ -119,26 +138,6 @@ function save_supplier_product_association(product, supplier, cell) {
}
/**
* Remove a supplier from the selected list & its associated products
*
* @param {int} supplier_id
*/
function
remove_supplier
(
supplier_id
)
{
// Remove from suppliers list
selected_suppliers
=
selected_suppliers
.
filter
(
supplier
=>
supplier
.
id
!=
supplier_id
);
// Remove the supplier from the products suppliers list
for
(
const
i
in
products
)
{
products
[
i
].
suppliers
=
products
[
i
].
suppliers
.
filter
(
supplier
=>
supplier
.
id
!=
supplier_id
);
}
// Remove products only associated to this product
products
=
products
.
filter
(
product
=>
product
.
suppliers
.
length
>
0
);
update_display
();
}
/**
* When products are fetched, save them and the relation with the supplier.
* If product already saved, add the supplier to its suppliers list.
* Else, add product with supplier.
...
...
@@ -221,7 +220,6 @@ function display_suppliers() {
const
supplier_id
=
el_id
[
el_id
.
length
-
1
];
let
modal_remove_supplier
=
$
(
'#templates #modal_remove_supplier'
);
modal_remove_supplier
.
find
(
".supplier_name"
).
text
(
supplier
.
display_name
);
openModal
(
...
...
@@ -285,7 +283,16 @@ function prepare_datatable_columns() {
{
data
:
"id"
,
title
:
"id"
,
visible
:
false
,
title
:
` <div id="table_header_select_all">
Tout
<input type="checkbox" class="select_product_cb" id="select_all_products_cb" value="all">
</div>`
,
className
:
"dt-body-center"
,
orderable
:
false
,
render
:
function
(
data
)
{
return
`<input type="checkbox" class="select_product_cb" id="select_product_
${
data
}
" value="
${
data
}
">`
;
},
width
:
"4%"
,
},
{
data
:
"default_code"
,
...
...
@@ -315,7 +322,7 @@ function prepare_datatable_columns() {
columns
.
push
({
data
:
supplier_column_name
(
supplier
),
title
:
supplier
.
display_name
,
width
:
"
8
%"
,
width
:
"
10
%"
,
className
:
`dt-body-center supplier_input_cell`
,
render
:
(
data
,
type
,
full
)
=>
{
const
base_id
=
`product_
${
full
.
id
}
_supplier_
${
supplier
.
id
}
`
;
...
...
@@ -411,8 +418,6 @@ function display_products() {
// Associate product to supplier on click on 'X' in the table
$
(
'#products_table'
).
on
(
'click'
,
'tbody .product_not_from_supplier'
,
function
()
{
// todo istimeto
// Get supplier & product id
const
el_id
=
$
(
this
).
children
().
first
().
attr
(
'id'
)
.
split
(
'_'
);
...
...
@@ -423,7 +428,6 @@ function display_products() {
const
supplier
=
selected_suppliers
.
find
(
s
=>
s
.
id
==
supplier_id
)
let
modal_attach_product_to_supplier
=
$
(
'#templates #modal_attach_product_to_supplier'
);
modal_attach_product_to_supplier
.
find
(
".product_name"
).
text
(
product
.
name
);
modal_attach_product_to_supplier
.
find
(
".supplier_name"
).
text
(
supplier
.
display_name
);
...
...
@@ -439,15 +443,141 @@ function display_products() {
);
});
// Select row(s) on checkbox change
$
(
'#products_table'
).
on
(
'click'
,
'thead th #select_all_products_cb'
,
function
()
{
if
(
this
.
checked
)
{
selected_rows
=
[]
products_table
.
rows
().
every
(
function
()
{
const
node
=
$
(
this
.
node
());
node
.
addClass
(
'selected'
);
node
.
find
(
".select_product_cb"
).
first
().
prop
(
"checked"
,
true
);
// Save selected rows in case the table is updated
selected_rows
.
push
(
this
.
data
().
id
)
});
}
else
{
unselect_all_rows
()
}
});
$
(
'#products_table'
).
on
(
'click'
,
'tbody td .select_product_cb'
,
function
()
{
$
(
this
).
closest
(
'tr'
).
toggleClass
(
'selected'
);
// Save / unsave selected row
p_id
=
products_table
.
row
(
$
(
this
).
closest
(
'tr'
)).
data
().
id
;
if
(
this
.
checked
)
{
selected_rows
.
push
(
p_id
)
}
else
{
const
i
=
selected_rows
.
findIndex
(
id
=>
id
==
p_id
)
selected_rows
.
splice
(
i
,
1
)
}
});
return
0
;
}
/**
* Unselect all rows from datatable.
*/
function
unselect_all_rows
()
{
products_table
.
rows
().
every
(
function
()
{
const
node
=
$
(
this
.
node
());
node
.
removeClass
(
'selected'
);
node
.
find
(
".select_product_cb"
).
first
().
prop
(
"checked"
,
false
);
});
selected_rows
=
[]
}
/**
* Update DOM display
*/
function
update_display
()
{
// Remove listener before recreating them
$
(
'#products_table'
).
off
(
'click'
,
'tbody .product_not_from_supplier'
);
$
(
'#products_table'
).
off
(
'click'
,
'thead th #select_all_products_cb'
);
$
(
'#products_table'
).
off
(
'click'
,
'tbody td .select_product_cb'
);
display_suppliers
();
display_products
();
// Re-select previously selected rows
if
(
selected_rows
.
length
>
0
)
{
products_table
.
rows
().
every
(
function
()
{
if
(
selected_rows
.
includes
(
this
.
data
().
id
))
{
const
node
=
$
(
this
.
node
());
node
.
addClass
(
'selected'
);
node
.
find
(
".select_product_cb"
).
first
().
prop
(
"checked"
,
true
);
}
});
}
}
function
generate_inventory
()
{
if
(
products_table
!==
null
)
{
const
selected_data
=
products_table
.
rows
(
'.selected'
).
data
();
if
(
selected_data
.
length
==
0
)
{
alert
(
"Veuillez sélectionner les produits à inventorier en cochant les cases sur la gauche du tableau."
)
}
else
{
data
=
{
lines
:
[],
partners_id
:
[],
type
:
'product_templates'
}
for
(
var
i
=
0
;
i
<
selected_data
.
length
;
i
++
)
{
const
product
=
products
.
find
(
p
=>
p
.
id
==
selected_data
[
i
].
id
)
data
.
lines
.
push
(
product
.
id
);
for
(
const
supplier
of
product
.
suppliers
)
{
if
(
data
.
partners_id
.
indexOf
(
supplier
.
id
)
===
-
1
)
{
data
.
partners_id
.
push
(
supplier
.
id
)
}
}
}
let
modal_create_inventory
=
$
(
'#templates #modal_create_inventory'
);
modal_create_inventory
.
find
(
".inventory_products_count"
).
text
(
data
.
lines
.
length
);
openModal
(
modal_create_inventory
.
html
(),
()
=>
{
$
.
ajax
({
type
:
"POST"
,
url
:
"/inventory/generate_inventory_list"
,
dataType
:
"json"
,
traditional
:
true
,
contentType
:
"application/json; charset=utf-8"
,
data
:
JSON
.
stringify
(
data
),
success
:
()
=>
{
unselect_all_rows
();
// Give time for modal to fade
setTimeout
(
function
(){
$
.
notify
(
"Inventaire créé !"
,
{
globalPosition
:
"top left"
,
className
:
"success"
}
);
},
500
);
},
error
:
function
(
data
)
{
let
msg
=
"erreur serveur lors de la création de l'inventaire"
.
err
=
{
msg
:
msg
,
ctx
:
'generate_inventory'
};
if
(
typeof
data
.
responseJSON
!=
'undefined'
&&
typeof
data
.
responseJSON
.
error
!=
'undefined'
)
{
err
.
msg
+=
' : '
+
data
.
responseJSON
.
error
;
}
report_JS_error
(
err
,
'orders'
);
alert
(
"Erreur lors de la création de l'inventaire. Réessayez plus tard."
);
}
});
},
'Valider'
,
);
}
}
}
$
(
document
).
ready
(
function
()
{
...
...
@@ -488,4 +618,8 @@ $(document).ready(function() {
e
.
preventDefault
();
add_supplier
();
});
$
(
"#do_inventory"
).
on
(
"click"
,
function
(
e
)
{
generate_inventory
();
});
});
templates/inventory/custom_lists.html
View file @
9279aa72
...
...
@@ -34,7 +34,7 @@
</div>
<script
type=
"text/javascript"
>
lists
=
{{
lists
|
safe
}}
var
lists
=
{{
lists
|
safe
}}
</script>
<script
src=
"{% static "
js
/
all_common
.
js
"
%}?
v=
"></script>
<script src="
{%
static
"
js
/
common
.
js
"
%}?
v=
"></script>
...
...
templates/orders/helper.html
View file @
9279aa72
...
...
@@ -10,10 +10,15 @@
{% block additionnal_scripts %}
<script
type=
"text/javascript"
src=
"{% static 'jquery-ui-1.12.1/jquery-ui.min.js' %}?v="
></script>
<script
type=
"text/javascript"
src=
"{% static 'js/datatables/jquery.dataTables.min.js' %}"
></script>
<script
type=
"text/javascript"
src=
"{% static 'js/notify.min.js' %}?v="
></script>
{% endblock %}
{% block content %}
<div
class=
"page_body"
>
<div
id=
"actions_buttons_area"
>
<button
type=
"button"
class=
'btn--primary'
id=
"do_inventory"
>
Faire un inventaire
</button>
</div>
<div
class=
"header txtcenter"
>
<h1>
Aide à la commande
</h1>
</div>
...
...
@@ -64,6 +69,14 @@
<p>
Êtez-vous sûr ?
</p>
<hr/>
</div>
<div
id=
"modal_create_inventory"
>
<p>
Vous vous apprêtez à créer un inventaire de
<span
class=
"inventory_products_count"
></span>
produits.
</p>
<p>
Êtez-vous sûr ?
</p>
<hr/>
</div>
</div>
<script
src=
"{% static "
js
/
all_common
.
js
"
%}?
v=
"></script>
...
...
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