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
97eaabd2
Commit
97eaabd2
authored
Aug 30, 2021
by
Damien Moulard
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'aide_a_la_commande' into dev_cooperatic
parents
f4fd7818
aa99f68f
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
320 additions
and
69 deletions
+320
-69
config_lacagette.py
coops_configurations/config_lacagette.py
+3
-0
models.py
orders/models.py
+6
-1
oders_helper_style.css
orders/static/css/oders_helper_style.css
+109
-21
orders_helper.js
orders/static/js/orders_helper.js
+0
-0
urls.py
orders/urls.py
+1
-0
views.py
orders/views.py
+23
-7
models.py
products/models.py
+75
-15
urls.py
products/urls.py
+1
-0
views.py
products/views.py
+15
-2
reception_index.js
reception/static/js/reception_index.js
+1
-1
stock_movements.js
stock/static/js/stock_movements.js
+16
-10
helper.html
templates/orders/helper.html
+70
-12
No files found.
coops_configurations/config_lacagette.py
View file @
97eaabd2
...
@@ -109,3 +109,6 @@ RECEPTION_PB = "Ici, vous pouvez signaler toute anomalie lors d'une réception,
...
@@ -109,3 +109,6 @@ RECEPTION_PB = "Ici, vous pouvez signaler toute anomalie lors d'une réception,
# display or not column "Autres" in reception process
# display or not column "Autres" in reception process
DISPLAY_COL_AUTRES
=
False
DISPLAY_COL_AUTRES
=
False
# URL to the metabase dashboard for orders helper
ORDERS_HELPER_METABASE_URL
=
"https://metabase.lacagette-coop.fr/dashboard/16"
orders/models.py
View file @
97eaabd2
...
@@ -258,6 +258,11 @@ class Order(models.Model):
...
@@ -258,6 +258,11 @@ class Order(models.Model):
}
}
for
line
in
order_lines
:
for
line
in
order_lines
:
product_line_name
=
line
[
"name"
]
if
"product_code"
in
line
and
line
[
"product_code"
]
is
not
False
:
product_code
=
str
(
line
[
"product_code"
])
product_line_name
=
"["
+
product_code
+
"] "
+
product_line_name
order_data
[
"order_line"
]
.
append
(
order_data
[
"order_line"
]
.
append
(
[
[
0
,
0
,
...
@@ -267,7 +272,7 @@ class Order(models.Model):
...
@@ -267,7 +272,7 @@ class Order(models.Model):
"price_policy"
:
"uom"
,
"price_policy"
:
"uom"
,
"indicative_package"
:
True
,
"indicative_package"
:
True
,
"product_id"
:
line
[
"product_variant_ids"
][
0
],
"product_id"
:
line
[
"product_variant_ids"
][
0
],
"name"
:
line
[
"name"
]
,
"name"
:
product_line_name
,
"date_planned"
:
date_planned
,
"date_planned"
:
date_planned
,
"account_analytic_id"
:
False
,
"account_analytic_id"
:
False
,
"product_qty_package"
:
line
[
"product_qty_package"
],
"product_qty_package"
:
line
[
"product_qty_package"
],
...
...
orders/static/css/oders_helper_style.css
View file @
97eaabd2
...
@@ -19,7 +19,7 @@
...
@@ -19,7 +19,7 @@
flex-direction
:
column
;
flex-direction
:
column
;
justify-content
:
center
;
justify-content
:
center
;
align-items
:
center
;
align-items
:
center
;
padding
:
5px
30px
5
px
30px
;
padding
:
7px
30px
7
px
30px
;
margin
:
0
10px
5px
10px
;
margin
:
0
10px
5px
10px
;
}
}
...
@@ -31,6 +31,26 @@
...
@@ -31,6 +31,26 @@
background-color
:
#a1a2a3
;
background-color
:
#a1a2a3
;
}
}
.link_as_button
:hover
{
text-decoration
:
none
;
color
:
white
;
}
.link_as_button
:active
{
text-decoration
:
none
;
color
:
white
;
}
.link_as_button
:focus
{
text-decoration
:
none
;
color
:
white
;
}
.remove_order_modal_text
{
font-size
:
2rem
;
}
.remove_order_name
{
font-weight
:
bold
;
}
/* - Order selection screen */
/* - Order selection screen */
#new_order_area
{
#new_order_area
{
margin-bottom
:
40px
;
margin-bottom
:
40px
;
...
@@ -50,6 +70,25 @@
...
@@ -50,6 +70,25 @@
padding-top
:
15px
;
padding-top
:
15px
;
}
}
.order_pill
{
flex-direction
:
row
;
}
.pill_order_name
{
flex
:
3
0
auto
;
}
.remove_order_icon
{
flex
:
0
1
auto
;
color
:
#912930
;
margin-left
:
5px
;
cursor
:
pointer
;
z-index
:
2
;
transform
:
scale
(
1.2
);
}
.remove_order_icon
:hover
{
color
:
#e62720
;
}
.order_last_update
{
.order_last_update
{
font-weight
:
bold
;
font-weight
:
bold
;
}
}
...
@@ -82,6 +121,40 @@
...
@@ -82,6 +121,40 @@
justify-content
:
flex-start
;
justify-content
:
flex-start
;
}
}
.right_action_buttons
{
display
:
flex
;
}
#actions_buttons_wrapper
{
position
:
relative
;
margin-right
:
5px
;
}
#toggle_action_buttons
{
width
:
250px
;
position
:
relative
;
}
.toggle_action_buttons_icon
{
position
:
absolute
;
top
:
50%
;
transform
:
translateY
(
-50%
);
right
:
15px
;
}
#actions_buttons_container
{
position
:
absolute
;
display
:
flex
;
flex-direction
:
column
;
width
:
250px
;
display
:
none
;
}
.action_button
{
width
:
100%
;
min-height
:
45px
;
}
/* -- Order data */
/* -- Order data */
#order_data_container
{
#order_data_container
{
font-size
:
1.8rem
;
font-size
:
1.8rem
;
...
@@ -92,17 +165,27 @@
...
@@ -92,17 +165,27 @@
}
}
#order_forms_container
{
#order_forms_container
{
margin-top
:
3
0px
;
margin-top
:
2
0px
;
display
:
flex
;
display
:
flex
;
flex-wrap
:
wrap
;
justify-content
:
space-evenly
;
justify-content
:
space-evenly
;
}
}
.order_form_item
{
margin-top
:
10px
;
}
#supplier_input
{
#supplier_input
{
width
:
350px
;
width
:
350px
;
border-radius
:
3px
;
border-radius
:
3px
;
}
}
#date_planned_input
,
#coverage_days_input
{
#stats_date_period_select
{
margin-left
:
5px
;
min-width
:
200px
;
}
#date_planned_input
,
#coverage_days_input
,
#stats_date_period_select
{
border-radius
:
3px
;
border-radius
:
3px
;
}
}
...
@@ -144,18 +227,27 @@
...
@@ -144,18 +227,27 @@
width
:
100px
;
width
:
100px
;
}
}
.product_ref_input
{
padding
:
.5rem
.5rem
;
}
.supplier_package_qty
{
.supplier_package_qty
{
font-style
:
italic
;
font-style
:
italic
;
font-size
:
1.3rem
;
font-size
:
1.3rem
;
}
}
.product_not_from_supplier
{
.product_not_from_supplier
{
background-color
:
#e
7e9ed
;
background-color
:
#e
8ebf0
;
cursor
:
pointer
;
cursor
:
pointer
;
}
}
.product_not_from_supplier
:hover
{
.product_not_from_supplier
:hover
{
background-color
:
#c7cace
;
background-color
:
#d3d7db
;
}
.product_ref_cell
:hover
{
background-color
:
#d3d7db
;
cursor
:
pointer
;
}
}
.product_name
,
.supplier_name
,
.product_npa
{
.product_name
,
.supplier_name
,
.product_npa
{
...
@@ -166,6 +258,10 @@
...
@@ -166,6 +258,10 @@
cursor
:
pointer
;
cursor
:
pointer
;
}
}
.focused_line
{
background-color
:
#76cf71
!important
;
}
/* -- Footer */
/* -- Footer */
#main_content_footer
{
#main_content_footer
{
...
@@ -185,19 +281,24 @@
...
@@ -185,19 +281,24 @@
align-items
:
center
;
align-items
:
center
;
flex-wrap
:
wrap
;
flex-wrap
:
wrap
;
margin
:
30px
0
20px
0
;
margin
:
30px
0
20px
0
;
position
:
-webkit-sticky
;
position
:
sticky
;
top
:
20px
;
z-index
:
3
;
}
}
.supplier_pill
{
.supplier_pill
{
background-color
:
#
e7e9ed
c5
;
background-color
:
#
a0daff
;
border
:
1px
solid
black
;
border
:
1px
solid
#6ea8cc
;
}
}
.pill_supplier_name
{
.pill_supplier_name
{
font-weight
:
bold
;
font-weight
:
bold
;
}
}
.supplier_
total_value_container
{
.supplier_
data
{
font-size
:
1.5rem
;
font-size
:
1.5rem
;
display
:
flex
;
}
}
.remove_supplier_icon
{
.remove_supplier_icon
{
...
@@ -253,19 +354,6 @@
...
@@ -253,19 +354,6 @@
margin-top
:
10px
;
margin-top
:
10px
;
}
}
.download_order_file_button
:hover
{
text-decoration
:
none
;
color
:
white
;
}
.download_order_file_button
:active
{
text-decoration
:
none
;
color
:
white
;
}
.download_order_file_button
:focus
{
text-decoration
:
none
;
color
:
white
;
}
#recap_delivery_date
{
#recap_delivery_date
{
font-weight
:
bold
;
font-weight
:
bold
;
}
}
...
...
orders/static/js/orders_helper.js
View file @
97eaabd2
This diff is collapsed.
Click to expand it.
orders/urls.py
View file @
97eaabd2
...
@@ -13,6 +13,7 @@ urlpatterns = [
...
@@ -13,6 +13,7 @@ urlpatterns = [
url
(
r'^get_suppliers$'
,
views
.
get_suppliers
),
url
(
r'^get_suppliers$'
,
views
.
get_suppliers
),
url
(
r'^get_supplier_products$'
,
views
.
get_supplier_products
),
url
(
r'^get_supplier_products$'
,
views
.
get_supplier_products
),
url
(
r'^associate_supplier_to_product$'
,
views
.
associate_supplier_to_product
),
url
(
r'^associate_supplier_to_product$'
,
views
.
associate_supplier_to_product
),
url
(
r'^end_supplier_product_association$'
,
views
.
end_supplier_product_association
),
url
(
r'^create_orders$'
,
views
.
create_orders
),
url
(
r'^create_orders$'
,
views
.
create_orders
),
url
(
r'^get_orders_attachment$'
,
views
.
get_orders_attachment
),
url
(
r'^get_orders_attachment$'
,
views
.
get_orders_attachment
),
]
]
orders/views.py
View file @
97eaabd2
...
@@ -19,7 +19,8 @@ def helper(request):
...
@@ -19,7 +19,8 @@ def helper(request):
'title'
:
'Aide à la commande'
,
'title'
:
'Aide à la commande'
,
'couchdb_server'
:
settings
.
COUCHDB
[
'url'
],
'couchdb_server'
:
settings
.
COUCHDB
[
'url'
],
'db'
:
settings
.
COUCHDB
[
'dbs'
][
'orders'
],
'db'
:
settings
.
COUCHDB
[
'dbs'
][
'orders'
],
'odoo_server'
:
settings
.
ODOO
[
'url'
]
'odoo_server'
:
settings
.
ODOO
[
'url'
],
'metabase_url'
:
getattr
(
settings
,
'ORDERS_HELPER_METABASE_URL'
,
''
)
}
}
template
=
loader
.
get_template
(
'orders/helper.html'
)
template
=
loader
.
get_template
(
'orders/helper.html'
)
...
@@ -42,7 +43,8 @@ def get_supplier_products(request):
...
@@ -42,7 +43,8 @@ def get_supplier_products(request):
""" Get supplier products """
""" Get supplier products """
suppliers_id
=
request
.
GET
.
getlist
(
'sids'
,
''
)
suppliers_id
=
request
.
GET
.
getlist
(
'sids'
,
''
)
res
=
CagetteProducts
.
get_products_for_order_helper
(
suppliers_id
)
stats_from
=
request
.
GET
.
get
(
'stats_from'
)
res
=
CagetteProducts
.
get_products_for_order_helper
(
suppliers_id
,
[],
stats_from
)
if
'error'
in
res
:
if
'error'
in
res
:
return
JsonResponse
(
res
,
status
=
500
)
return
JsonResponse
(
res
,
status
=
500
)
...
@@ -52,15 +54,29 @@ def get_supplier_products(request):
...
@@ -52,15 +54,29 @@ def get_supplier_products(request):
def
associate_supplier_to_product
(
request
):
def
associate_supplier_to_product
(
request
):
""" This product is now supplied by this supplier """
""" This product is now supplied by this supplier """
res
=
{}
res
=
{}
try
:
data
=
json
.
loads
(
request
.
body
.
decode
())
data
=
json
.
loads
(
request
.
body
.
decode
())
res
=
CagetteProduct
.
associate_supplier_to_product
(
data
)
res
=
CagetteProduct
.
associate_supplier_to_product
(
data
)
except
Exception
as
e
:
res
[
"error"
]
=
str
(
e
)
if
'error'
in
res
:
return
JsonResponse
(
res
,
status
=
500
)
return
JsonResponse
(
res
,
status
=
500
)
else
:
return
JsonResponse
({
'res'
:
res
})
return
JsonResponse
({
'res'
:
res
})
return
JsonResponse
({
'res'
:
res
})
def
end_supplier_product_association
(
request
):
""" This product is now unavailable from this supplier """
res
=
{}
data
=
json
.
loads
(
request
.
body
.
decode
())
res
=
CagetteProduct
.
end_supplier_product_association
(
data
)
if
'error'
in
res
:
return
JsonResponse
(
res
,
status
=
500
)
else
:
return
JsonResponse
({
'res'
:
res
})
def
create_orders
(
request
):
def
create_orders
(
request
):
""" Create products orders """
""" Create products orders """
res
=
{
"created"
:
[]
}
res
=
{
"created"
:
[]
}
...
...
products/models.py
View file @
97eaabd2
...
@@ -130,6 +130,7 @@ class CagetteProduct(models.Model):
...
@@ -130,6 +130,7 @@ class CagetteProduct(models.Model):
@staticmethod
@staticmethod
def
associate_supplier_to_product
(
data
):
def
associate_supplier_to_product
(
data
):
api
=
OdooAPI
()
api
=
OdooAPI
()
res
=
{}
product_tmpl_id
=
data
[
"product_tmpl_id"
]
product_tmpl_id
=
data
[
"product_tmpl_id"
]
partner_id
=
data
[
"supplier_id"
]
partner_id
=
data
[
"supplier_id"
]
...
@@ -140,6 +141,8 @@ class CagetteProduct(models.Model):
...
@@ -140,6 +141,8 @@ class CagetteProduct(models.Model):
c
=
[[
'product_tmpl_id'
,
'='
,
product_tmpl_id
]]
c
=
[[
'product_tmpl_id'
,
'='
,
product_tmpl_id
]]
res_products
=
api
.
search_read
(
'product.product'
,
c
,
f
)
res_products
=
api
.
search_read
(
'product.product'
,
c
,
f
)
product
=
res_products
[
0
]
product
=
res_products
[
0
]
today
=
datetime
.
date
.
today
()
.
strftime
(
"
%
Y-
%
m-
%
d"
)
f
=
{
f
=
{
'product_tmpl_id'
:
product_tmpl_id
,
'product_tmpl_id'
:
product_tmpl_id
,
...
@@ -149,9 +152,40 @@ class CagetteProduct(models.Model):
...
@@ -149,9 +152,40 @@ class CagetteProduct(models.Model):
'price'
:
price
,
'price'
:
price
,
'base_price'
:
price
,
'base_price'
:
price
,
'package_qty'
:
package_qty
,
'package_qty'
:
package_qty
,
'date_start'
:
today
,
'sequence'
:
1000
# lowest priority for the new suppliers
'sequence'
:
1000
# lowest priority for the new suppliers
}
}
res
=
api
.
create
(
'product.supplierinfo'
,
f
)
try
:
res
[
'create'
]
=
api
.
create
(
'product.supplierinfo'
,
f
)
except
Exception
as
e
:
res
[
'error'
]
=
str
(
e
)
return
res
@staticmethod
def
end_supplier_product_association
(
data
):
api
=
OdooAPI
()
res
=
{}
product_tmpl_id
=
data
[
"product_tmpl_id"
]
partner_id
=
data
[
"supplier_id"
]
f
=
[
"id"
]
c
=
[[
'product_tmpl_id'
,
'='
,
product_tmpl_id
],
[
'name'
,
'='
,
partner_id
],
[
'date_end'
,
'='
,
False
]]
res_supplierinfo
=
api
.
search_read
(
'product.supplierinfo'
,
c
,
f
)
psi_id
=
res_supplierinfo
[
0
][
'id'
]
today
=
datetime
.
date
.
today
()
.
strftime
(
"
%
Y-
%
m-
%
d"
)
f
=
{
'date_end'
:
today
}
try
:
res
[
"update"
]
=
api
.
update
(
'product.supplierinfo'
,
psi_id
,
f
)
except
Exception
as
e
:
res
[
'error'
]
=
str
(
e
)
return
res
return
res
...
@@ -172,6 +206,23 @@ class CagetteProduct(models.Model):
...
@@ -172,6 +206,23 @@ class CagetteProduct(models.Model):
return
res
return
res
@staticmethod
def
update_product_internal_ref
(
product_tmpl_id
,
default_code
):
api
=
OdooAPI
()
res
=
{}
f
=
{
'default_code'
:
default_code
}
try
:
res
[
"update"
]
=
api
.
update
(
'product.template'
,
product_tmpl_id
,
f
)
except
Exception
as
e
:
res
[
"error"
]
=
str
(
e
)
print
(
str
(
e
))
return
res
class
CagetteProducts
(
models
.
Model
):
class
CagetteProducts
(
models
.
Model
):
"""Initially used to make massive barcode update."""
"""Initially used to make massive barcode update."""
...
@@ -456,31 +507,32 @@ class CagetteProducts(models.Model):
...
@@ -456,31 +507,32 @@ class CagetteProducts(models.Model):
return
res
return
res
@staticmethod
@staticmethod
def
get_products_for_order_helper
(
supplier_ids
,
pids
=
[]):
def
get_products_for_order_helper
(
supplier_ids
,
pids
=
[]
,
stats_from
=
None
):
"""
"""
One of the two parameters must be not empty
.
supplier_ids: Get products by supplier if one or more supplier id is set. If set, pids is ignored
.
Get products by supplier if one or more supplier_id is set.
pids: If set & supplier_ids is None/empty, get products specified in pids. In this case, suppliers info won't be fetched.
If supplier_ids is empty, get products specified in pids. In this case, suppliers info won't be fetched
.
stats_from: date from which we should calculate sells stats
.
"""
"""
api
=
OdooAPI
()
api
=
OdooAPI
()
res
=
{}
res
=
{}
# todo : try with no result
try
:
try
:
today
=
datetime
.
date
.
today
()
.
strftime
(
"
%
Y-
%
m-
%
d"
)
today
=
datetime
.
date
.
today
()
.
strftime
(
"
%
Y-
%
m-
%
d"
)
if
supplier_ids
is
not
None
and
len
(
supplier_ids
)
>
0
:
if
supplier_ids
is
not
None
and
len
(
supplier_ids
)
>
0
:
# Get products/supplier relation
# Get products/supplier relation
f
=
[
"product_tmpl_id"
,
'date_start'
,
'date_end'
,
'package_qty'
,
'price'
,
'name'
]
f
=
[
"product_tmpl_id"
,
'date_start'
,
'date_end'
,
'package_qty'
,
'price'
,
'name'
,
'product_code'
]
c
=
[[
'name'
,
'in'
,
[
int
(
x
)
for
x
in
supplier_ids
]]]
c
=
[[
'name'
,
'in'
,
[
int
(
x
)
for
x
in
supplier_ids
]]]
psi
=
api
.
search_read
(
'product.supplierinfo'
,
c
,
f
)
psi
=
api
.
search_read
(
'product.supplierinfo'
,
c
,
f
)
# Filter valid data
# Filter valid data
ptids
=
[]
ptids
=
[]
valid_psi
=
[]
for
p
in
psi
:
for
p
in
psi
:
if
(
p
[
"product_tmpl_id"
]
is
not
False
if
(
p
[
"product_tmpl_id"
]
is
not
False
and
(
p
[
"date_start"
]
is
False
or
p
[
"date_end"
]
is
not
False
and
p
[
"date_start"
]
<=
today
)
and
(
p
[
"date_start"
]
is
False
or
p
[
"date_start"
]
is
not
False
and
p
[
"date_start"
]
<=
today
)
and
(
p
[
"date_end"
]
is
False
or
p
[
"date_end"
]
is
not
False
and
p
[
"date_end"
]
>=
today
)):
and
(
p
[
"date_end"
]
is
False
or
p
[
"date_end"
]
is
not
False
and
p
[
"date_end"
]
>
today
)):
valid_psi
.
append
(
p
)
ptids
.
append
(
p
[
"product_tmpl_id"
][
0
])
ptids
.
append
(
p
[
"product_tmpl_id"
][
0
])
else
:
else
:
ptids
=
[
int
(
x
)
for
x
in
pids
]
ptids
=
[
int
(
x
)
for
x
in
pids
]
...
@@ -507,6 +559,10 @@ class CagetteProducts(models.Model):
...
@@ -507,6 +559,10 @@ class CagetteProducts(models.Model):
# 'from': '2019-04-10',
# 'from': '2019-04-10',
# 'to': '2019-08-10',
# 'to': '2019-08-10',
}
}
if
stats_from
is
not
None
and
stats_from
!=
''
:
sales_average_params
[
'from'
]
=
stats_from
sales
=
CagetteProducts
.
get_template_products_sales_average
(
sales_average_params
)
sales
=
CagetteProducts
.
get_template_products_sales_average
(
sales_average_params
)
if
'list'
in
sales
and
len
(
sales
[
'list'
])
>
0
:
if
'list'
in
sales
and
len
(
sales
[
'list'
])
>
0
:
...
@@ -517,12 +573,16 @@ class CagetteProducts(models.Model):
...
@@ -517,12 +573,16 @@ class CagetteProducts(models.Model):
# Add supplier data to product data
# Add supplier data to product data
for
i
,
fp
in
enumerate
(
filtered_products_t
):
for
i
,
fp
in
enumerate
(
filtered_products_t
):
if
supplier_ids
is
not
None
and
len
(
supplier_ids
)
>
0
:
if
supplier_ids
is
not
None
and
len
(
supplier_ids
)
>
0
:
psi_item
=
next
(
item
for
item
in
psi
if
item
[
"product_tmpl_id"
]
is
not
False
and
item
[
"product_tmpl_id"
][
0
]
==
fp
[
"id"
])
# Add all the product suppliersinfo (products from multiple suppliers into the suppliers list provided)
filtered_products_t
[
i
][
'suppliersinfo'
]
=
[{
filtered_products_t
[
i
][
'suppliersinfo'
]
=
[]
'supplier_id'
:
int
(
psi_item
[
"name"
][
0
]),
for
psi_item
in
valid_psi
:
'package_qty'
:
psi_item
[
"package_qty"
],
if
psi_item
[
"product_tmpl_id"
]
is
not
False
and
psi_item
[
"product_tmpl_id"
][
0
]
==
fp
[
"id"
]:
'price'
:
psi_item
[
"price"
]
filtered_products_t
[
i
][
'suppliersinfo'
]
.
append
({
}]
'supplier_id'
:
int
(
psi_item
[
"name"
][
0
]),
'package_qty'
:
psi_item
[
"package_qty"
],
'price'
:
psi_item
[
"price"
],
'product_code'
:
psi_item
[
"product_code"
]
})
for
s
in
sales
:
for
s
in
sales
:
if
s
[
"id"
]
==
fp
[
"id"
]:
if
s
[
"id"
]
==
fp
[
"id"
]:
...
...
products/urls.py
View file @
97eaabd2
...
@@ -10,6 +10,7 @@ urlpatterns = [
...
@@ -10,6 +10,7 @@ urlpatterns = [
url
(
r'^get_products_stdprices$'
,
views
.
get_products_stdprices
),
url
(
r'^get_products_stdprices$'
,
views
.
get_products_stdprices
),
url
(
r'^update_product_stock$'
,
views
.
update_product_stock
),
url
(
r'^update_product_stock$'
,
views
.
update_product_stock
),
url
(
r'^update_product_purchase_ok$'
,
views
.
update_product_purchase_ok
),
url
(
r'^update_product_purchase_ok$'
,
views
.
update_product_purchase_ok
),
url
(
r'^update_product_internal_ref$'
,
views
.
update_product_internal_ref
),
url
(
r'^labels_appli_csv(\/?[a-z]*)$'
,
views
.
labels_appli_csv
,
name
=
'labels_appli_csv'
),
url
(
r'^labels_appli_csv(\/?[a-z]*)$'
,
views
.
labels_appli_csv
,
name
=
'labels_appli_csv'
),
url
(
r'^label_print/([0-9]+)/?([0-9\.]*)/?([a-z]*)/?([0-9]*)$'
,
views
.
label_print
),
url
(
r'^label_print/([0-9]+)/?([0-9\.]*)/?([a-z]*)/?([0-9]*)$'
,
views
.
label_print
),
url
(
r'^shelf_labels$'
,
views
.
shelf_labels
),
# massive print
url
(
r'^shelf_labels$'
,
views
.
shelf_labels
),
# massive print
...
...
products/views.py
View file @
97eaabd2
...
@@ -42,8 +42,10 @@ def get_simple_list(request):
...
@@ -42,8 +42,10 @@ def get_simple_list(request):
def
get_product_for_order_helper
(
request
):
def
get_product_for_order_helper
(
request
):
res
=
{}
res
=
{}
try
:
try
:
pids
=
json
.
loads
(
request
.
body
.
decode
())
data
=
json
.
loads
(
request
.
body
.
decode
())
res
=
CagetteProducts
.
get_products_for_order_helper
(
None
,
pids
)
pids
=
data
[
'pids'
]
stats_from
=
data
[
'stats_from'
]
res
=
CagetteProducts
.
get_products_for_order_helper
(
None
,
pids
,
stats_from
)
except
Exception
as
e
:
except
Exception
as
e
:
coop_logger
.
error
(
"get_product_for_help_order_line :
%
s"
,
str
(
e
))
coop_logger
.
error
(
"get_product_for_help_order_line :
%
s"
,
str
(
e
))
res
[
'error'
]
=
str
(
e
)
res
[
'error'
]
=
str
(
e
)
...
@@ -112,6 +114,17 @@ def update_product_purchase_ok(request):
...
@@ -112,6 +114,17 @@ def update_product_purchase_ok(request):
else
:
else
:
return
JsonResponse
({
"res"
:
res
})
return
JsonResponse
({
"res"
:
res
})
def
update_product_internal_ref
(
request
):
res
=
{}
data
=
json
.
loads
(
request
.
body
.
decode
())
res
=
CagetteProduct
.
update_product_internal_ref
(
data
[
"product_tmpl_id"
],
data
[
"default_code"
])
if
(
'error'
in
res
):
return
JsonResponse
(
res
,
status
=
500
)
else
:
return
JsonResponse
({
"res"
:
res
})
def
labels_appli_csv
(
request
,
params
):
def
labels_appli_csv
(
request
,
params
):
"""Generate files to put in DAV directory to be retrieved by scales app."""
"""Generate files to put in DAV directory to be retrieved by scales app."""
withCandidate
=
False
withCandidate
=
False
...
...
reception/static/js/reception_index.js
View file @
97eaabd2
...
@@ -366,7 +366,7 @@ function display_orders_table() {
...
@@ -366,7 +366,7 @@ function display_orders_table() {
$
(
'#orders'
).
empty
();
$
(
'#orders'
).
empty
();
}
}
for
(
let
j
in
orders
)
{
for
(
let
j
in
orders
)
{
console
.
log
(
orders
[
j
].
id
)
console
.
log
(
orders
[
j
].
id
)
;
}
}
table_orders
=
$
(
'#orders'
).
DataTable
({
table_orders
=
$
(
'#orders'
).
DataTable
({
data
:
orders
,
data
:
orders
,
...
...
stock/static/js/stock_movements.js
View file @
97eaabd2
...
@@ -166,6 +166,7 @@ function init_datatable() {
...
@@ -166,6 +166,7 @@ function init_datatable() {
let
data
=
row
.
data
();
let
data
=
row
.
data
();
let
validated_data
=
qty_validation
(
qty
,
data
.
uom
.
id
);
let
validated_data
=
qty_validation
(
qty
,
data
.
uom
.
id
);
if
(
validated_data
>=
0
)
{
if
(
validated_data
>=
0
)
{
data
.
qty
=
validated_data
;
data
.
qty
=
validated_data
;
row
.
remove
().
draw
();
row
.
remove
().
draw
();
...
@@ -423,28 +424,33 @@ var update_existing_product = function(product, added_qty, undo_option = false)
...
@@ -423,28 +424,33 @@ var update_existing_product = function(product, added_qty, undo_option = false)
function
qty_validation
(
qty
,
uom_id
)
{
function
qty_validation
(
qty
,
uom_id
)
{
if
(
qty
==
null
||
qty
==
''
)
{
if
(
qty
==
null
||
qty
==
''
)
{
$
.
notify
(
"Il n'y a pas de quantité indiquée, ou ce n'est pas un nombre"
,
{
$
.
notify
(
"Il n'y a pas de quantité indiquée, ou ce n'est pas un nombre"
,
{
globalPosition
:
"top right"
,
globalPosition
:
"top right"
,
className
:
"error"
});
className
:
"error"
});
return
-
1
;
return
-
1
;
}
}
if
(
uom_id
==
1
)
{
if
(
uom_id
==
1
)
{
if
(
qty
/
parseInt
(
qty
)
!=
1
&&
qty
!=
0
){
if
(
qty
/
parseInt
(
qty
)
!=
1
&&
qty
!=
0
)
{
$
.
notify
(
"Une quantité avec décimale est indiquée alors que c'est un article à l'unité"
,
{
$
.
notify
(
"Une quantité avec décimale est indiquée alors que c'est un article à l'unité"
,
{
globalPosition
:
"top right"
,
globalPosition
:
"top right"
,
className
:
"error"
});
className
:
"error"
});
return
-
2
;}
return
-
2
;
}
qty
=
parseInt
(
qty
);
// product by unit
qty
=
parseInt
(
qty
);
// product by unit
}
else
{
}
else
{
qty
=
parseFloat
(
qty
).
toFixed
(
2
);
qty
=
parseFloat
(
qty
).
toFixed
(
2
);
}
}
if
(
isNaN
(
qty
)){
if
(
isNaN
(
qty
))
{
$
.
notify
(
"Une quantité n'est pas un nombre"
,
{
$
.
notify
(
"Une quantité n'est pas un nombre"
,
{
globalPosition
:
"top right"
,
globalPosition
:
"top right"
,
className
:
"error"
});
className
:
"error"
});
return
-
3
;}
return
-
3
;
}
return
qty
;
return
qty
;
}
}
...
...
templates/orders/helper.html
View file @
97eaabd2
...
@@ -40,10 +40,29 @@
...
@@ -40,10 +40,29 @@
<button
type=
"button"
class=
"btn--danger"
id=
"back_to_order_selection_from_main"
>
<button
type=
"button"
class=
"btn--danger"
id=
"back_to_order_selection_from_main"
>
<i
class=
"fas fa-arrow-left"
></i>
Retour
<i
class=
"fas fa-arrow-left"
></i>
Retour
</button>
</button>
<div
class=
"rights_buttons"
>
<div
class=
"right_action_buttons"
>
<button
type=
"button"
class=
'btn--primary'
id=
"do_inventory"
style=
"display:none;"
>
Faire un inventaire
<div
id=
"actions_buttons_wrapper"
>
</button>
<button
type=
"button"
class=
'btn--primary'
id=
"toggle_action_buttons"
>
<span
class=
"button_content"
>
Actions
</span>
<span
class=
"toggle_action_buttons_icon"
>
<i
class=
"fas fa-chevron-down"
></i>
</span>
</button>
<div
id=
"actions_buttons_container"
>
<button
type=
"button"
class=
'btn--primary action_button'
id=
"do_inventory"
style=
"display:none;"
>
Faire un inventaire
</button>
<button
type=
"button"
class=
'btn--danger action_button'
id=
"delete_order_button"
>
Supprimer la commande
</button>
</div>
</div>
<a
class=
'btn--warning link_as_button'
id=
"access_metabase"
style=
"display:none;"
href=
"{{metabase_url}}"
target=
"_blank"
>
Stats Métabase
</a>
</div>
</div>
</div>
</div>
...
@@ -57,14 +76,23 @@
...
@@ -57,14 +76,23 @@
</div>
</div>
<div
class=
"txtcenter"
id=
"order_forms_container"
>
<div
class=
"txtcenter"
id=
"order_forms_container"
>
<form
action=
"javascript:;"
id=
"coverage_form"
>
<form
action=
"javascript:;"
id=
"supplier_form"
class=
"order_form_item"
>
<input
type=
"number"
name=
"coverage_days"
id=
"coverage_days_input"
placeholder=
"Nb jours de couverture"
min=
"1"
>
<button
type=
"submit"
class=
'btn--primary'
>
Calculer les besoins
</button>
</form>
<form
action=
"javascript:;"
id=
"supplier_form"
>
<input
type=
"text"
name=
"supplier"
id=
"supplier_input"
placeholder=
"Rechercher un fournisseur par son nom"
>
<input
type=
"text"
name=
"supplier"
id=
"supplier_input"
placeholder=
"Rechercher un fournisseur par son nom"
>
<button
type=
"submit"
class=
'btn--primary'
>
Ajouter le fournisseur
</button>
<button
type=
"submit"
class=
'btn--primary'
>
Ajouter le fournisseur
</button>
</form>
</form>
<form
action=
"javascript:;"
id=
"stats_date_from_form"
class=
"order_form_item"
>
<label
for=
"stats_date_period_select"
>
Période de calcul de la conso moyenne
</label>
<select
name=
"stats_date_period_select"
id=
"stats_date_period_select"
>
<option
value=
""
>
Par défaut
</option>
<option
value=
"1week"
>
1 semaine
</option>
<option
value=
"2weeks"
>
2 semaines
</option>
</select>
</form>
<form
action=
"javascript:;"
id=
"coverage_form"
class=
"order_form_item"
>
<input
type=
"number"
name=
"coverage_days"
id=
"coverage_days_input"
placeholder=
"Nb jours de couverture"
min=
"1"
>
<button
type=
"submit"
class=
'btn--primary'
>
Calculer les besoins
</button>
</form>
</div>
</div>
<div
id=
"suppliers_container"
></div>
<div
id=
"suppliers_container"
></div>
...
@@ -125,8 +153,14 @@
...
@@ -125,8 +153,14 @@
<span
class=
"pill_supplier_name"
></span>
<span
class=
"pill_supplier_name"
></span>
<i
class=
"fas fa-times remove_supplier_icon"
></i>
<i
class=
"fas fa-times remove_supplier_icon"
></i>
</div>
</div>
<div
class=
"supplier_total_value_container"
>
<div
class=
"supplier_data"
>
Total:
<span
class=
"supplier_total_value"
>
0
</span>
€
<div
class=
"supplier_total_value_container"
>
Total :
<span
class=
"supplier_total_value"
>
0
</span>
€
</div>
|
<div
class=
"supplier_total_packages_container"
>
Nb colis :
<span
class=
"supplier_total_packages"
>
0
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -134,6 +168,7 @@
...
@@ -134,6 +168,7 @@
<div
id=
"order_pill_template"
>
<div
id=
"order_pill_template"
>
<div
class=
"pill order_pill btn btn--primary"
>
<div
class=
"pill order_pill btn btn--primary"
>
<span
class=
"pill_order_name"
></span>
<span
class=
"pill_order_name"
></span>
<i
class=
"fas fa-times remove_order_icon"
></i>
</div>
</div>
</div>
</div>
...
@@ -144,7 +179,7 @@
...
@@ -144,7 +179,7 @@
<h4
class=
"new_order_date_planned"
></h4>
<h4
class=
"new_order_date_planned"
></h4>
<div
class=
'download_order_file'
>
<div
class=
'download_order_file'
>
<i
class=
"fas fa-spinner fa-spin download_order_file_loading"
></i>
<i
class=
"fas fa-spinner fa-spin download_order_file_loading"
></i>
<a
class=
'btn--success download_order_file_button'
style=
"display:none;"
href=
"#"
>
<a
class=
'btn--success download_order_file_button
link_as_button
'
style=
"display:none;"
href=
"#"
>
Télécharger le fichier de commande
Télécharger le fichier de commande
</a>
</a>
</div>
</div>
...
@@ -164,6 +199,15 @@
...
@@ -164,6 +199,15 @@
<p>
Voulez-vous quand même y accéder ?
</p>
<p>
Voulez-vous quand même y accéder ?
</p>
<hr/>
<hr/>
</div>
</div>
<div
id=
"modal_remove_order"
>
<h3>
Attention !
</h3>
<p
class=
"remove_order_modal_text"
>
Vous vous apprêtez à
<b
style=
"color: #d9534f;"
>
supprimer
</b>
cette commande en cours :
<span
class=
"remove_order_name"
></span>
.
<br/>
</p>
<p>
Êtez-vous sûr ?
</p>
<hr/>
</div>
<div
id=
"modal_remove_supplier"
>
<div
id=
"modal_remove_supplier"
>
<h3>
Attention !
</h3>
<h3>
Attention !
</h3>
...
@@ -201,6 +245,19 @@
...
@@ -201,6 +245,19 @@
<p>
Êtez-vous sûr ?
</p>
<p>
Êtez-vous sûr ?
</p>
<hr/>
<hr/>
</div>
</div>
<div
id=
"modal_end_supplier_product_association"
>
<h3>
Attention !
</h3>
<p>
Vous vous apprêtez à rendre le produit
<span
class=
"product_name"
></span>
indisponible chez le fournisseur
<span
class=
"supplier_name"
></span>
.
</p>
<p>
L'association sera supprimée dès que vous aurez cliqué sur "Valider".
<br/>
</p>
<p>
Êtez-vous sûr ?
</p>
<hr/>
</div>
<div
id=
"modal_create_inventory"
>
<div
id=
"modal_create_inventory"
>
<p>
<p>
...
@@ -252,6 +309,7 @@
...
@@ -252,6 +309,7 @@
var
couchdb_dbname
=
'{{db}}'
;
var
couchdb_dbname
=
'{{db}}'
;
var
couchdb_server
=
'{{couchdb_server}}'
+
couchdb_dbname
;
var
couchdb_server
=
'{{couchdb_server}}'
+
couchdb_dbname
;
var
odoo_server
=
'{{odoo_server}}'
;
var
odoo_server
=
'{{odoo_server}}'
;
var
metabase_url
=
'{{metabase_url}}'
;
</script>
</script>
<script
src=
"{% static "
js
/
all_common
.
js
"
%}?
v=
"></script>
<script
src=
"{% static "
js
/
all_common
.
js
"
%}?
v=
"></script>
<script type="
text
/
javascript
"
src=
"{% static 'js/orders_helper.js' %}?v="
></script>
<script type="
text
/
javascript
"
src=
"{% static 'js/orders_helper.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