PaySheetTransaction.py 8.62 KB
Newer Older
Yoshinori Okuji's avatar
Yoshinori Okuji committed
1 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
##############################################################################
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability 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
# garantees 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
##############################################################################

from AccessControl import ClassSecurityInfo
30
from Products.ERP5Type import Permissions, PropertySheet
31
from Products.ERP5.Document.Invoice import Invoice
Yoshinori Okuji's avatar
Yoshinori Okuji committed
32

Fabien Morin's avatar
Fabien Morin committed
33 34 35
#XXX TODO: review naming of new methods
#XXX WARNING: current API naming may change although model should be stable.

36
class PaySheetTransaction(Invoice):
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
  """
  A paysheet will store data about the salary of an employee
  """
  meta_type = 'ERP5 Pay Sheet Transaction'
  portal_type = 'Pay Sheet Transaction'
  add_permission = Permissions.AddPortalContent
  isPortalContent = 1
  isRADContent = 1

  # Declarative security
  security = ClassSecurityInfo()
  security.declareObjectProtected(Permissions.AccessContentsInformation)

  # Default Properties
  property_sheets = ( PropertySheet.Base
                    , PropertySheet.SimpleItem
                    , PropertySheet.CategoryCore
                    , PropertySheet.Task
                    , PropertySheet.Arrow
                    , PropertySheet.Delivery
                    , PropertySheet.PaySheet
                    , PropertySheet.Movement
                    , PropertySheet.Amount
                    , PropertySheet.XMLObject
                    , PropertySheet.TradeCondition
                    , PropertySheet.DefaultAnnotationLine
                    )

  # Declarative Interface
  __implements__ = ( )

68
  security.declareProtected(Permissions.AccessContentsInformation,
Fabien Morin's avatar
Fabien Morin committed
69
                            'getRatioQuantityFromReference')
70 71 72 73 74
  def getRatioQuantityFromReference(self, ratio_reference=None):
    """
    return the ratio value correponding to the ratio_reference,
    None if ratio_reference not found
    """
75 76
    # get ratio lines
    portal_type_list = ['Pay Sheet Model Ratio Line']
Fabien Morin's avatar
Fabien Morin committed
77 78 79
    object_ratio_list = self.contentValues(portal_type=portal_type_list)
    # look for ratio lines on the paysheet
    if object_ratio_list:
80 81 82
      for obj in object_ratio_list:
        if obj.getReference() == ratio_reference:
          return obj.getQuantity()
Fabien Morin's avatar
Fabien Morin committed
83
    # if not find in the paysheet, look on dependence tree
84
    sub_object_list = self.getInheritedObjectValueList(portal_type_list)
85
    object_ratio_list = sub_object_list
86 87 88
    for document in object_ratio_list:
      if document.getReference() == ratio_reference:
        return document.getQuantity()
Fabien Morin's avatar
typo  
Fabien Morin committed
89
    return None
90 91

  security.declareProtected(Permissions.AccessContentsInformation,
Fabien Morin's avatar
Fabien Morin committed
92
                            'getRatioQuantityList')
93 94 95 96 97 98
  def getRatioQuantityList(self, ratio_reference_list):
    """
    Return a list of reference_ratio_list correponding values.
    reference_ratio_list is a list of references to the ratio lines
    we want to get.
    """
99
    if not isinstance(ratio_reference_list, (list, tuple)):
100 101 102 103
      return [self.getRatioQuantityFromReference(ratio_reference_list)]
    return [self.getRatioQuantityFromReference(reference) \
        for reference in ratio_reference_list]

104
  security.declareProtected(Permissions.AccessContentsInformation,
Fabien Morin's avatar
Fabien Morin committed
105
                            'getAnnotationLineFromReference')
106
  def getAnnotationLineFromReference(self, reference=None):
107 108
    """Return the annotation line corresponding to the reference.
    Returns None if reference not found
109
    """
Fabien Morin's avatar
Fabien Morin committed
110
    # look for annotation lines on the paysheet
111
    annotation_line_list = self.contentValues(portal_type=['Annotation Line'])
Fabien Morin's avatar
Fabien Morin committed
112 113
    if annotation_line_list:
      for annotation_line in annotation_line_list:
114
        if (annotation_line.getReference() or annotation_line.getId()) == reference :
