testERP5Simulation.py 14 KB
Newer Older
1
# -*- coding: utf-8 -*-
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
##############################################################################
#
# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
"""
This test is experimental for new simulation implementation.
"""


33 34
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from Products.ERP5Type.tests.Sequence import SequenceList
35
from testPackingList import TestPackingListMixin
36 37


38
class TestERP5Simulation(TestPackingListMixin, ERP5TypeTestCase):
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
39 40 41
  run_all_test = 1
  quiet = 0

42
  def afterSetUp(self):
43
    super(TestERP5Simulation, self).afterSetUp()
44
    self.login('manager')
45 46 47
    self.portal.portal_rules.new_delivery_simulation_rule.quantity_tester.edit(
      quantity_range_max=2,
      quantity_range_min=-1)
48 49

  def beforeTearDown(self):
50 51 52 53 54
    super(TestERP5Simulation, self).beforeTearDown()
    self.portal.portal_rules.new_delivery_simulation_rule.quantity_tester.edit(
      quantity_range_max=None,
      quantity_range_min=None)
    self.tic()
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
55 56 57 58 59 60 61 62 63

  def _modifyPackingListLineQuantity(self, sequence=None,
      sequence_list=None, delta=0.0):
    """
    Set a increased quantity on packing list lines
    """
    packing_list = sequence.get('packing_list')
    for packing_list_line in packing_list.objectValues(
        portal_type=self.packing_list_line_portal_type):
64
      packing_list_line.edit(quantity=packing_list_line.getQuantity() + delta)
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
65 66 67 68 69 70
    sequence.edit(last_delta=delta)

  def stepIncreasePackingListLineQuantity2(self, sequence=None,
      sequence_list=None, **kw):
    return self._modifyPackingListLineQuantity(sequence, sequence_list, 2.0)

71
  def stepDecreasePackingListLineQuantity3(self, sequence=None,
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
72
      sequence_list=None, **kw):
73
    return self._modifyPackingListLineQuantity(sequence, sequence_list, -3.0)
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
74

75
  def stepDecreasePackingListLineQuantity4(self, sequence=None,
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
76
      sequence_list=None, **kw):
77 78 79 80 81 82 83 84 85
    return self._modifyPackingListLineQuantity(sequence, sequence_list, -4.0)

  def stepDecreasePackingListLineQuantity9(self, sequence=None,
      sequence_list=None, **kw):
    return self._modifyPackingListLineQuantity(sequence, sequence_list, -9.0)

  def stepDecreasePackingListLineQuantity1010(self, sequence=None,
      sequence_list=None, **kw):
    return self._modifyPackingListLineQuantity(sequence, sequence_list, -1010.0)
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
86 87 88 89 90 91

  def stepSplitAndDeferPackingList(self, sequence=None, sequence_list=None, **kw):
    """
      Do the split and defer action
    """
    packing_list = sequence.get('packing_list')
Sebastien Robin's avatar
Sebastien Robin committed
92 93
    solver_process_tool = self.portal.portal_solver_processes
    solver_process = solver_process_tool.newSolverProcess(packing_list)
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
94 95 96 97 98
    sequence.edit(solver_process=solver_process)
    quantity_solver_decision = filter(
      lambda x:x.getCausalityValue().getTestedProperty()=='quantity',
      solver_process.contentValues())[0]
    # use Quantity Split Solver.
Sebastien Robin's avatar
Sebastien Robin committed
99 100
    quantity_solver_decision.setSolverValue(
        self.portal.portal_solvers['Quantity Split Solver'])
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
101
    # configure for Quantity Split Solver.
Sebastien Robin's avatar
Sebastien Robin committed
102
    kw = {'delivery_solver':'FIFO Delivery Solver',
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
103 104 105
          'start_date':packing_list.getStartDate() + 10}
    quantity_solver_decision.updateConfiguration(**kw)
    solver_process.buildTargetSolverList()
Sebastien Robin's avatar
Sebastien Robin committed
106

Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
    solver_process.solve()
    # build split deliveries manually. XXX ad-hoc
    previous_tag = None
    for delivery_builder in packing_list.getBuilderList():
      this_builder_tag = '%s_split_%s' % (packing_list.getPath(),
                                          delivery_builder.getId())
      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 stepCheckPackingListSplitted(self, sequence=None, sequence_list=None, **kw):
    """
      Test if packing list was splitted
    """
    order = sequence.get('order')
    packing_list_list = order.getCausalityRelatedValueList(
                               portal_type=self.packing_list_portal_type)
