[MERGE] Merge from trunk-payroll main project branch

bzr revid: mra@mra-laptop-20110512050150-m4qysq80qgo48fp1
This commit is contained in:
Mustufa Rangwala 2011-05-12 10:31:50 +05:30
commit ed0311cb56
8 changed files with 335 additions and 329 deletions

View File

@ -142,8 +142,8 @@ class hr_employee(osv.osv):
'work_email': fields.char('Work E-mail', size=240),
'work_location': fields.char('Office Location', size=32),
'notes': fields.text('Notes'),
'parent_id': fields.many2one('hr.employee', 'Manager'),
'category_ids': fields.many2many('hr.employee.category', 'employee_category_rel', 'emp_id', 'category_id', 'Category'),
'parent_id': fields.many2one('hr.employee', 'Manager'),
'category_ids': fields.many2many('hr.employee.category', 'employee_category_rel', 'emp_id', 'category_id', 'Categories'),
'child_ids': fields.one2many('hr.employee', 'parent_id', 'Subordinates'),
'resource_id': fields.many2one('resource.resource', 'Resource', ondelete='cascade', required=True),
'coach_id': fields.many2one('hr.employee', 'Coach'),
@ -231,7 +231,7 @@ class res_users(osv.osv):
except:
# Tolerate a missing shortcut. See product/product.py for similar code.
logging.getLogger('orm').debug('Skipped meetings shortcut for user "%s"', data.get('name','<new'))
return user_id
res_users()

View File

@ -110,6 +110,7 @@
<filter icon="terp-personal+" domain="[('department_id','=',context.get('department_id',False))]" string="My Departments Employee"/>
</field>
<field name="job_id" widget="selection"/>
<field name="category_ids" select="1" groups="base.group_extended"/>
<field name="parent_id"/>
<newline />
<group expand="0" string="Group By...">
@ -157,12 +158,12 @@
<menuitem action="open_view_employee_list_my" id="menu_open_view_employee_list_my" sequence="3" parent="menu_hr_main"/>
<record id="ir_ui_view_sc_employee" model="ir.ui.view_sc">
<field name="name">Employees</field>
<field name="resource">ir.ui.menu</field>
<field name="user_id" ref="base.user_root"/>
<field name="res_id" ref="hr.menu_open_view_employee_list_my"/>
</record>
<record id="ir_ui_view_sc_employee" model="ir.ui.view_sc">
<field name="name">Employees</field>
<field name="resource">ir.ui.menu</field>
<field name="user_id" ref="base.user_root"/>
<field name="res_id" ref="hr.menu_open_view_employee_list_my"/>
</record>
<!--
=======================
@ -280,7 +281,7 @@
<field eval="True" name="object"/>
</record>
<menuitem action="open_view_categ_tree"
<menuitem action="open_view_categ_tree"
id="menu_view_employee_category_tree" parent="hr.menu_view_employee_category_form"/>
<record id="view_hr_job_form" model="ir.ui.view">

View File

