FIFODeliverySolver.py 4.07 KB
Newer Older
1 2 3
# -*- coding: utf-8 -*-
##############################################################################
#
4
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
#
# 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
25
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 27 28
#
##############################################################################

29
import zope.interface
30 31 32
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.XMLObject import XMLObject
33

34
class FIFODeliverySolver(XMLObject):
35
  """
Leonardo Rochael Almeida's avatar
typo  
Leonardo Rochael Almeida committed
36
  The FIFO solver reduces delivered quantity by reducing the quantity of
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
37
  simulation movements from the last order.
38
  """
39 40 41 42
  meta_type = 'ERP5 FIFO Delivery Solver'
  portal_type = 'FIFO Delivery Solver'
  add_permission = Permissions.AddPortalContent
  isIndexable = 0 # We do not want to fill the catalog with objects on which we need no reporting
Jean-Paul Smets's avatar
Jean-Paul Smets committed
43

44 45 46
  # Declarative security
  security = ClassSecurityInfo()
  security.declareObjectProtected(Permissions.AccessContentsInformation)
47

48 49 50 51 52 53 54
  # Default Properties
  property_sheets = ( PropertySheet.Base
                    , PropertySheet.XMLObject
                    , PropertySheet.CategoryCore
                    , PropertySheet.DublinCore
                    , PropertySheet.DeliverySolver
                    )
55

56 57
  # Declarative interfaces
  zope.interface.implements(interfaces.IDeliverySolver,)
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
58

59
  # IDeliverySolver Implementation
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
60
  def getTotalQuantity(self):
61 62 63 64
    """
      Move this to mixin
    """
    total_quantity = 0
65
    for movement in self.getDeliveryValueList():
66 67 68
      total_quantity += movement.getQuantity()
    return total_quantity

69
  def setTotalQuantity(self, new_quantity, activate_kw=None):
Jean-Paul Smets's avatar
Jean-Paul Smets committed
70 71 72
    """
    """
    result = []
73
    remaining_quantity = self.getTotalQuantity() - new_quantity
74 75 76
    if remaining_quantity < 0:
      return result
    simulation_movement_list = self._getSimulationMovementList()
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
77
    for movement in simulation_movement_list:
Jean-Paul Smets's avatar
Jean-Paul Smets committed
78
      if remaining_quantity:
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
79 80 81 82
        quantity = movement.getQuantity()
        if quantity < remaining_quantity:
          result.append((movement, quantity))
          remaining_quantity -= quantity
83
          movement.edit(quantity=0, delivery_ratio=0, activate_kw=activate_kw)
Jean-Paul Smets's avatar
Jean-Paul Smets committed
84
        else:
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
85
          result.append((movement, remaining_quantity))
86
          movement_quantity = quantity - remaining_quantity
87 88 89
          delivery_ratio = 1.
          if new_quantity:
            delivery_ratio = movement_quantity / new_quantity
90
          movement.edit(quantity=movement_quantity,
91
                        delivery_ratio=delivery_ratio,
92
                        activate_kw=activate_kw)
Jean-Paul Smets's avatar
Jean-Paul Smets committed
93 94
          remaining_quantity = 0
    # Return movement, split_quantity tuples
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
95 96 97 98 99 100
    return result

  def _getSimulationMovementList(self):
    """
    Returns a list of simulation movement sorted from the last order.
    """
101
    simulation_movement_list = self.getDeliveryValueList()
102
    if len(simulation_movement_list) > 1:
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
103
      return sorted(simulation_movement_list,
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
104
        key=lambda x:x.getExplainationValue().getStartDate(), reverse=True)
Kazuhiko Shiozaki's avatar
Kazuhiko Shiozaki committed
105 106
    else:
      return simulation_movement_list