130
    self.assertEqual(2,len(packing_list_list))
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
131 132 133 134 135 136 137 138
    packing_list1 = None
    packing_list2 = None
    for packing_list in packing_list_list:
      if packing_list.getUid() == sequence.get('packing_list').getUid():
        packing_list1 = packing_list
      else:
        packing_list2 = packing_list
    sequence.edit(new_packing_list=packing_list2)
139 140 141 142 143 144
    line, = packing_list1.objectValues(
          portal_type= self.packing_list_line_portal_type)
    self.assertEqual(self.default_quantity-10,line.getQuantity())
    line, = packing_list2.objectValues(
          portal_type= self.packing_list_line_portal_type)
    self.assertEqual(10,line.getQuantity())
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
145 146 147 148 149 150 151 152 153

  def _checkSolverState(self, sequence=None, sequence_list=None,
                        state='solved'):
    """
      Check if target solvers' state.
    """
    solver_process = sequence.get('solver_process')
    for solver in solver_process.objectValues(
      portal_type=self.portal.getPortalTargetSolverTypeList()):
154
      self.assertEqual(state, solver.getValidationState())
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
155 156 157 158 159 160 161 162 163 164 165 166 167

  def stepCheckSolverIsSolving(self, sequence=None, sequence_list=None, **kw):
    """
      Check if all target solvers have 'solving' state.
    """
    self._checkSolverState(sequence, sequence_list, 'solving')

  def stepCheckSolverIsSolved(self, sequence=None, sequence_list=None, **kw):
    """
      Check if all target solvers have 'solved' state.
    """
    self._checkSolverState(sequence, sequence_list, 'solved')

168 169 170 171 172 173 174 175 176
  def test_00_simulationToolIsIndexed(self):
    """
    Parts of simulation (only legacy & "legacy legacy" simulation?)
    expect the simulation tool to be indexed in SQL queries, notably
    thanks to grand_parent related keys on Simulation Movements
    """
    portal_catalog = self.portal.portal_catalog

    portal_simulation_path = self.portal.portal_simulation.getPath()
177
    self.assertEqual(1,
178 179
        len(portal_catalog(path=portal_simulation_path)))

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
  def stepCheckPackingListSplittedTwoTimes(self, sequence=None, sequence_list=None, **kw):
    """
      Test if packing list was splitted two times
    """
    order = sequence.get('order')
    packing_list_list = self.getOrderedPackingListFromOrder(order)
    packing_list1, packing_list2, packing_list3 = packing_list_list

    sequence.edit(new_packing_list=packing_list2)
    line, = packing_list1.objectValues(
          portal_type= self.packing_list_line_portal_type)
    self.assertEqual(self.default_quantity-10,line.getQuantity())
    line, = packing_list2.objectValues(
          portal_type= self.packing_list_line_portal_type)
    self.assertEqual(6, line.getQuantity())
    line, = packing_list3.objectValues(
          portal_type= self.packing_list_line_portal_type)
    self.assertEqual(4, line.getQuantity())
    # Check the id in simulation is not too long after multiple splitting
    simulation_movement, = line.getDeliveryRelatedValueList()
    self.assertEqual('1_split_1', simulation_movement.getId())

  def stepSetNewPackingListAsPackingList(self, sequence=None, sequence_list=None, **kw):
    sequence.edit(packing_list=sequence.get('new_packing_list'))

Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
205 206
  def test_01_splitAndDefer(self, quiet=quiet, run=run_all_test):
    """
207 208 209 210 211 212 213
      Change the quantity on an delivery line, then see if the packing list
      remains solved when we change a little bit the quantity (within the range
      accepted by the quantity tester).

      Then see if the packing list becomes divergent when the quantity is
      heavily changed (outside the range accepted by the quantity tester).
      Split and defer the packing list and check newly created packing list.
214 215 216 217

      Finally, split the new packing list to make sure we can split splitted
      packing list. In the same time, check if we do not create very long
      ids for simulation movements (this was the case before)
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
218 219 220 221 222 223 224 225 226 227 228
    """
    if not run: return
    sequence_list = SequenceList()

    # Test with a simply order without cell
    sequence_string = self.default_sequence + '\
                      stepIncreasePackingListLineQuantity2 \
                      stepCheckPackingListIsCalculating \
                      stepTic \
                      stepCheckPackingListIsNotDivergent \
                      stepCheckPackingListIsSolved \
229
                      stepDecreasePackingListLineQuantity3 \
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
230 231 232 233
                      stepCheckPackingListIsCalculating \
                      stepTic \
                      stepCheckPackingListIsNotDivergent \
                      stepCheckPackingListIsSolved \
