odex30_standard/exp_payroll_custom/models/hr_contract.py

354 lines
18 KiB
Python

# -*- coding: utf-8 -*-
from datetime import datetime
from odoo import models, fields, api, _
from odoo.exceptions import UserError
class HrContractSalaryScale(models.Model):
_inherit = 'hr.contract'
salary_level = fields.Many2one(comodel_name='hr.payroll.structure', domain=[('id', 'in', [])])
salary_scale = fields.Many2one(comodel_name='hr.payroll.structure', domain=[('id', 'in', [])], index=True)
salary_group = fields.Many2one(comodel_name='hr.payroll.structure', domain=[('id', 'in', [])])
salary_degree = fields.Many2one(comodel_name='hr.payroll.structure', domain=[('id', 'in', [])])
hide = fields.Boolean(string='Hide', compute="compute_type")
required_condition = fields.Boolean(string='Required Condition', compute='compute_move_type')
total_allowance = fields.Float(string='Total Allowance', compute='compute_function',store=True)
total_deduction = fields.Float(string='Total Deduction', compute='compute_function',store=True)
total_net = fields.Float(string='Total Net', compute='compute_function',store=True)
advantages = fields.One2many('contract.advantage', 'contract_advantage_id', string='Advantages')
house_allowance_temp = fields.Float(string='House Allowance', compute='compute_function',store=True)
transport_allowance = fields.Float(string='Transport Allowance', compute='compute_function',store=True)
@api.constrains('advantages', 'salary', 'salary_group')
def amount_constrains(self):
for rec in self:
localdict = dict(employee=rec.employee_id.id, contract=rec.env['hr.contract'].search([
('employee_id', '=', rec.employee_id.id)]))
if rec.salary_group.gread_max > 0 and rec.salary_group.gread_min > 0:
if rec.salary > rec.salary_group.gread_max or rec.salary < rec.salary_group.gread_min:
raise UserError(_('The Basic Salary Is Greater Than Group Gread Max Or less than Gread Min'))
for item in self.advantages:
item.to_get_contract_id()
if item.benefits_discounts._compute_rule(localdict)[0] < item.amount and item.type == 'exception':
raise UserError(_(
'The amount you put is greater than fact value of this Salary rule %s (%s).') % (
item.benefits_discounts.name, item.benefits_discounts.code))
@api.depends('salary_scale.transfer_type')
def compute_move_type(self):
self.compute_function()
if self.salary_scale.transfer_type == 'one_by_one':
self.required_condition = True
else:
self.required_condition = False
@api.depends('salary_scale', 'salary_level', 'salary_group', 'salary_degree','salary','advantages','house_allowance_temp','transport_allowance','total_deduction','salary_insurnce','total_allowance','state')
def compute_function(self):
for item in self:
item.house_allowance_temp = 0
item.transport_allowance = 0
item.total_net = 0
contract = self.env['hr.contract'].search([('employee_id', '=', item.employee_id.id)])
localdict = dict(employee=item.employee_id.id, contract=contract)
current_date = datetime.now().date()
# customize type in advantages
allowance_customize_items = item.advantages.filtered(
lambda key: key.type == 'customize' and key.out_rule is False and
key.benefits_discounts.category_id.rule_type == 'allowance' and
(datetime.strptime(str(key.date_to), "%Y-%m-%d").date() if key.date_to else current_date)
>= current_date >= datetime.strptime(str(key.date_from), "%Y-%m-%d").date())
allow_sum_custom = sum(x.amount for x in allowance_customize_items)
for x in allowance_customize_items:
if x.benefits_discounts.rules_type == 'house':
item.house_allowance_temp += x.amount
if x.benefits_discounts.rules_type == 'transport':
item.transport_allowance += x.amount
# allow_custom_ids = [record.benefits_discounts.id for record in allowance_customize_items]
deduction_customize_items = item.advantages.filtered(
lambda key: key.type == 'customize' and key.out_rule is False and
key.benefits_discounts.category_id.rule_type == 'deduction' and
(datetime.strptime(str(key.date_to), "%Y-%m-%d").date() if key.date_to else current_date)
>= current_date >= datetime.strptime(str(key.date_from), "%Y-%m-%d").date())
ded_sum_custom = sum(x.amount for x in deduction_customize_items)
ded_custom_ids = [record.benefits_discounts.id for record in deduction_customize_items]
# exception type in advantages
exception_items = item.advantages.filtered(lambda key: key.type == 'exception')
total_rule_result, sum_except, sum_customize_expect = 0.0, 0.0, 0.0
for x in exception_items:
rule_result = x.benefits_discounts._compute_rule(localdict)[0]
if x.date_from >= str(current_date):
total_rule_result = rule_result
elif str(current_date) > x.date_from:
if x.date_to and str(current_date) <= x.date_to:
total_rule_result = rule_result - x.amount
elif x.date_to and str(current_date) >= x.date_to:
total_rule_result = 0 # rule_result
elif not x.date_to:
total_rule_result = rule_result - x.amount
else:
if rule_result > x.amount:
total_rule_result = rule_result - x.amount
if total_rule_result:
if x.benefits_discounts.category_id.rule_type == 'allowance':
sum_customize_expect += total_rule_result
if x.benefits_discounts.rules_type == 'house':
item.house_allowance_temp += total_rule_result - x.amount
else:
sum_except += total_rule_result
if exception_items:
exception_items = item.advantages.filtered(
lambda key: (datetime.strptime(str(key.date_to),
"%Y-%m-%d").date().month if key.date_to else current_date.month)
>= current_date.month >= datetime.strptime(str(key.date_from), "%Y-%m-%d").date().month)
except_ids = [record.benefits_discounts.id for record in exception_items]
rule_ids = item.salary_scale.rule_ids.filtered(
lambda key: key.id not in ded_custom_ids and key.id not in except_ids)
level_rule_ids = item.salary_level.benefits_discounts_ids.filtered(lambda key: key.id not in except_ids)
# key.id not in allow_custom_ids and key.id not in ded_custom_ids and
group_rule_ids = item.salary_group.benefits_discounts_ids.filtered(lambda key: key.id not in except_ids)
# key.id not in allow_custom_ids and key.id not in ded_custom_ids and
total_allowance = 0
total_ded = 0
for line in rule_ids:
if line.category_id.rule_type == 'allowance':
try:
total_allowance += line._compute_rule(localdict)[0]
except:
total_allowance += 0
if line.category_id.rule_type == 'deduction':
try:
total_ded += line._compute_rule(localdict)[0]
except:
total_ded += 0
if line.rules_type == 'house':
item.house_allowance_temp += line._compute_rule(localdict)[0]
if line.rules_type == 'transport':
item.transport_allowance += line._compute_rule(localdict)[0]
item.total_allowance = total_allowance
item.total_deduction = -total_ded
if item.salary_level:
total_allowance = 0
total_deduction = 0
for line in level_rule_ids:
if line.category_id.rule_type == 'allowance':
try:
total_allowance += line._compute_rule(localdict)[0]
except:
total_allowance += 0
elif line.category_id.rule_type == 'deduction':
try:
total_deduction += line._compute_rule(localdict)[0]
except:
total_deduction += 0
item.total_allowance += total_allowance
item.total_deduction += -total_deduction
if item.salary_group:
total_allowance = 0
total_deduction = 0
for line in group_rule_ids:
if line.category_id.rule_type == 'allowance':
total_allowance += line._compute_rule(localdict)[0]
elif line.category_id.rule_type == 'deduction':
total_deduction += line._compute_rule(localdict)[0]
item.total_allowance += total_allowance
item.total_deduction += -total_deduction
item.total_allowance += allow_sum_custom
item.total_allowance += sum_customize_expect
item.total_deduction += -ded_sum_custom
item.total_deduction += -sum_except
item.total_net = item.total_allowance + item.total_deduction
# filter salary_level,salary_group,salary_degree
@api.onchange('salary_scale')
def onchange_salary_scale(self):
for item in self:
if item.salary_scale:
level_ids = self.env['hr.payroll.structure'].search(
[('salary_scale_id', '=', item.salary_scale.id), ('type', '=', 'level')])
group_ids = self.env['hr.payroll.structure'].search(
[('salary_scale_id', '=', item.salary_scale.id), ('type', '=', 'group')])
degree_ids = self.env['hr.payroll.structure'].search(
[('salary_scale_id', '=', item.salary_scale.id), ('type', '=', 'degree')])
return {'domain': {'salary_level': [('id', 'in', level_ids.ids)],
'salary_group': [('id', 'in', group_ids.ids)],
'salary_degree': [('id', 'in', degree_ids.ids)]}}
else:
item.total_allowance = 0.0
item.total_deduction = 0.0
item.total_net = 0.0
return {'domain': {'salary_level': [('id', 'in', [])],
'salary_group': [('id', 'in', [])],
'salary_degree': [('id', 'in', [])]}}
# filter depend on salary_level
@api.onchange('salary_level')
def onchange_salary_level(self):
for item in self:
if item.salary_level:
group_ids = self.env['hr.payroll.structure'].search(
[('salary_scale_level_id', '=', item.salary_level.id), ('type', '=', 'group')])
return {'domain': {'salary_group': [('id', 'in', group_ids.ids)],
'salary_degree': [('id', 'in', [])]}}
else:
return {'domain': {'salary_group': [('id', 'in', [])],
'salary_degree': [('id', 'in', [])]}}
# filter depend on salary_group
@api.onchange('salary_group')
def onchange_salary_group(self):
for item in self:
if item.salary_group:
degree_ids = self.env['hr.payroll.structure'].search(
[('salary_scale_group_id', '=', item.salary_group.id), ('type', '=', 'degree')])
return {'domain': {'salary_degree': [('id', 'in', degree_ids.ids)]}}
else:
return {'domain': {'salary_degree': [('id', 'in', [])]}}
@api.depends('salary_degree')
def _get_amount(self):
for record in self:
record.transport_allowance_temp = record.transport_allowance * record.wage / 100 \
if record.transport_allowance_type == 'perc' else record.transport_allowance
record.house_allowance_temp = record.house_allowance * record.wage / 100 \
if record.house_allowance_type == 'perc' else record.house_allowance
record.communication_allowance_temp = record.communication_allowance * record.wage / 100 \
if record.communication_allowance_type == 'perc' else record.communication_allowance
record.field_allowance_temp = record.field_allowance * record.wage / 100 \
if record.field_allowance_type == 'perc' else record.field_allowance
record.special_allowance_temp = record.special_allowance * record.wage / 100 \
if record.special_allowance_type == 'perc' else record.special_allowance
record.other_allowance_temp = record.other_allowance * record.wage / 100 \
if record.other_allowance_type == 'perc' else record.other_allowance
@api.depends('contractor_type.salary_type')
def compute_type(self):
if self.contractor_type.salary_type == 'scale':
self.hide = True
else:
self.hide = False
class Advantages(models.Model):
_name = 'contract.advantage'
_rec_name = 'benefits_discounts'
_inherit = ['mail.thread', 'mail.activity.mixin']
date_from = fields.Date(string='Date From')
date_to = fields.Date(string='Date To')
amount = fields.Float(string='Amount', tracking=True)
type = fields.Selection(selection=[
('customize', 'Customize'),
('exception', 'Exception')
], string='Type', default="customize")
# to link employee move line from official mission to advantages line in contract
official_mission_id = fields.Boolean(string="Official Mission", default=False)
# To link employee move line from over time to advantages line in contract
over_time_id = fields.Boolean(string="OverTime", default=False)
# To link employee move line from employee reward to advantages line in contract
reward_id = fields.Boolean(string="Reward", default=False)
penalty_id = fields.Boolean(string='Penalty Name', default=False)
# Relational fields
benefits_discounts = fields.Many2one(comodel_name='hr.salary.rule', string='Benefits/Discounts')
contract_advantage_id = fields.Many2one('hr.contract')
done = fields.Boolean(string="Done in Payroll")
out_rule = fields.Boolean(string="Out of Payroll", default=True)
employee_id = fields.Many2one('hr.employee', 'Employee Name', domain=[('state', '=', 'open')], tracking=True)
state = fields.Selection(selection=[
('draft', 'Draft'),
('confirm', 'Confirmed'),
('refused', 'Refused')
], default='draft', tracking=True)
comments = fields.Text(string='Comments')
payroll_month = fields.Text(string='Payroll Month', tracking=True)
company_id = fields.Many2one('res.company', string='Company', related='employee_id.company_id', store=True)
@api.constrains('date_from', 'date_to', 'amount')
def _chick_date(self):
for rec in self:
if rec.date_to:
if rec.date_to <= rec.date_from:
raise UserError(_('The Date Form Must be Less than Date To'))
if rec.amount <= 0:
raise UserError(_('The Amount Must be Greater Than Zero The Employee %s')% rec.employee_id.name)
def confirm(self):
self.state = 'confirm'
def refused(self):
self.state = 'refused'
def draft(self):
for rec in self:
rec.state = 'draft'
@api.onchange('employee_id')
def to_get_contract_id(self):
contract_id = self.employee_id.contract_id
self.employee_id = self.contract_advantage_id.employee_id.id
if contract_id:
self.contract_advantage_id = contract_id.id
self.employee_id = self.contract_advantage_id.employee_id.id
else:
return False
def unlink(self):
for item in self:
if item.state != 'draft':
raise UserError(_('You cannot delete The Salary rule %s For the Employee %s is Not Draft') % (
item.benefits_discounts.name, item.employee_id.name))
# if item.done == True:
# raise UserError(_('Sorry, The Salary rule %s For the Employee %s is Already Computed in Payroll') % (
# item.benefits_discounts.name, item.employee_id.name))
return super(Advantages, self).unlink()
@api.constrains('employee_id', 'date_from', 'date_to', 'benefits_discounts')
def check_rule_dates(self):
""" Function Can Not add Same Advantage at The Same Month
same employee.
"""
for rec in self:
domain = [
('date_from', '<=', rec.date_to),
('date_to', '>=', rec.date_from),
('employee_id', '=', rec.employee_id.id),
('id', '!=', rec.id),
('benefits_discounts', '=', rec.benefits_discounts.id), ]
advantages_id = self.search_count(domain)
if advantages_id:
# for adv in advantages_id:
raise UserError(
_('You Can Not add Same Allowance/Deduction at The Same Employee %s For The Same Month!')
% rec.employee_id.name)