Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
7
Merge Requests
7
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
Jérome Perrin
erp5
Commits
6263cc2b
Commit
6263cc2b
authored
May 11, 2016
by
Jérome Perrin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
SimulationTool: implement "linear" flow API
parent
be3ed7e2
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
151 additions
and
12 deletions
+151
-12
product/ERP5/Tool/SimulationTool.py
product/ERP5/Tool/SimulationTool.py
+45
-1
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetInventoryList.xml
...tem/portal_skins/erp5_core/Resource_zGetInventoryList.xml
+40
-11
product/ERP5/tests/testInventoryAPI.py
product/ERP5/tests/testInventoryAPI.py
+66
-0
No files found.
product/ERP5/Tool/SimulationTool.py
View file @
6263cc2b
...
...
@@ -627,6 +627,8 @@ class SimulationTool(BaseTool):
omit_output
=
0
,
omit_asset_increase
=
0
,
omit_asset_decrease
=
0
,
# flow_valuation_method
flow_valuation_method
=
'default'
,
# group by
group_by_node
=
0
,
group_by_node_category
=
0
,
...
...
@@ -713,6 +715,24 @@ class SimulationTool(BaseTool):
date_dict
[
'range'
]
=
'ngt'
if
date_dict
:
column_value_dict
[
'date'
]
=
date_dict
if
flow_valuation_method
!=
'default'
:
assert
from_date
and
to_date
# if we consider flow, we also select movement whose mirror date is
# in the from_date/to_date range and movement whose
# start_date/stop_date contains the report range.
column_value_dict
[
'date'
]
=
ComplexQuery
(
Query
(
date
=
(
from_date
,
to_date
),
range
=
'minmax'
),
Query
(
mirror_date
=
(
from_date
,
to_date
),
range
=
'minmax'
),
ComplexQuery
(
Query
(
mirror_date
=
from_date
,
range
=
'min'
),
Query
(
date
=
to_date
,
range
=
'max'
),
operator
=
"AND"
),
ComplexQuery
(
Query
(
date
=
from_date
,
range
=
'min'
),
Query
(
mirror_date
=
to_date
,
range
=
'max'
),
operator
=
"AND"
),
operator
=
"OR"
)
else
:
column_value_dict
[
'date'
]
=
{
'query'
:
[
to_date
],
'range'
:
'ngt'
}
column_value_dict
[
'mirror_date'
]
=
{
'query'
:
[
from_date
],
'range'
:
'nlt'
}
...
...
@@ -1082,6 +1102,12 @@ class SimulationTool(BaseTool):
output_simulation_state - only take rows with specified simulation_state
and quantity < 0
flow_valuation_method - XXX name ???? how to evaluate flow movement.
* full (default): Consider the movement decreases 100% of source stock on
start date and increase 100% of the destination node stock on stop date.
* linear: consider the movement decreases source stock and increase
destination stock linearly between start date and stop date.
ignore_variation - do not take into account variation in inventory
calculation (useless on getInventory, but useful on
getInventoryList)
...
...
@@ -1256,6 +1282,7 @@ class SimulationTool(BaseTool):
omit_simulation
=
0
,
only_accountable
=
True
,
default_stock_table
=
'stock'
,
flow_valuation_method
=
'default'
,
selection_domain
=
None
,
selection_report
=
None
,
statistic
=
0
,
inventory_list
=
1
,
precision
=
None
,
connection_id
=
None
,
...
...
@@ -1334,6 +1361,7 @@ class SimulationTool(BaseTool):
'stock_table_id'
:
default_stock_table
,
'src__'
:
src__
,
'ignore_variation'
:
ignore_variation
,
'flow_valuation_method'
:
flow_valuation_method
,
'standardise'
:
standardise
,
'omit_simulation'
:
omit_simulation
,
'only_accountable'
:
only_accountable
,
...
...
@@ -1379,7 +1407,7 @@ class SimulationTool(BaseTool):
kw
[
'from_date'
]
=
cached_date
else
:
cached_result
=
[]
sql_kw
,
new_kw
=
self
.
_generateKeywordDict
(
**
kw
)
sql_kw
,
new_kw
=
self
.
_generateKeywordDict
(
flow_valuation_method
=
flow_valuation_method
,
**
kw
)
# Copy kw content as _generateSQLKeywordDictFromKeywordDict
# remove some values from it
try
:
...
...
@@ -1392,6 +1420,22 @@ class SimulationTool(BaseTool):
stock_sql_kw
=
self
.
_generateSQLKeywordDictFromKeywordDict
(
table
=
default_stock_table
,
sql_kw
=
sql_kw
,
new_kw
=
new_kw_copy
)
stock_sql_kw
.
update
(
base_inventory_kw
)
# TODO: move in _generateSQLKeywordDictFromKeywordDict
if
flow_valuation_method
==
'linear'
:
# XXX only DateTime instance are supported
from_date
=
kw
.
get
(
'from_date'
)
if
from_date
:
from_date
=
from_date
.
toZone
(
"UTC"
)
to_date
=
kw
.
get
(
'to_date'
)
if
to_date
:
to_date
=
to_date
.
toZone
(
"UTC"
)
# TODO: support at_date ?
stock_sql_kw
[
'flow_valuation_method_from_date'
]
=
from_date
stock_sql_kw
[
'flow_valuation_method_to_date'
]
=
to_date
elif
flow_valuation_method
!=
'default'
:
raise
ValueError
(
"Unsupported flow_valuation_method %r"
%
(
flow_valuation_method
,))
delta_result
=
self
.
Resource_zGetInventoryList
(
**
stock_sql_kw
)
if
src__
:
...
...
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetInventoryList.xml
View file @
6263cc2b
...
...
@@ -45,7 +45,10 @@ convert_quantity_result\r\n
quantity_unit_uid\r\n
stock_table_id=stock\r\n
transformed_uid\r\n
transformed_variation_text
</string>
</value>
transformed_variation_text\r\n
flow_valuation_method\r\n
flow_valuation_method_from_date\r\n
flow_valuation_method_to_date
</string>
</value>
</item>
<item>
<key>
<string>
cache_time_
</string>
</key>
...
...
@@ -84,28 +87,54 @@ transformed_variation_text</string> </value>
<value>
<string
encoding=
"cdata"
>
<![CDATA[
SELECT\n
<dtml-if expr="flow_valuation_method == \'linear\'">
\n
@flow_ratio := CASE\n
WHEN
<dtml-var
stock_table_id
>
.mirror_date =
<dtml-var
stock_table_id
>
.date THEN 1\n
ELSE (\n
UNIX_TIMESTAMP(LEAST(
<dtml-sqlvar
flow_valuation_method_to_date
type=
"datetime"
>
,\n
GREATEST(
<dtml-var
stock_table_id
>
.date,
<dtml-var
stock_table_id
>
.mirror_date) ))\n
- UNIX_TIMESTAMP(GREATEST(
<dtml-sqlvar
flow_valuation_method_from_date
type=
"datetime"
>
,\n
LEAST(
<dtml-var
stock_table_id
>
.date,
<dtml-var
stock_table_id
>
.mirror_date))))\n
/ ( UNIX_TIMESTAMP(GREATEST(
<dtml-var
stock_table_id
>
.date,
<dtml-var
stock_table_id
>
.mirror_date)) -\n
UNIX_TIMESTAMP(LEAST(
<dtml-var
stock_table_id
>
.date,
<dtml-var
stock_table_id
>
.mirror_date)) ) END\n
<dtml-else>
\n
@flow_ratio := 1\n
</dtml-if>
flow_ratio,\n
\n
<dtml-if
expr=
"precision is not None"
>
\n
SUM(ROUND(
<dtml-var
stock_table_id
>
.quantity\n
<dtml-if
transformed_uid
>
* transformation.quantity
</dtml-if>
,
<dtml-var
precision
>
)) AS inventory,\n
SUM(ROUND(
<dtml-var
stock_table_id
>
.quantity\n
<dtml-if
transformed_uid
>
* transformation.quantity
</dtml-if>
,
<dtml-var
precision
>
)) AS total_quantity,\n
SUM(ROUND(\n
<dtml-var
stock_table_id
>
.quantity\n
<dtml-if
transformed_uid
>
* transformation.quantity
</dtml-if>
\n
* @flow_ratio,
<dtml-var
precision
>
)) AS inventory,\n
SUM(ROUND(\n
<dtml-var
stock_table_id
>
.quantity\n
<dtml-if
transformed_uid
>
* transformation.quantity
</dtml-if>
\n
* @flow_ratio,
<dtml-var
precision
>
)) AS total_quantity,\n
<dtml-if
convert_quantity_result
>
\n
SUM(ROUND(
<dtml-var
stock_table_id
>
.quantity * measure.quantity\n
<dtml-if
quantity_unit_uid
>
/ quantity_unit_conversion.quantity
</dtml-if>
\n
<dtml-if
transformed_uid
>
* transformation.quantity
</dtml-if>
,
<dtml-var
precision
>
))\n
* @flow_ratio
,
<dtml-var
precision
>
))\n
AS converted_quantity,\n
</dtml-if>
\n
IFNULL(SUM(ROUND(
<dtml-var
stock_table_id
>
.total_price,
<dtml-var
precision
>
)), 0) AS total_price\n
\n
IFNULL(SUM(ROUND(\n
<dtml-var
stock_table_id
>
.total_price * @flow_ratio,
<dtml-var
precision
>
)), 0) AS total_price\n
<dtml-else>
\n
SUM(
<dtml-var
stock_table_id
>
.quantity
<dtml-if
transformed_uid
>
* transformation.quantity
</dtml-if>
) AS inventory,\n
SUM(
<dtml-var
stock_table_id
>
.quantity
<dtml-if
transformed_uid
>
* transformation.quantity
</dtml-if>
) AS total_quantity,\n
SUM(
<dtml-var
stock_table_id
>
.quantity\n
<dtml-if
transformed_uid
>
* transformation.quantity
</dtml-if>
\n
* @flow_ratio\n
) AS inventory,\n
SUM(
<dtml-var
stock_table_id
>
.quantity\n
<dtml-if
transformed_uid
>
* transformation.quantity
</dtml-if>
\n
* @flow_ratio\n
) AS total_quantity,\n
<dtml-if
convert_quantity_result
>
\n
ROUND(SUM(
<dtml-var
stock_table_id
>
.quantity * measure.quantity\n
<dtml-if
quantity_unit_uid
>
/ quantity_unit_conversion.quantity
</dtml-if>
\n
<dtml-if
transformed_uid
>
* transformation.quantity
</dtml-if>
), 12)\n
<dtml-if
transformed_uid
>
* transformation.quantity
</dtml-if>
* @flow_ratio
), 12)\n
AS converted_quantity,\n
</dtml-if>
\n
IFNULL(SUM(
<dtml-var
stock_table_id
>
.total_price), 0) AS total_price\n
IFNULL(SUM(
<dtml-var
stock_table_id
>
.total_price)
* @flow_ratio
, 0) AS total_price\n
</dtml-if>
\n
<dtml-if
inventory_list
>
\n
,\n
...
...
product/ERP5/tests/testInventoryAPI.py
View file @
6263cc2b
...
...
@@ -816,6 +816,72 @@ class TestInventory(InventoryAPITestCase):
resource
=
self
.
resource
.
getRelativeUrl
(),
at_date
=
date_gmt_1
)
def
test_flow_linear
(
self
):
self
.
_makeMovement
(
quantity
=
10
,
start_date
=
DateTime
(
"2016/01/01 01:00:00"
),
stop_date
=
DateTime
(
"2016/01/01 11:00:00"
),
)
# With a time frame that does not contain the movement, we have 0%
self
.
assertInventoryEquals
(
0
,
node_uid
=
self
.
node
.
getUid
(),
from_date
=
DateTime
(
"2016/02/01 00:00:00"
),
to_date
=
DateTime
(
"2016/02/02 00:00:00"
),
flow_valuation_method
=
'linear'
)
# With a time frame that contains the full movement, we have 100% of the quantity
self
.
assertInventoryEquals
(
10
,
node_uid
=
self
.
node
.
getUid
(),
from_date
=
DateTime
(
"2016/01/01 00:00:00"
),
to_date
=
DateTime
(
"2016/01/02 00:00:00"
),
flow_valuation_method
=
'linear'
)
# corner case: exact same time, we also have 100%
self
.
assertInventoryEquals
(
10
,
node_uid
=
self
.
node
.
getUid
(),
from_date
=
DateTime
(
"2016/01/01 01:00:00"
),
to_date
=
DateTime
(
"2016/01/01 11:00:00"
),
flow_valuation_method
=
'linear'
)
# With a time frame containing the 50% of the movement, we have 50% of the quantity
# time frame start before movement
self
.
assertInventoryEquals
(
5
,
node_uid
=
self
.
node
.
getUid
(),
from_date
=
DateTime
(
"2016/01/01 00:00:00"
),
to_date
=
DateTime
(
"2016/01/01 06:00:00"
),
flow_valuation_method
=
'linear'
)
# time frame start at exact same time as movement
self
.
assertInventoryEquals
(
5
,
node_uid
=
self
.
node
.
getUid
(),
from_date
=
DateTime
(
"2016/01/01 01:00:00"
),
to_date
=
DateTime
(
"2016/01/01 06:00:00"
),
flow_valuation_method
=
'linear'
)
# Time frame is contained inside the movement
self
.
assertInventoryEquals
(
5
,
node_uid
=
self
.
node
.
getUid
(),
from_date
=
DateTime
(
"2016/01/01 02:00:00"
),
to_date
=
DateTime
(
"2016/01/01 07:00:00"
),
flow_valuation_method
=
'linear'
)
# Time frame finishes after movement end
self
.
assertInventoryEquals
(
5
,
node_uid
=
self
.
node
.
getUid
(),
from_date
=
DateTime
(
"2016/01/01 06:00:00"
),
to_date
=
DateTime
(
"2016/01/01 12:00:00"
),
flow_valuation_method
=
'linear'
)
# Time frame finishes at exact same time that movement end
self
.
assertInventoryEquals
(
5
,
node_uid
=
self
.
node
.
getUid
(),
from_date
=
DateTime
(
"2016/01/01 06:00:00"
),
to_date
=
DateTime
(
"2016/01/01 11:00:00"
),
flow_valuation_method
=
'linear'
)
class
TestInventoryList
(
InventoryAPITestCase
):
"""Tests getInventoryList methods.
"""
...
...
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