PaySheetTransaction.py 8.57 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
##############################################################################
#
# 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.
#
##############################################################################

29

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

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

37
class PaySheetTransaction(Invoice):
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
  """
  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
                    )


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

  security.declareProtected(Permissions.AccessContentsInformation,
Fabien Morin's avatar
Fabien Morin committed
91
                            'getRatioQuantityList')
92 93 94 95 96 97
  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.
    """
98
    if not isinstance(ratio_reference_list, (list, tuple)):
99 100 101 102
      return [self.getRatioQuantityFromReference(ratio_reference_list)]
    return [self.getRatioQuantityFromReference(reference) \
        for reference in ratio_reference_list]

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

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

Fabien Morin's avatar
Fabien Morin committed
133 134
  security.declareProtected(Permissions.AccessContentsInformation,
                            'getInheritedObjectValueList')
135
  def getInheritedObjectValueList(self, portal_type_list, property_list=()):
136
    '''Return a list of all subobjects of the herited model (incuding the
137 138
      dependencies).
      If property_list is provided, only subobjects with at least one of those
139
      properties will be taken into account
140
    '''
141 142 143 144
    model = self.getSpecialiseValue().getEffectiveModel(\
        start_date=self.getStartDate(),
        stop_date=self.getStopDate())
    model_reference_dict = model.getInheritanceReferenceDict(
145 146
                                   portal_type_list=portal_type_list,
                                   property_list=property_list)
147
    sub_object_list = []
148 149 150 151
    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])
152 153
    return sub_object_list

Fabien Morin's avatar
Fabien Morin committed
154 155
  security.declareProtected(Permissions.ModifyPortalContent,
                            'applyTransformation')
156
  def applyTransformation(self):
Fabien Morin's avatar
Fabien Morin committed
157
    '''use a delivery builder to create all the paysheet lines using
158 159 160 161 162 163 164 165
      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
166 167 168
      if len(parent.contentValues(portal_type='Pay Sheet Cell')) == 0:
        # the line contain no movements, remove it
        self.manage_delObjects(parent.getId())
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
    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)
187
        for business_path in business_path_list:
188 189 190 191 192
          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])