# -*- coding: utf-8 -*- from datetime import datetime from odoo import models, fields, api, _ from odoo.exceptions import UserError # -*- 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, contract=rec) 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 rec.advantages: if item.type == 'exception': rule_val = item.benefits_discounts._compute_rule(localdict)[0] if rule_val < item.amount: 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', 'total_allowance', 'state') def compute_function(self): for item in self: item.house_allowance_temp = 0 item.transport_allowance = 0 item.total_net = 0 localdict = dict(employee=item.employee_id, contract=item) current_date = fields.Date.today() 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 (key.date_to if key.date_to else current_date) >= current_date >= key.date_from ) 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 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 (key.date_to if key.date_to else current_date) >= current_date >= key.date_from ) ded_sum_custom = sum(x.amount for x in deduction_customize_items) ded_custom_ids = deduction_customize_items.mapped('benefits_discounts.id') exception_items = item.advantages.filtered(lambda key: key.type == 'exception') if exception_items: exception_items = exception_items.filtered( lambda key: (key.date_to.month if key.date_to else current_date.month) >= current_date.month >= key.date_from.month ) 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 >= current_date: total_rule_result = rule_result elif current_date > x.date_from: if x.date_to and current_date <= x.date_to: total_rule_result = rule_result - x.amount elif x.date_to and current_date >= x.date_to: total_rule_result = 0 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 except_ids = exception_items.mapped('benefits_discounts.id') rule_ids = item.salary_scale.rule_ids.filtered( lambda key: key.id not in ded_custom_ids and key.id not in except_ids) if item.salary_level: rule_ids += item.salary_level.rule_ids.filtered( lambda key: key.id not in except_ids) if item.salary_group: rule_ids += item.salary_group.rule_ids.filtered( lambda key: key.id not in except_ids) total_allowance = 0 total_ded = 0 for line in rule_ids: try: amount = line._compute_rule(localdict)[0] except Exception: amount = 0.0 if line.category_id.rule_type == 'allowance': total_allowance += amount elif line.category_id.rule_type == 'deduction': total_ded += amount if line.rules_type == 'house': item.house_allowance_temp += amount if line.rules_type == 'transport': item.transport_allowance += amount item.total_allowance = total_allowance + allow_sum_custom + sum_customize_expect item.total_deduction = -(total_ded + ded_sum_custom + sum_except) item.total_net = item.total_allowance + item.total_deduction @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', [])]}} @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', [])]}} @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('contractor_type.salary_type') def compute_type(self): for rec in self: if rec.contractor_type.salary_type == 'scale': rec.hide = True else: rec.hide = False # # 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 >= current_date: # total_rule_result = rule_result # elif current_date > x.date_from: # if x.date_to and current_date <= x.date_to: # total_rule_result = rule_result - x.amount # elif x.date_to and 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: (key.date_to.month if key.date_to else current_date.month) # >= current_date.month >= key.date_from.month) # # if exception_items: # # exception_items = item.advantages.filtered( # # lambda key: (datetime.strptime(key.date_to, # # "%Y-%m-%d").date().month if key.date_to else current_date.month) # # >= current_date.month >= datetime.strptime(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 # # # # filter depend on salary_level # # # # filter depend on salary_group # # # # @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)