234
                      stepDecreasePackingListLineQuantity9 \
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
235 236 237 238 239 240 241 242 243
                      stepCheckPackingListIsCalculating \
                      stepTic \
                      stepCheckPackingListIsDiverged \
                      stepSplitAndDeferPackingList \
                      stepCheckSolverIsSolving \
                      stepTic \
                      stepCheckPackingListSplitted \
                      stepCheckPackingListIsSolved \
                      stepCheckSolverIsSolved \
244 245 246 247 248 249 250 251 252 253 254 255 256
                      stepSetNewPackingListAsPackingList \
                      stepCheckPackingListIsNotDivergent \
                      stepCheckPackingListIsSolved \
                      stepDecreasePackingListLineQuantity4 \
                      stepCheckPackingListIsCalculating \
                      stepTic \
                      stepCheckPackingListIsDiverged \
                      stepSplitAndDeferPackingList \
                      stepCheckSolverIsSolving \
                      stepTic \
                      stepCheckPackingListSplittedTwoTimes \
                      stepCheckPackingListIsSolved \
                      stepCheckSolverIsSolved \
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
257 258 259 260
                      '
    sequence_list.addSequenceString(sequence_string)

    sequence_list.play(self, quiet=quiet)
261 262 263 264 265 266 267 268 269

  def stepIncreasePackingListLineQuantity1000(self, sequence=None, sequence_list=None, **kw):
    self._modifyPackingListLineQuantity(sequence, sequence_list, 1000.0)

  def stepCheckPackingListSplittedForTest02(self, sequence=None, sequence_list=None, **kw):
    """
      Test if packing list was splitted
    """
    order = sequence.get('order')
270 271
    packing_list_list = self.getOrderedPackingListFromOrder(order)
    packing_list1, packing_list2 = packing_list_list
272 273

    destination_value = sequence.get('organisation3')
274 275
    self.assertEqual(packing_list1.getDestinationValue(), destination_value)
    self.assertEqual(packing_list2.getDestinationValue(), destination_value)
276

277 278 279
    sequence.edit(new_packing_list=packing_list2)
    for line in packing_list1.objectValues(
          portal_type= self.packing_list_line_portal_type):
280
      self.assertEqual(self.default_quantity-10,line.getQuantity())
281 282
    for line in packing_list2.objectValues(
          portal_type= self.packing_list_line_portal_type):
283
      self.assertEqual(10+1000,line.getQuantity())
284

285 286 287 288 289 290 291
  def getOrderedPackingListFromOrder(self, order):
    packing_list_list = order.getCausalityRelatedValueList(
                               portal_type=self.packing_list_portal_type)
    packing_list_list.sort(key=lambda x: int(x.getId()))
    return packing_list_list


292 293 294 295 296 297 298
  def test_02_splitAndDeferAfterAcceptDecision(self, quiet=quiet, run=run_all_test):
    """
      Change the quantity on an delivery line, then
      see if the packing list is divergent and then
      accept decision, then change the quantity again
      and see if the packing list is divergent and then
      split and defer the packing list and then see
299
      if two packing lists has correct quantity and
300 301 302 303 304 305 306 307
      they are not diverged.
    """
    if not run: return
    sequence_list = SequenceList()

    # Test with a simply order without cell
    sequence_string = self.default_sequence + '\
                      stepIncreasePackingListLineQuantity1000 \
308
                      stepChangePackingListDestination \
309 310 311
                      stepCheckPackingListIsCalculating \
                      stepTic \
                      stepCheckPackingListIsDiverged \
312
                      stepAcceptDecisionDestination \
313 314 315 316 317
                      stepAcceptDecisionQuantity \
                      stepCheckPackingListIsCalculating \
                      stepTic \
                      stepCheckPackingListIsNotDivergent \
                      stepCheckPackingListIsSolved \
318
                      stepDecreasePackingListLineQuantity1010 \
319 320 321 322 323 324 325 326 327 328 329 330 331
                      stepCheckPackingListIsCalculating \
                      stepTic \
                      stepCheckPackingListIsDiverged \
                      stepSplitAndDeferPackingList \
                      stepCheckSolverIsSolving \
                      stepTic \
                      stepCheckPackingListSplittedForTest02 \
                      stepCheckPackingListIsSolved \
                      stepCheckSolverIsSolved \
                      '
    sequence_list.addSequenceString(sequence_string)

    sequence_list.play(self, quiet=quiet)