@ -164,30 +164,28 @@ class contrib_register(osv.osv):
contrib_register()
class hr_salary_head(osv.osv):
class hr_salary_rule_category(osv.osv):
"""
HR Salary Head
HR Salary Rule Category
"""
_name = 'hr.salary.head'
_description = 'Salary Head'
_name = 'hr.salary.rule.category'
_description = 'Salary Rule Category'
_columns = {
'name':fields.char('Name', size=64, required=True, readonly=False),
'code':fields.char('Code', size=64, required=True, readonly=False),
'parent_id':fields.many2one('hr.salary.head', 'Parent', help="Linking a salary head to its parent is used only for the reporting purpose."),
'parent_id':fields.many2one('hr.salary.rule.category', 'Parent', help="Linking a salary category to its parent is used only for the reporting purpose."),
'note': fields.text('Description'),
'company_id':fields.many2one('res.company', 'Company', required=False),
'sequence': fields.integer('Sequence', required=True, help='Display sequence order'),
}
_defaults = {
'company_id': lambda self, cr, uid, context: \
self.pool.get('res.users').browse(cr, uid, uid,
context=context).company_id.id,
'sequence': 5
}
hr_salary_head()
hr_salary_rule_category()
class one2many_mod2(fields.one2many):
@ -212,13 +210,13 @@ class hr_payslip(osv.osv):
_name = 'hr.payslip'
_description = 'Pay Slip'
def _get_lines_salary_head(self, cr, uid, ids, field_names, arg=None, context=None):
def _get_lines_salary_rule_category(self, cr, uid, ids, field_names, arg=None, context=None):
result = {}
if not ids: return result
cr.execute('''SELECT pl.slip_id, pl.id FROM hr_payslip_line AS pl \
LEFT JOIN hr_salary_head AS sh on (pl.category_id = sh.id) \
LEFT JOIN hr_salary_rule_category AS sh on (pl.category_id = sh.id) \
WHERE pl.slip_id in %s \
GROUP BY pl.slip_id, sh.sequence, pl.sequence, pl.id ORDER BY sh.sequence, pl.sequence''',(tuple(ids),))
GROUP BY pl.slip_id, pl.sequence, pl.id ORDER BY pl.sequence''',(tuple(ids),))
res = cr.fetchall()
for r in res:
result.setdefault(r[0], [])
@ -247,13 +245,14 @@ class hr_payslip(osv.osv):
\n* If the salary is paid then state is set to \'Paid Salary\'.\
\n* The \'Reject\' state is used when user cancel payslip.'),
# 'line_ids': fields.one2many('hr.payslip.line', 'slip_id', 'Payslip Line', required=False, readonly=True, states={'draft': [('readonly', False)]}),
'line_ids': one2many_mod2('hr.payslip.line', 'slip_id', 'Payslip Line',readonly=True, states={'draft':[('readonly',False)]}),
'line_ids': one2many_mod2('hr.payslip.line', 'slip_id', 'Payslip Line',readonly=True),
'company_id': fields.many2one('res.company', 'Company', required=False, readonly=True, states={'draft': [('readonly', False)]}),
'worked_days_line_ids': fields.one2many('hr.payslip.worked_days', 'payslip_id', 'Payslip Worked Days', required=False, readonly=True, states={'draft': [('readonly', False)]}),
'input_line_ids': fields.one2many('hr.payslip.input', 'payslip_id', 'Payslip Inputs', required=False, readonly=True, states={'draft': [('readonly', False)]}),
'paid': fields.boolean('Made Payment Order ? ', required=False, readonly=True, states={'draft': [('readonly', False)]}),
'note': fields.text('Description'),
'contract_id': fields.many2one('hr.contract', 'Contract', required=False, readonly=True, states={'draft': [('readonly', False)]}),
'details_by_salary_head': fields.function(_get_lines_salary_head, method=True, type='one2many', relation='hr.payslip.line', string='Details by Salary Head'),
'details_by_salary_rule_category': fields.function(_get_lines_salary_rule_category, method=True, type='one2many', relation='hr.payslip.line', string='Details by Salary Rule Category'),
'credit_note': fields.boolean('Credit Note', help="Indicates this payslip has a refund of another"),
}
_defaults = {
@ -417,7 +416,7 @@ class hr_payslip(osv.osv):
self.write(cr, uid, [payslip.id], {'line_ids': lines, 'number': number,}, context=context)
return True
def get_input_lines(self, cr, uid, contract_ids, date_from, date_to, context=None):
def get_worked_day_lines(self, cr, uid, contract_ids, date_from, date_to, context=None):
"""
@param contract_ids: list of contract id
@return: returns a list of dict containing the input that should be applied for the given contract between date_from and date_to
@ -474,21 +473,46 @@ class hr_payslip(osv.osv):
res += [attendances] + leaves
return res
def get_inputs(self, cr, uid, contract_ids, date_from, date_to, context=None):
res = []
contract_obj = self.pool.get('hr.contract')
rule_obj = self.pool.get('hr.salary.rule')
structure_ids = contract_obj.get_all_structures(cr, uid, contract_ids, context=context)
rule_ids = self.pool.get('hr.payroll.structure').get_all_rules(cr, uid, structure_ids, context=context)
sorted_rule_ids = [id for id, sequence in sorted(rule_ids, key=lambda x:x[1])]
for contract in contract_obj.browse(cr, uid, contract_ids, context=context):
for rule in rule_obj.browse(cr, uid, sorted_rule_ids, context=context):
if rule.input_ids:
for input in rule.input_ids:
inputs = {
'name': input.name,
'code': input.code,
'contract_id': contract.id,
}
res += [inputs]
return res
def get_payslip_lines(self, cr, uid, contract_ids, payslip_id, context):
def _sum_salary_head(localdict, head, amount):
if head.parent_id:
localdict = _sum_salary_head(localdict, head.parent_id, amount)
localdict['heads'][head.code] = head.code in localdict['heads'] and localdict['heads'][head.code] + amount or amount
def _sum_salary_rule_category(localdict, category, amount):
if category.parent_id:
localdict = _sum_salary_rule_category(localdict, category.parent_id, amount)
localdict['categories'][category.code] = category.code in localdict['categories'] and localdict['categories'][category.code] + amount or amount
return localdict
#we keep a dict with the result because a value can be overwritten by another rule with the same code
result_dict = {}
blacklist = []
obj_rule = self.pool.get('hr.salary.rule')
payslip = self.pool.get('hr.payslip').browse(cr, uid, payslip_id, context=context)
worked_days = {}
for worked_days_line in payslip.worked_days_line_ids:
worked_days[worked_days_line.code] = worked_days_line
inputs = {}
for input_line in payslip.input_line_ids:
worked_days[input_line.code] = input_line
localdict = {'rules': {}, 'heads': {}, 'payslip': payslip, 'worked_days': worked_days}
inputs[input_line.code] = input_line
localdict = {'categories': {}, 'payslip': payslip, 'worked_days': worked_days, 'inputs': inputs}
#get the ids of the structures on the contracts and their parent id as well
structure_ids = self.pool.get('hr.contract').get_all_structures(cr, uid, contract_ids, context=context)
#get the rules of the structure and thier children
@ -499,19 +523,19 @@ class hr_payslip(osv.osv):
for contract in self.pool.get('hr.contract').browse(cr, uid, contract_ids, context=context):
employee = contract.employee_id
localdict.update({'employee': employee, 'contract': contract})
for rule in self.pool.get('hr.salary.rule').browse(cr, uid, sorted_rule_ids, context=context):
for rule in obj_rule.browse(cr, uid, sorted_rule_ids, context=context):
key = rule.code + '-' + str(contract.id)
localdict['result'] = None
#check if the rule can be applied
if self.pool.get('hr.salary.rule').satisfy_condition(cr, uid, rule.id, localdict, context=context) and rule.id not in blacklist:
if obj_rule.satisfy_condition(cr, uid, rule.id, localdict, context=context) and rule.id not in blacklist:
#compute the amount of the rule
amount = self.pool.get('hr.salary.rule').compute_rule(cr, uid, rule.id, localdict, context=context)
amount = obj_rule.compute_rule(cr, uid, rule.id, localdict, context=context)
#check if there is already a rule computed with that code
previous_amount = rule.code in localdict['rules'] and localdict['rules'][rule.code] or 0.0
previous_amount = rule.code in localdict and localdict[rule.code] or 0.0
#set/overwrite the amount computed for this rule in the localdict
localdict['rules'][rule.code] = amount
#sum the amount for its salary head
localdict = _sum_salary_head(localdict, rule.category_id, amount - previous_amount)
localdict[rule.code] = amount
#sum the amount for its salary category
localdict = _sum_salary_rule_category(localdict, rule.category_id, amount - previous_amount)
#create/overwrite the rule in the temporary results
result_dict[key] = {
'salary_rule_id': rule.id,
@ -534,29 +558,37 @@ class hr_payslip(osv.osv):
'register_id': rule.register_id.id,
'total': amount,
'employee_id': contract.employee_id.id,
'quantity': rule.quantity,
}
else:
#blacklist this rule and its children
blacklist += [id for id, seq in self.pool.get('hr.salary.rule')._recursive_search_of_rules(cr, uid, [rule], context=context)]
result = [value for code, value in result_dict.items()]
return result
def onchange_employee_id(self, cr, uid, ids, date_from, date_to, employee_id=False, contract_id=False, context=None):
empolyee_obj = self.pool.get('hr.employee')
contract_obj = self.pool.get('hr.contract')
worked_days_obj = self.pool.get('hr.payslip.worked_days')
input_obj = self.pool.get('hr.payslip.input')
if context is None:
context = {}
#delete old worked days lines
old_worked_days_ids = ids and worked_days_obj.search(cr, uid, [('payslip_id', '=', ids[0])], context=context) or False
if old_worked_days_ids:
worked_days_obj.unlink(cr, uid, old_worked_days_ids, context=context)
#delete old input lines
old_input_ids = ids and input_obj.search(cr, uid, [('payslip_id', '=', ids[0])], context=context) or False
if old_input_ids:
input_obj.unlink(cr, uid, old_input_ids, context=context)
#defaults
res = {'value':{
'line_ids':[],
#'details_by_salary_head':[], TODO put me back
'name':'',
'contract_id': False,
'struct_id': False,
@ -592,8 +624,10 @@ class hr_payslip(osv.osv):
return res
#computation of the salary input
input_line_ids = self.get_input_lines(cr, uid, contract_ids, date_from, date_to, context=context)
worked_days_line_ids = self.get_worked_day_lines(cr, uid, contract_ids, date_from, date_to, context=context)
input_line_ids = self.get_inputs(cr, uid, contract_ids, date_from, date_to, context=context)
res['value'].update({
'worked_days_line_ids': worked_days_line_ids,
'input_line_ids': input_line_ids,
})
return res
@ -613,6 +647,28 @@ class hr_payslip(osv.osv):
hr_payslip()
class hr_payslip_worked_days(osv.osv):
'''
Payslip Worked Days
'''
_name = 'hr.payslip.worked_days'
_description = 'Payslip Worked Days'
_columns = {
'name': fields.char('Description', size=256, required=True),
'payslip_id': fields.many2one('hr.payslip', 'Pay Slip', required=True),
'sequence': fields.integer('Sequence', required=True,),
'code': fields.char('Code', size=52, required=True, help="The code that can be used in the salary rules"),
'number_of_days': fields.float('Number of Days'),
'number_of_hours': fields.float('Number of Hours'),
'contract_id': fields.many2one('hr.contract', 'Contract', required=True, help="The contract for which applied this input"),
}
_order = 'payslip_id, sequence'
_defaults = {
'sequence': 10,
}
hr_payslip_worked_days()
class hr_payslip_input(osv.osv):
'''
Payslip Input
@ -625,13 +681,13 @@ class hr_payslip_input(osv.osv):
'payslip_id': fields.many2one('hr.payslip', 'Pay Slip', required=True),
'sequence': fields.integer('Sequence', required=True,),
'code': fields.char('Code', size=52, required=True, help="The code that can be used in the salary rules"),
'number_of_days': fields.float('Number of Days'),
'number_of_hours': fields.float('Number of Hours'),
'quantity': fields.float('Quantity', help="It is used in computation. For e.g. A rule for sales having 1% commission of basic salary for per product can defined in expression like result = inputs['S-ASUS']['qunatity']*contract.wage*0.01."),
'contract_id': fields.many2one('hr.contract', 'Contract', required=True, help="The contract for which applied this input"),
}
_order = 'payslip_id,sequence'
_order = 'payslip_id, sequence'
_defaults = {
'sequence': 10,
'quantity': 0.0,
}
hr_payslip_input()
@ -640,15 +696,16 @@ class hr_salary_rule(osv.osv):
_name = 'hr.salary.rule'
_columns = {
'name':fields.char('Name', size=256, required=True, readonly=False),
'code':fields.char('Code', size=64, required=True),
'code':fields.char('Code', size=64, required=True, help="The code of salary rules can be used as reference in computation of other rules. In that case, it is case sensitive."),
'sequence': fields.integer('Sequence', required=True, help='Use to arrange calculation sequence'),
'category_id':fields.many2one('hr.salary.head', 'Salary Head', required=True),
'quantity': fields.char('Quantity', size=256, help="It is used in computation for percentage and fixed amount.For e.g. A rule for Meal Voucher having fixed amount of 1€ per worked day can have its quantity defined in expression like worked_days['WORK100']['number_of_days']."),
'category_id':fields.many2one('hr.salary.rule.category', 'Category', required=True),
'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."),
'appears_on_payslip': fields.boolean('Appears on Payslip', help="Used for the display of rule on payslip"),
'parent_rule_id':fields.many2one('hr.salary.rule', 'Parent Salary Rule', select=True),
'company_id':fields.many2one('res.company', 'Company', required=False),
'condition_select': fields.selection([('none', 'Always True'),('range', 'Range'), ('python', 'Python Expression')], "Condition Based on", required=True),
'condition_range':fields.char('Range Based on',size=1024, 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'),#old name = conputional expression
'condition_range':fields.char('Range Based on',size=1024, readonly=False, help='This will use to computer the % fields values, in general its on basic, but You can use all categories code field in small letter as a variable name i.e. hra, ma, lta, etc...., also you can use, static varible basic'),
'condition_python':fields.text('Python Condition', required=True, readonly=False, help='Applied this rule for calculation if condition is true. You can specify condition like basic > 1000.'),#old name = conditions
'condition_range_min': fields.float('Minimum Range', required=False, help="The minimum amount, applied for this rule."),
'condition_range_max': fields.float('Maximum Range', required=False, help="The maximum amount, applied for this rule."),
@ -660,7 +717,7 @@ class hr_salary_rule(osv.osv):
'amount_fix': fields.float('Fixed Amount', digits_compute=dp.get_precision('Account'),),
'amount_percentage': fields.float('Percentage (%)', digits_compute=dp.get_precision('Account'), help='For example, enter 50.0 to apply a percentage of 50%'),
'amount_python_compute':fields.text('Python Code'),
'amount_percentage_base':fields.char('Percentage based on',size=1024, required=False, readonly=False, help='result will be affected to a variable'), #old name = expressiont
'amount_percentage_base':fields.char('Percentage based on',size=1024, required=False, readonly=False, help='result will be affected to a variable'),
'child_ids':fields.one2many('hr.salary.rule', 'parent_rule_id', 'Child Salary Rule'),
'register_id':fields.property(
'hr.contribution.register',
@ -672,6 +729,7 @@ class hr_salary_rule(osv.osv):
help="Contribution register based on company",
required=False
),
'input_ids': fields.one2many('hr.rule.input', 'input_id', 'Inputs'),
'note':fields.text('Description'),
}
_defaults = {
@ -681,9 +739,10 @@ class hr_salary_rule(osv.osv):
# payslip: hr.payslip object
# employee: hr.employee object
# contract: hr.contract object
# rules: dictionary containing the previsouly computed rules. Keys are the rule codes.
# heads: dictionary containing the computed heads (sum of amount of all rules belonging to that head). Keys are the head codes.
# rules: rules code (previously computed)
# categories: dictionary containing the computed salary rule categories (sum of amount of all rules belonging to that category). Keys are the category codes.
# worked_days: dictionary containing the computed worked days. Keys are the worked days codes.
# inputs: dictionary containing the computed inputs. Keys are the inputs codes.
# Note: returned value have to be set in the variable 'result'
@ -695,13 +754,14 @@ result = contract.wage * 0.10''',
# payslip: hr.payslip object
# employee: hr.employee object
# contract: hr.contract object
# rules: dictionary containing the previsouly computed rules. Keys are the rule codes.
# heads: dictionary containing the computed heads (sum of amount of all rules belonging to that head). Keys are the head codes.
# rules: rules code (previously computed)
# categories: dictionary containing the computed salary rule categories (sum of amount of all rules belonging to that category). Keys are the category codes.
# worked_days: dictionary containing the computed worked days. Keys are the worked days codes.
# inputs: dictionary containing the computed inputs. Keys are the inputs codes.
# Note: returned value have to be set in the variable 'result'
result = rules['NET'] > heads['NET'] * 0.10''',
result = rules['NET'] > categories['NET'] * 0.10''',
'condition_range': 'contract.wage',
'sequence': 5,
'appears_on_payslip': True,
@ -713,6 +773,7 @@ result = rules['NET'] > heads['NET'] * 0.10''',
'amount_select': 'fix',
'amount_fix': 0.0,
'amount_percentage': 0.0,
'quantity': '1',
}
def _recursive_search_of_rules(self, cr, uid, rule_ids, context=None):
@ -735,12 +796,16 @@ result = rules['NET'] > heads['NET'] * 0.10''',
"""
rule = self.browse(cr, uid, rule_id, context=context)
if rule.amount_select == 'fix':
return rule.amount_fix
try:
return rule.amount_fix * eval(rule.quantity, localdict)
except:
raise osv.except_osv(_('Error'), _('Wrong quantity defined for salary rule %s (%s)')% (rule.name, rule.code))
elif rule.amount_select == 'percentage':
try:
return rule.amount_percentage * eval(rule.amount_percentage_base, localdict) / 100
amount = rule.amount_percentage * eval(rule.amount_percentage_base, localdict) / 100
return amount * eval(rule.quantity, localdict)
except:
raise osv.except_osv(_('Error'), _('Wrong percentage base defined for salary rule %s (%s)')% (rule.name, rule.code))
raise osv.except_osv(_('Error'), _('Wrong percentage base or quantity defined for salary rule %s (%s)')% (rule.name, rule.code))
else:
try:
eval(rule.amount_python_compute, localdict, mode='exec', nocopy=True)
@ -773,6 +838,21 @@ result = rules['NET'] > heads['NET'] * 0.10''',
hr_salary_rule()
class hr_rule_input(osv.osv):
'''
Salary Rule Input
'''
_name = 'hr.rule.input'
_description = 'Salary Rule Input'
_columns = {
'name': fields.char('Description', size=256, required=True),
'code': fields.char('Code', size=52, required=True, help="The code that can be used in the salary rules"),
'input_id': fields.many2one('hr.salary.rule', 'Salary Rule Input', required=True)
}
hr_rule_input()
class hr_payslip_line(osv.osv):
'''
Payslip Line

View File

@ -2,164 +2,36 @@
<openerp>
<data noupdate="1">
<record id="BASIC" model="hr.salary.head">
<record id="BASIC" model="hr.salary.rule.category">
<field name="name">Basic</field>
<field name="code">BASIC</field>
</record>
<record id="ALW" model="hr.salary.head">
<record id="ALW" model="hr.salary.rule.category">
<field name="name">Allowance</field>
<field name="code">ALW</field>
</record>
<record id="DED" model="hr.salary.head">
<record id="DED" model="hr.salary.rule.category">
<field name="name">Deduction</field>
<field name="code">DED</field>
</record>
<record id="GROSS" model="hr.salary.head">
<record id="GROSS" model="hr.salary.rule.category">
<field name="name">Gross</field>
<field name="code">GROSS</field>
</record>
<record id="NET" model="hr.salary.head">
<record id="NET" model="hr.salary.rule.category">
<field name="name">Net</field>
<field name="code">NET</field>
</record>
<record id="COMP" model="hr.salary.head">
<record id="COMP" model="hr.salary.rule.category">
<field name="name">Company Contribution</field>
<field name="code">COMP</field>
</record>
<!-- <record id="HRA" model="hr.salary.head">
<field name="code">HRA</field>
<field name="parent_id" ref="AL"/>
<field name="name">House Rent Allowance</field>
<field name="sequence" eval="5"/>
</record>
<record id="CA" model="hr.salary.head">
<field name="code">CA</field>
<field name="parent_id" ref="AL"/>
<field name="name">Conveyance Allowance</field>
<field name="sequence" eval="10"/>
</record>
<record id="MA" model="hr.salary.head">
<field name="code">MA</field>
<field name="parent_id" ref="AL"/>
<field name="name">Medical Allowance</field>
<field name="sequence" eval="15"/>
</record>
<record id="TELA" model="hr.salary.head">
<field name="code">TELA</field>
<field name="parent_id" ref="AL"/>
<field name="name">Telephone Allowance</field>
<field name="sequence" eval="20"/>
</record>
<record id="LTA" model="hr.salary.head">
<field name="code">LTA</field>
<field name="parent_id" ref="AL"/>
<field name="name">Leave Travel Allowance</field>
<field name="sequence" eval="25"/>
</record>
<record id="NA" model="hr.salary.head">
<field name="code">NA</field>
<field name="parent_id" ref="AL"/>
<field name="name">Newspaper Allowance</field>
<field name="sequence" eval="30"/>
</record>
<record id="TA" model="hr.salary.head">
<field name="code">TA</field>
<field name="parent_id" ref="AL"/>
<field name="name">Traveling Allowance</field>
<field name="sequence" eval="35"/>
</record>
<record id="FA" model="hr.salary.head">
<field name="code">FA</field>
<field name="parent_id" ref="AL"/>
<field name="name">Food Allowance</field>
<field name="sequence" eval="40"/>
</record>
<record id="DA" model="hr.salary.head">
<field name="code">DA</field>
<field name="parent_id" ref="AL"/>
<field name="name">Dearness Allowance</field>
<field name="sequence" eval="45"/>
</record>
<record id="PF" model="hr.salary.head">
<field name="code">PF</field>
<field name="parent_id" ref="DED"/>
<field name="name">Provident Fund</field>
<field name="sequence" eval="50"/>
</record>
<record id="PT" model="hr.salary.head">
<field name="code">PT</field>
<field name="parent_id" ref="DED"/>
<field name="name">Professional Tax</field>
<field name="sequence" eval="55"/>
</record>
<record id="WF" model="hr.salary.head">
<field name="code">WF</field>
<field name="parent_id" ref="DED"/>
<field name="name">Welfare</field>
<field name="sequence" eval="60"/>
</record>
<record id="TDS" model="hr.salary.head">
<field name="code">TDS</field>
<field name="parent_id" ref="DED"/>
<field name="name">Tax Deduct at Source</field>
<field name="sequence" eval="65"/>
</record>
<record id="LWP" model="hr.salary.head">
<field name="code">LWP</field>
<field name="parent_id" ref="DED"/>
<field name="name">Leave without pay</field>
<field name="sequence" eval="70"/>
</record>
<record id="FC" model="hr.salary.head">
<field name="code">FC</field>
<field name="parent_id" ref="DED"/>
<field name="name">Food Coupons</field>
<field name="sequence" eval="75"/>
</record>
<record id="ESI" model="hr.salary.head">
<field name="code">ESI</field>
<field name="parent_id" ref="DED"/>
<field name="name">Employee's State Insurance</field>
<field name="sequence" eval="80"/>
</record>
<record id="NET" model="hr.salary.head">
<field name="code">TP</field>
<field name="parent_id" ref="AL"/>
<field name="name">Total Payment</field>
<field name="sequence" eval="85"/>
</record>
<record id="hr_salary_rule_net" model="hr.salary.rule">
<field name="amount_type">code</field>
<field name="code">NET</field>
<field name="category_id" ref="NET"/>
<field name="name">NET</field>
<field name="sequence" eval="500"/>
<field name="python_compute">total = basic+allowance+deduction</field>
</record>
-->
<record id="hr_rule_basic" model="hr.salary.rule">
<field name="name">Basic</field>
<field name="sequence" eval="1"/>
@ -177,7 +49,7 @@
<field name="category_id" ref="hr_payroll.GROSS"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = heads['BASIC'] + ('ALW' in heads and heads['ALW'] or 0.0)</field>
<field name="amount_python_compute">result = categories['BASIC'] + ('ALW' in categories and categories['ALW'] or 0.0)</field>
</record>
<record id="hr_rule_net" model="hr.salary.rule">
@ -187,7 +59,7 @@
<field name="category_id" ref="hr_payroll.NET"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = heads['BASIC'] + ('ALW' in heads and heads['ALW'] or 0.0) + ('DED' in heads and heads['DED'] or 0.0)</field>
<field name="amount_python_compute">result = categories['BASIC'] + ('ALW' in categories and categories['ALW'] or 0.0) + ('DED' in categories and categories['DED'] or 0.0)</field>
</record>

View File

@ -52,13 +52,38 @@
</record>
<record id="hr_salary_rule_meal_voucher" model="hr.salary.rule">
<field name="amount_select">code</field>
<field name="amount_python_compute">result = worked_days['WORK100']['number_of_days'] * 1</field>
<field name="amount_select">fix</field>
<field eval="1" name="amount_fix"/>
<field name="quantity">worked_days['WORK100']['number_of_days']</field>
<field name="code">MA</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="name">Meal Voucher</field>
<field name="sequence" eval="16"/>
</record>
<record id="hr_salary_rule_sales_commission" model="hr.salary.rule">
<field name="amount_select">code</field>
<field name="code">SALE</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="name">Get 1% of sales</field>
<field name="sequence" eval="17"/>
<field name="amount_python_compute">result = (inputs['S-ASUS']['quantity'] + inputs['S-CHINA']['quantity']) * contract.wage * 0.01</field>
</record>
<!-- Rule Inputs -->
<record id="hr_rule_input_sale_a" model="hr.rule.input">
<field name="code">S-ASUS</field>
<field name="name">Sale to ASUStek</field>
<field name="input_id" ref="hr_salary_rule_sales_commission"/>
</record>
<record id="hr_rule_input_sale_b" model="hr.rule.input">
<field name="code">S-CHINA</field>
<field name="name">Sale to China Export</field>
<field name="input_id" ref="hr_salary_rule_sales_commission"/>
</record>
<!-- Salary Structure -->
<record id="structure_001" model="hr.payroll.structure">

View File

@ -135,15 +135,13 @@
<field name="model">hr.payslip.line</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Salary Structure" editable="bottom">
<tree string="Salary Structure" editable="bottom" colors="blue:total == 0">
<field name="category_id"/>
<field name="employee_id" invisible="1"/>
<field name="sequence" groups="base.group_extended"/>
<field name="name"/>
<field name="code"/>
<field name="amount_select"/>
<field name="amount_fix"/>
<field name="amount_percentage"/>
<field name="total"/>
</tree>
</field>
</record>
@ -188,14 +186,14 @@
<field name="arch" type="xml">
<search string="Search Payslip Lines">
<group col="8" colspan="4">
<field name="name"/>
<field name="code"/>
<field name="name"/>
<field name="code"/>
<field name="slip_id"/>
<field name="amount_select"/>
</group>
<newline/>
<group col="8" colspan="4" expand="0" string="Group By...">
<filter string="Salary Head" icon="terp-camera_test" name="category_id" context="{'group_by':'category_id'}"/>
<filter string="Salary Rule Category" icon="terp-camera_test" name="category_id" context="{'group_by':'category_id'}"/>
<separator orientation="vertical"/>
<filter string="Amount Type" name="amount_select" icon="terp-stock_symbol-selection" context="{'group_by':'amount_select'}"/>
<separator orientation="vertical"/>
@ -242,7 +240,7 @@
<notebook colspan="4">
<page string="Salary Computation" >
<field name="line_ids" colspan="4" nolabel="1">
<tree string="Salary Structure" editable="bottom">
<tree string="Salary Structure" editable="bottom" colors="blue:total == 0">
<field name="name"/>
<field name="code"/>
<field name="category_id"/>
@ -250,37 +248,21 @@
<field name="total"/>
</tree>
<form string="Payslip Line">
<group col="6" colspan="4">
<field name="name" colspan="4" select="1"/>
<group>
<field name="name" select="1"/>
<field name="code" select="1"/>
<field name="appears_on_payslip"/>
<field name="salary_rule_id"/>
</group>
<group col="2" colspan="2">
<separator colspan="4" string="Calculations"/>
<field name="category_id"/>
<field name="amount_select"/>
<field name="amount_fix" attrs="{'readonly':[('amount_select','&lt;&gt;','fix')]}"/>
<field name="amount_percentage" attrs="{'readonly':[('amount_select','=','percentage')]}"/>
<field name="sequence" groups="base.group_extended"/>
<field name="total"/>
<field name="salary_rule_id" groups="base.group_extended"/>
</group>
<group col="2" colspan="2">
<separator colspan="4" string="Company contribution"/>
<field name="company_contrib"/>
</group>
<notebook colspan="4">
<page string="Description">
<separator colspan="4" string="Description"/>
<field name="note" colspan="4" nolabel="1"/>
</page>
</notebook>
</form>
</field>
</page>
<!-- TODO: put me back -->
<page string="Details By Salary Head">
<field name="details_by_salary_head" context="{'group_by':'category_id'}" domain="[('appears_on_payslip', '=', True)]" nolabel="1">
<tree string="Payslip Lines">
<page string="Details By Salary Rule Category">
<field name="details_by_salary_rule_category" context="{'group_by':'category_id'}" domain="[('appears_on_payslip', '=', True)]" nolabel="1">
<tree string="Payslip Lines" colors="blue:total == 0">
<field name="category_id"/>
<field name="name"/>
<field name="code"/>
@ -290,8 +272,8 @@
</page>
<page string="Worked Days">
<field name="input_line_ids" colspan="4" nolabel="1" mode="tree">
<tree editable="bottom">
<field name="worked_days_line_ids" colspan="4" nolabel="1">
<tree string="Worked Days" editable="bottom">
<field name="name"/>
<field name="code"/>
<field name="number_of_days" sum="Total Working Days"/>
@ -299,6 +281,36 @@
<field name="contract_id" groups="base.group_extended"/>
<field name="sequence" invisible="True"/>
</tree>
<form string="Worked Day">
<group>
<field name="name" select="1"/>
<field name="code" select="1"/>
<field name="payslip_id"/>
<field name="sequence" groups="base.group_extended"/>
<field name="number_of_days"/>
<field name="number_of_hours"/>
<field name="contract_id" groups="base.group_extended"/>
</group>
</form>
</field>
<field name="input_line_ids" colspan="4" nolabel="1">
<tree string="Input Data" editable="bottom">
<field name="name"/>
<field name="code"/>
<field name="quantity"/>
<field name="contract_id" groups="base.group_extended"/>
<field name="sequence" invisible="True"/>
</tree>
<form string="Payslip Line">
<group>
<field name="name" select="1"/>
<field name="code" select="1"/>
<field name="payslip_id"/>
<field name="sequence" groups="base.group_extended"/>
<field name="quantity"/>
<field name="contract_id" groups="base.group_extended"/>
</group>
</form>
</field>
</page>
@ -364,64 +376,62 @@
</record>
<menuitem action="action_view_hr_payslip_form" id="menu_department_tree" parent="menu_hr_root_payroll"/>
<!-- Payment Heads -->
<record id="hr_salary_head_form" model="ir.ui.view">
<field name="name">hr.salary.head.form</field>
<field name="model">hr.salary.head</field>
<!-- Salary Category-->
<record id="hr_salary_rule_category_form" model="ir.ui.view">
<field name="name">hr.salary.rule.category.form</field>
<field name="model">hr.salary.rule.category</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Salary Heads">
<form string="Salary Categories">
<group col="3" colspan="6">
<field name="name" select="1"/>
<field name="code" select="1"/>
<field name="parent_id" select="1"/>
<field name="sequence" select="1"/>
</group>
<separator colspan="4" string="Description"/>
<separator colspan="4" string="Notes"/>
<field name="note" colspan="4" nolabel="1"/>
</form>
</field>
</record>
<record id="hr_salary_head_tree" model="ir.ui.view">
<field name="name">hr.salary.head.tree</field>
<field name="model">hr.salary.head</field>
<record id="hr_salary_rule_category_tree" model="ir.ui.view">
<field name="name">hr.salary.rule.category.tree</field>
<field name="model">hr.salary.rule.category</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Salary Heads">
<tree string="Salary Rule Categories">
<field name="name"/>
<field name="sequence"/>
<field name="code"/>
<field name="parent_id"/>
<field name="parent_id" invisible="1"/>
</tree>
</field>
</record>
<record id="view_hr_salary_head_filter" model="ir.ui.view">
<field name="name">hr.salary.head.select</field>
<field name="model">hr.salary.head</field>
<record id="view_hr_salary_rule_category_filter" model="ir.ui.view">
<field name="name">hr.salary.rule.category.select</field>
<field name="model">hr.salary.rule.category</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Salary Heads">
<search string="Salary Rule Categories">
<field name="name" select="1"/>
<field name="code" select="1"/>
</search>
</field>
</record>
<record id="action_hr_salary_head" model="ir.actions.act_window">
<field name="name">Salary Heads</field>
<field name="res_model">hr.salary.head</field>
<record id="action_hr_salary_rule_category" model="ir.actions.act_window">
<field name="name">Salary Rule Categories</field>
<field name="res_model">hr.salary.rule.category</field>
<field name="view_type">form</field>
<field name="view_id" ref="hr_salary_head_tree"/>
<field name="search_view_id" ref="view_hr_salary_head_filter"/>
<field name="view_id" ref="hr_salary_rule_category_tree"/>
<field name="search_view_id" ref="view_hr_salary_rule_category_filter"/>
</record>
<menuitem
id="menu_hr_salary_head"
action="action_hr_salary_head"
id="menu_hr_salary_rule_category"
action="action_hr_salary_rule_category"
parent="payroll_configure"
sequence="11"
/>
<!-- End Payment Heads -->
<!--
Contribution Register
@ -507,7 +517,7 @@
<!-- Salary Rules -->
<record id="hr_salary_rule_tree" model="ir.ui.view">
<record id="hr_salary_rule_tree" model="ir.ui.view">
<field name="name">hr.salary.rule.tree</field>
<field name="model">hr.salary.rule</field>
<field name="type">tree</field>
@ -521,85 +531,94 @@
</tree>
</field>
</record>
<record id="hr_salary_rule_form" model="ir.ui.view">
<field name="name">hr.salary.rule.form</field>
<field name="model">hr.salary.rule</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Salary Rules">
<group col="6" colspan="6">
<field name="name"/>
<field name="code" select="1"/>
<field name="category_id"/>
<field name="sequence" />
<field name="active"/>
<field name="appears_on_payslip" attrs="{'readonly':[('company_contribution','=', True)]}" />
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
</group>
<notebook colspan="6">
<page string="General">
<group col="4" colspan="6">
<separator colspan="4" string="Conditions"/>
<field name="condition_select"/><newline/>
<field name="condition_python" attrs="{'invisible':[('condition_select','&lt;&gt;','python')], 'required': [('condition_select','=','python')]}" colspan="4"/> <newline/>
<field name="condition_range" attrs="{'invisible':[('condition_select','&lt;&gt;','range')], 'required':[('condition_select','=','range')]}"/><newline/>
<field name="condition_range_min" colspan="2" attrs="{'invisible':[('condition_select','&lt;&gt;','range')], 'required':[('condition_select','=','range')]}"/>
<field name="condition_range_max" colspan="2" attrs="{'invisible':[('condition_select','&lt;&gt;','range')], 'required':[('condition_select','=','range')]}"/>
<separator colspan="4" string="Computation"/>
<field name="amount_select"/><newline/>
<field name="amount_fix" attrs="{'invisible':[('amount_select','&lt;&gt;','fix')], 'required':[('amount_select','=','fix')]}"/>
<field colspan="4" name="amount_python_compute" attrs="{'invisible':[('amount_select','&lt;&gt;','code')], 'required':[('amount_select','=','code')]}"/>
<field name="amount_percentage_base" attrs="{'invisible':[('amount_select','&lt;&gt;','percentage')], 'required': [('amount_select','=','percentage')]}"/>
<field name="amount_percentage" attrs="{'invisible':[('amount_select','&lt;&gt;','percentage')], 'required':[('amount_select','=','percentage')]}"/>
<separator colspan="4" string="Company contribution"/>
<field name="register_id"/>
</group>
</page>
<page string="Child Rules">
<field name="parent_rule_id"/>
<separator colspan="4" string="Children definition"/>
<field colspan="4" name="child_ids" nolabel="1"/>
</page>
<page string="Description">
<field name="note" colspan="4" nolabel="1"/>
</page>
</notebook>
</form>
</field>
</record>
<record id="hr_salary_rule_form" model="ir.ui.view">
<field name="name">hr.salary.rule.form</field>
<field name="model">hr.salary.rule</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Salary Rules">
<group col="6" colspan="6">
<field name="name"/>
<field name="code" select="1"/>
<field name="category_id"/>
<field name="sequence" />
<field name="active"/>
<field name="appears_on_payslip" attrs="{'readonly':[('company_contribution','=', True)]}" />
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
</group>
<notebook colspan="6">
<page string="General">
<group col="4" colspan="6">
<separator colspan="4" string="Conditions"/>
<field name="condition_select"/><newline/>
<field name="condition_python" attrs="{'invisible':[('condition_select','&lt;&gt;','python')], 'required': [('condition_select','=','python')]}" colspan="4"/> <newline/>
<field name="condition_range" attrs="{'invisible':[('condition_select','&lt;&gt;','range')], 'required':[('condition_select','=','range')]}"/><newline/>
<field name="condition_range_min" colspan="2" attrs="{'invisible':[('condition_select','&lt;&gt;','range')], 'required':[('condition_select','=','range')]}"/>
<field name="condition_range_max" colspan="2" attrs="{'invisible':[('condition_select','&lt;&gt;','range')], 'required':[('condition_select','=','range')]}"/>
<separator colspan="4" string="Computation"/>
<field name="amount_select"/>
<field name="quantity" attrs="{'invisible':[('amount_select','=','code')], 'required':[('amount_select','!=','code')]}"/><newline/>
<field name="amount_fix" attrs="{'invisible':[('amount_select','&lt;&gt;','fix')], 'required':[('amount_select','=','fix')]}"/>
<field colspan="4" name="amount_python_compute" attrs="{'invisible':[('amount_select','&lt;&gt;','code')], 'required':[('amount_select','=','code')]}"/>
<field name="amount_percentage_base" attrs="{'invisible':[('amount_select','&lt;&gt;','percentage')], 'required': [('amount_select','=','percentage')]}"/>
<field name="amount_percentage" attrs="{'invisible':[('amount_select','&lt;&gt;','percentage')], 'required':[('amount_select','=','percentage')]}"/>
<separator colspan="4" string="Company contribution"/>
<field name="register_id"/>
</group>
</page>
<page string="Child Rules">
<field name="parent_rule_id"/>
<separator colspan="4" string="Children definition"/>
<field colspan="4" name="child_ids" nolabel="1"/>
</page>
<page string="Inputs">
<field name="input_ids" colspan="4" nolabel="1" mode="tree, form">
<tree string="Input Data" editable="bottom">
<field name="name"/>
<field name="code"/>
</tree>
</field>
</page>
<page string="Description">
<field name="note" colspan="4" nolabel="1"/>
</page>
</notebook>
</form>
</field>
</record>
<record id="view_hr_rule_filter" model="ir.ui.view">
<field name="name">hr.salary.rule.select</field>
<field name="model">hr.salary.rule</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Search Salary Rule">
<group col="8" colspan="4">
<field name="name"/>
<field name="code" select="1"/>
<field name="category_id"/>
<field name="condition_range_min"/>
</group>
<newline/>
<group col="8" colspan="4" expand="0" string="Group By...">
<filter string="Head" icon="terp-folder-yellow" name="head" context="{'group_by':'category_id'}"/>
</group>
</search>
</field>
</record>
<record id="view_hr_rule_filter" model="ir.ui.view">
<field name="name">hr.salary.rule.select</field>
<field name="model">hr.salary.rule</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Search Salary Rule">
<group col="8" colspan="4">
<field name="name"/>
<field name="code" select="1"/>
<field name="category_id"/>
<field name="condition_range_min"/>
</group>
<newline/>
<group col="8" colspan="4" expand="0" string="Group By...">
<filter string="Head" icon="terp-folder-yellow" name="head" context="{'group_by':'category_id'}"/>
</group>
</search>
</field>
</record>
<record id="action_salary_rule_form" model="ir.actions.act_window">
<field name="name">Salary Rules</field>
<field name="res_model">hr.salary.rule</field>
<field name="view_type">form</field>
<field name="view_id" ref="hr_salary_rule_tree"/>
<field name="domain">[('parent_rule_id','=',False)]</field>
<field name="search_view_id" ref="view_hr_rule_filter"/>
</record>
<record id="action_salary_rule_form" model="ir.actions.act_window">
<field name="name">Salary Rules</field>
<field name="res_model">hr.salary.rule</field>
<field name="view_type">form</field>
<field name="view_id" ref="hr_salary_rule_tree"/>
<field name="domain">[('parent_rule_id','=',False)]</field>
<field name="search_view_id" ref="view_hr_rule_filter"/>
</record>
<menuitem id="menu_action_hr_salary_rule_form" action="action_salary_rule_form" parent="payroll_configure" sequence="12"/>
<menuitem id="menu_action_hr_salary_rule_form" action="action_salary_rule_form" parent="payroll_configure" sequence="12"/>
<act_window domain="[('slip_id', '=', active_id)]" id="act_payslip_lines" name="Payslip Lines" res_model="hr.payslip.line" src_model="hr.payslip"/>
<act_window domain="[('slip_id', '=', active_id)]" id="act_payslip_lines" name="Payslip Lines" res_model="hr.payslip.line" src_model="hr.payslip"/>
</data>
</openerp>

View File

@ -6,5 +6,12 @@
<!-- <field name="name">Human Resources / Payroll</field>-->
<!-- </record>-->
<record id="property_rule_employee_payslip" model="ir.rule">
<field name="name">Employee Payslip</field>
<field model="ir.model" name="model_id" ref="model_hr_payslip"/>
<field name="domain_force">['|', ('employee_id.user_id', '=', user.id), ('employee_id.department_id.manager_id.user_id', '=', user.id)]</field>
<field name="groups" eval="[(4,ref('base.group_hr_user'))]"/>
</record>
</data>
</openerp>

View File

@ -1,12 +1,14 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_hr_payroll_structure","hr.payroll.structure","model_hr_payroll_structure","base.group_hr_user",1,1,1,1
"access_hr_contribution_register","hr.contribution.register","model_hr_contribution_register","base.group_hr_user",1,1,1,1
"access_hr_salary_head","hr.salary.head","model_hr_salary_head","base.group_hr_user",1,1,1,1
"access_hr_salary_rule_category","hr.salary.rule.category","model_hr_salary_rule_category","base.group_hr_user",1,1,1,1
"access_hr_payslip","hr.payslip","model_hr_payslip","base.group_hr_user",1,1,1,1
"access_hr_payslip_line","hr.payslip.line","model_hr_payslip_line","base.group_hr_user",1,1,1,1
"access_res_partner_payroll","res.partner.payroll","base.model_res_partner","base.group_hr_user",1,1,1,1
"access_hr_payslip_input_user","hr.payslip.input.user","model_hr_payslip_input","base.group_hr_user",1,1,1,1
"access_hr_payslip_manager","hr.payslip.manager","model_hr_payslip","base.group_hr_manager",1,1,1,1
"access_hr_payslip_line_manager","hr.payslip.line.manager","model_hr_payslip_line","base.group_hr_manager",1,1,1,1
"access_hr_payroll_structure_manager","hr.payroll.structure.manager","model_hr_payroll_structure","base.group_hr_manager",1,1,1,1
"access_hr_payslip_input ","hr.payslip.input","model_hr_payslip_input","base.group_hr_manager",1,1,1,1
"access_hr_payslip_worked_days ","hr.payslip.worked_days","model_hr_payslip_worked_days","base.group_hr_manager",1,1,1,1
"access_hr_salary_rule","hr.salary.rule","model_hr_salary_rule","base.group_hr_manager",1,1,1,1
"access_hr_payslip_input","hr.payslip.input","model_hr_payslip_input","base.group_hr_manager",1,1,1,1
"access_hr_rule_input","hr.rule.input","model_hr_rule_input","base.group_hr_manager",1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_hr_payroll_structure hr.payroll.structure model_hr_payroll_structure base.group_hr_user 1 1 1 1
3 access_hr_contribution_register hr.contribution.register model_hr_contribution_register base.group_hr_user 1 1 1 1
4 access_hr_salary_head access_hr_salary_rule_category hr.salary.head hr.salary.rule.category model_hr_salary_head model_hr_salary_rule_category base.group_hr_user 1 1 1 1
5 access_hr_payslip hr.payslip model_hr_payslip base.group_hr_user 1 1 1 1
6 access_hr_payslip_line hr.payslip.line model_hr_payslip_line base.group_hr_user 1 1 1 1
7 access_res_partner_payroll access_hr_payslip_input_user res.partner.payroll hr.payslip.input.user base.model_res_partner model_hr_payslip_input base.group_hr_user 1 1 1 1
8 access_hr_payslip_manager hr.payslip.manager model_hr_payslip base.group_hr_manager 1 1 1 1
9 access_hr_payslip_line_manager hr.payslip.line.manager model_hr_payslip_line base.group_hr_manager 1 1 1 1
10 access_hr_payroll_structure_manager hr.payroll.structure.manager model_hr_payroll_structure base.group_hr_manager 1 1 1 1
11 access_hr_payslip_input access_hr_payslip_worked_days hr.payslip.input hr.payslip.worked_days model_hr_payslip_input model_hr_payslip_worked_days base.group_hr_manager 1 1 1 1
12 access_hr_salary_rule hr.salary.rule model_hr_salary_rule base.group_hr_manager 1 1 1 1
13 access_hr_payslip_input hr.payslip.input model_hr_payslip_input base.group_hr_manager 1 1 1 1
14 access_hr_rule_input hr.rule.input model_hr_rule_input base.group_hr_manager 1 1 1 1