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
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Romain Courteaud
erp5
Commits
8150caa2
Commit
8150caa2
authored
Oct 13, 2017
by
Sebastien Robin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
simulation: add tests for Split Move Solver and for FIFO solver
parent
38f33857
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
165 additions
and
24 deletions
+165
-24
product/ERP5/Document/QuantitySplitMoveSolver.py
product/ERP5/Document/QuantitySplitMoveSolver.py
+12
-6
product/ERP5/tests/testOrder.py
product/ERP5/tests/testOrder.py
+2
-0
product/ERP5/tests/testPackingList.py
product/ERP5/tests/testPackingList.py
+135
-18
product/ERP5Type/tests/ERP5TypeTestCase.py
product/ERP5Type/tests/ERP5TypeTestCase.py
+16
-0
No files found.
product/ERP5/Document/QuantitySplitMoveSolver.py
View file @
8150caa2
...
@@ -71,17 +71,23 @@ class QuantitySplitMoveSolver(QuantitySplitSolver):
...
@@ -71,17 +71,23 @@ class QuantitySplitMoveSolver(QuantitySplitSolver):
delivery
=
diverged_simulation_movement
.
getDeliveryValue
().
getParentValue
()
delivery
=
diverged_simulation_movement
.
getDeliveryValue
().
getParentValue
()
assert
delivery
.
isDelivery
()
assert
delivery
.
isDelivery
()
trade_phase
=
self
.
getDeliveryValue
().
getTradePhase
()
trade_phase
=
self
.
getDeliveryValue
().
getTradePhase
()
assert
trade_phase
is
not
None
,
"Unable to solve, no trade phase is defined for %s"
%
diverged_simulation_movement
.
getRelativeUrl
()
assert
trade_phase
is
not
None
,
"Unable to solve, no trade phase is defined for %s"
%
\
business_link_list
=
diverged_simulation_movement
.
asComposedDocument
().
getBusinessLinkValueList
(
trade_phase
=
trade_phase
)
diverged_simulation_movement
.
getRelativeUrl
()
assert
len
(
business_link_list
)
==
1
,
"Expected to find only one business link for trade_phase %s, but found %r"
%
(
trade_phase
,
business_link_list
=
diverged_simulation_movement
.
asComposedDocument
(
).
getBusinessLinkValueList
(
trade_phase
=
trade_phase
)
assert
len
(
business_link_list
)
==
1
,
\
"Expected to find only one business link for trade_phase %s, but found %r"
%
(
trade_phase
,
[
x
.
getRelativeUrl
()
for
x
in
business_link_list
])
[
x
.
getRelativeUrl
()
for
x
in
business_link_list
])
business_link
,
=
business_link_list
business_link
,
=
business_link_list
delivery_builder_list
=
business_link
.
getDeliveryBuilderValueList
()
delivery_builder_list
=
[
x
for
x
in
business_link
.
getDeliveryBuilderValueList
()
\
assert
len
(
delivery_builder_list
)
==
1
,
"Expected to find only one builder on business link, but found %r"
%
(
if
x
.
getDeliveryPortalType
()
==
delivery
.
getPortalType
()]
assert
len
(
delivery_builder_list
)
==
1
,
\
"Expected to find only one builder on business link, but found %r"
%
(
business_link
.
getRelativeUrl
(),
[
x
.
getRelativeUrl
()
for
x
in
delivery_builder_list
])
business_link
.
getRelativeUrl
(),
[
x
.
getRelativeUrl
()
for
x
in
delivery_builder_list
])
delivery_builder
,
=
delivery_builder_list
delivery_builder
,
=
delivery_builder_list
# Update simulation movements to make sure they match the new delivery
# Update simulation movements to make sure they match the new delivery
delivery_level_movement_group
=
[
x
for
x
in
delivery_builder
.
objectValues
()
if
x
.
getCollectOrderGroup
()
==
"delivery"
]
delivery_level_movement_group
=
[
x
for
x
in
delivery_builder
.
objectValues
()
\
if
x
.
getCollectOrderGroup
()
==
"delivery"
]
delivery_to_move
=
portal
.
unrestrictedTraverse
(
configuration_dict
[
'delivery_url'
])
delivery_to_move
=
portal
.
unrestrictedTraverse
(
configuration_dict
[
'delivery_url'
])
assert
delivery_to_move
.
getDivergenceList
()
==
[]
assert
delivery_to_move
.
getDivergenceList
()
==
[]
for
movement_group
in
delivery_level_movement_group
:
for
movement_group
in
delivery_level_movement_group
:
...
...
product/ERP5/tests/testOrder.py
View file @
8150caa2
...
@@ -115,8 +115,10 @@ class TestOrderMixin(SubcontentReindexingWrapper):
...
@@ -115,8 +115,10 @@ class TestOrderMixin(SubcontentReindexingWrapper):
#
#
# 1. All calculations are done relative to the same time
# 1. All calculations are done relative to the same time
# 2. We don't get random failures when tests run close to midnight
# 2. We don't get random failures when tests run close to midnight
self
.
datetime
=
DateTime
()
-
2
self
.
pinDateTime
(
self
.
datetime
)
self
.
pinDateTime
(
self
.
datetime
)
self
.
loginByUserName
(
'test_user'
)
self
.
loginByUserName
(
'test_user'
)
self
.
begin
=
self
.
datetime
def
beforeTearDown
(
self
):
def
beforeTearDown
(
self
):
self
.
unpinDateTime
()
self
.
unpinDateTime
()
...
...
product/ERP5/tests/testPackingList.py
View file @
8150caa2
...
@@ -322,18 +322,7 @@ class TestPackingListMixin(TestOrderMixin):
...
@@ -322,18 +322,7 @@ class TestPackingListMixin(TestOrderMixin):
quantity_solver_decision
.
updateConfiguration
(
**
kw
)
quantity_solver_decision
.
updateConfiguration
(
**
kw
)
solver_process
.
buildTargetSolverList
()
solver_process
.
buildTargetSolverList
()
solver_process
.
solve
()
solver_process
.
solve
()
# build split deliveries manually. XXX ad-hoc
self
.
callPackingListBuilderList
(
packing_list
)
previous_tag
=
None
for
delivery_builder
in
packing_list
.
getBuilderList
():
after_tag
=
[]
if
previous_tag
:
after_tag
.
append
(
previous_tag
)
delivery_builder
.
activate
(
after_method_id
=
(
'solve'
,
'immediateReindexObject'
,
'recursiveImmediateReindexObject'
,),
# XXX too brutal.
after_tag
=
after_tag
,
).
build
(
explanation_uid
=
packing_list
.
getCausalityValue
().
getUid
())
def
stepSplitAndDeferDoNothingPackingList
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
def
stepSplitAndDeferDoNothingPackingList
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
"""
"""
...
@@ -389,12 +378,10 @@ class TestPackingListMixin(TestOrderMixin):
...
@@ -389,12 +378,10 @@ class TestPackingListMixin(TestOrderMixin):
packing_list1
=
packing_list
packing_list1
=
packing_list
else
:
else
:
packing_list2
=
packing_list
packing_list2
=
packing_list
for
line
in
packing_list1
.
objectValues
(
line1
,
=
packing_list1
.
objectValues
(
portal_type
=
self
.
packing_list_line_portal_type
)
portal_type
=
self
.
packing_list_line_portal_type
):
self
.
assertEqual
(
self
.
default_quantity
-
2
,
line1
.
getQuantity
())
self
.
assertEqual
(
self
.
default_quantity
-
2
,
line
.
getQuantity
())
line2
,
=
packing_list2
.
objectValues
(
portal_type
=
self
.
packing_list_line_portal_type
)
for
line
in
packing_list2
.
objectValues
(
self
.
assertEqual
(
2
,
line2
.
getQuantity
())
portal_type
=
self
.
packing_list_line_portal_type
):
self
.
assertEqual
(
2
,
line
.
getQuantity
())
def
stepCheckPackingListNotSplitted
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
def
stepCheckPackingListNotSplitted
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
"""
"""
...
@@ -1013,6 +1000,20 @@ class TestPackingListMixin(TestOrderMixin):
...
@@ -1013,6 +1000,20 @@ class TestPackingListMixin(TestOrderMixin):
portal_type
=
self
.
packing_list_line_portal_type
)
portal_type
=
self
.
packing_list_line_portal_type
)
self
.
_checkRecordedProperty
(
movement_list
,
'resource'
,
False
)
self
.
_checkRecordedProperty
(
movement_list
,
'resource'
,
False
)
def
callPackingListBuilderList
(
self
,
packing_list
):
# build split deliveries manually. XXX ad-hoc
previous_tag
=
None
for
delivery_builder
in
packing_list
.
getBuilderList
():
after_tag
=
[]
if
previous_tag
:
after_tag
.
append
(
previous_tag
)
delivery_builder
.
activate
(
after_method_id
=
(
'solve'
,
'immediateReindexObject'
,
'recursiveImmediateReindexObject'
,),
# XXX too brutal.
after_tag
=
after_tag
,
).
build
(
explanation_uid
=
packing_list
.
getCausalityValue
().
getUid
())
class
TestPackingList
(
TestPackingListMixin
,
ERP5TypeTestCase
)
:
class
TestPackingList
(
TestPackingListMixin
,
ERP5TypeTestCase
)
:
run_all_test
=
1
run_all_test
=
1
...
@@ -1484,6 +1485,122 @@ class TestPackingList(TestPackingListMixin, ERP5TypeTestCase) :
...
@@ -1484,6 +1485,122 @@ class TestPackingList(TestPackingListMixin, ERP5TypeTestCase) :
sequence_list
.
play
(
self
,
quiet
=
quiet
)
sequence_list
.
play
(
self
,
quiet
=
quiet
)
def
stepSplitAndMovePackingList
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
"""
Do the split and move to another delivery action
"""
packing_list
=
sequence
.
get
(
'packing_list'
)
new_packing_list
=
sequence
.
get
(
'new_packing_list'
)
solver_process_tool
=
self
.
portal
.
portal_solver_processes
solver_process
=
solver_process_tool
.
newSolverProcess
(
packing_list
)
quantity_solver_decision
,
=
[
x
for
x
in
solver_process
.
contentValues
()
if
'quantity'
in
x
.
getCausalityValue
().
getTestedPropertyList
()]
# use Quantity Split Solver.
quantity_solver_decision
.
setSolverValue
(
self
.
portal
.
portal_solvers
[
'Quantity Split Move Solver'
])
# configure for Quantity Split Solver.
kw
=
{
'delivery_solver'
:
'FIFO Delivery Solver'
,
'delivery_url'
:
new_packing_list
.
getRelativeUrl
()}
quantity_solver_decision
.
updateConfiguration
(
**
kw
)
solver_process
.
buildTargetSolverList
()
solver_process
.
solve
()
def
stepCheckSeveralDivergenceAction
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
"""
Do the split and move to another delivery action
"""
packing_list1
=
sequence
.
get
(
'packing_list'
)
line1
,
=
packing_list1
.
objectValues
(
portal_type
=
self
.
packing_list_line_portal_type
)
packing_list2
=
sequence
.
get
(
'new_packing_list'
)
# Make sure we can split and defer the new packing list, this would make
# use of FIFO delivery solver in the case we have several lines
line2
,
=
packing_list2
.
objectValues
(
portal_type
=
self
.
packing_list_line_portal_type
)
line2
.
setQuantity
(
1.5
)
self
.
tic
()
self
.
assertEqual
(
'diverged'
,
packing_list2
.
getCausalityState
())
solver_process
,
=
[
x
for
x
in
packing_list2
.
getSolverValueList
()
if
\
x
.
getValidationState
()
==
"draft"
]
quantity_solver_decision
,
=
[
x
for
x
in
solver_process
.
contentValues
()
if
'quantity'
in
x
.
getCausalityValue
().
getTestedPropertyList
()]
# use Quantity Split Solver.
quantity_solver_decision
.
setSolverValue
(
self
.
portal
.
portal_solvers
[
'Quantity Split Solver'
])
# configure for Quantity Split Solver.
kw
=
{
'delivery_solver'
:
'FIFO Delivery Solver'
,
'start_date'
:
self
.
datetime
+
35
,
'stop_date'
:
self
.
datetime
+
45
}
quantity_solver_decision
.
updateConfiguration
(
**
kw
)
solver_process
.
buildTargetSolverList
()
solver_process
.
solve
()
self
.
callPackingListBuilderList
(
packing_list2
)
self
.
tic
()
packing_list1
,
packing_list2
,
packing_list3
=
self
.
getCreatedTypeList
(
self
.
packing_list_portal_type
)
line3
,
=
packing_list3
.
objectValues
(
portal_type
=
self
.
packing_list_line_portal_type
)
self
.
assertEqual
(
0.5
,
line3
.
getQuantity
())
self
.
assertEqual
(
'solved'
,
packing_list1
.
getCausalityState
())
self
.
assertEqual
(
'solved'
,
packing_list2
.
getCausalityState
())
self
.
assertEqual
(
'solved'
,
packing_list3
.
getCausalityState
())
# And now make sure we could accept a new quantity in case we have several
# simulation movements
line2
.
setQuantity
(
1.2
)
self
.
tic
()
self
.
assertEqual
(
'diverged'
,
packing_list2
.
getCausalityState
())
solver_process
,
=
[
x
for
x
in
packing_list2
.
getSolverValueList
()
if
\
x
.
getValidationState
()
==
"draft"
]
quantity_solver_decision
,
=
[
x
for
x
in
solver_process
.
contentValues
()
if
'quantity'
in
x
.
getCausalityValue
().
getTestedPropertyList
()]
# use Quantity Split Solver.
quantity_solver_decision
.
setSolverValue
(
self
.
portal
.
portal_solvers
[
'Accept Solver'
])
kw
=
{
'tested_property_list'
:[
'quantity'
]}
quantity_solver_decision
.
updateConfiguration
(
**
kw
)
solver_process
.
buildTargetSolverList
()
solver_process
.
solve
()
self
.
callPackingListBuilderList
(
packing_list2
)
self
.
tic
()
packing_list1
,
packing_list2
,
packing_list3
=
self
.
getCreatedTypeList
(
self
.
packing_list_portal_type
)
self
.
assertEqual
(
'solved'
,
packing_list1
.
getCausalityState
())
self
.
assertEqual
(
'solved'
,
packing_list2
.
getCausalityState
())
self
.
assertEqual
(
'solved'
,
packing_list3
.
getCausalityState
())
self
.
assertEqual
(
self
.
default_quantity
-
2
,
line1
.
getQuantity
())
self
.
assertEqual
(
1.2
,
line2
.
getQuantity
())
self
.
assertEqual
(
0.5
,
line3
.
getQuantity
())
def
test_11b_PackingListDecreaseTwoTimesQuantityAndMoveToDelivery
(
self
,
quiet
=
quiet
,
run
=
run_all_test
):
"""
Change the quantity on an delivery line, then
split and defer the packing list. Then decrease again the quantity,
and use solver "split and move" to move the quantity to the second packing
list. The second packing list would be solved by the "split and move"
solver
"""
if
not
run
:
return
sequence_list
=
SequenceList
()
sequence_string
=
self
.
default_sequence
+
"""
DecreasePackingListLineQuantity
CheckPackingListIsCalculating
Tic
CheckPackingListIsDiverged
SplitAndDeferPackingList
Tic
CheckPackingListIsSolved
CheckPackingListSplitted
DecreasePackingListLineQuantity
CheckPackingListIsCalculating
Tic
CheckPackingListIsDiverged
SplitAndMovePackingList
Tic
CheckNewPackingListIsSolved
CheckPackingListSplittedTwoTimes
CheckSeveralDivergenceAction
"""
sequence_list
.
addSequenceString
(
sequence_string
)
sequence_list
.
play
(
self
,
quiet
=
quiet
)
def
test_SplitAndDeferDoNothing
(
self
,
quiet
=
quiet
,
run
=
run_all_test
):
def
test_SplitAndDeferDoNothing
(
self
,
quiet
=
quiet
,
run
=
run_all_test
):
"""
"""
Use split & defer to solve a divergence, but choose do nothing for all
Use split & defer to solve a divergence, but choose do nothing for all
...
...
product/ERP5Type/tests/ERP5TypeTestCase.py
View file @
8150caa2
...
@@ -96,6 +96,7 @@ from Products.ERP5Type.tests.ProcessingNodeTestCase import \
...
@@ -96,6 +96,7 @@ from Products.ERP5Type.tests.ProcessingNodeTestCase import \
onsetup
(
patchActivityTool
)()
onsetup
(
patchActivityTool
)()
from
AccessControl.SecurityManagement
import
newSecurityManager
,
noSecurityManager
from
AccessControl.SecurityManagement
import
newSecurityManager
,
noSecurityManager
from
Products.ZSQLCatalog.SQLCatalog
import
Query
from
Acquisition
import
aq_base
from
Acquisition
import
aq_base
...
@@ -412,6 +413,21 @@ class ERP5TypeTestCaseMixin(ProcessingNodeTestCase, PortalTestCase):
...
@@ -412,6 +413,21 @@ class ERP5TypeTestCaseMixin(ProcessingNodeTestCase, PortalTestCase):
return
getattr
(
self
.
portal
,
'currency_module'
,
return
getattr
(
self
.
portal
,
'currency_module'
,
getattr
(
self
.
portal
,
'currency'
,
None
))
getattr
(
self
.
portal
,
'currency'
,
None
))
def
getCreatedTypeList
(
self
,
portal_type
,
from_date
=
None
):
"""
Convenient method to retrieve new documents created in the testn in
particular documents that are created indirectly, like trough activities.
"begin" attribute of test class instance could be initialized in an
afterSetup.
"""
if
from_date
is
None
:
from_date
=
getattr
(
self
,
'begin'
)
type_list
=
[
x
.
getObject
()
for
x
in
self
.
portal
.
portal_catalog
(
portal_type
=
portal_type
,
query
=
Query
(
creation_date
=
from_date
,
range
=
"min"
))]
type_list
.
sort
(
key
=
lambda
x
:
x
.
getCreationDate
())
return
type_list
def
_addPropertySheet
(
self
,
portal_type_name
,
def
_addPropertySheet
(
self
,
portal_type_name
,
property_sheet_name
=
'TestPropertySheet'
,
property_sheet_name
=
'TestPropertySheet'
,
deprecated
=
None
):
deprecated
=
None
):
...
...
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