Fabien Morin's avatar
Fabien Morin committed
115 116
          return annotation_line
    # if not find in the paysheet, look on dependence tree
117
    for annotation_line in self.getInheritedObjectValueList(['Annotation Line']):
118
      if (annotation_line.getReference() or annotation_line.getId()) == reference:
119
        return annotation_line
Fabien Morin's avatar
typo  
Fabien Morin committed
120
    return None
121 122

  security.declareProtected(Permissions.AccessContentsInformation,
Fabien Morin's avatar
Fabien Morin committed
123
                            'getAnnotationLineListList')
124
  def getAnnotationLineListList(self, reference_list):
125
    """Return a list of annotation lines corresponding to the reference_list
Fabien Morin's avatar
Fabien Morin committed
126
    reference_list is a list of references to the Annotation Line we want
127 128
    to get.
    """
129
    if not isinstance(reference_list, (list, tuple)):
130 131 132
      return [self.getAnnotationLineFromReference(reference_list)]
    return [self.getAnnotationLineFromReference(reference) \
        for reference in reference_list]
133

Fabien Morin's avatar
Fabien Morin committed
134 135
  security.declareProtected(Permissions.AccessContentsInformation,
                            'getInheritedObjectValueList')
136
  def getInheritedObjectValueList(self, portal_type_list, property_list=()):
137
    '''Return a list of all subobjects of the herited model (incuding the
138 139
      dependencies).
      If property_list is provided, only subobjects with at least one of those
140
      properties will be taken into account
141
    '''
142 143 144 145
    model = self.getSpecialiseValue().getEffectiveModel(\
        start_date=self.getStartDate(),
        stop_date=self.getStopDate())
    model_reference_dict = model.getInheritanceReferenceDict(
146 147
                                   portal_type_list=portal_type_list,
                                   property_list=property_list)
148
    sub_object_list = []
149 150 151 152
    traverse = self.getPortalObject().unrestrictedTraverse
    for model_url, id_list in model_reference_dict.items():
      model = traverse(model_url)
      sub_object_list.extend([model._getOb(x) for x in id_list])
153 154
    return sub_object_list

Fabien Morin's avatar
Fabien Morin committed
155 156
  security.declareProtected(Permissions.ModifyPortalContent,
                            'applyTransformation')
157
  def applyTransformation(self):
Fabien Morin's avatar
Fabien Morin committed
158
    '''use a delivery builder to create all the paysheet lines using
159 160 161 162 163 164 165 166
      movements return by updateAggregatedAmountList
    '''
    portal = self.getPortalObject()
    paysheet_model = self.getSpecialiseValue()
    movement_dict = paysheet_model.updateAggregatedAmountList(context=self)
    for movement in movement_dict['movement_to_delete_list']:
      parent = movement.getParentValue()
      parent.manage_delObjects(movement.getId())
Fabien Morin's avatar
Fabien Morin committed
167 168 169
      if len(parent.contentValues(portal_type='Pay Sheet Cell')) == 0:
        # the line contain no movements, remove it
        self.manage_delObjects(parent.getId())
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
    business_process_list = paysheet_model.findSpecialiseValueList(\
        context=paysheet_model,
        portal_type_list=['Business Process'])
    if len(business_process_list):
      # XXX currently, we consider that is to complicated to use more than one
      # Business Process, so we take the first (wich is the nearest from
      # the paysheet)
      business_process = business_process_list[0]
      movement_list_trade_phase_dic = {}
      for movement in movement_dict['movement_to_add_list']:
        trade_phase = movement.getTradePhase()
        if not movement_list_trade_phase_dic.has_key(trade_phase):
          movement_list_trade_phase_dic[trade_phase] = []
        movement_list_trade_phase_dic[trade_phase].append(movement)

      for trade_phase in movement_list_trade_phase_dic.keys():
        business_path_list = business_process.getPathValueList(trade_phase=\
            trade_phase)
188
        for business_path in business_path_list:
189 190 191 192 193
          builder_list = [portal.restrictedTraverse(url) for url in\
                          business_path.getDeliveryBuilderList()]
          for builder in builder_list:
            builder.build(delivery_relative_url_list=[self.getRelativeUrl(),],
                      movement_list = movement_list_trade_phase_dic[trade_phase])