Browse Source

[UPDT] bug fix:num of worked days,new fields,demo data,help,arabic

pull/145/head
Ajmal JK 5 years ago
parent
commit
fe9e72e0b1
  1. 91
      hr_payroll_community/data/hr_payroll_data.xml
  2. 6
      hr_payroll_community/models/hr_contract.py
  3. 2
      hr_payroll_community/models/hr_employee.py
  4. 134
      hr_payroll_community/models/hr_payslip.py
  5. 27
      hr_payroll_community/views/hr_contract_views.xml

91
hr_payroll_community/data/hr_payroll_data.xml

@ -36,6 +36,36 @@
<field name="code">COMP</field> <field name="code">COMP</field>
</record> </record>
<record id="HRA" model="hr.salary.rule.category">
<field name="name">House Rent Allowance</field>
<field name="code">HRA</field>
</record>
<record id="DA" model="hr.salary.rule.category">
<field name="name">Dearness Allowance</field>
<field name="code">DA</field>
</record>
<record id="Travel" model="hr.salary.rule.category">
<field name="name">Travel Allowance</field>
<field name="code">Travel</field>
</record>
<record id="Meal" model="hr.salary.rule.category">
<field name="name">Meal Allowance</field>
<field name="code">Meal</field>
</record>
<record id="Medical" model="hr.salary.rule.category">
<field name="name">Medical Allowance</field>
<field name="code">Medical</field>
</record>
<record id="Other" model="hr.salary.rule.category">
<field name="name">Other Allowance</field>
<field name="code">Other</field>
</record>
<record id="DEDUCTION" model="hr.salary.rule.category"> <record id="DEDUCTION" model="hr.salary.rule.category">
<field name="name">Deduction</field> <field name="name">Deduction</field>
@ -74,6 +104,67 @@
<field name="register_id" ref="contrib_register_employees"/> <field name="register_id" ref="contrib_register_employees"/>
</record> </record>
<record id="hr_rule_hra" model="hr.salary.rule">
<field name="name">House Rent Allowance</field>
<field name="sequence" eval="1"/>
<field name="code">HRA</field>
<field name="category_id" ref="hr_payroll_community.HRA"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = contract.hra</field>
</record>
<record id="hr_rule_da" model="hr.salary.rule">
<field name="name">Dearness Allowance</field>
<field name="sequence" eval="1"/>
<field name="code">DA</field>
<field name="category_id" ref="hr_payroll_community.DA"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = contract.da</field>
</record>
<record id="hr_rule_travel" model="hr.salary.rule">
<field name="name">Travel Allowance</field>
<field name="sequence" eval="1"/>
<field name="code">Travel</field>
<field name="category_id" ref="hr_payroll_community.Travel"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = contract.travel_allowance</field>
</record>
<record id="hr_rule_meal" model="hr.salary.rule">
<field name="name">Meal Allowance</field>
<field name="sequence" eval="1"/>
<field name="code">Meal</field>
<field name="category_id" ref="hr_payroll_community.Meal"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = contract.meal_allowance</field>
</record>
<record id="hr_rule_medical" model="hr.salary.rule">
<field name="name">Medical Allowance</field>
<field name="sequence" eval="1"/>
<field name="code">Medical</field>
<field name="category_id" ref="hr_payroll_community.Medical"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = contract.medical_allowance</field>
</record>
<record id="hr_rule_other" model="hr.salary.rule">
<field name="name">Other Allowance</field>
<field name="sequence" eval="1"/>
<field name="code">Other</field>
<field name="category_id" ref="hr_payroll_community.Other"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = contract.other_allowance</field>
</record>
<!-- Salary Structure --> <!-- Salary Structure -->

6
hr_payroll_community/models/hr_contract.py

@ -23,6 +23,12 @@ class HrContract(models.Model):
], string='Scheduled Pay', index=True, default='monthly', ], string='Scheduled Pay', index=True, default='monthly',
help="Defines the frequency of the wage payment.") help="Defines the frequency of the wage payment.")
resource_calendar_id = fields.Many2one(required=True, help="Employee's working schedule.") resource_calendar_id = fields.Many2one(required=True, help="Employee's working schedule.")
hra = fields.Integer(string="HRA", help="House rent allowance")
travel_allowance = fields.Integer(string="Travel Allowance", help="Travel allowance")
da = fields.Integer(string="DA", help="Dearness allowance")
meal_allowance = fields.Integer(string="Meal Allowance", help="Meal allowance")
medical_allowance = fields.Integer(string="Medical Allowance", help="Medical allowance")
other_allowance = fields.Integer(string="Other Allowance", help="Other allowances")
def get_all_structures(self): def get_all_structures(self):
""" """

