[Erp5-report] r17693 - /erp5/trunk/products/ERP5/Document/PaySheetTransaction.py
nobody at svn.erp5.org
nobody at svn.erp5.org
Mon Nov 19 19:09:38 CET 2007
Author: fabien
Date: Mon Nov 19 19:09:38 2007
New Revision: 17693
URL: http://svn.erp5.org?rev=17693&view=rev
Log:
add int_index on Pay Sheet Model Line. Now the calclation will be made in the order of
the Pay Sheet Model Lines int_index. int_index have been added in the Pay Sheet
Line in order to be displayed in a particular order on the paysheet.
Modified:
erp5/trunk/products/ERP5/Document/PaySheetTransaction.py
Modified: erp5/trunk/products/ERP5/Document/PaySheetTransaction.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/PaySheetTransaction.py?rev=17693&r1=17692&r2=17693&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/PaySheetTransaction.py (original)
+++ erp5/trunk/products/ERP5/Document/PaySheetTransaction.py Mon Nov 19 19:09:38 2007
@@ -29,6 +29,7 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface
from Products.ERP5.Document.Invoice import Invoice
+from zLOG import LOG
class PaySheetTransaction(Invoice):
"""
@@ -278,31 +279,6 @@
column, row = getDictList(['tax_category', 'base_amount'])
base_amount_table = getEmptyTwoDimentionalTable(nb_columns=len(column),
nb_rows=len(row))
- # XXX currently, there is a problem not resolved yet :
- # if a tax_category have a base_application ('non_deductible_tax','bonus')
- # and if a bonus have a base_application ('base_salary',), calculation
- # must be made in a particular order, and sometimes, it's possible to
- # have circular dependencies and so, impossible to resove this cases.
- # The best, will to do calculation with understanding dependencies and
- # raise an error if there is circular dependence. Currently, caluls are
- # made in a paticular order defined by the list order_of_calculation
- # so dependencies are not taken into account.
- # And result are wrong in some cases.
- # solutions :
- # 1 - do calculation without any order and redo evry calculs while a value
- # in the base_amount_table have changed. This is a little slow but safe.
- # 2 - determine an order using dependencies graph, but this solution
- # is not evolutive and safe, because it not take into account the new
- # categories
- # 3 - add an order field in paysheet lines and model lines : the user
- # must determine an order manually and it will be easy to apply it
- # in my opinion, the best solution for the accountant is the first, but it
- # will be slow, the easier is the 3.
-
-
- # It's important to do calculation in a precise order,
- # most of time, a tax could depend on base_salary and bonus,
- # so they must be calculated before
def sortByIntIndex(a, b):
return cmp(a.getIntIndex(),
@@ -311,13 +287,10 @@
base_amount_list = self.portal_categories['base_amount'].contentValues()
base_amount_list.sort(sortByIntIndex)
- order_of_calculation = [x.getRelativeUrl() for x in base_amount_list]
- #order_of_calculation = ('base_amount/base_salary', 'base_amount/bonus',
- # 'base_amount/non_deductible_tax',
- # 'base_amount/deductible_tax')
# it's important to get the editable lines to know if they contribute to
- # a base_amount (this is required to do the calcul later
+ # a base_amount (this is required to do the calcul later)
+
# get edited lines:
paysheetline_list = self.contentValues(portal_type = ['Pay Sheet Line'])
@@ -342,152 +315,135 @@
# get not editables model lines
model = self.getSpecialiseValue()
- model_line_list = model.contentValues(portal_type='Pay Sheet Model Line')
+ model_line_list = model.contentValues(portal_type='Pay Sheet Model Line',
+ sort_on='int_index')
+ model_line_list = [line for line in model_line_list if not line.getEditable()]
pay_sheet_line_list = []
employee_tax_amount = 0
- # initilise a dict with model_line relative url and 0 value to know
- # if a contribution have already been calculated
- already_calculate = dict([[model_line.getRelativeUrl(), 0] \
- for model_line in model_line_list])
-
# main loop : find all informations and create cell and PaySheetLines
- for base_ordered in order_of_calculation:
- for model_line in model_line_list:
-
- # get only not editables model lines
- if model_line.getEditable():
- continue
- if model_line.getResourceValue().getBaseAmountList(base=1) and \
- base_ordered not in \
- model_line.getResourceValue().getBaseAmountList(base=1):
- continue
- if already_calculate[model_line.getRelativeUrl()]:
- continue
- else:
- already_calculate[model_line.getRelativeUrl()] = 1
- # this prevent to calculate two times the same model line if it's
- # resource have many Base Participation, it will be calculate
- # many times.
-
- cell_list = []
- # test with predicate if this model line could be applied
- if not model_line.test(self,):
- # This line should not be used
- continue
-
- service = model_line.getResourceValue()
- title = model_line.getTitleOrId()
- id = model_line.getId()
- res = service.getRelativeUrl()
- if model_line.getDescription():
- desc = ''.join(model_line.getDescription())
- # if the model_line description is empty, the payroll service
- # description is used
- else: desc = ''.join(service.getDescription())
-
- variation_share_list = model_line.getVariationCategoryList(\
- base_category_list=['tax_category',])
- variation_slice_list = model_line.getVariationCategoryList(\
- base_category_list=['salary_range',])
-
- for share in variation_share_list:
- base_application = None
- for slice in variation_slice_list:
-
- #get the amount of application for this line
- base_application_list = model_line.getBaseAmountList(base=1)
- if base_application is None:
- base_application = 0
- for base in model_line.getBaseAmountList(base=1):
- if base_amount_table[column[share]][row[base]] is not None:
- base_application += \
- base_amount_table[column[share]][row[base]]
-
- cell = model_line.getCell(slice, share)
+ for model_line in model_line_list:
+ cell_list = []
+ # test with predicate if this model line could be applied
+ if not model_line.test(self,):
+ # This line should not be used
+ continue
+
+ service = model_line.getResourceValue()
+ title = model_line.getTitleOrId()
+ id = model_line.getId()
+ res = service.getRelativeUrl()
+ if model_line.getDescription():
+ desc = ''.join(model_line.getDescription())
+ # if the model_line description is empty, the payroll service
+ # description is used
+ else: desc = ''.join(service.getDescription())
+
+ variation_share_list = model_line.getVariationCategoryList(\
+ base_category_list=['tax_category',])
+ variation_slice_list = model_line.getVariationCategoryList(\
+ base_category_list=['salary_range',])
+
+ for share in variation_share_list:
+ base_application = None
+ for slice in variation_slice_list:
+
+ #get the amount of application for this line
+ base_application_list = model_line.getBaseAmountList(base=1)
+ if base_application is None:
+ base_application = 0
+ for base in model_line.getBaseAmountList(base=1):
+ if base_amount_table[column[share]][row[base]] is not None:
+ base_application += \
+ base_amount_table[column[share]][row[base]]
- if cell is not None:
- # get the slice :
- model_slice = None
- model_slice = model_line.getParentValue().getCell(slice)
- quantity = 0.0
- price = 0.0
- if model_slice is not None:
- model_slice_min = model_slice.getQuantityRangeMin()
- model_slice_max = model_slice.getQuantityRangeMax()
- quantity = cell.getQuantity()
- price = cell.getPrice()
-
- ######################
- # calculation part : #
- ######################
- script_name = model.getLocalizedCalculationScriptId()
- if script_name is None or \
- getattr(self, script_name, None) is None:
- # if no calculation script found, use a default method :
- if not quantity:
- if base_application <= model_slice_max:
- quantity = base_application
- else:
- quantity = model_slice_max
+ cell = model_line.getCell(slice, share)
+
+ if cell is not None:
+ # get the slice :
+ model_slice = None
+ model_slice = model_line.getParentValue().getCell(slice)
+ quantity = 0.0
+ price = 0.0
+ if model_slice is not None:
+ model_slice_min = model_slice.getQuantityRangeMin()
+ model_slice_max = model_slice.getQuantityRangeMax()
+ quantity = cell.getQuantity()
+ price = cell.getPrice()
+
+ ######################
+ # calculation part : #
+ ######################
+ script_name = model.getLocalizedCalculationScriptId()
+ if script_name is None or \
+ getattr(self, script_name, None) is None:
+ # if no calculation script found, use a default method :
+ if not quantity:
+ if base_application <= model_slice_max:
+ quantity = base_application
+ else:
+ quantity = model_slice_max
+ else:
+ localized_calculation_script = getattr(self, script_name,
+ None)
+ quantity, price = localized_calculation_script(\
+ paysheet=self,
+ model_slice_min = model_slice_min,
+ model_slice_max=model_slice_max,
+ quantity=quantity,
+ price=price,
+ model_line=model_line)
+
+ # Cell creation :
+ # Define an empty new cell
+ new_cell = { 'axe_list' : [share, slice]
+ , 'quantity' : quantity
+ , 'price' : price
+ }
+ cell_list.append(new_cell)
+
+ #XXX this is a hack to have the net salary
+ base_list = model_line.getResourceValue().getBaseAmountList()
+ if price is not None and 'employee_share' in share and\
+ not ('base_salary' in base_list or\
+ 'bonus' in base_list or\
+ 'gross_salary' in base_list):
+ employee_tax_amount += round((price * quantity), precision)
+
+ # update base participation
+ base_participation_list = service.getBaseAmountList(base=1)
+ for base_participation in base_participation_list:
+ old_val = \
+ base_amount_table[column[share]][row[base_participation]]
+
+ if quantity:
+ if old_val is not None:
+ new_val = old_val + quantity
else:
- localized_calculation_script = getattr(self, script_name,
- None)
- quantity, price = localized_calculation_script(\
- paysheet=self,
- model_slice_min = model_slice_min,
- model_slice_max=model_slice_max,
- quantity=quantity,
- price=price,
- model_line=model_line)
-
- # Cell creation :
- # Define an empty new cell
- new_cell = { 'axe_list' : [share, slice]
- , 'quantity' : quantity
- , 'price' : price
- }
- cell_list.append(new_cell)
-
- #XXX this is a hack to have the net salary
- if price is not None and 'employee_share' in share and\
- base_ordered not in ('base_salary', 'bonus') :
- employee_tax_amount += round((price * quantity), precision)
-
- # update base participation
- base_participation_list = service.getBaseAmountList(base=1)
- for base_participation in base_participation_list:
- old_val = \
- base_amount_table[column[share]][row[base_participation]]
-
- if quantity:
+ new_val = quantity
+ if price:
if old_val is not None:
- new_val = old_val + quantity
- else:
- new_val = quantity
- if price:
- if old_val is not None:
- new_val = round((old_val + quantity*price), precision)
- base_amount_table[column[share]][row[base_participation]]= \
- new_val
- base_amount_table[column[share]][row[base_participation]] = \
- new_val
-
- # decrease the base_application used for this model line if
- if cell is not None :
- base_application -= quantity
-
- if cell_list:
- # create the PaySheetLine
- pay_sheet_line = self.createPaySheetLine(
- title = title,
- id = id,
- res = res,
- desc = desc,
- cell_list = cell_list,
- )
- pay_sheet_line_list.append(pay_sheet_line)
+ new_val = round((old_val + quantity*price), precision)
+ base_amount_table[column[share]][row[base_participation]]= \
+ new_val
+ base_amount_table[column[share]][row[base_participation]] = \
+ new_val
+
+ # decrease the base_application used for this model line
+ if cell is not None :
+ base_application -= quantity
+
+ if cell_list:
+ # create the PaySheetLine
+ pay_sheet_line = self.createPaySheetLine(
+ title = title,
+ id = id,
+ res = res,
+ desc = desc,
+ cell_list = cell_list,
+ )
+ pay_sheet_line_list.append(pay_sheet_line)
# create a line of the total tax payed by the employee
# this hack permit to calculate the net salary
More information about the Erp5-report
mailing list