diff --git a/addons/hr_payroll/hr_payroll.py b/addons/hr_payroll/hr_payroll.py index 30ffe8d6fde..b92f9c51c60 100644 --- a/addons/hr_payroll/hr_payroll.py +++ b/addons/hr_payroll/hr_payroll.py @@ -463,7 +463,7 @@ class hr_payslip(osv.osv): if res: result[record.id] = [x[0] for x in res] return result - + def _get_parent_structure(self, cr, uid, struct_id, context=None): if not struct_id: return [] @@ -512,7 +512,7 @@ class hr_payslip(osv.osv): rul.append(r.id) res[record.id] = {fn: rul} return res - + def _compute(self, cr, uid, id, value, context=None): rule_obj = self.pool.get('hr.salary.rule') contrib = rule_obj.browse(cr, uid, id, context=context) @@ -647,18 +647,6 @@ class hr_payslip(osv.osv): return True def get_contract(self, cr, uid, employee, date, context=None): -# sql_req= ''' -# SELECT c.id as id, c.wage as wage, struct_id as function -# FROM hr_contract c -# LEFT JOIN hr_employee emp on (c.employee_id=emp.id) -# LEFT JOIN hr_contract_wage_type cwt on (cwt.id = c.wage_type_id) -# LEFT JOIN hr_contract_wage_type_period p on (cwt.period_id = p.id) #PSI@ improve as we need period but wage_type_id field removed -# WHERE -# (emp.id=%s) AND -# (date_start <= %s) AND -# (date_end IS NULL OR date_end >= %s) -# LIMIT 1 -# ''' sql_req= ''' SELECT c.id as id, c.wage as wage, struct_id as function FROM hr_contract c @@ -667,11 +655,10 @@ class hr_payslip(osv.osv): (emp.id=%s) AND (date_start <= %s) AND (date_end IS NULL OR date_end >= %s) - LIMIT 1 ''' cr.execute(sql_req, (employee.id, date, date)) - contract = cr.dictfetchone() - return contract and contract or {} + contracts = cr.dictfetchall() + return contracts and contracts or {} def _get_leaves(self, cr, user, ddate, employee, context=None): """ @@ -704,145 +691,159 @@ class hr_payslip(osv.osv): holiday_pool = self.pool.get('hr.holidays') sequence_obj = self.pool.get('ir.sequence') salary_rule_pool = self.pool.get('hr.salary.rule') + contract_obj = self.pool.get('hr.contract') resource_attendance_pool = self.pool.get('resource.calendar.attendance') if context is None: context = {} date = self.read(cr, uid, ids, ['date'], context=context)[0]['date'] for slip in self.browse(cr, uid, ids, context=context): - old_slip_ids = slip_line_pool.search(cr, uid, [('slip_id','=',slip.id)], context=context) + old_slip_ids = slip_line_pool.search(cr, uid, [('slip_id', '=', slip.id)], context=context) slip_line_pool.unlink(cr, uid, old_slip_ids, context=context) - update = {} ttyme = datetime.fromtimestamp(time.mktime(time.strptime(slip.date, "%Y-%m-%d"))) - contracts = self.get_contract(cr, uid, slip.employee_id, date, context) - if contracts.get('id', False) == False: + contract_id = slip.contract_id.id + if not contract_id: + update.update({'struct_id': False}) + contracts = self.get_contract(cr, uid, slip.employee_id, date, context=context) + else: + contracts = [contract_obj.read(cr, uid, contract_id, ['wage', 'struct_id', 'id'], context=context)] update.update({ - 'basic': 0.0, + 'struct_id': contracts[0].get('struct_id', False), + 'contract_id': contract_id + }) + if not contracts: + update.update({ + 'basic_amount': 0.0, 'basic_before_leaves': 0.0, 'name': 'Salary Slip of %s for %s' % (slip.employee_id.name, tools.ustr(ttyme.strftime('%B-%Y'))), 'state': 'draft', 'contract_id': False, + 'struct_id': False, 'company_id': slip.employee_id.company_id.id }) self.write(cr, uid, [slip.id], update, context=context) continue - contract = slip.employee_id.contract_id - function = contract.struct_id.id - sal_structure = [] - if function: - sal_structure = self._get_parent_structure(cr, uid, [function], context=context) - lines = [] - rules = [] - for struct in sal_structure: - lines = func_pool.browse(cr, uid, struct, context=context).rule_ids - for rl in lines: - if rl.child_ids: - for r in rl.child_ids: - lines.append(r) - rules.append(rl) - ad = [] - total = 0.0 - obj = {'basic': contract.wage} - for line in rules: - cd = line.code.lower() - obj[cd] = line.amount or 0.0 - - for line in rules: - if line.category_id.code in ad: + for contract in contracts: + if contract.get('id', False) == False: continue - ad.append(line.category_id.code) - cd = line.category_id.code.lower() - calculate = False - try: - exp = line.conditions - calculate = eval(exp, obj) - except Exception, e: - raise osv.except_osv(_('Variable Error !'), _('Variable Error: %s ') % (e)) + contract_id = contract.get('id') + contract = self.pool.get('hr.contract').browse(cr, uid, contract_id, context=context) + function = contract.struct_id.id + sal_structure = [] + if function: + sal_structure = self._get_parent_structure(cr, uid, [function], context=context) + lines = [] + rules = [] + for struct in sal_structure: + lines = func_pool.browse(cr, uid, struct, context=context).rule_ids + for rl in lines: + if rl.child_ids: + for r in rl.child_ids: + lines.append(r) + rules.append(rl) + ad = [] + total = 0.0 + obj = {'basic': contract.wage} + for line in rules: + cd = line.code.lower() + obj[cd] = line.amount or 0.0 - if not calculate: - continue - - value = 0.0 - base = line.computational_expression - try: - amt = eval(base, obj) - except Exception, e: - raise osv.except_osv(_('Variable Error !'), _('Variable Error: %s ') % (e)) - if line.amount_type == 'per': + for line in rules: + if line.category_id.code in ad: + continue + ad.append(line.category_id.code) + cd = line.category_id.code.lower() + calculate = False try: - if line.child_depend == False: - if line.parent_rule_id: - for rul in [line.parent_rule_id]: - val = rul.amount * amt - amt = val - value = line.amount * amt - if line.condition_range_min or line.condition_range_max: - if ((value < line.condition_range_min) or (value > line.condition_range_max)): - value = 0.0 - else: - value = value - else: - value = value + exp = line.conditions + calculate = eval(exp, obj) except Exception, e: raise osv.except_osv(_('Variable Error !'), _('Variable Error: %s ') % (e)) - elif line.amount_type == 'fix': - if line.child_depend == False: - if line.parent_rule_id: - for rul in [line.parent_rule_id]: - value = value - if line.condition_range_min or line.condition_range_max: - if ((line.amount < line.condition_range_min) or (line.amount > line.condition_range_max)): - value = value + if not calculate: + continue + + value = 0.0 + base = line.computational_expression + try: + amt = eval(base, obj) + except Exception, e: + raise osv.except_osv(_('Variable Error !'), _('Variable Error: %s ') % (e)) + if line.amount_type == 'per': + try: + if line.child_depend == False: + if line.parent_rule_id: + for rul in [line.parent_rule_id]: + val = rul.amount * amt + amt = val + value = line.amount * amt + if line.condition_range_min or line.condition_range_max: + if ((value < line.condition_range_min) or (value > line.condition_range_max)): + value = 0.0 + else: + value = value + else: + value = value + except Exception, e: + raise osv.except_osv(_('Variable Error !'), _('Variable Error: %s ') % (e)) + + elif line.amount_type == 'fix': + if line.child_depend == False: + if line.parent_rule_id: + for rul in [line.parent_rule_id]: + value = value + if line.condition_range_min or line.condition_range_max: + if ((line.amount < line.condition_range_min) or (line.amount > line.condition_range_max)): + value = value + else: + value = line.amount else: value = line.amount - else: - value = line.amount - elif line.amount_type=='code': - localdict = {'basic':amt, 'employee':slip.employee_id, 'contract':contract} - exec line.python_compute in localdict - value = localdict['result'] - total += value - vals = { - 'slip_id': slip.id, - 'category_id': line.category_id.id, - 'name': line.name, - 'sequence': line.sequence, - 'type': line.type.id, - 'code': line.code, - 'amount_type': line.amount_type, - 'amount': line.amount, - 'total': value, - 'employee_id': slip.employee_id.id, - 'base': line.computational_expression - } - if line.appears_on_payslip: - if line.parent_rule_id: - for l in salary_rule_pool.browse(cr, uid, [line.parent_rule_id.id], context=context): - slip_line_pool.create(cr, uid, vals, {}) - else: - if line.condition_range_min or line.condition_range_max: - if not ((value < line.condition_range_min) or (value > line.condition_range_max)): + elif line.amount_type=='code': + localdict = {'basic':amt, 'employee':slip.employee_id, 'contract':contract} + exec line.python_compute in localdict + value = localdict['result'] + total += value + vals = { + 'slip_id': slip.id, + 'category_id': line.category_id.id, + 'name': line.name, + 'sequence': line.sequence, + 'type': line.type.id, + 'code': line.code, + 'amount_type': line.amount_type, + 'amount': line.amount, + 'total': value, + 'employee_id': slip.employee_id.id, + 'base': line.computational_expression + } + if line.appears_on_payslip: + if line.parent_rule_id: + for l in salary_rule_pool.browse(cr, uid, [line.parent_rule_id.id], context=context): slip_line_pool.create(cr, uid, vals, {}) else: - slip_line_pool.create(cr, uid, vals, {}) + if line.condition_range_min or line.condition_range_max: + if not ((value < line.condition_range_min) or (value > line.condition_range_max)): + slip_line_pool.create(cr, uid, vals, {}) + else: + slip_line_pool.create(cr, uid, vals, {}) - basic = contract.wage - number = sequence_obj.get(cr, uid, 'salary.slip') - update.update({ - 'struct_id': function, - 'number': number, - 'basic_amount': basic, - 'basic_before_leaves': basic, - 'total_pay': basic + total, - 'name': 'Salary Slip of %s for %s' % (slip.employee_id.name, tools.ustr(ttyme.strftime('%B-%Y'))), - 'state':'draft', - 'contract_id': contract.id, - 'company_id': slip.employee_id.company_id.id - }) - self.write(cr, uid, [slip.id], update, context=context) + basic = contract.wage + number = sequence_obj.get(cr, uid, 'salary.slip') + update.update({ + 'struct_id': function, + 'number': number, + 'basic_amount': basic, + 'basic_before_leaves': basic, + 'total_pay': basic + total, + 'name': 'Salary Slip of %s for %s' % (slip.employee_id.name, tools.ustr(ttyme.strftime('%B-%Y'))), + 'state':'draft', + 'contract_id': contract.id, + 'company_id': slip.employee_id.company_id.id + }) + self.write(cr, uid, [slip.id], update, context=context) for slip in self.browse(cr, uid, ids, context=context): if not slip.contract_id: @@ -853,7 +854,7 @@ class hr_payslip(osv.osv): dates = prev_bounds(slip.date) calendar_id = slip.employee_id.contract_id.working_hours.id if not calendar_id: - raise osv.except_osv(_('Error !'), _("Please define working schedule on %s's contract") % (employee_id.name)) + raise osv.except_osv(_('Error !'), _("Please define working schedule on %s's contract") % (slip.employee_id.name)) week_days = {"0": "mon", "1": "tue", "2": "wed","3": "thu", "4": "fri", "5": "sat", "6": "sun"} wk_days = {} week_ids = resource_attendance_pool.search(cr, uid, [('calendar_id', '=', calendar_id)], context=context) @@ -908,7 +909,7 @@ class hr_payslip(osv.osv): elif salary_rule.amount_type == 'fix': value = salary_rule.amount * days elif salary_rule.amount_type=='code': - localdict = {'basic':amt, 'employee':slip.employee_id, 'contract':contract} + localdict = {'basic': amt, 'employee': slip.employee_id, 'contract': contract} exec salary_rule.python_compute in localdict value = localdict['result'] * days res['amount'] = salary_rule.amount @@ -938,6 +939,7 @@ class hr_payslip(osv.osv): holiday_pool = self.pool.get('hr.holidays') sequence_obj = self.pool.get('ir.sequence') empolyee_obj = self.pool.get('hr.employee') + contract_obj = self.pool.get('hr.contract') resource_attendance_pool = self.pool.get('resource.calendar.attendance') if context is None: @@ -954,144 +956,155 @@ class hr_payslip(osv.osv): employee_id = empolyee_obj.browse(cr, uid, employee_id, context=context) ttyme = datetime.fromtimestamp(time.mktime(time.strptime(ddate, "%Y-%m-%d"))) if not contract_id: + update['value'].update({'struct_id': False}) contracts = self.get_contract(cr, uid, employee_id, ddate, context=context) - if not contracts.get('id', False): - update['value'].update({ - 'basic_amount': 0.0, - 'basic_before_leaves': 0.0, - 'name':'Salary Slip of %s for %s' % (employee_id.name, tools.ustr(ttyme.strftime('%B-%Y'))), - 'contract_id':False, - 'company_id':employee_id.company_id.id - }) - return update - contract = employee_id.contract_id else: - contract = self.pool.get('hr.contract').browse(cr, uid, contract_id, context=context) - - function = contract.struct_id.id - sal_structure = [] - if function: - sal_structure = self._get_parent_structure(cr, uid, [function], context=context) - - lines = [] - rules = [] - for struct in sal_structure: - lines = func_pool.browse(cr, uid, struct, context=context).rule_ids - for rl in lines: - if rl.child_ids: - for r in rl.child_ids: - lines.append(r) - rules.append(rl) - ad = [] - total = 0.0 - obj = {'basic': contract.wage} - for line in rules: - cd = line.code.lower() - obj[cd] = line.amount or 0.0 - - for line in rules: - if line.category_id.code in ad: + contracts = [contract_obj.read(cr, uid, contract_id, ['wage', 'struct_id', 'id'], context=context)] + update['value'].update({ + 'struct_id': contracts[0].get('struct_id', False), + 'contract_id': contract_id + }) + if not contracts: + update['value'].update({ + 'basic_amount': 0.0, + 'basic_before_leaves': 0.0, + 'name':'Salary Slip of %s for %s' % (employee_id.name, tools.ustr(ttyme.strftime('%B-%Y'))), + 'contract_id': False, + 'struct_id': False, + 'company_id':employee_id.company_id.id + }) + return update + final_total = 0.0 + all_basic = 0.0 + for contract in contracts: + if contract.get('id', False) == False: continue - ad.append(line.category_id.code) - cd = line.category_id.code.lower() - calculate = False - try: - exp = line.conditions - calculate = eval(exp, obj) - except Exception, e: - raise osv.except_osv(_('Variable Error !'), _('Variable Error: %s ') % (e)) + contract_id = contract.get('id') + contract_id = self.pool.get('hr.contract').browse(cr, uid, contract_id, context=context) + function = contract_id.struct_id.id + sal_structure = [] + if function: + sal_structure = self._get_parent_structure(cr, uid, [function], context=context) + lines = [] + rules = [] + for struct in sal_structure: + lines = func_pool.browse(cr, uid, struct, context=context).rule_ids + for rl in lines: + if rl.child_ids: + for r in rl.child_ids: + lines.append(r) + rules.append(rl) + ad = [] + total = 0.0 + obj = {'basic': contract_id.wage} + for line in rules: + cd = line.code.lower() + obj[cd] = line.amount or 0.0 - if not calculate: - continue - - value = 0.0 - base = line.computational_expression - try: - amt = eval(base, obj) - except Exception, e: - raise osv.except_osv(_('Variable Error !'), _('Variable Error: %s ') % (e)) - if line.amount_type == 'per': + for line in rules: + if line.category_id.code in ad: + continue + ad.append(line.category_id.code) + cd = line.category_id.code.lower() + calculate = False try: - if line.child_depend == False: - if line.parent_rule_id: - for rul in [line.parent_rule_id]: - val = rul.amount * amt - amt = val - value = line.amount * amt - if line.condition_select == 'range': - if line.condition_range_min or line.condition_range_max: - if ((value < line.condition_range_min) or (value > line.condition_range_max)): - value = 0.0 - else: - value = value - else: - value = value + exp = line.conditions + calculate = eval(exp, obj) except Exception, e: raise osv.except_osv(_('Variable Error !'), _('Variable Error: %s ') % (e)) - elif line.amount_type == 'fix': - if line.child_depend == False: - if line.parent_rule_id: - for rul in [line.parent_rule_id]: - value = value - if line.condition_select == 'range': - if line.condition_range_min or line.condition_range_max: - if ((line.amount < line.condition_range_min) or (line.amount > line.condition_range_max)): - value = value - else: - value = line.amount - else: - value = line.amount + if not calculate: + continue - elif line.amount_type=='code': - localdict = {'basic':amt, 'employee':employee_id, 'contract':contract} - exec line.python_compute in localdict - val = localdict['result'] - if line.child_depend == False: - if line.parent_rule_id: - for rul in [line.parent_rule_id]: - value = val - if line.condition_select == 'range': - if line.condition_range_min or line.condition_range_max: - if ((line.amount < line.condition_range_min) or (line.amount > line.condition_range_max)): - value = value + value = 0.0 + base = line.computational_expression + try: + amt = eval(base, obj) + except Exception, e: + raise osv.except_osv(_('Variable Error !'), _('Variable Error: %s ') % (e)) + if line.amount_type == 'per': + try: + if line.child_depend == False: + if line.parent_rule_id: + for rul in [line.parent_rule_id]: + val = rul.amount * amt + amt = val + value = line.amount * amt + if line.condition_select == 'range': + if line.condition_range_min or line.condition_range_max: + if ((value < line.condition_range_min) or (value > line.condition_range_max)): + value = 0.0 + else: + value = value else: + value = value + except Exception, e: + raise osv.except_osv(_('Variable Error !'), _('Variable Error: %s ') % (e)) + + elif line.amount_type == 'fix': + if line.child_depend == False: + if line.parent_rule_id: + for rul in [line.parent_rule_id]: + value = value + if line.condition_select == 'range': + if line.condition_range_min or line.condition_range_max: + if ((line.amount < line.condition_range_min) or (line.amount > line.condition_range_max)): + value = value + else: + value = line.amount + else: + value = line.amount + + elif line.amount_type=='code': + localdict = {'basic':amt, 'employee':employee_id, 'contract':contract} + exec line.python_compute in localdict + val = localdict['result'] + if line.child_depend == False: + if line.parent_rule_id: + for rul in [line.parent_rule_id]: value = val + if line.condition_select == 'range': + if line.condition_range_min or line.condition_range_max: + if ((line.amount < line.condition_range_min) or (line.amount > line.condition_range_max)): + value = value + else: + value = val + else: + value = val + total += value + vals = { + 'category_id': line.category_id.id, + 'name': line.name, + 'sequence': line.sequence, + 'type': line.type.id, + 'code': line.code, + 'amount_type': line.amount_type, + 'amount': line.amount, + 'total': value, + 'employee_id': employee_id.id, + 'base': line.computational_expression + } + if line.appears_on_payslip: + if line.condition_range_min or line.condition_range_max: + if not ((value < line.condition_range_min) or (value > line.condition_range_max)): + update['value']['line_ids'].append(vals) else: - value = val - - total += value - vals = { - 'category_id': line.category_id.id, - 'name': line.name, - 'sequence': line.sequence, - 'type': line.type.id, - 'code': line.code, - 'amount_type': line.amount_type, - 'amount': line.amount, - 'total': value, - 'employee_id': employee_id.id, - 'base': line.computational_expression - } - if line.appears_on_payslip: - if line.condition_range_min or line.condition_range_max: - if not ((value < line.condition_range_min) or (value > line.condition_range_max)): update['value']['line_ids'].append(vals) - else: - update['value']['line_ids'].append(vals) - basic = contract.wage - number = sequence_obj.get(cr, uid, 'salary.slip') - update['value'].update({ -# 'struct_id': function, - 'number': number, - 'basic_amount': basic, - 'basic_before_leaves': basic, - 'total_pay': basic + total, - 'name': 'Salary Slip of %s for %s' % (employee_id.name, tools.ustr(ttyme.strftime('%B-%Y'))), - 'contract_id': contract.id, - 'company_id': employee_id.company_id.id - }) + basic = contract_id.wage + all_basic += basic + final_total += basic + total + number = sequence_obj.get(cr, uid, 'salary.slip') + update['value'].update({ + # 'struct_id': function, + 'number': number, + 'basic_amount': all_basic, + 'basic_before_leaves': basic, + 'total_pay': final_total, + 'name': 'Salary Slip of %s for %s' % (employee_id.name, tools.ustr(ttyme.strftime('%B-%Y'))), + # 'contract_id': contract_id.id, + 'company_id': employee_id.company_id.id + }) basic_before_leaves = update['value']['basic_amount'] total_before_leaves = update['value']['total_pay'] @@ -1113,7 +1126,7 @@ class hr_payslip(osv.osv): off_days += get_days(1, dates[1].day, dates[1].month, dates[1].year, days_arr[dy]) total_off = off_days working_day = dates[1].day - total_off - perday = working_day and basic / working_day or 0.0 +# perday = working_day and basic / working_day or 0.0 total = 0.0 leave = 0.0 leave_ids = self._get_leaves(cr, uid, ddate, employee_id, context) @@ -1187,7 +1200,7 @@ class hr_payslip(osv.osv): value = salary_rule.amount * days elif salary_rule.amount_type=='code': - localdict = {'basic':amt, 'employee':employee_id, 'contract':contract} + localdict = {'basic':amt, 'employee':employee_id, 'contract':contract_id} exec salary_rule.python_compute in localdict val = localdict['result'] * days if salary_rule.child_depend == False: @@ -1326,7 +1339,7 @@ class hr_salary_rule(osv.osv): 'gratuity':fields.boolean('Use for Gratuity ?', required=False), 'condition_select': fields.selection([('range', 'Range'), ('python', 'Python Expression')], "Condition based on"), 'computational_expression':fields.text('Computational Expression', required=True, readonly=False, help='This will use to computer the % fields values, in general its on basic, but You can use all heads code field in small letter as a variable name i.e. hra, ma, lta, etc...., also you can use, static varible basic'), - 'conditions':fields.char('Condition', size=1024, required=True, readonly=False, help='Applied this head for calculation if condition is true'), + 'conditions':fields.char('Condition', size=1024, required=True, readonly=False, help='Applied this rule for calculation if condition is true.You can specify condition like basic > 1000.'), 'sequence': fields.integer('Sequence', required=True, help='Use to arrange calculation sequence'), 'active':fields.boolean('Active', help="If the active field is set to false, it will allow you to hide the salary rule without removing it."), 'python_compute':fields.text('Python Code'), @@ -1348,6 +1361,7 @@ class hr_salary_rule(osv.osv): 'company_id': lambda self, cr, uid, context: \ self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id, + 'condition_select': 'python', } # def _execute_function(self, cr, uid, id, value, context=None): diff --git a/addons/hr_payroll/hr_payroll_view.xml b/addons/hr_payroll/hr_payroll_view.xml index e7a51a4ae64..57ab584d34a 100644 --- a/addons/hr_payroll/hr_payroll_view.xml +++ b/addons/hr_payroll/hr_payroll_view.xml @@ -212,9 +212,8 @@ - + - @@ -283,21 +282,21 @@ - + - + - + - +