2
hr_payroll_community/models/hr_employee.py

@ -7,7 +7,7 @@ class HrEmployee(models.Model):
_inherit = 'hr.employee' _inherit = 'hr.employee'
_description = 'Employee' _description = 'Employee'
slip_ids = fields.One2many('hr.payslip', 'employee_id', string='Payslips', readonly=True) slip_ids = fields.One2many('hr.payslip', 'employee_id', string='Payslips', readonly=True, help="payslip")
payslip_count = fields.Integer(compute='_compute_payslip_count', string='Payslip Count', groups="hr_payroll_community.group_hr_payroll_user") payslip_count = fields.Integer(compute='_compute_payslip_count', string='Payslip Count', groups="hr_payroll_community.group_hr_payroll_user")
def _compute_payslip_count(self): def _compute_payslip_count(self):

134
hr_payroll_community/models/hr_payslip.py

@ -16,6 +16,7 @@ from odoo.tools import float_utils
# This will generate 16th of days # This will generate 16th of days
ROUNDING_FACTOR = 16 ROUNDING_FACTOR = 16
class HrPayslip(models.Model): class HrPayslip(models.Model):
_name = 'hr.payslip' _name = 'hr.payslip'
_description = 'Pay Slip' _description = 'Pay Slip'
@ -28,14 +29,16 @@ class HrPayslip(models.Model):
'structure of all contracts of the employee valid for the chosen period') 'structure of all contracts of the employee valid for the chosen period')
name = fields.Char(string='Payslip Name', readonly=True, name = fields.Char(string='Payslip Name', readonly=True,
states={'draft': [('readonly', False)]}) states={'draft': [('readonly', False)]})
number = fields.Char(string='Reference', readonly=True, copy=False, number = fields.Char(string='Reference', readonly=True, copy=False, help="References",
states={'draft': [('readonly', False)]})
employee_id = fields.Many2one('hr.employee', string='Employee', required=True, readonly=True, help="Employee",
states={'draft': [('readonly', False)]}) states={'draft': [('readonly', False)]})
employee_id = fields.Many2one('hr.employee', string='Employee', required=True, readonly=True, date_from = fields.Date(string='Date From', readonly=True, required=True, help="Start date",
default=lambda self: fields.Date.to_string(date.today().replace(day=1)),
states={'draft': [('readonly', False)]}) states={'draft': [('readonly', False)]})
date_from = fields.Date(string='Date From', readonly=True, required=True, date_to = fields.Date(string='Date To', readonly=True, required=True, help="End date",
default=lambda self: fields.Date.to_string(date.today().replace(day=1)), states={'draft': [('readonly', False)]}) default=lambda self: fields.Date.to_string(
date_to = fields.Date(string='Date To', readonly=True, required=True, (datetime.now() + relativedelta(months=+1, day=1, days=-1)).date()),
default=lambda self: fields.Date.to_string((datetime.now() + relativedelta(months=+1, day=1, days=-1)).date()),
states={'draft': [('readonly', False)]}) states={'draft': [('readonly', False)]})
# this is chaos: 4 states are defined, 3 are used ('verify' isn't) and 5 exist ('confirm' seems to have existed) # this is chaos: 4 states are defined, 3 are used ('verify' isn't) and 5 exist ('confirm' seems to have existed)
state = fields.Selection([ state = fields.Selection([
@ -50,21 +53,23 @@ class HrPayslip(models.Model):
\n* When user cancel payslip the status is \'Rejected\'.""") \n* When user cancel payslip the status is \'Rejected\'.""")
line_ids = fields.One2many('hr.payslip.line', 'slip_id', string='Payslip Lines', readonly=True, line_ids = fields.One2many('hr.payslip.line', 'slip_id', string='Payslip Lines', readonly=True,
states={'draft': [('readonly', False)]}) states={'draft': [('readonly', False)]})
company_id = fields.Many2one('res.company', string='Company', readonly=True, copy=False, company_id = fields.Many2one('res.company', string='Company', readonly=True, copy=False, help="Company",
default=lambda self: self.env['res.company']._company_default_get(), default=lambda self: self.env['res.company']._company_default_get(),
states={'draft': [('readonly', False)]}) states={'draft': [('readonly', False)]})
worked_days_line_ids = fields.One2many('hr.payslip.worked_days', 'payslip_id', worked_days_line_ids = fields.One2many('hr.payslip.worked_days', 'payslip_id',
string='Payslip Worked Days', copy=True, readonly=True, string='Payslip Worked Days', copy=True, readonly=True,
help="Payslip worked days",
states={'draft': [('readonly', False)]}) states={'draft': [('readonly', False)]})
input_line_ids = fields.One2many('hr.payslip.input', 'payslip_id', string='Payslip Inputs', input_line_ids = fields.One2many('hr.payslip.input', 'payslip_id', string='Payslip Inputs',
readonly=True, states={'draft': [('readonly', False)]}) readonly=True, states={'draft': [('readonly', False)]})
paid = fields.Boolean(string='Made Payment Order ? ', readonly=True, copy=False, paid = fields.Boolean(string='Made Payment Order ? ', readonly=True, copy=False,
states={'draft': [('readonly', False)]}) states={'draft': [('readonly', False)]})
note = fields.Text(string='Internal Note', readonly=True, states={'draft': [('readonly', False)]}) note = fields.Text(string='Internal Note', readonly=True, states={'draft': [('readonly', False)]})
contract_id = fields.Many2one('hr.contract', string='Contract', readonly=True, contract_id = fields.Many2one('hr.contract', string='Contract', readonly=True, help="Contract",
states={'draft': [('readonly', False)]}) states={'draft': [('readonly', False)]})
details_by_salary_rule_category = fields.One2many('hr.payslip.line', details_by_salary_rule_category = fields.One2many('hr.payslip.line',
compute='_compute_details_by_salary_rule_category', string='Details by Salary Rule Category') compute='_compute_details_by_salary_rule_category',
string='Details by Salary Rule Category', help="Details from the salary rule category")
credit_note = fields.Boolean(string='Credit Note', readonly=True, credit_note = fields.Boolean(string='Credit Note', readonly=True,
states={'draft': [('readonly', False)]}, states={'draft': [('readonly', False)]},
help="Indicates this payslip has a refund of another") help="Indicates this payslip has a refund of another")
@ -112,7 +117,8 @@ class HrPayslip(models.Model):
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',
'target': 'current', 'target': 'current',
'domain': "[('id', 'in', %s)]" % copied_payslip.ids, 'domain': "[('id', 'in', %s)]" % copied_payslip.ids,
'views': [(treeview_ref and treeview_ref.id or False, 'tree'), (formview_ref and formview_ref.id or False, 'form')], 'views': [(treeview_ref and treeview_ref.id or False, 'tree'),
(formview_ref and formview_ref.id or False, 'form')],
'context': {} 'context': {}
} }
@ -139,7 +145,8 @@ class HrPayslip(models.Model):
clause_2 = ['&', ('date_start', '<=', date_to), ('date_start', '>=', date_from)] clause_2 = ['&', ('date_start', '<=', date_to), ('date_start', '>=', date_from)]
# OR if it starts before the date_from and finish after the date_end (or never finish) # OR if it starts before the date_from and finish after the date_end (or never finish)
clause_3 = ['&', ('date_start', '<=', date_from), '|', ('date_end', '=', False), ('date_end', '>=', date_to)] clause_3 = ['&', ('date_start', '<=', date_from), '|', ('date_end', '=', False), ('date_end', '>=', date_to)]
clause_final = [('employee_id', '=', employee.id), ('state', '=', 'open'), '|', '|'] + clause_1 + clause_2 + clause_3 clause_final = [('employee_id', '=', employee.id), ('state', '=', 'open'), '|',
'|'] + clause_1 + clause_2 + clause_3
return self.env['hr.contract'].search(clause_final).ids return self.env['hr.contract'].search(clause_final).ids
def compute_sheet(self): def compute_sheet(self):
@ -171,7 +178,8 @@ class HrPayslip(models.Model):
leaves = {} leaves = {}
calendar = contract.resource_calendar_id calendar = contract.resource_calendar_id
tz = timezone(calendar.tz) tz = timezone(calendar.tz)
day_leave_intervals = contract.employee_id.list_leaves(day_from, day_to, calendar=contract.resource_calendar_id) day_leave_intervals = contract.employee_id.list_leaves(day_from, day_to,
calendar=contract.resource_calendar_id)
for day, hours, leave in day_leave_intervals: for day, hours, leave in day_leave_intervals:
holiday = leave.holiday_id holiday = leave.holiday_id
current_leave_struct = leaves.setdefault(holiday.holiday_status_id, { current_leave_struct = leaves.setdefault(holiday.holiday_status_id, {
@ -192,7 +200,8 @@ class HrPayslip(models.Model):
current_leave_struct['number_of_days'] += hours / work_hours current_leave_struct['number_of_days'] += hours / work_hours
# compute worked days # compute worked days
work_data = contract.employee_id.get_work_days_data(day_from, day_to, calendar=contract.resource_calendar_id) work_data = contract.employee_id.get_work_days_data(day_from, day_to,
calendar=contract.resource_calendar_id)
attendances = { attendances = {
'name': _("Normal Working Days paid at 100%"), 'name': _("Normal Working Days paid at 100%"),
'sequence': 1, 'sequence': 1,
@ -212,7 +221,7 @@ class HrPayslip(models.Model):
structure_ids = contracts.get_all_structures() structure_ids = contracts.get_all_structures()
rule_ids = self.env['hr.payroll.structure'].browse(structure_ids).get_all_rules() rule_ids = self.env['hr.payroll.structure'].browse(structure_ids).get_all_rules()
sorted_rule_ids = [id for id, sequence in sorted(rule_ids, key=lambda x:x[1])] sorted_rule_ids = [id for id, sequence in sorted(rule_ids, key=lambda x: x[1])]
inputs = self.env['hr.salary.rule'].browse(sorted_rule_ids).mapped('input_ids') inputs = self.env['hr.salary.rule'].browse(sorted_rule_ids).mapped('input_ids')
for contract in contracts: for contract in contracts:
@ -223,8 +232,6 @@ class HrPayslip(models.Model):
'contract_id': contract.id, 'contract_id': contract.id,
} }
res += [input_data] res += [input_data]
print(("In Super function"))
print(res)
return res return res
@api.model @api.model
@ -232,7 +239,8 @@ class HrPayslip(models.Model):
def _sum_salary_rule_category(localdict, category, amount): def _sum_salary_rule_category(localdict, category, amount):
if category.parent_id: if category.parent_id:
localdict = _sum_salary_rule_category(localdict, category.parent_id, amount) localdict = _sum_salary_rule_category(localdict, category.parent_id, amount)
localdict['categories'].dict[category.code] = category.code in localdict['categories'].dict and localdict['categories'].dict[category.code] + amount or amount localdict['categories'].dict[category.code] = category.code in localdict['categories'].dict and \
localdict['categories'].dict[category.code] + amount or amount
return localdict return localdict
class BrowsableObject(object): class BrowsableObject(object):
@ -246,6 +254,7 @@ class HrPayslip(models.Model):
class InputLine(BrowsableObject): class InputLine(BrowsableObject):
"""a class that will be used into the python code, mainly for usability purposes""" """a class that will be used into the python code, mainly for usability purposes"""
def sum(self, code, from_date, to_date=None): def sum(self, code, from_date, to_date=None):
if to_date is None: if to_date is None:
to_date = fields.Date.today() to_date = fields.Date.today()
@ -259,6 +268,7 @@ class HrPayslip(models.Model):
class WorkedDays(BrowsableObject): class WorkedDays(BrowsableObject):
"""a class that will be used into the python code, mainly for usability purposes""" """a class that will be used into the python code, mainly for usability purposes"""
def _sum(self, code, from_date, to_date=None): def _sum(self, code, from_date, to_date=None):
if to_date is None: if to_date is None:
to_date = fields.Date.today() to_date = fields.Date.today()
@ -292,7 +302,7 @@ class HrPayslip(models.Model):
res = self.env.cr.fetchone() res = self.env.cr.fetchone()
return res and res[0] or 0.0 return res and res[0] or 0.0
#we keep a dict with the result because a value can be overwritten by another rule with the same code # we keep a dict with the result because a value can be overwritten by another rule with the same code
result_dict = {} result_dict = {}
rules_dict = {} rules_dict = {}
worked_days_dict = {} worked_days_dict = {}
@ -310,17 +320,18 @@ class HrPayslip(models.Model):
payslips = Payslips(payslip.employee_id.id, payslip, self.env) payslips = Payslips(payslip.employee_id.id, payslip, self.env)
rules = BrowsableObject(payslip.employee_id.id, rules_dict, self.env) rules = BrowsableObject(payslip.employee_id.id, rules_dict, self.env)
baselocaldict = {'categories': categories, 'rules': rules, 'payslip': payslips, 'worked_days': worked_days, 'inputs': inputs} baselocaldict = {'categories': categories, 'rules': rules, 'payslip': payslips, 'worked_days': worked_days,
#get the ids of the structures on the contracts and their parent id as well 'inputs': inputs}
# get the ids of the structures on the contracts and their parent id as well
contracts = self.env['hr.contract'].browse(contract_ids) contracts = self.env['hr.contract'].browse(contract_ids)
if len(contracts) == 1 and payslip.struct_id: if len(contracts) == 1 and payslip.struct_id:
structure_ids = list(set(payslip.struct_id._get_parent_structure().ids)) structure_ids = list(set(payslip.struct_id._get_parent_structure().ids))
else: else:
structure_ids = contracts.get_all_structures() structure_ids = contracts.get_all_structures()
#get the rules of the structure and thier children # get the rules of the structure and thier children
rule_ids = self.env['hr.payroll.structure'].browse(structure_ids).get_all_rules() rule_ids = self.env['hr.payroll.structure'].browse(structure_ids).get_all_rules()
#run the rules by sequence # run the rules by sequence
sorted_rule_ids = [id for id, sequence in sorted(rule_ids, key=lambda x:x[1])] sorted_rule_ids = [id for id, sequence in sorted(rule_ids, key=lambda x: x[1])]
sorted_rules = self.env['hr.salary.rule'].browse(sorted_rule_ids) sorted_rules = self.env['hr.salary.rule'].browse(sorted_rule_ids)
for contract in contracts: for contract in contracts:
@ -331,19 +342,19 @@ class HrPayslip(models.Model):
localdict['result'] = None localdict['result'] = None
localdict['result_qty'] = 1.0 localdict['result_qty'] = 1.0
localdict['result_rate'] = 100 localdict['result_rate'] = 100
#check if the rule can be applied # check if the rule can be applied
if rule._satisfy_condition(localdict) and rule.id not in blacklist: if rule._satisfy_condition(localdict) and rule.id not in blacklist:
#compute the amount of the rule # compute the amount of the rule
amount, qty, rate = rule._compute_rule(localdict) amount, qty, rate = rule._compute_rule(localdict)
#check if there is already a rule computed with that code # check if there is already a rule computed with that code
previous_amount = rule.code in localdict and localdict[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 # set/overwrite the amount computed for this rule in the localdict
tot_rule = amount * qty * rate / 100.0 tot_rule = amount * qty * rate / 100.0
localdict[rule.code] = tot_rule localdict[rule.code] = tot_rule
rules_dict[rule.code] = rule rules_dict[rule.code] = rule
#sum the amount for its salary category # sum the amount for its salary category
localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount)
#create/overwrite the rule in the temporary results # create/overwrite the rule in the temporary results
result_dict[key] = { result_dict[key] = {
'salary_rule_id': rule.id, 'salary_rule_id': rule.id,
'contract_id': contract.id, 'contract_id': contract.id,
@ -369,7 +380,7 @@ class HrPayslip(models.Model):
'rate': rate, 'rate': rate,
} }
else: else:
#blacklist this rule and its children # blacklist this rule and its children
blacklist += [id for id, seq in rule._recursive_search_of_rules()] blacklist += [id for id, seq in rule._recursive_search_of_rules()]
return list(result_dict.values()) return list(result_dict.values())
@ -377,15 +388,15 @@ class HrPayslip(models.Model):
# YTI TODO To rename. This method is not really an onchange, as it is not in any view # YTI TODO To rename. This method is not really an onchange, as it is not in any view
# employee_id and contract_id could be browse records # employee_id and contract_id could be browse records
def onchange_employee_id(self, date_from, date_to, employee_id=False, contract_id=False): def onchange_employee_id(self, date_from, date_to, employee_id=False, contract_id=False):
#defaults # defaults
res = { res = {
'value': { 'value': {
'line_ids': [], 'line_ids': [],
#delete old input lines # delete old input lines
'input_line_ids': [(2, x,) for x in self.input_line_ids.ids], 'input_line_ids': [(2, x,) for x in self.input_line_ids.ids],
#delete old worked days lines # delete old worked days lines
'worked_days_line_ids': [(2, x,) for x in self.worked_days_line_ids.ids], 'worked_days_line_ids': [(2, x,) for x in self.worked_days_line_ids.ids],
#'details_by_salary_head':[], TODO put me back # 'details_by_salary_head':[], TODO put me back
'name': '', 'name': '',
'contract_id': False, 'contract_id': False,
'struct_id': False, 'struct_id': False,
@ -397,19 +408,20 @@ class HrPayslip(models.Model):
employee = self.env['hr.employee'].browse(employee_id) employee = self.env['hr.employee'].browse(employee_id)
locale = self.env.context.get('lang') or 'en_US' locale = self.env.context.get('lang') or 'en_US'
res['value'].update({ res['value'].update({
'name': _('Salary Slip of %s for %s') % (employee.name, tools.ustr(babel.dates.format_date(date=ttyme, format='MMMM-y', locale=locale))), 'name': _('Salary Slip of %s for %s') % (
employee.name, tools.ustr(babel.dates.format_date(date=ttyme, format='MMMM-y', locale=locale))),
'company_id': employee.company_id.id, 'company_id': employee.company_id.id,
}) })
if not self.env.context.get('contract'): if not self.env.context.get('contract'):
#fill with the first contract of the employee # fill with the first contract of the employee
contract_ids = self.get_contract(employee, date_from, date_to) contract_ids = self.get_contract(employee, date_from, date_to)
else: else:
if contract_id: if contract_id:
#set the list of contract for which the input have to be filled # set the list of contract for which the input have to be filled
contract_ids = [contract_id] contract_ids = [contract_id]
else: else:
#if we don't give the contract, then the input to fill should be for all current contracts of the employee # 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(employee, date_from, date_to) contract_ids = self.get_contract(employee, date_from, date_to)
if not contract_ids: if not contract_ids:
@ -424,7 +436,7 @@ class HrPayslip(models.Model):
res['value'].update({ res['value'].update({
'struct_id': struct.id, 'struct_id': struct.id,
}) })
#computation of the salary input # computation of the salary input
contracts = self.env['hr.contract'].browse(contract_ids) contracts = self.env['hr.contract'].browse(contract_ids)
worked_days_line_ids = self.get_worked_day_lines(contracts, date_from, date_to) worked_days_line_ids = self.get_worked_day_lines(contracts, date_from, date_to)
input_line_ids = self.get_inputs(contracts, date_from, date_to) input_line_ids = self.get_inputs(contracts, date_from, date_to)
@ -447,7 +459,8 @@ class HrPayslip(models.Model):
ttyme = datetime.combine(fields.Date.from_string(date_from), time.min) ttyme = datetime.combine(fields.Date.from_string(date_from), time.min)
locale = self.env.context.get('lang') or 'en_US' locale = self.env.context.get('lang') or 'en_US'
self.name = _('Salary Slip of %s for %s') % (employee.name, tools.ustr(babel.dates.format_date(date=ttyme, format='MMMM-y', locale=locale))) self.name = _('Salary Slip of %s for %s') % (
employee.name, tools.ustr(babel.dates.format_date(date=ttyme, format='MMMM-y', locale=locale)))
self.company_id = employee.company_id self.company_id = employee.company_id
if not self.env.context.get('contract') or not self.contract_id: if not self.env.context.get('contract') or not self.contract_id:
@ -459,8 +472,9 @@ class HrPayslip(models.Model):
if not self.contract_id.struct_id: if not self.contract_id.struct_id:
return return
self.struct_id = self.contract_id.struct_id self.struct_id = self.contract_id.struct_id
if self.contract_id:
#computation of the salary input contract_ids = self.contract_id.ids
# computation of the salary input
contracts = self.env['hr.contract'].browse(contract_ids) contracts = self.env['hr.contract'].browse(contract_ids)
worked_days_line_ids = self.get_worked_day_lines(contracts, date_from, date_to) worked_days_line_ids = self.get_worked_day_lines(contracts, date_from, date_to)
worked_days_lines = self.worked_days_line_ids.browse([]) worked_days_lines = self.worked_days_line_ids.browse([])
@ -497,14 +511,14 @@ class HrPayslipLine(models.Model):
_description = 'Payslip Line' _description = 'Payslip Line'
_order = 'contract_id, sequence' _order = 'contract_id, sequence'
slip_id = fields.Many2one('hr.payslip', string='Pay Slip', required=True, ondelete='cascade') slip_id = fields.Many2one('hr.payslip', string='Pay Slip', required=True, ondelete='cascade', help="Payslip")
salary_rule_id = fields.Many2one('hr.salary.rule', string='Rule', required=True) salary_rule_id = fields.Many2one('hr.salary.rule', string='Rule', required=True, help="salary rule")
employee_id = fields.Many2one('hr.employee', string='Employee', required=True) employee_id = fields.Many2one('hr.employee', string='Employee', required=True, help="Employee")
contract_id = fields.Many2one('hr.contract', string='Contract', required=True, index=True) contract_id = fields.Many2one('hr.contract', string='Contract', required=True, index=True, help="Contract")
rate = fields.Float(string='Rate (%)', digits=dp.get_precision('Payroll Rate'), default=100.0) rate = fields.Float(string='Rate (%)', digits=dp.get_precision('Payroll Rate'), default=100.0)
amount = fields.Float(digits=dp.get_precision('Payroll')) amount = fields.Float(digits=dp.get_precision('Payroll'))
quantity = fields.Float(digits=dp.get_precision('Payroll'), default=1.0) quantity = fields.Float(digits=dp.get_precision('Payroll'), default=1.0)
total = fields.Float(compute='_compute_total', string='Total', digits=dp.get_precision('Payroll'), store=True) total = fields.Float(compute='_compute_total', string='Total', help="Total", digits=dp.get_precision('Payroll'), store=True)
@api.depends('quantity', 'amount', 'rate') @api.depends('quantity', 'amount', 'rate')
def _compute_total(self): def _compute_total(self):
@ -529,11 +543,11 @@ class HrPayslipWorkedDays(models.Model):
_order = 'payslip_id, sequence' _order = 'payslip_id, sequence'
name = fields.Char(string='Description', required=True) name = fields.Char(string='Description', required=True)
payslip_id = fields.Many2one('hr.payslip', string='Pay Slip', required=True, ondelete='cascade', index=True) payslip_id = fields.Many2one('hr.payslip', string='Pay Slip', required=True, ondelete='cascade', index=True, help="Payslip")
sequence = fields.Integer(required=True, index=True, default=10) sequence = fields.Integer(required=True, index=True, default=10, help="Sequence")
code = fields.Char(required=True, help="The code that can be used in the salary rules") code = fields.Char(required=True, help="The code that can be used in the salary rules")
number_of_days = fields.Float(string='Number of Days') number_of_days = fields.Float(string='Number of Days', help="Number of days worked")
number_of_hours = fields.Float(string='Number of Hours') number_of_hours = fields.Float(string='Number of Hours', help="Number of hours worked")
contract_id = fields.Many2one('hr.contract', string='Contract', required=True, contract_id = fields.Many2one('hr.contract', string='Contract', required=True,
help="The contract for which applied this input") help="The contract for which applied this input")
@ -544,8 +558,8 @@ class HrPayslipInput(models.Model):
_order = 'payslip_id, sequence' _order = 'payslip_id, sequence'
name = fields.Char(string='Description', required=True) name = fields.Char(string='Description', required=True)
payslip_id = fields.Many2one('hr.payslip', string='Pay Slip', required=True, ondelete='cascade', index=True) payslip_id = fields.Many2one('hr.payslip', string='Pay Slip', required=True, ondelete='cascade', help="Payslip", index=True)
sequence = fields.Integer(required=True, index=True, default=10) sequence = fields.Integer(required=True, index=True, default=10, help="Sequence")
code = fields.Char(required=True, help="The code that can be used in the salary rules") code = fields.Char(required=True, help="The code that can be used in the salary rules")
amount = fields.Float(help="It is used in computation. For e.g. A rule for sales having " amount = fields.Float(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 " "1% commission of basic salary for per product can defined in expression "
@ -565,14 +579,17 @@ class HrPayslipRun(models.Model):
('draft', 'Draft'), ('draft', 'Draft'),
('close', 'Close'), ('close', 'Close'),
], string='Status', index=True, readonly=True, copy=False, default='draft') ], string='Status', index=True, readonly=True, copy=False, default='draft')
date_start = fields.Date(string='Date From', required=True, readonly=True, date_start = fields.Date(string='Date From', required=True, readonly=True, help="start date",
states={'draft': [('readonly', False)]}, default=lambda self: fields.Date.to_string(date.today().replace(day=1))) states={'draft': [('readonly', False)]},
date_end = fields.Date(string='Date To', required=True, readonly=True, default=lambda self: fields.Date.to_string(date.today().replace(day=1)))
date_end = fields.Date(string='Date To', required=True, readonly=True, help="End date",
states={'draft': [('readonly', False)]}, states={'draft': [('readonly', False)]},
default=lambda self: fields.Date.to_string((datetime.now() + relativedelta(months=+1, day=1, days=-1)).date())) default=lambda self: fields.Date.to_string(
(datetime.now() + relativedelta(months=+1, day=1, days=-1)).date()))
credit_note = fields.Boolean(string='Credit Note', readonly=True, credit_note = fields.Boolean(string='Credit Note', readonly=True,
states={'draft': [('readonly', False)]}, states={'draft': [('readonly', False)]},
help="If its checked, indicates that all payslips generated from here are refund payslips.") help="If its checked, indicates that all payslips generated from here are refund "
"payslips.")
def draft_payslip_run(self): def draft_payslip_run(self):
return self.write({'state': 'draft'}) return self.write({'state': 'draft'})
@ -580,6 +597,7 @@ class HrPayslipRun(models.Model):
def close_payslip_run(self): def close_payslip_run(self):
return self.write({'state': 'close'}) return self.write({'state': 'close'})
class ResourceMixin(models.AbstractModel): class ResourceMixin(models.AbstractModel):
_inherit = "resource.mixin" _inherit = "resource.mixin"

27
hr_payroll_community/views/hr_contract_views.xml

@ -2,7 +2,8 @@
<odoo> <odoo>
<!-- Root Menus --> <!-- Root Menus -->
<menuitem id="menu_hr_payroll_community_root" name="Payroll" sequence="45" web_icon="hr_payroll_community,static/description/icon.png"/> <menuitem id="menu_hr_payroll_community_root" name="Payroll" sequence="45"
web_icon="hr_payroll_community,static/description/icon.png"/>
<menuitem id="menu_hr_payroll_community_configuration" name="Configuration" parent="menu_hr_payroll_community_root" <menuitem id="menu_hr_payroll_community_configuration" name="Configuration" parent="menu_hr_payroll_community_root"
sequence="100" groups="hr_payroll_community.group_hr_payroll_community_manager"/> sequence="100" groups="hr_payroll_community.group_hr_payroll_community_manager"/>
@ -16,7 +17,7 @@
<field name="struct_id" required="1"/> <field name="struct_id" required="1"/>
</xpath> </xpath>
<xpath expr="//field[@name='type_id']" position="before"> <xpath expr="//field[@name='type_id']" position="before">
<field name="company_id" groups="base.group_multi_company"/> <!-- <field name="company_id" groups="base.group_multi_company"/>-->
<field name="currency_id" invisible="1"/> <field name="currency_id" invisible="1"/>
</xpath> </xpath>
<xpath expr="//field[@name='resource_calendar_id']" position="after"> <xpath expr="//field[@name='resource_calendar_id']" position="after">
@ -53,6 +54,28 @@
</field> </field>
</record> </record>
<record id="hr_contract_form_additional_allowance" model="ir.ui.view">
<field name="name">hr.contract.view.additional.allowance</field>
<field name="model">hr.contract</field>
<field name="inherit_id" ref="hr_contract.hr_contract_view_form"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='salary_and_advantages']" position="after">
<group name="allowances" string="Allowance">
<group>
<field name="hra"/>
<field name="da"/>
<field name="travel_allowance"/>
<field name="meal_allowance"/>
<field name="medical_allowance"/>
<field name="other_allowance"/>
</group>
</group>
</xpath>
</field>
</record>
<record id="hr_contract_advantage_template_view_tree" model="ir.ui.view"> <record id="hr_contract_advantage_template_view_tree" model="ir.ui.view">
<field name="name">hr.contract.advantage.template.tree</field> <field name="name">hr.contract.advantage.template.tree</field>
<field name="model">hr.contract.advantage.template</field> <field name="model">hr.contract.advantage.template</field>

Loading…
Cancel
Save