[MERGE, IMP] merge with main payroll branch, Add payslip lines by contribution register on Employee payslip report
bzr revid: psi@tinyerp.co.in-20110512083943-5e5eys6j7ae0af8e bzr revid: psi@tinyerp.co.in-20110512130543-ld0w9si6oypo298u
This commit is contained in:
+3
-3
@@ -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()
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -49,6 +49,7 @@ Generic Payroll system.
|
||||
],
|
||||
'update_xml': [
|
||||
'security/hr_security.xml',
|
||||
'wizard/hr_payroll_payslips_by_employees.xml',
|
||||
'hr_payroll_view.xml',
|
||||
'hr_payroll_workflow.xml',
|
||||
'hr_payroll_sequence.xml',
|
||||
|
||||
+166
-55
@@ -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):
|
||||
|
||||
@@ -204,6 +202,29 @@ class one2many_mod2(fields.one2many):
|
||||
res[r[self._fields_id]].append( r['id'] )
|
||||
return res
|
||||
|
||||
class hr_payslip_run(osv.osv):
|
||||
|
||||
_name = 'hr.payslip.run'
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=64, required=True, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'slip_ids': fields.one2many('hr.payslip', 'payslip_run_id', 'Payslips', required=False, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'state': fields.selection([
|
||||
('draft', 'Draft'),
|
||||
('close', 'Close'),
|
||||
], 'State', select=True, readonly=True)
|
||||
}
|
||||
_defaults = {
|
||||
'state': 'draft',
|
||||
}
|
||||
|
||||
def draft_payslip_run(self, cr, uid, ids, context=None):
|
||||
return self.write(cr, uid, ids, {'state': 'draft'}, context=context)
|
||||
|
||||
def close_payslip_run(self, cr, uid, ids, context=None):
|
||||
return self.write(cr, uid, ids, {'state': 'close'}, context=context)
|
||||
|
||||
hr_payslip_run()
|
||||
|
||||
class hr_payslip(osv.osv):
|
||||
'''
|
||||
Pay Slip
|
||||
@@ -212,21 +233,22 @@ 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
|
||||
for id in ids:
|
||||
result.setdefault(id, [])
|
||||
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], [])
|
||||
result[r[0]].append(r[1])
|
||||
return result
|
||||
|
||||
_columns = {
|
||||
'struct_id': fields.many2one('hr.payroll.structure', 'Structure', help='Defines the rules that have to be applied to this payslip, accordingly to the contract chosen. If you let empty the field contract, this field isn\'t mandatory anymore and thus the rules applied will be all the rules set on the structure of all contracts of the employee valid for the chosen period'),
|
||||
'struct_id': fields.many2one('hr.payroll.structure', 'Structure', readonly=True, states={'draft': [('readonly', False)]}, help='Defines the rules that have to be applied to this payslip, accordingly to the contract chosen. If you let empty the field contract, this field isn\'t mandatory anymore and thus the rules applied will be all the rules set on the structure of all contracts of the employee valid for the chosen period'),
|
||||
'name': fields.char('Description', size=64, required=False, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'number': fields.char('Reference', size=64, required=False, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'employee_id': fields.many2one('hr.employee', 'Employee', required=True, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
@@ -247,14 +269,16 @@ 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 Lines', readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'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'),
|
||||
'note': fields.text('Description', readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'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"),
|
||||
'payslip_run_id': fields.many2one('hr.payslip.run', 'Payslip Run', readonly=True, states={'draft': [('readonly', False)]}),
|
||||
}
|
||||
_defaults = {
|
||||
'date_from': lambda *a: time.strftime('%Y-%m-01'),
|
||||
@@ -402,7 +426,7 @@ class hr_payslip(osv.osv):
|
||||
for payslip in self.browse(cr, uid, ids, context=context):
|
||||
#delete old payslip lines
|
||||
old_slipline_ids = slip_line_pool.search(cr, uid, [('slip_id', '=', payslip.id)], context=context)
|
||||
old_slipline_ids
|
||||
# old_slipline_ids
|
||||
if old_slipline_ids:
|
||||
slip_line_pool.unlink(cr, uid, old_slipline_ids, context=context)
|
||||
if payslip.contract_id:
|
||||
@@ -415,7 +439,7 @@ class hr_payslip(osv.osv):
|
||||
self.write(cr, uid, [payslip.id], {'line_ids': lines}, 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
|
||||
@@ -472,21 +496,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
|
||||
@@ -497,19 +546,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,
|
||||
@@ -532,49 +581,60 @@ 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':[],
|
||||
'input_line_ids': [],
|
||||
'worked_days_line_ids': [],
|
||||
#'details_by_salary_head':[], TODO put me back
|
||||
'name':'',
|
||||
'contract_id': False,
|
||||
'struct_id': False,
|
||||
}
|
||||
}
|
||||
}
|
||||
if not employee_id:
|
||||
return res
|
||||
ttyme = datetime.fromtimestamp(time.mktime(time.strptime(date_from, "%Y-%m-%d")))
|
||||
employee_id = empolyee_obj.browse(cr, uid, employee_id, context=context)
|
||||
res['value'].update({
|
||||
'name': _('Salary Slip of %s for %s') % (employee_id.name, tools.ustr(ttyme.strftime('%B-%Y'))),
|
||||
'company_id': employee_id.company_id.id
|
||||
})
|
||||
'name': _('Salary Slip of %s for %s') % (employee_id.name, tools.ustr(ttyme.strftime('%B-%Y'))),
|
||||
'company_id': employee_id.company_id.id
|
||||
})
|
||||
|
||||
if not context.get('contract', False):
|
||||
#fill with the first contract of the employee
|
||||
contract_ids = self.get_contract(cr, uid, employee_id, date_from, date_to, context=context)
|
||||
res['value'].update({
|
||||
'struct_id': contract_ids and contract_obj.read(cr, uid, contract_ids[0], ['struct_id'], context=context)['struct_id'][0] or False,
|
||||
'contract_id': contract_ids and contract_ids[0] or False,
|
||||
'struct_id': contract_ids and contract_obj.read(cr, uid, contract_ids[0], ['struct_id'], context=context)['struct_id'][0] or False,
|
||||
'contract_id': contract_ids and contract_ids[0] or False,
|
||||
})
|
||||
else:
|
||||
if contract_id:
|
||||
@@ -582,7 +642,10 @@ class hr_payslip(osv.osv):
|
||||
contract_ids = [contract_id]
|
||||
#fill the structure with the one on the selected contract
|
||||
contract_record = contract_obj.browse(cr, uid, contract_id, context=context)
|
||||
res['value'].update({'struct_id': contract_record.struct_id.id, 'contract_id': contract_id})
|
||||
res['value'].update({
|
||||
'struct_id': contract_record.struct_id.id,
|
||||
'contract_id': contract_id
|
||||
})
|
||||
else:
|
||||
#if we don't give the contract, then the input to fill should be for all current contracts of the employee
|
||||
contract_ids = self.get_contract(cr, uid, employee_id, date_from, date_to, context=context)
|
||||
@@ -590,10 +653,12 @@ 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
|
||||
|
||||
def onchange_contract_id(self, cr, uid, ids, date_from, date_to, employee_id=False, contract_id=False, context=None):
|
||||
@@ -611,6 +676,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
|
||||
@@ -623,13 +710,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()
|
||||
|
||||
@@ -638,15 +725,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."),
|
||||
@@ -658,7 +746,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',
|
||||
@@ -670,6 +758,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 = {
|
||||
@@ -679,9 +768,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'
|
||||
|
||||
@@ -693,13 +783,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,
|
||||
@@ -711,6 +802,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):
|
||||
@@ -733,12 +825,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)
|
||||
@@ -771,6 +867,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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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"/>
|
||||
@@ -211,7 +209,7 @@
|
||||
<field name="model">hr.payslip</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree colors="blue:state in ('confirm','hr_check','accont_check');black:state in ('new');gray:state in('cancel')" string="Payslip">
|
||||
<tree colors="blue:state in ('confirm','hr_check','accont_check');black:state in ('new');gray:state in('cancel')" string="Payslips">
|
||||
<field name="number"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="name"/>
|
||||
@@ -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','<>','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>
|
||||
|
||||
@@ -306,6 +318,7 @@
|
||||
<separator colspan="4" string="Other Information"/>
|
||||
<group col="5" colspan="2">
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
<field name="payslip_run_id" domain="[('state','=','draft')]"/>
|
||||
<field name="paid" readonly="1"/>
|
||||
</group>
|
||||
<newline/>
|
||||
@@ -364,64 +377,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 +518,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 +532,149 @@
|
||||
</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>
|
||||
<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','<>','python')], 'required': [('condition_select','=','python')]}" colspan="4"/> <newline/>
|
||||
<field name="condition_range" attrs="{'invisible':[('condition_select','<>','range')], 'required':[('condition_select','=','range')]}"/><newline/>
|
||||
<field name="condition_range_min" colspan="2" attrs="{'invisible':[('condition_select','<>','range')], 'required':[('condition_select','=','range')]}"/>
|
||||
<field name="condition_range_max" colspan="2" attrs="{'invisible':[('condition_select','<>','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','<>','fix')], 'required':[('amount_select','=','fix')]}"/>
|
||||
<field colspan="4" name="amount_python_compute" attrs="{'invisible':[('amount_select','<>','code')], 'required':[('amount_select','=','code')]}"/>
|
||||
<field name="amount_percentage_base" attrs="{'invisible':[('amount_select','<>','percentage')], 'required': [('amount_select','=','percentage')]}"/>
|
||||
<field name="amount_percentage" attrs="{'invisible':[('amount_select','<>','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="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"/>
|
||||
|
||||
<act_window domain="[('slip_id', '=', active_id)]" id="act_payslip_lines" name="Payslip Lines" res_model="hr.payslip.line" src_model="hr.payslip"/>
|
||||
|
||||
<record id="hr_payslip_run_filter" model="ir.ui.view">
|
||||
<field name="name">hr.payslip.run.search</field>
|
||||
<field name="model">hr.payslip.run</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Payslips Group">
|
||||
<field name="name"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_payslip_run_tree" model="ir.ui.view">
|
||||
<field name="name">hr.payslip.run.tree</field>
|
||||
<field name="model">hr.payslip.run</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Payslips Run">
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_payslip_run_form" model="ir.ui.view">
|
||||
<field name="name">hr.payslip.run.form</field>
|
||||
<field name="model">hr.payslip.run</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Salary Rules">
|
||||
<form string="Payslips Run">
|
||||
<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"/>
|
||||
<field name="name"/>
|
||||
</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','<>','python')], 'required': [('condition_select','=','python')]}" colspan="4"/> <newline/>
|
||||
<field name="condition_range" attrs="{'invisible':[('condition_select','<>','range')], 'required':[('condition_select','=','range')]}"/><newline/>
|
||||
<field name="condition_range_min" colspan="2" attrs="{'invisible':[('condition_select','<>','range')], 'required':[('condition_select','=','range')]}"/>
|
||||
<field name="condition_range_max" colspan="2" attrs="{'invisible':[('condition_select','<>','range')], 'required':[('condition_select','=','range')]}"/>
|
||||
<separator colspan="4" string="Computation"/>
|
||||
<field name="amount_select"/><newline/>
|
||||
<field name="amount_fix" attrs="{'invisible':[('amount_select','<>','fix')], 'required':[('amount_select','=','fix')]}"/>
|
||||
<field colspan="4" name="amount_python_compute" attrs="{'invisible':[('amount_select','<>','code')], 'required':[('amount_select','=','code')]}"/>
|
||||
<field name="amount_percentage_base" attrs="{'invisible':[('amount_select','<>','percentage')], 'required': [('amount_select','=','percentage')]}"/>
|
||||
<field name="amount_percentage" attrs="{'invisible':[('amount_select','<>','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 string="Payslips">
|
||||
<field name="slip_ids" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<group col="6" colspan="6">
|
||||
<field name="state"/>
|
||||
<button name="%(action_hr_payslip_by_employees)d" type="action" states="draft" icon="gtk-execute" string="Generate Payslips" />
|
||||
<button name="close_payslip_run" type="object" icon="gtk-jump-to" string="Close" states="draft"/>
|
||||
<button string="Set to Draft" icon="terp-stock_effects-object-colorize" name="draft_payslip_run" type="object" states="close"/>
|
||||
</group>
|
||||
</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="action_salary_rule_form" model="ir.actions.act_window">
|
||||
<field name="name">Salary Rules</field>
|
||||
<field name="res_model">hr.salary.rule</field>
|
||||
<record id="action_hr_payslip_run_tree" model="ir.actions.act_window">
|
||||
<field name="name">Payslips Run</field>
|
||||
<field name="res_model">hr.payslip.run</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"/>
|
||||
<field name="view_id" ref="hr_payslip_run_tree"/>
|
||||
<field name="search_view_id" ref="hr_payslip_run_filter"/>
|
||||
</record>
|
||||
|
||||
<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"/>
|
||||
<menuitem action="action_hr_payslip_run_tree" id="menu_hr_payslip_run" parent="menu_hr_root_payroll"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -37,7 +37,8 @@ class payslip_report(report_sxw.rml_parse):
|
||||
'get_deductions':self.get_deductions,
|
||||
'get_leave': self.get_leave,
|
||||
'get_payslip_lines': self.get_payslip_lines,
|
||||
'get_details_by_salary_head': self.get_details_by_salary_head,
|
||||
'get_details_by_rule_category': self.get_details_by_rule_category,
|
||||
'get_lines_by_contribution_register': self.get_lines_by_contribution_register,
|
||||
})
|
||||
|
||||
def convert(self, amount, cur):
|
||||
@@ -96,52 +97,51 @@ class payslip_report(report_sxw.rml_parse):
|
||||
res = payslip_line.browse(self.cr, self.uid, ids)
|
||||
return res
|
||||
|
||||
def get_recursive_parent(self, heads):
|
||||
if not heads:
|
||||
def get_recursive_parent(self, rule_categories):
|
||||
if not rule_categories:
|
||||
return []
|
||||
if heads[0].parent_id:
|
||||
heads.insert(0, heads[0].parent_id)
|
||||
self.get_recursive_parent(heads)
|
||||
return heads
|
||||
if rule_categories[0].parent_id:
|
||||
rule_categories.insert(0, rule_categories[0].parent_id)
|
||||
self.get_recursive_parent(rule_categories)
|
||||
return rule_categories
|
||||
|
||||
def get_details_by_salary_head(self, obj):
|
||||
def get_details_by_rule_category(self, obj):
|
||||
payslip_line = self.pool.get('hr.payslip.line')
|
||||
salary_head = self.pool.get('hr.salary.head')
|
||||
rule_cate_obj = self.pool.get('hr.salary.rule.category')
|
||||
res = []
|
||||
result = {}
|
||||
ids = []
|
||||
|
||||
|
||||
for id in range(len(obj)):
|
||||
ids.append(obj[id].id)
|
||||
if ids:
|
||||
self.cr.execute('''SELECT pl.id, pl.category_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 rc on (pl.category_id = rc.id) \
|
||||
WHERE pl.id in %s \
|
||||
GROUP BY sh.parent_id, sh.sequence, pl.sequence, pl.id, pl.category_id \
|
||||
ORDER BY sh.sequence, pl.sequence, sh.parent_id''',(tuple(ids),))
|
||||
GROUP BY rc.parent_id, pl.sequence, pl.id, pl.category_id \
|
||||
ORDER BY pl.sequence, rc.parent_id''',(tuple(ids),))
|
||||
for x in self.cr.fetchall():
|
||||
result.setdefault(x[1], [])
|
||||
result[x[1]].append(x[0])
|
||||
for key, value in result.iteritems():
|
||||
heads = salary_head.browse(self.cr, self.uid, [key])
|
||||
parents = self.get_recursive_parent(heads)
|
||||
head_total = 0
|
||||
rule_categories = rule_cate_obj.browse(self.cr, self.uid, [key])
|
||||
parents = self.get_recursive_parent(rule_categories)
|
||||
category_total = 0
|
||||
for line in payslip_line.browse(self.cr, self.uid, value):
|
||||
head_total += line.total
|
||||
category_total += line.total
|
||||
level = 0
|
||||
for parent in parents:
|
||||
res.append({
|
||||
'salary_head': parent.name,
|
||||
'rule_category': parent.name,
|
||||
'name': parent.name,
|
||||
'code': parent.code,
|
||||
'level': level,
|
||||
'total': head_total,
|
||||
'total': category_total,
|
||||
})
|
||||
level += 1
|
||||
lines = payslip_line.browse(self.cr, self.uid, value)
|
||||
for line in lines:
|
||||
for line in payslip_line.browse(self.cr, self.uid, value):
|
||||
res.append({
|
||||
'salary_head': line.name,
|
||||
'rule_category': line.name,
|
||||
'name': line.name,
|
||||
'code': line.code,
|
||||
'total': line.total,
|
||||
@@ -149,6 +149,27 @@ class payslip_report(report_sxw.rml_parse):
|
||||
})
|
||||
return res
|
||||
|
||||
def get_lines_by_contribution_register(self, obj):
|
||||
payslip_line = self.pool.get('hr.payslip.line')
|
||||
result = {}
|
||||
res = []
|
||||
|
||||
for id in range(len(obj)):
|
||||
if obj[id].register_id:
|
||||
result.setdefault(obj[id].register_id.name, [])
|
||||
result[obj[id].register_id.name].append(obj[id].id)
|
||||
for key, value in result.iteritems():
|
||||
res.append({
|
||||
'register_name': key,
|
||||
})
|
||||
for line in payslip_line.browse(self.cr, self.uid, value):
|
||||
res.append({
|
||||
'name': line.name,
|
||||
'code': line.code,
|
||||
'total': line.total,
|
||||
})
|
||||
return res
|
||||
|
||||
#report_sxw.report_sxw('report.payslip.pdf', 'hr.payslip', 'hr_payroll/report/payslip.rml', parser=payslip_report)
|
||||
report_sxw.report_sxw('report.test.pdf', 'hr.payslip', 'hr_payroll/report/report_payslip.rml', parser=payslip_report)
|
||||
|
||||
|
||||
@@ -147,6 +147,35 @@
|
||||
<lineStyle kind="LINEBELOW" colorName="#000000" start="2,-1" stop="2,-1"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#000000" start="3,-1" stop="3,-1"/>
|
||||
</blockTableStyle>
|
||||
<blockTableStyle id="Table14">
|
||||
<blockAlignment value="LEFT"/>
|
||||
<blockValign value="TOP"/>
|
||||
</blockTableStyle>
|
||||
<blockTableStyle id="Table15">
|
||||
<blockAlignment value="LEFT"/>
|
||||
<blockValign value="TOP"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="0,0" stop="0,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="0,0" stop="0,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#000000" start="0,-1" stop="0,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="1,0" stop="1,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="1,0" stop="1,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#000000" start="1,-1" stop="1,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="2,0" stop="2,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="2,0" stop="2,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#000000" start="2,-1" stop="2,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
|
||||
<lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="3,0" stop="3,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#000000" start="3,-1" stop="3,-1"/>
|
||||
</blockTableStyle>
|
||||
<blockTableStyle id="Table16">
|
||||
<blockAlignment value="LEFT"/>
|
||||
<blockValign value="TOP"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#000000" start="0,-1" stop="0,-1"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#000000" start="1,-1" stop="1,-1"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#000000" start="2,-1" stop="2,-1"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#000000" start="3,-1" stop="3,-1"/>
|
||||
</blockTableStyle>
|
||||
<blockTableStyle id="Table13">
|
||||
<blockAlignment value="LEFT"/>
|
||||
<blockValign value="TOP"/>
|
||||
@@ -160,25 +189,31 @@
|
||||
<paraStyle name="P4" rightIndent="-56.0" leftIndent="0.0" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P5" rightIndent="-56.0" leftIndent="0.0" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P6" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P7" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P8" fontName="Helvetica-Bold" fontSize="14.0" leading="17" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P9" fontName="Helvetica" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P10" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P11" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P7" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P8" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P9" fontName="Helvetica-Bold" fontSize="14.0" leading="17" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P10" fontName="Helvetica" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P11" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P12" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P13" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="2.0" leading="3" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P14" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica" fontSize="2.0" leading="3" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P15" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P16" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT"/>
|
||||
<paraStyle name="P17" fontName="Helvetica-Bold" fontSize="8.0" leading="10"/>
|
||||
<paraStyle name="P13" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P14" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="2.0" leading="3" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P15" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica" fontSize="2.0" leading="3" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P16" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P17" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT"/>
|
||||
<paraStyle name="P18" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="RIGHT"/>
|
||||
<paraStyle name="P19" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P20" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P21" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P22" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P23" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="RIGHT"/>
|
||||
<paraStyle name="P24" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P25" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P19" fontName="Helvetica-Bold" fontSize="8.0" leading="10"/>
|
||||
<paraStyle name="P20" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="RIGHT"/>
|
||||
<paraStyle name="P21" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P22" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P23" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P24" fontName="Helvetica" fontSize="2.0" leading="3"/>
|
||||
<paraStyle name="P25" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P26" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P27" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P28" rightIndent="0.0" leftIndent="0.0" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P29" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="P30" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT"/>
|
||||
<paraStyle name="P31" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="RIGHT"/>
|
||||
<paraStyle name="Standard" fontName="Helvetica"/>
|
||||
<paraStyle name="Heading" fontName="Helvetica" fontSize="14.0" leading="17" spaceBefore="12.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="Text body" fontName="Helvetica" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
@@ -208,7 +243,7 @@
|
||||
<blockTable colWidths="539.0" style="Table1">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P8">Pay Slip</para>
|
||||
<para style="P9">Pay Slip</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
@@ -218,17 +253,17 @@
|
||||
<font face="Helvetica" size="14.0"/>
|
||||
<font face="Helvetica-Bold" size="14.0">Note</font>
|
||||
</para>
|
||||
<para style="P9">([[o.name]])</para>
|
||||
<para style="P10">([[o.name]])</para>
|
||||
<blockTable colWidths="63.0,206.0,89.0,181.0" style="Table2">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P19">Name</para>
|
||||
<para style="P21">Name</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P19">[[o.employee_id.name]]</para>
|
||||
<para style="P21">[[o.employee_id.name]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P19">Designation </para>
|
||||
<para style="P21">Designation </para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P6">[[ o.employee_id.job_id.name or '' ]]</para>
|
||||
@@ -250,7 +285,7 @@
|
||||
<blockTable colWidths="63.0,206.0,89.0,181.0" style="Table4">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P19">Email</para>
|
||||
<para style="P21">Email</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P6">[[ o.employee_id.work_email or '' ]]</para>
|
||||
@@ -268,23 +303,23 @@
|
||||
<blockTable colWidths="63.0,205.0,89.0,181.0" style="Table5">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P19">Reference</para>
|
||||
<para style="P21">Reference</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P6">[[ o.number or '' ]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P19">Bank Account</para>
|
||||
<para style="P21">Bank Account</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P6">[[o.employee_id.bank_account_id and o.employee_id.bank_account_id.acc_number or '' ]]</para>
|
||||
<para style="P6">[[ o.employee_id.otherid or '' ]]</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
<blockTable colWidths="63.0,205.0,89.0,181.0" style="Table6">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P19">Date From</para>
|
||||
<para style="P21">Date From</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P6">[[ o.date_from or '']]</para>
|
||||
@@ -299,27 +334,27 @@
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
<para style="P7">
|
||||
<para style="P8">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<para style="P7"/>
|
||||
<para style="P8"/>
|
||||
<blockTable colWidths="539.0" style="Table7">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P11">Payslip Lines: </para>
|
||||
<para style="P12">Payslip Lines: </para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
<blockTable colWidths="54.0,387.0,97.0" style="Table8">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P16">Code</para>
|
||||
<para style="P17">Code</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P16">Name</para>
|
||||
<para style="P17">Name</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P23">Amount (in [[o.company_id and o.company_id.currency_id.symbol or '']])</para>
|
||||
<para style="P18">Amount (in [[o.company_id and o.company_id.currency_id.symbol or '']])</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
@@ -334,68 +369,107 @@
|
||||
<para style="P6">[[ p.name ]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P22">[[ p.total or '0.0']]</para>
|
||||
<para style="P7">[[ p.total or '0.0']]</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
</section>
|
||||
<para style="P10">
|
||||
<para style="P11">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<blockTable colWidths="539.0" style="Table10">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P12">Details By Salary Head: </para>
|
||||
<para style="P13">Details by Salary Rule Category: </para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
<blockTable colWidths="54.0,215.0,173.0,97.0" style="Table11">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P17">Code</para>
|
||||
<para style="P19">Code</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P17">Salary Head</para>
|
||||
<para style="P19">Salary Rule Category</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P19">Name</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P20">Amount<font face="Helvetica">(in [[o.company_id and o.company_id.currency_id.symbol or '']])</font></para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
<para style="P1">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<section>
|
||||
<para style="P21">[[repeatIn(get_details_by_rule_category(o.line_ids),'h') ]]</para>
|
||||
<blockTable colWidths="54.0,215.0,173.0,97.0" style="Table12">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P21">
|
||||
<font face="Helvetica">[[ h['code'] ]]</font>
|
||||
<font face="Helvetica">[[ h['level']!=0 and ( setTag('para','para',{'style':'terp_default_8'})) or removeParentNode('font')]]</font>
|
||||
</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P22"><font face="Helvetica" color="white">[[ '..'*h['level'] ]]</font>[[ h['rule_category'] ]]<font face="Helvetica">[[ h['level']!=0 and ( setTag('para','para',{'style':'terp_default_8'})) or removeParentNode('font') ]]</font></para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P23">[[ h['name'] ]]<font face="Helvetica">[[ h['level']!=0 and ( setTag('para','para',{'style':'terp_default_8'})) or removeParentNode('font')]]</font></para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P7">[[ h['total'] ]] <font face="Helvetica" size="8.0">[[ h['level']!=0 and ( setTag('para','para',{'style':'terp_default_10'})) or removeParentNode('font') ]]</font></para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
</section>
|
||||
<para style="P8">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<blockTable colWidths="539.0" style="Table14">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P13">Payslip Lines by Contribution Register:</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
<blockTable colWidths="115.0,46.0,289.0,88.0" style="Table15">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P17">Register Name</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P17">Code</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P17">Name</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P18">Amount<font face="Helvetica">(in [[o.company_id and o.company_id.currency_id.symbol or '']])</font></para>
|
||||
<para style="P18">Amount (in [[o.company_id and o.company_id.currency_id.symbol or '']])</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
<section>
|
||||
<para style="P19">[[repeatIn(get_details_by_salary_head(o.line_ids),'h') ]]</para>
|
||||
<blockTable colWidths="54.0,215.0,173.0,97.0" style="Table12">
|
||||
<para style="P21">[[repeatIn(get_lines_by_contribution_register(o.line_ids),'r') ]]</para>
|
||||
<blockTable colWidths="116.0,46.0,289.0,88.0" style="Table16">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P19">
|
||||
<font face="Helvetica">[[ h['code'] ]]</font>
|
||||
<font face="Helvetica">[[ h['level']!=0 and ( setTag('para','para',{'style':'terp_default_8'})) or removeParentNode('font') ]]</font>
|
||||
</para>
|
||||
<para style="P21">[[ r.get('register_name', False) ]]<font face="Helvetica">[[ h.get('register_name', False) and ( setTag('para','para',{'style':'terp_default_8'})) or removeParentNode('font')]]</font></para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P20"><font face="Helvetica" color="white">[[ '..'*h['level'] ]]</font>[[ h['salary_head'] ]]<font face="Helvetica">[[ h['level']!=0 and ( setTag('para','para',{'style':'terp_default_9'})) or removeParentNode('font') ]]</font></para>
|
||||
<para style="P6">[[ r['code'] ]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P24">[[ h['name'] ]]<font face="Helvetica">[[ h['level']!=0 and ( setTag('para','para',{'style':'terp_default_8'})) or removeParentNode('font') ]]</font></para>
|
||||
<para style="P6">[[ r['name'] ]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P25">[[ h['total'] ]]<font face="Helvetica">[[ h['level']!=0 and ( setTag('para','para',{'style':'terp_default_10'})) or removeParentNode('font') ]]</font></para>
|
||||
<para style="P7">[[ r['total'] or '0.0']]</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
</section>
|
||||
<para style="P2">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<para style="P2">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<para style="P2">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<blockTable colWidths="269.0,269.0" style="Table13">
|
||||
<tr>
|
||||
<td>
|
||||
@@ -404,7 +478,16 @@
|
||||
</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P15">Authorized Signature </para>
|
||||
<para style="P16">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<para style="P16">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<para style="P16">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<para style="P16">Authorized Signature </para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
|
||||
@@ -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>
|
||||
@@ -1,12 +1,15 @@
|
||||
"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_run","hr.payslip.run","model_hr_payslip_run","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,7 +1,7 @@
|
||||
#-*- coding:utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# d$
|
||||
#
|
||||
@@ -24,5 +24,6 @@
|
||||
import hr_payroll_employees_detail
|
||||
#import hr_payroll_create_analytic
|
||||
import hr_payroll_year_salary
|
||||
import hr_payroll_payslips_by_employees
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
@@ -0,0 +1,63 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
from datetime import datetime
|
||||
from dateutil import relativedelta
|
||||
|
||||
from osv import fields, osv
|
||||
from tools.translate import _
|
||||
|
||||
class hr_payslip_employees(osv.osv_memory):
|
||||
|
||||
_name ='hr.payslip.employees'
|
||||
_description = 'Generate payslips for all selected employees'
|
||||
_columns = {
|
||||
'employee_ids': fields.many2many('hr.employee', 'hr_employee_group_rel', 'payslip_id', 'employee_id', 'Employees'),
|
||||
}
|
||||
|
||||
def compute_sheet(self, cr, uid, ids, context=None):
|
||||
emp_pool = self.pool.get('hr.employee')
|
||||
slip_pool = self.pool.get('hr.payslip')
|
||||
slip_ids = []
|
||||
if context is None:
|
||||
context = {}
|
||||
data = self.read(cr, uid, ids, context=context)[0]
|
||||
if not data['employee_ids']:
|
||||
raise osv.except_osv(_("Warning !"), _("You must select employee(s) to generate payslip(s)"))
|
||||
for emp in emp_pool.browse(cr, uid, data['employee_ids'], context=context):
|
||||
slip_data = slip_pool.onchange_employee_id(cr, uid, [], time.strftime('%Y-%m-01'), str(datetime.now() + relativedelta.relativedelta(months=+1, day=1, days=-1))[:10], emp.id, contract_id=False, context=context)
|
||||
res = {
|
||||
'employee_id': emp.id,
|
||||
'name': slip_data['value'].get('name', False),
|
||||
'struct_id': slip_data['value'].get('struct_id', False),
|
||||
'contract_id': slip_data['value'].get('contract_id', False),
|
||||
'payslip_run_id': context.get('active_id', False),
|
||||
'input_line_ids': [(0, 0, x) for x in slip_data['value'].get('input_line_ids', False)],
|
||||
'worked_days_line_ids': [(0, 0, x) for x in slip_data['value'].get('worked_days_line_ids', False)]
|
||||
}
|
||||
slip_ids.append(slip_pool.create(cr, uid, res, context=context))
|
||||
slip_pool.compute_sheet(cr, uid, slip_ids, context=context)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
hr_payslip_employees()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_hr_payslip_by_employees" model="ir.ui.view">
|
||||
<field name="name">hr_payroll_payslip_employees</field>
|
||||
<field name="model">hr.payslip.employees</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Payslips by Employees">
|
||||
<group colspan="4" >
|
||||
<separator string="Payslips by Employees" colspan="4"/>
|
||||
<label colspan="4" nolabel="1" string="This wizard will generate payslips for all selected employee(s)" />
|
||||
<newline/>
|
||||
<field name="employee_ids" nolabel="1"/>
|
||||
</group>
|
||||
<separator string="" colspan="4" />
|
||||
<group colspan="4" col="6">
|
||||
<label string ="" colspan="2"/>
|
||||
<button icon="gtk-cancel" special="cancel" string="Cancel"/>
|
||||
<button icon="gtk-execute" string="Generate" name="compute_sheet" type="object"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_hr_payslip_by_employees" model="ir.actions.act_window">
|
||||
<field name="name">Generate Payslips</field>
|
||||
<field name="res_model">hr.payslip.employees</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="view_hr_payslip_by_employees"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
Reference in New Issue
Block a user