Commit 492eb660 authored by Sebastien Robin's avatar Sebastien Robin

simulation: make FIFO delivery solver working with negative quantities

in MRP, we have manufacturing execution having a mix of lines with
positive and negative values. It must be possible to use split and
defer solver in that case.
parent 4862a9a8
...@@ -70,15 +70,24 @@ class FIFODeliverySolver(XMLObject): ...@@ -70,15 +70,24 @@ class FIFODeliverySolver(XMLObject):
security.declareProtected(Permissions.ModifyPortalContent, 'setTotalQuantity') security.declareProtected(Permissions.ModifyPortalContent, 'setTotalQuantity')
def setTotalQuantity(self, new_quantity, activate_kw=None): def setTotalQuantity(self, new_quantity, activate_kw=None):
""" """
Affect the difference of quantity to different simulation movements
We assume that quantities are either all positives, or all negatives.
""" """
result = [] result = []
remaining_quantity = self.getTotalQuantity() - new_quantity remaining_quantity = self.getTotalQuantity() - new_quantity
if remaining_quantity < 0: if new_quantity < 0:
return result if remaining_quantity > 0:
return result
else:
if remaining_quantity < 0:
return result
simulation_movement_list = self._getSimulationMovementList() simulation_movement_list = self._getSimulationMovementList()
for movement in simulation_movement_list: for movement in simulation_movement_list:
quantity = movement.getQuantity() quantity = movement.getQuantity()
if quantity < remaining_quantity: # make sure we have same sign, or this code solver would not work
assert (quantity * remaining_quantity) >= 0, "Could not solve if we do not have same sign"
if abs(quantity) < abs(remaining_quantity):
result.append((movement, quantity)) result.append((movement, quantity))
remaining_quantity -= quantity remaining_quantity -= quantity
movement.edit(quantity=0, delivery_ratio=0, activate_kw=activate_kw) movement.edit(quantity=0, delivery_ratio=0, activate_kw=activate_kw)
......
...@@ -165,6 +165,21 @@ class TestOrderMixin(SubcontentReindexingWrapper): ...@@ -165,6 +165,21 @@ class TestOrderMixin(SubcontentReindexingWrapper):
portal_type='Category', portal_type='Category',
id=category_id) id=category_id)
def getTwoRelatedPackingList(self, sequence):
order = sequence.get('order')
packing_list_list = order.getCausalityRelatedValueList(
portal_type=self.packing_list_portal_type)
self.assertEqual(2,len(packing_list_list))
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)
return packing_list1, packing_list2
def stepCreateNotVariatedResource(self,sequence=None, sequence_list=None, \ def stepCreateNotVariatedResource(self,sequence=None, sequence_list=None, \
**kw): **kw):
""" """
......
...@@ -344,44 +344,21 @@ class TestPackingListMixin(TestOrderMixin): ...@@ -344,44 +344,21 @@ class TestPackingListMixin(TestOrderMixin):
""" """
Test if packing list was splitted Test if packing list was splitted
""" """
order = sequence.get('order') packing_list1, packing_list2 = self.getTwoRelatedPackingList(sequence)
packing_list_list = order.getCausalityRelatedValueList( packing_list1_line, = packing_list1.objectValues(portal_type=self.packing_list_line_portal_type)
portal_type=self.packing_list_portal_type) self.assertEqual(self.default_quantity-1,packing_list1_line.getQuantity())
self.assertEqual(2,len(packing_list_list)) packing_list2_line, = packing_list2.objectValues(portal_type=self.packing_list_line_portal_type)
packing_list1 = None self.assertEqual(1,packing_list2_line.getQuantity())
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)
for line in packing_list1.objectValues(
portal_type= self.packing_list_line_portal_type):
self.assertEqual(self.default_quantity-1,line.getQuantity())
for line in packing_list2.objectValues(
portal_type= self.packing_list_line_portal_type):
self.assertEqual(1,line.getQuantity())
def stepCheckPackingListSplittedTwoTimes(self, sequence=None, sequence_list=None, **kw): def stepCheckPackingListSplittedTwoTimes(self, sequence=None, sequence_list=None, **kw):
""" """
Test if packing list is divergent Test if packing list is divergent
""" """
order = sequence.get('order') packing_list1, packing_list2 = self.getTwoRelatedPackingList(sequence)
packing_list_list = order.getCausalityRelatedValueList( packing_list1_line, = packing_list1.objectValues(portal_type=self.packing_list_line_portal_type)
portal_type=self.packing_list_portal_type) self.assertEqual(self.default_quantity-2,packing_list1_line.getQuantity())
self.assertEqual(2,len(packing_list_list)) packing_list2_line, = packing_list2.objectValues(portal_type=self.packing_list_line_portal_type)
packing_list1 = None self.assertEqual(2,packing_list2_line.getQuantity())
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
line1, = packing_list1.objectValues(portal_type=self.packing_list_line_portal_type)
self.assertEqual(self.default_quantity-2,line1.getQuantity())
line2, = packing_list2.objectValues(portal_type=self.packing_list_line_portal_type)
self.assertEqual(2,line2.getQuantity())
def stepCheckPackingListNotSplitted(self, sequence=None, sequence_list=None, **kw): def stepCheckPackingListNotSplitted(self, sequence=None, sequence_list=None, **kw):
""" """
...@@ -2051,6 +2028,76 @@ class TestPackingList(TestPackingListMixin, ERP5TypeTestCase) : ...@@ -2051,6 +2028,76 @@ class TestPackingList(TestPackingListMixin, ERP5TypeTestCase) :
sequence_list.play(self, quiet=quiet) sequence_list.play(self, quiet=quiet)
def stepIncreasePackingListLineNegativeQuantity(self, sequence=None,
sequence_list=None, **kw):
"""
Set a decreased quantity on packing list lines
"""
packing_list = sequence.get('packing_list')
quantity = sequence.get('line_quantity',default=self.default_quantity)
quantity = quantity + 1
sequence.edit(line_quantity=quantity)
packing_list_line, = packing_list.getMovementList(portal_type=self.packing_list_line_portal_type)
packing_list_line.edit(quantity=quantity)
for packing_list_line in packing_list.objectValues(
portal_type=self.packing_list_line_portal_type):
packing_list_line.edit(quantity=quantity)
def stepCheckPackingListSplittedWithNegativeQuantity(self, sequence=None, sequence_list=None, **kw):
"""
Test if packing list was splitted
"""
packing_list1, packing_list2 = self.getTwoRelatedPackingList(sequence)
packing_list1_line, = packing_list1.objectValues(portal_type=self.packing_list_line_portal_type)
self.assertEqual(self.default_quantity+1,packing_list1_line.getQuantity())
packing_list2_line, = packing_list2.objectValues(portal_type=self.packing_list_line_portal_type)
self.assertEqual(-1,packing_list2_line.getQuantity())
def stepCheckPackingListSplittedTwoTimesWithNegativeQuantity(self, sequence=None, sequence_list=None, **kw):
"""
Test if packing list is splitted two times
"""
packing_list1, packing_list2 = self.getTwoRelatedPackingList(sequence)
packing_list1_line, = packing_list1.objectValues(portal_type=self.packing_list_line_portal_type)
self.assertEqual(self.default_quantity+2,packing_list1_line.getQuantity())
packing_list2_line, = packing_list2.objectValues(portal_type=self.packing_list_line_portal_type)
self.assertEqual(-2,packing_list2_line.getQuantity())
def test_21_PackingListQuantitySplitNegativeQuantity(self):
"""
Make sur quantity split solver works fine in the case we have
negative quantities. Probably rarely useful in the case of sale packing
list, but could be useful in other kinds of delivery (like in MRP).
"""
try:
self.default_quantity = -99
sequence_list = SequenceList()
sequence_string = self.default_sequence + """
IncreasePackingListLineNegativeQuantity
CheckPackingListIsCalculating
Tic
CheckPackingListIsDiverged
SplitAndDeferPackingList
Tic
CheckPackingListIsSolved
CheckPackingListSplittedWithNegativeQuantity
IncreasePackingListLineNegativeQuantity
CheckPackingListIsCalculating
Tic
CheckPackingListIsDiverged
SplitAndMovePackingList
Tic
CheckNewPackingListIsSolved
stepCheckPackingListSplittedTwoTimesWithNegativeQuantity
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
finally:
delattr(self, "default_quantity")
class TestSolvingPackingList(TestPackingListMixin, ERP5TypeTestCase): class TestSolvingPackingList(TestPackingListMixin, ERP5TypeTestCase):
quiet = 0 quiet = 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment