← Back to team overview

openerp-india team mailing list archive

[Bug 1044611] [NEW] payslip rule calculation (compute_rule) fixes

 

Public bug reported:

Hello,

Using stock OpenERP 6.1.1, I discovered a few issues with compute_rule()
method of hr.salary.rule which really made my work a mess. I fixed them
in my custom module by overriding the method and that worked well. Would
you please include the improvements in OpenERP?

1) When consecutive "code" rules were calculated with result_qty and result_rate, if there was a rule which did not set these values, they were carried over from the previous one, obviously messing up the calculation. 
Workaround: Assign these variables in each python "code" rule
Fix: Change the code to remove these values before/after each calculation 

2) When result_qty and result_rate were intentionally set to 0, the original code set them back to 1 or 100. This would mess up calculations where 0 is a valid outcome.
Workaround: Make sure it's like 0.0001 if it's zero in your calculation
Fix: Change the code to accept 0

3) No information available when calculation fails, not even in the log... This was especially confusing when I had a division by zero - which is not caused by wrong code, but rather by wrong data!
Workaround: Debug the server in Pdb, investigate the variables
Fix: Change the exception handling to include original exception info in the secondary exception thrown

My fixes:

class hr_salary_rule(osv.osv):
    _inherit = 'hr.salary.rule'


    #TODO: remove once fixed in OpenERP
    # This fixes three problems: 
    #   1) result_qty and result_rate remaining in the localdict - affecting next calculation
    #   2) result_qty and result_rate set to 1, resp 100 when 0
    #   3) lack of information about failures
    def compute_rule(self, cr, uid, rule_id, localdict, context=None):
        """
        :param rule_id: id of rule to compute
        :param localdict: dictionary containing the environement in which to compute the rule
        :return: returns a tuple build as the base/amount computed, the quantity and the rate 
        :rtype: (float, float, float)
        """
        
	from tools.translate import _
	from tools.safe_eval import safe_eval as eval

	# Make sure no residuals are left behind
	localdict.pop('result', False)
	localdict.pop('result_qty', False)
	localdict.pop('result_rate', False)
	
        rule = self.browse(cr, uid, rule_id, context=context)
        if rule.amount_select == 'fix':
            try:
                return rule.amount_fix, eval(rule.quantity, localdict), 100.0
            except Exception as x:
                raise osv.except_osv(_('Error'), _('Failed calculating quantity defined for salary rule %s (%s), Exception: %s')% (rule.name, rule.code, x))
        elif rule.amount_select == 'percentage':
            try:
                return eval(rule.amount_percentage_base, localdict), eval(rule.quantity, localdict), rule.amount_percentage
            except Exception as x:
                raise osv.except_osv(_('Error'), _('Failed calculating percentage base or quantity defined for salary rule %s (%s), Exception: %s')% (rule.name, rule.code, x))
        else:
            try:
                eval(rule.amount_python_compute, localdict, mode='exec', nocopy=True)
                # Using pop with default to both remove the item and get a default sensibly
                return localdict.pop('result'), localdict.pop('result_qty', 1.0), localdict.pop('result_rate', 100.0)
            except Exception as x:
                raise osv.except_osv(_('Error'), _('Failed calculating python code defined for salary rule %s (%s), Exception: %s')% (rule.name, rule.code, x))

hr_salary_rule()

** Affects: openobject-addons
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of OpenERP
Indian Team, which is subscribed to OpenERP Addons.
https://bugs.launchpad.net/bugs/1044611

Title:
  payslip rule calculation (compute_rule) fixes

Status in OpenERP Addons (modules):
  New

Bug description:
  Hello,

  Using stock OpenERP 6.1.1, I discovered a few issues with
  compute_rule() method of hr.salary.rule which really made my work a
  mess. I fixed them in my custom module by overriding the method and
  that worked well. Would you please include the improvements in
  OpenERP?

  1) When consecutive "code" rules were calculated with result_qty and result_rate, if there was a rule which did not set these values, they were carried over from the previous one, obviously messing up the calculation. 
  Workaround: Assign these variables in each python "code" rule
  Fix: Change the code to remove these values before/after each calculation 

  2) When result_qty and result_rate were intentionally set to 0, the original code set them back to 1 or 100. This would mess up calculations where 0 is a valid outcome.
  Workaround: Make sure it's like 0.0001 if it's zero in your calculation
  Fix: Change the code to accept 0

  3) No information available when calculation fails, not even in the log... This was especially confusing when I had a division by zero - which is not caused by wrong code, but rather by wrong data!
  Workaround: Debug the server in Pdb, investigate the variables
  Fix: Change the exception handling to include original exception info in the secondary exception thrown

  My fixes:

  class hr_salary_rule(osv.osv):
      _inherit = 'hr.salary.rule'

  
      #TODO: remove once fixed in OpenERP
      # This fixes three problems: 
      #   1) result_qty and result_rate remaining in the localdict - affecting next calculation
      #   2) result_qty and result_rate set to 1, resp 100 when 0
      #   3) lack of information about failures
      def compute_rule(self, cr, uid, rule_id, localdict, context=None):
          """
          :param rule_id: id of rule to compute
          :param localdict: dictionary containing the environement in which to compute the rule
          :return: returns a tuple build as the base/amount computed, the quantity and the rate 
          :rtype: (float, float, float)
          """
          
  	from tools.translate import _
  	from tools.safe_eval import safe_eval as eval

  	# Make sure no residuals are left behind
  	localdict.pop('result', False)
  	localdict.pop('result_qty', False)
  	localdict.pop('result_rate', False)
  	
          rule = self.browse(cr, uid, rule_id, context=context)
          if rule.amount_select == 'fix':
              try:
                  return rule.amount_fix, eval(rule.quantity, localdict), 100.0
              except Exception as x:
                  raise osv.except_osv(_('Error'), _('Failed calculating quantity defined for salary rule %s (%s), Exception: %s')% (rule.name, rule.code, x))
          elif rule.amount_select == 'percentage':
              try:
                  return eval(rule.amount_percentage_base, localdict), eval(rule.quantity, localdict), rule.amount_percentage
              except Exception as x:
                  raise osv.except_osv(_('Error'), _('Failed calculating percentage base or quantity defined for salary rule %s (%s), Exception: %s')% (rule.name, rule.code, x))
          else:
              try:
                  eval(rule.amount_python_compute, localdict, mode='exec', nocopy=True)
                  # Using pop with default to both remove the item and get a default sensibly
                  return localdict.pop('result'), localdict.pop('result_qty', 1.0), localdict.pop('result_rate', 100.0)
              except Exception as x:
                  raise osv.except_osv(_('Error'), _('Failed calculating python code defined for salary rule %s (%s), Exception: %s')% (rule.name, rule.code, x))

  hr_salary_rule()

To manage notifications about this bug go to:
https://bugs.launchpad.net/openobject-addons/+bug/1044611/+subscriptions


Follow ups

References