# -*- coding: utf-8 -*- import itertools as it import time from datetime import datetime, timedelta from operator import itemgetter import babel from dateutil.relativedelta import relativedelta from odoo import api, fields, models, tools, _ from odoo.exceptions import UserError # solve Python uses "round half to even" by default from decimal import Decimal, ROUND_HALF_UP # New object for loans lines in payslip class PayslipLoans(models.Model): _name = 'payslip.loans' name = fields.Char(string='Name') code = fields.Char(string='Code') amount = fields.Float(string='Amount') date = fields.Date(string='Installment Date') paid = fields.Boolean() # Relational field payslip_loan = fields.Many2one('hr.payslip', ondelete='cascade') account_id = fields.Many2one('account.account') class SalaryRuleInput(models.Model): _inherit = 'hr.payslip' total_allowances = fields.Float(string='Total Allowance', compute='compute_totals') total_deductions = fields.Float(string='Total Deduction', compute='compute_totals') total_loans = fields.Float(string='Total Loans', compute='compute_totals') total_sum = fields.Float(string='Total Net', compute='compute_totals') state = fields.Selection(selection_add=[('computed', 'Computed'), ('confirmed', 'Confirmed'), ('transfered', 'Transfer'), ('close', 'Close')], tracking=True) level_id = fields.Many2one('hr.payroll.structure', string='Level', readonly=True) group_id = fields.Many2one('hr.payroll.structure', string='Group', readonly=True) degree_id = fields.Many2one('hr.payroll.structure', string='Degree', readonly=True) # Relational fields allowance_ids = fields.One2many('hr.payslip.line', 'payslip_allowance', string='Allowances', index=True) deduction_ids = fields.One2many('hr.payslip.line', 'payslip_deduction', string='Deductions', index=True) loan_ids = fields.One2many('payslip.loans', 'payslip_loan', string='Loans', index=True) employee_id = fields.Many2one('hr.employee', string='Employee', required=True, readonly=False, domain="[('state','=','open')]", index=True) # TODO: Add readonly logic in XML view: readonly="state != 'draft'" contract_id = fields.Many2one('hr.contract', string='Contract', readonly=True, related='employee_id.contract_id') struct_id = fields.Many2one('hr.payroll.structure', string='Structure', readonly=True, related='employee_id.contract_id.salary_scale', 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') percentage = fields.Float(string='Percentage', default=100) move_id = fields.Many2one('account.move', string="Move Number") # bank_id = fields.Many2one(related='employee_id.bank_account_id.bank_id') basic_allowances = fields.Float(string='Basic Salary', compute='compute_allowances_') house_allowances = fields.Float(string='House Allowance', compute='compute_allowances_') trans_allowances = fields.Float(string='Transport Allowance', compute='compute_allowances_') other_allowances = fields.Float(string='Others Allowance', compute='compute_allowances_') employee_insurnce = fields.Float(string='Employee Insurnce', compute='compute_allowances_') company_insurnce = fields.Float(string='Company Insurnce', compute='compute_allowances_') employee_no = fields.Char(related='employee_id.emp_no', readonly=True,string='Employee Number', store=True) holiday_start_date = fields.Date(string="Holiday Start Date") holiday_end_date = fields.Date(string="Holiday End Date") def compute_allowances_(self): for item in self: item.basic_allowances = item.house_allowances = item.trans_allowances = item.employee_insurnce = item.company_insurnce = 0.0 for line in item.allowance_ids: if line.salary_rule_id.rules_type == 'salary': item.basic_allowances = line.total elif line.salary_rule_id.rules_type == 'house': item.house_allowances = line.total elif line.salary_rule_id.rules_type == 'transport': item.trans_allowances = line.total item.other_allowances = item.total_allowances - ( item.basic_allowances + item.house_allowances + item.trans_allowances) for line in item.deduction_ids: if line.salary_rule_id.rules_type == 'insurnce': item.employee_insurnce = line.total # TO Dooo '''if item.employee_insurnce and line.employee_id.contract_id.is_gosi_deducted=='yes': total_insurnce = item.employee_insurnce*100/10 item.company_insurnce = total_insurnce*12/100 else: item.company_insurnce = (item.basic_allowances + item.house_allowances)*2/100''' def confirm(self): self.write({'state': 'confirmed'}) def payslip_close(self): self.write({'state': 'close'}) def withdraw(self): payslip = self.env['hr.payslip'].search([('number', '=', self.number)]) if 'hr.loan.salary.advance' in self.env: loans = self.env['hr.loan.salary.advance'].search([('employee_id', '=', self.employee_id.id)]) if self.number == payslip.number: if self.loan_ids: for loan in self.loan_ids: loan.paid = False if loans: for i in loans: if i.id == loan.loan_id.id: for l in i.deduction_lines: if loan.date == l.installment_date and loan.paid is False: l.paid = False #i.remaining_loan_amount += l.installment_amount i.get_remaining_loan_amount() # check remaining loan and change state to pay if i.state == 'closed' and i.remaining_loan_amount > 0.0: i.state = 'pay' elif i.remaining_loan_amount == 0.0 and i.gm_propos_amount > 0.0: i.state = 'closed' for line in payslip.worked_days_line_ids: if line.name != 'Working days for this month': line.unlink() self.write({'allowance_ids': [fields.Command.clear()], 'deduction_ids': [fields.Command.clear()], 'loan_ids': [fields.Command.clear()]}) self.write({'state': 'draft'}) def return_button(self): if self.contract_id.advantages: for advantage_rule in self.contract_id.advantages: advantage_rule.write({'done': False}) if self.move_id: if self.move_id.state == 'posted': raise UserError(_('You can not Return account move %s in state not draft') % self.move_id.name) else: self.move_id.unlink() self.move_id = False if self.payslip_run_id: if self.payslip_run_id.move_id: raise UserError( _('You can not Return Payslips Patch Has account move %s') % self.payslip_run_id.move_id.name) self.write({'state': 'computed'}) def transfer(self): total_list = [] amount, amount1, amount2 = 0.0, 0.0, 0.0 total_allow, total_ded, total_loan = 0.0, 0.0, 0.0 #if self.struct_id.transfer_type == 'one_by_one': if self.struct_id.transfer_type == 'one_by_one' or self.struct_id.transfer_type == 'all' : for l in self.allowance_ids: amount_allow = l.total account = l.salary_rule_id.rule_debit_account_id total_list.append({ 'name': l.name, 'account_id': account.id, 'debit': amount_allow, 'partner_id': self.employee_id.user_id.partner_id.id, 'analytic_account_id': self.employee_id.contract_id.analytic_account_id.id, }) amount += amount_allow total_allow += amount for ded in self.deduction_ids: amount_ded = -ded.total account = ded.salary_rule_id.rule_credit_account_id total_list.append({ 'name': ded.name, 'account_id': account.id, 'credit': amount_ded, 'partner_id': self.employee_id.user_id.partner_id.id }) amount1 += amount_ded total_ded += amount1 for lo in self.loan_ids: amount_loans = -lo.amount total_list.append({ 'name': lo.name + ' (' + lo.code + ')', 'account_id': lo.account_id.id, 'credit': amount_loans, 'partner_id': self.employee_id.user_id.partner_id.id }) amount2 += amount_loans total_loan += amount2 # create line for total of all allowance, deduction, loans of one employee total = total_allow - total_ded - total_loan total_list.append({ 'name': self.name, 'account_id': self.contract_id.journal_id.default_account_id.id, 'partner_id': self.employee_id.user_id.partner_id.id, 'credit': total, }) if not self.contract_id.journal_id.id: raise UserError( _("Please be sure that the employee is linked to contract and contract linked with journal")) move = self.env['account.move'].create({ 'journal_id': self.contract_id.journal_id.id, 'date': self.date_to, 'ref': self.name, 'line_ids': [(0, 0, item) for item in total_list] }) self.move_id = move.id else: if self.employee_id.payment_method == 'bank': journal = self.env['account.journal'].search([('type', '=', self.employee_id.payment_method)], limit=1) if not journal: raise UserError( ' There is no journal For that Bank..' ' Please define a sale journal') else: journal = self.contract_id.journal_id for l in self.allowance_ids: amount_allow = l.total account = l.salary_rule_id.rule_debit_account_id total_list.append({ 'name': l.name, 'account_id': account.id, 'debit': amount_allow, 'partner_id': self.employee_id.user_id.partner_id.id }) amount += amount_allow total_allow += amount for ded in self.deduction_ids: amount_ded = -ded.total account = ded.salary_rule_id.rule_credit_account_id total_list.append({ 'name': ded.name, 'account_id': account.id, 'credit': amount_ded, 'partner_id': self.employee_id.user_id.partner_id.id }) amount1 += amount_ded total_ded += amount1 for lo in self.loan_ids: amount_loans = -lo.amount total_list.append({ 'name': lo.name + ' (' + lo.code + ')', 'account_id': lo.account_id.id, 'credit': amount_loans, 'partner_id': self.employee_id.user_id.partner_id.id }) total_loan += amount_loans # create line for total of all allowance, deduction, loans of one employee total = total_allow - total_ded - total_loan total_list.append({ 'name': "Total", 'account_id': journal.id, 'partner_id': self.employee_id.user_id.partner_id.id, 'credit': total, }) if not self.move_id: move = self.env['account.move'].create({ 'journal_id': journal.id, # 'date': fields.Date.context_today(self), 'date': self.date_to, 'ref': self.name, 'line_ids': [(0, 0, item) for item in total_list] }) self.move_id = move.id self.write({'state': 'transfered'}) def compute_totals(self): for item in self: item.total_allowances = item.total_deductions = item.total_loans = 0.0 for line in item.allowance_ids: allow_tot = line.total item.total_allowances += allow_tot for line in item.deduction_ids: ded_tot = line.total item.total_deductions += ded_tot for line in item.loan_ids: item.total_loans += line.amount item.total_sum = item.total_allowances + item.total_deductions + item.total_loans def get_inputs(self, contract_ids, date_from, date_to): """This Compute the other inputs to employee payslip.""" res = super(SalaryRuleInput, self).get_inputs(contract_ids, date_from, date_to) contract_obj = self.env['hr.contract'] emp_id = contract_obj.browse(contract_ids[0].id).employee_id adv_salary = self.env['salary.advance'].search([('employee_id', '=', emp_id.id)]) for adv_obj in adv_salary: current_date = datetime.strptime(str(date_from), '%Y-%m-%d').date().month date = adv_obj.date existing_date = datetime.strptime(str(date), '%Y-%m-%d').date().month if current_date == existing_date: state = adv_obj.state amount = adv_obj.advance for result in res: if state == 'approve' and amount != 0 and result.get('code') == 'SAR': result['amount'] = amount return res # Override function compute sheet in employee payslips def compute_sheet(self): for payslip in self: payslip_loans = [] amount = 0 flag = False number = payslip.number or self.env['ir.sequence'].next_by_code('salary.slip') # delete old payslip lines payslip.line_ids.unlink() # set the list of contract for which the rules have to be applied # if we don't give the contract, then the rules to apply should be for all current contracts of the employee contract_ids = payslip.contract_id.ids or \ self.get_contract(payslip.employee_id, payslip.date_from, payslip.date_to) # lines = [(0, 0, line) for line in self._get_payslip_lines(contract_ids, payslip.id)] # Holidays # holidays = self.env['hr.holidays'].search([('employee_id', '=', payslip.employee_id.id), ('state', '=', 'validate1')]).filtered( lambda item: item.employee_id.state == 'open') contract = self.env['hr.contract'].search([('employee_id', '=', payslip.employee_id.id)]) localdict = dict(employee=payslip.employee_id.id, contract=contract) number_of_days = 0 for line in payslip.worked_days_line_ids: if line.name == 'Unpaid Holidays For this month': line.unlink() elif line.name == 'Paid Holidays By percentage': line.unlink() elif line.name == 'Additional Paid Holidays': line.unlink() elif line.name == 'Exclusion or Reconcile Paid Holidays': line.unlink() for holiday in holidays: if holiday.date_from and holiday.date_to: holiday_date_from = datetime.strptime(str(holiday.date_from), '%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d') holiday_date_to = datetime.strptime(str(holiday.date_to), '%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d') payslip_date_from = str(payslip.date_from) payslip_date_to = str(payslip.date_to) if payslip.holiday_start_date and payslip.holiday_end_date: payslip_date_from = str(payslip.holiday_start_date) payslip_date_to = str(payslip.holiday_end_date) if holiday.holiday_status_id.payslip_type == 'unpaid': if payslip_date_to >= holiday_date_to and holiday_date_from >= payslip_date_from: payroll_start = datetime.strptime(payslip_date_from, "%Y-%m-%d").date() pyroll_end = datetime.strptime(payslip_date_to, "%Y-%m-%d").date() pyroll_days = relativedelta(pyroll_end, payroll_start).days + 1 number_of_days = holiday.number_of_days_temp if number_of_days >=28: if pyroll_days ==28: number_of_days= number_of_days + 2 if pyroll_days ==29: number_of_days= number_of_days + 1 if pyroll_days ==31: number_of_days= number_of_days - 1 if holiday.number_of_days_temp >= 0: # if holiday.number_of_days_temp <= 0: payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Unpaid Holidays For this month", 'sequence': 1, 'payslip_id': payslip.id, 'code': 'unpaid', 'number_of_days': number_of_days, 'number_of_hours': 0.0, 'contract_id': payslip.contract_id.id})] elif holiday_date_from >= payslip_date_from and payslip_date_to <= holiday_date_to and holiday_date_from <= payslip_date_to: payroll_start = datetime.strptime(payslip_date_from, "%Y-%m-%d").date() pyroll_end = datetime.strptime(payslip_date_to, "%Y-%m-%d").date() pyroll_days = relativedelta(pyroll_end, payroll_start).days + 1 start_date = datetime.strptime(str(holiday.date_from), "%Y-%m-%d").date() end_date = datetime.strptime(str(payslip.date_to), "%Y-%m-%d").date() number_of_days = relativedelta(end_date, start_date).days + 1 #if number_of_days >=28: if pyroll_days ==28: number_of_days= number_of_days + 2 if pyroll_days ==29: number_of_days= number_of_days + 1 if pyroll_days ==31: number_of_days= number_of_days - 1 if number_of_days >= 0: # number_of_days <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Unpaid Holidays For this month", 'sequence': 1, 'payslip_id': payslip.id, 'code': 'unpaid', 'number_of_days': number_of_days, 'number_of_hours': 0.0, 'contract_id': payslip.contract_id.id})] elif payslip_date_from >= holiday_date_from and payslip_date_to >= holiday_date_to and holiday_date_to >= payslip_date_from : payroll_start = datetime.strptime(payslip_date_from, "%Y-%m-%d").date() pyroll_end = datetime.strptime(payslip_date_to, "%Y-%m-%d").date() pyroll_days = relativedelta(pyroll_end, payroll_start).days + 1 start_date = datetime.strptime(payslip_date_from, "%Y-%m-%d").date() end_date = datetime.strptime(str(holiday.date_to), "%Y-%m-%d").date() number_of_days = relativedelta(end_date, start_date).days +1 if number_of_days >=28: if pyroll_days ==28: number_of_days= number_of_days + 2 if pyroll_days ==29: number_of_days= number_of_days + 1 if pyroll_days ==31: number_of_days= number_of_days - 1 if number_of_days >= 0: # number_of_days <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Unpaid Holidays For this month", 'sequence': 1, 'payslip_id': payslip.id, 'code': 'unpaid', 'number_of_days': number_of_days, 'number_of_hours': 0.0, 'contract_id': payslip.contract_id.id })] else: if payslip_date_to <= holiday_date_to and holiday_date_from <= payslip_date_from: #if payslip_date_to <= holiday_date_to: start_date = datetime.strptime(str(payslip.date_from), "%Y-%m-%d").date() end_date = datetime.strptime(str(payslip.date_to), "%Y-%m-%d").date() number_of_days = relativedelta(end_date, start_date).days + 1 if number_of_days ==28: number_of_days= number_of_days + 2 if number_of_days ==29: number_of_days= number_of_days + 1 if number_of_days ==31: number_of_days= number_of_days - 1 if number_of_days >= 0: # number_of_days <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Unpaid Holidays For this month", 'sequence': 1, 'payslip_id': payslip.id, 'code': 'unpaid', 'number_of_days': number_of_days, 'number_of_hours': 0.0, 'contract_id': payslip.contract_id.id})] elif holiday.holiday_status_id.payslip_type == 'percentage': #if payslip.date_from >= holiday.date_from and payslip.date_to >= holiday.date_to: if payslip_date_from >= holiday_date_from and payslip_date_to >= holiday_date_to: start_date = datetime.strptime(payslip_date_from, "%Y-%m-%d").date() end_date = datetime.strptime(holiday_date_to, "%Y-%m-%d").date() + timedelta( days=1) number_of_days = relativedelta(end_date, start_date).days if number_of_days >= 0: # number_of_days <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Paid Holidays By percentage", 'sequence': 1, 'payslip_id': payslip.id, 'code': 'percentage', 'number_of_days': number_of_days, 'number_of_hours': holiday.holiday_status_id.percentage, 'contract_id': payslip.contract_id.id})] elif payslip_date_to >= holiday_date_to and holiday_date_from >= payslip_date_from: if holiday.number_of_days_temp >= 0: # holiday.number_of_days_temp <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Paid Holidays By percentage", 'sequence': 1, 'payslip_id': payslip.id, 'code': 'percentage', 'number_of_days': holiday.number_of_days_temp, 'number_of_hours': holiday.holiday_status_id.percentage, 'contract_id': payslip.contract_id.id})] elif holiday_date_from >= payslip_date_from and payslip_date_to <= holiday_date_to: start_date = datetime.strptime(holiday_date_from, "%Y-%m-%d").date() end_date = datetime.strptime(payslip_date_to, "%Y-%m-%d").date() number_of_days = relativedelta(end_date, start_date).days + 1 if number_of_days >= 0: # number_of_days <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Paid Holidays By percentage", 'sequence': 1, 'payslip_id': payslip.id, 'code': 'percentage', 'number_of_days': number_of_days, 'number_of_hours': holiday.holiday_status_id.percentage, 'contract_id': payslip.contract_id.id})] else: if payslip_date_to <= holiday_date_to: start_date = datetime.strptime(payslip_date_from, "%Y-%m-%d").date() end_date = datetime.strptime(payslip_date_to, "%Y-%m-%d").date() + timedelta( days=1) number_of_days = relativedelta(end_date, start_date).days if number_of_days >= 0: # number_of_days <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Paid Holidays By percentage", 'sequence': 1, 'payslip_id': payslip.id, 'code': 'percentage', 'number_of_days': number_of_days, 'number_of_hours': holiday.holiday_status_id.percentage, 'contract_id': payslip.contract_id.id})] elif holiday.holiday_status_id.payslip_type == 'addition': if payslip_date_to >= holiday_date_to and holiday_date_from >= payslip_date_from: payroll_start = datetime.strptime(payslip_date_from, "%Y-%m-%d").date() pyroll_end = datetime.strptime(payslip_date_to, "%Y-%m-%d").date() pyroll_days = relativedelta(pyroll_end, payroll_start).days + 1 number_of_days = holiday.number_of_days_temp if number_of_days >= 28: if pyroll_days == 28: number_of_days = number_of_days + 2 if pyroll_days == 29: number_of_days = number_of_days + 1 if pyroll_days == 31: number_of_days = number_of_days - 1 if holiday.number_of_days_temp >= 0: # if holiday.number_of_days_temp <= 0: payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Additional Paid Holidays", 'sequence': 1, 'payslip_id': payslip.id, 'code': 'addition', 'number_of_days': number_of_days, 'number_of_hours': 0.0, 'contract_id': payslip.contract_id.id})] elif holiday_date_from >= payslip_date_from and payslip_date_to <= holiday_date_to and holiday_date_from <= payslip_date_to: payroll_start = datetime.strptime(payslip_date_from, "%Y-%m-%d").date() pyroll_end = datetime.strptime(payslip_date_to, "%Y-%m-%d").date() pyroll_days = relativedelta(pyroll_end, payroll_start).days + 1 start_date = datetime.strptime(str(holiday.date_from), "%Y-%m-%d").date() end_date = datetime.strptime(str(payslip.date_to), "%Y-%m-%d").date() number_of_days = relativedelta(end_date, start_date).days + 1 # if number_of_days >=28: if pyroll_days == 28: number_of_days = number_of_days + 2 if pyroll_days == 29: number_of_days = number_of_days + 1 if pyroll_days == 31: number_of_days = number_of_days - 1 if number_of_days >= 0: # number_of_days <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Additional Paid Holidays", 'sequence': 1, 'payslip_id': payslip.id, 'code': 'addition', 'number_of_days': number_of_days, 'number_of_hours': 0.0, 'contract_id': payslip.contract_id.id})] elif payslip_date_from >= holiday_date_from and payslip_date_to >= holiday_date_to and holiday_date_to >= payslip_date_from: payroll_start = datetime.strptime(payslip_date_from, "%Y-%m-%d").date() pyroll_end = datetime.strptime(payslip_date_to, "%Y-%m-%d").date() pyroll_days = relativedelta(pyroll_end, payroll_start).days + 1 start_date = datetime.strptime(payslip_date_from, "%Y-%m-%d").date() end_date = datetime.strptime(str(holiday.date_to), "%Y-%m-%d %H:%M:%S").date() number_of_days = relativedelta(end_date, start_date).days + 1 if number_of_days >= 28: if pyroll_days == 28: number_of_days = number_of_days + 2 if pyroll_days == 29: number_of_days = number_of_days + 1 if pyroll_days == 31: number_of_days = number_of_days - 1 if number_of_days >= 0: # number_of_days <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Additional Paid Holidays", 'sequence': 1, 'payslip_id': payslip.id, 'code': 'addition', 'number_of_days': number_of_days, 'number_of_hours': 0.0, 'contract_id': payslip.contract_id.id })] else: if payslip_date_to <= holiday_date_to and holiday_date_from <= payslip_date_from: # if payslip_date_to <= holiday_date_to: start_date = datetime.strptime(str(payslip.date_from), "%Y-%m-%d").date() end_date = datetime.strptime(str(payslip.date_to), "%Y-%m-%d").date() number_of_days = relativedelta(end_date, start_date).days + 1 if number_of_days == 28: number_of_days = number_of_days + 2 if number_of_days == 29: number_of_days = number_of_days + 1 if number_of_days == 31: number_of_days = number_of_days - 1 if number_of_days >= 0: # number_of_days <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Additional Paid Holidays", 'sequence': 1, 'payslip_id': payslip.id, 'code': 'addition', 'number_of_days': number_of_days, 'number_of_hours': 0.0, 'contract_id': payslip.contract_id.id})] if payslip.worked_days_line_ids: if number_of_days < 0 or holiday.number_of_days_temp < 0: pass else: for line in holiday.holiday_status_id.salary_rules_ids: if line.amount_select == 'fix': for allowance in payslip.allowance_ids: if line.name == allowance.name: if line._compute_rule(localdict)[0] != allowance.amount: amount = allowance.amount else: amount = line._compute_rule(localdict)[0] else: amount = line._compute_rule(localdict)[0] for deduction in payslip.deduction_ids: if line.name == deduction.name: if line._compute_rule(localdict)[0] != deduction.amount: amount = (-deduction.amount) else: amount = line._compute_rule(localdict)[0] elif line.amount_select == 'percentage': if line.related_benefits_discounts: for li in line.related_benefits_discounts: for allowance in payslip.allowance_ids: if line.name == allowance.name: if li._compute_rule(localdict)[0] != allowance.amount: amount = allowance.amount else: amount = li._compute_rule(localdict)[0] for deduction in payslip.deduction_ids: if line.name == deduction.name: if li._compute_rule(localdict)[0] != deduction.amount: amount = (-deduction.amount) else: amount = li._compute_rule(localdict)[0] else: for allowance in payslip.allowance_ids: if line.name == allowance.name: if line._compute_rule(localdict)[0] != allowance.amount: amount = allowance.amount else: amount = line._compute_rule(localdict)[0] for deduction in payslip.deduction_ids: if line.name == deduction.name: if line._compute_rule(localdict)[0] != deduction.amount: amount = (-deduction.amount) else: amount = line._compute_rule(localdict)[0] # Update 29/07/2019 for allow in payslip.allowance_ids: if line.name == allow.name: allow.update({ 'name': line.name, 'code': line.code, 'category_id': line.category_id.id, 'contract_id': payslip.contract_id.id, 'slip_id': payslip.id, 'quantity': 1, 'rate': 100, 'salary_rule_id': line.id, 'leave_request_case': True, 'amount': amount }) for ded in payslip.deduction_ids: if line.name == ded.name: ded.update({ 'name': line.name, 'code': line.code, 'category_id': line.category_id.id, 'contract_id': payslip.contract_id.id, 'slip_id': payslip.id, 'quantity': 1, 'rate': 100, 'salary_rule_id': line.id, 'leave_request_case': True, 'amount': -amount }) elif holiday.holiday_status_id.payslip_type == 'exclusion' or ( holiday.holiday_status_id.payslip_type == 'reconcile' and holiday.reconcile_leave is True): start_holiday = datetime.strptime(str(holiday_date_from), "%Y-%m-%d %H:%M:%S").date() end_holiday = datetime.strptime(str(holiday_date_to), "%Y-%m-%d %H:%M:%S").date() payroll_start = datetime.strptime(str(payslip_date_from), "%Y-%m-%d").date() pyroll_end = datetime.strptime(str(payslip_date_to), "%Y-%m-%d").date() if payslip.date_from >= start_holiday and payslip_date_to >= end_holiday and end_holiday >= payslip_date_from: pyroll_days = relativedelta(pyroll_end, payroll_start).days + 1 number_of_days = relativedelta(end_holiday, payroll_start).days+ 1 if pyroll_days == 28: number_of_days = number_of_days + 2 if pyroll_days == 29: number_of_days = number_of_days + 1 if number_of_days >= 0: # number_of_days <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Exclusion or Reconcile Paid Holidays", 'sequence': 2, 'payslip_id': payslip.id, 'code': 'exclusion', 'number_of_days': number_of_days, 'number_of_hours': 0.0, 'contract_id': payslip.contract_id.id})] elif payslip.date_to >= end_holiday and start_holiday >= payslip.date_from: pyroll_days = relativedelta(pyroll_end, payroll_start).days + 1 number_of_days = relativedelta(pyroll_end, start_holiday).days + 1 if pyroll_days == 28: number_of_days = number_of_days + 2 if pyroll_days == 29: number_of_days = number_of_days + 1 if pyroll_days == 31: number_of_days = number_of_days - 1 if holiday.number_of_days_temp >= 0: # holiday.number_of_days_temp <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Exclusion or Reconcile Paid Holidays", 'sequence': 2, 'payslip_id': payslip.id, 'code': 'exclusion', 'number_of_days': number_of_days, 'number_of_hours': 0.0, 'contract_id': payslip.contract_id.id})] elif start_holiday >= payslip.date_from and payslip.date_to <= end_holiday and start_holiday <= payslip.date_to: pyroll_days = relativedelta(pyroll_end, payroll_start).days + 1 number_of_days = relativedelta(pyroll_end, start_holiday).days + 1 if pyroll_days == 28: number_of_days = number_of_days + 2 if pyroll_days == 29: number_of_days = number_of_days + 1 if pyroll_days == 31: number_of_days = number_of_days - 1 if number_of_days >= 0: # number_of_days <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Exclusion or Reconcile Paid Holidays", 'sequence': 2, 'payslip_id': payslip.id, 'code': 'exclusion', 'number_of_days': number_of_days, 'number_of_hours': 0.0, 'contract_id': payslip.contract_id.id})] else: if payslip.date_to <= end_holiday and start_holiday <= payslip.date_from: number_of_days = relativedelta(pyroll_end, payroll_start).days + 1 if number_of_days == 28: number_of_days = number_of_days + 2 if number_of_days == 29: number_of_days = number_of_days + 1 if number_of_days ==31: number_of_days= number_of_days - 1 if number_of_days >= 0: # number_of_days <= 0 payslip.worked_days_line_ids = [fields.Command.create({ 'name': "Exclusion or Reconcile Paid Holidays", 'sequence': 2, 'payslip_id': payslip.id, 'code': 'exclusion', 'number_of_days': number_of_days, 'number_of_hours': 0.0, 'contract_id': payslip.contract_id.id})] if payslip.worked_days_line_ids: for line in holiday.holiday_status_id.salary_rules_ids: if line.amount_select == 'fix': for allowance in payslip.allowance_ids: if line.name == allowance.name: if line._compute_rule(localdict)[0] != allowance.amount: amount = allowance.amount else: amount = line._compute_rule(localdict)[0] else: amount = line._compute_rule(localdict)[0] for deduction in payslip.deduction_ids: if line.name == deduction.name: if line._compute_rule(localdict)[0] != deduction.amount: amount = (-deduction.amount) else: amount = line._compute_rule(localdict)[0] elif line.amount_select == 'percentage': if line.related_benefits_discounts: for li in line.related_benefits_discounts: for allowance in payslip.allowance_ids: if line.name == allowance.name: if li._compute_rule(localdict)[0] != allowance.amount: amount = allowance.amount else: amount = li._compute_rule(localdict)[0] for deduction in payslip.deduction_ids: if line.name == deduction.name: if li._compute_rule(localdict)[0] != deduction.amount: amount = (-deduction.amount) else: amount = li._compute_rule(localdict)[0] else: for allowance in payslip.allowance_ids: if line.name == allowance.name: if line._compute_rule(localdict)[0] != allowance.amount: amount = allowance.amount else: amount = line._compute_rule(localdict)[0] for deduction in payslip.deduction_ids: if line.name == deduction.name: if line._compute_rule(localdict)[0] != deduction.amount: amount = (-deduction.amount) else: amount = line._compute_rule(localdict)[0] for allow in payslip.allowance_ids: if line.name == allow.name: allow.update({ 'name': line.name, 'code': line.code, 'category_id': line.category_id.id, 'contract_id': payslip.contract_id.id, 'slip_id': payslip.id, 'quantity': 1, 'rate': 100, 'salary_rule_id': line.id, 'leave_request_case': True, 'amount': amount }) for ded in payslip.deduction_ids: if line.name == ded.name: ded.update({ 'name': line.name, 'code': line.code, 'category_id': line.category_id.id, 'contract_id': payslip.contract_id.id, 'slip_id': payslip.id, 'quantity': 1, 'rate': 100, 'salary_rule_id': line.id, 'leave_request_case': True, 'amount': -amount }) lines = [(0, 0, line) for line in self._get_payslip_lines(contract_ids, payslip.id)] payslip.write({'line_ids': lines, 'number': number, 'level_id': payslip.contract_id.salary_level.id, 'group_id': payslip.contract_id.salary_group.id, 'degree_id': payslip.contract_id.salary_degree.id, }) for line in payslip.line_ids: if line.category_id.rule_type == 'allowance' or line.category_id.rule_type == 'deduction': flag = True if flag: allowances = payslip.line_ids.filtered( lambda a: a.amount != 0 and a.rate != 0 and a.category_id.rule_type == 'allowance') payslip.allowance_ids = [fields.Command.set(allowances.ids)] deductions = payslip.line_ids.filtered( lambda a: a.amount != 0 and a.rate != 0 and a.category_id.rule_type == 'deduction') for d in deductions: if d.amount > 0: d.amount = -d.amount else: d.amount = d.amount payslip.deduction_ids = [fields.Command.set(deductions.ids)] if 'hr.loan.salary.advance' in self.env: loans = self.env['hr.loan.salary.advance'].search([('employee_id', '=', payslip.employee_id.id), ('request_type.refund_from', '=', 'salary'), ('state', '=', 'pay')]).filtered( lambda item: item.employee_id.state == 'open') if loans: for loan in loans: for l in loan.deduction_lines: if not l.paid and ( str(l.installment_date) <= str(payslip.date_from) or str(l.installment_date) <= str( payslip.date_to)): employee_loan_id = payslip.loan_ids.filtered( lambda item: item.name == loan.request_type.name) if not employee_loan_id: payslip_loans.append({ 'name': loan.request_type.name, 'code': loan.code, 'amount': round((-l.installment_amount), 2), 'date': l.installment_date, 'account_id': loan.request_type.account_id.id, 'loan_id': loan.id }) l.paid = True l.payment_date = payslip.date_to else: payslip.loan_ids = [(0, 0, loan_item) for loan_item in payslip_loans] # check remaining loan and change state to closed if loan.remaining_loan_amount <= 0.0 < loan.gm_propos_amount: loan.state = 'closed' payslip.loan_ids = [(0, 0, loan_item) for loan_item in payslip_loans] payslip.allowance_ids._compute_total() payslip.deduction_ids._compute_total() for pay in payslip: if pay.total_sum < 0: raise UserError(_("Salary is less than 0 this month for the following employees \n %s") % ( pay.employee_id.name)) self.write({'state': 'computed'}) return True # Override function get_payslip_lines @api.model def _get_payslip_lines(self, contract_ids, payslip_id): def _sum_salary_rule_category(localdict, category, amount): if category.parent_id: 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 return localdict class BrowsableObject(object): def __init__(self, employee_id, dict, env): self.employee_id = employee_id self.dict = dict self.env = env def __getattr__(self, attr): return attr in self.dict and self.dict.__getitem__(attr) or 0.0 class InputLine(BrowsableObject): """a class that will be used into the python code, mainly for usability purposes""" def sum(self, code, from_date, to_date=None): if to_date is None: to_date = fields.Date.today() self.env.cr.execute(""" SELECT sum(amount) as sum FROM hr_payslip as hp, hr_payslip_input as pi WHERE hp.employee_id = %s AND hp.state = 'done' AND hp.date_from >= %s AND hp.date_to <= %s AND hp.id = pi.payslip_id AND pi.code = %s""", (self.employee_id, from_date, to_date, code)) return self.env.cr.fetchone()[0] or 0.0 class WorkedDays(BrowsableObject): """a class that will be used into the python code, mainly for usability purposes""" def _sum(self, code, from_date, to_date=None): if to_date is None: to_date = fields.Date.today() self.env.cr.execute(""" SELECT sum(number_of_days) as number_of_days, sum(number_of_hours) as number_of_hours FROM hr_payslip as hp, hr_payslip_worked_days as pi WHERE hp.employee_id = %s AND hp.state = 'done' AND hp.date_from >= %s AND hp.date_to <= %s AND hp.id = pi.payslip_id AND pi.code = %s""", (self.employee_id, from_date, to_date, code)) return self.env.cr.fetchone() def sum(self, code, from_date, to_date=None): res = self._sum(code, from_date, to_date) return res and res[0] or 0.0 def sum_hours(self, code, from_date, to_date=None): res = self._sum(code, from_date, to_date) return res and res[1] or 0.0 class Payslips(BrowsableObject): """a class that will be used into the python code, mainly for usability purposes""" def sum(self, code, from_date, to_date=None): if to_date is None: to_date = fields.Date.today() self.env.cr.execute("""SELECT sum(case when hp.credit_note = False then (pl.total) else (-pl.total) end) FROM hr_payslip as hp, hr_payslip_line as pl WHERE hp.employee_id = %s AND hp.state = 'done' AND hp.date_from >= %s AND hp.date_to <= %s AND hp.id = pl.slip_id AND pl.code = %s""", (self.employee_id, from_date, to_date, code)) res = self.env.cr.fetchone() 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 result_dict, rules_dict, worked_days_dict, inputs_dict = {}, {}, {}, {} blacklist = [] payslip = self.env['hr.payslip'].browse(payslip_id) for worked_days_line in payslip.worked_days_line_ids: worked_days_dict[worked_days_line.code] = worked_days_line for input_line in payslip.input_line_ids: inputs_dict[input_line.code] = input_line categories = BrowsableObject(payslip.employee_id.id, {}, self.env) inputs = InputLine(payslip.employee_id.id, inputs_dict, self.env) worked_days = WorkedDays(payslip.employee_id.id, worked_days_dict, self.env) payslips = Payslips(payslip.employee_id.id, payslip, 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} # get the ids of the structures on the contracts and their parent id as well contracts = self.env['hr.contract'].browse(contract_ids) if len(contracts) == 1 and payslip.struct_id: structure_ids = list(set(payslip.contract_id.salary_scale.ids)) else: structure_ids = contracts.get_all_structures() # get the rules of the structure and their children rule_ids = self.env['hr.payroll.structure'].browse(structure_ids).get_all_rules() # run the rules by sequence 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) for contract in contracts: employee = contract.employee_id localdict = dict(baselocaldict, payslip=payslip, employee=employee, contract=contract) if contract.contractor_type.salary_type == 'scale': for rule in sorted_rules: key1 = rule.code + '-' + str(contract.id) localdict['result'] = None localdict['result_qty'] = 1.0 localdict['result_rate'] = 100 # check if the rule can be applied if rule._satisfy_condition(localdict) and rule.id not in blacklist: if payslip.contract_id.advantages: for advantage_rule in payslip.contract_id.advantages: date1 = datetime.strptime(str(advantage_rule.date_from), "%Y-%m-%d") key = str(advantage_rule.benefits_discounts.code) + '-' + str(contract.id) if advantage_rule.date_to: date2 = datetime.strptime(str(advantage_rule.date_to), "%Y-%m-%d") if (datetime.strptime(str(payslip.date_from), "%Y-%m-%d") >= date1 and date2 >= datetime.strptime(str(payslip.date_to), "%Y-%m-%d")) \ or date2 >= datetime.strptime(str(payslip.date_from), "%Y-%m-%d") >= date1 \ or date2 >= datetime.strptime(str(payslip.date_to), "%Y-%m-%d") >= date1 \ or (datetime.strptime(str(payslip.date_to), "%Y-%m-%d") >= date1 and date2 >= datetime.strptime(str(payslip.date_from), "%Y-%m-%d")): if advantage_rule.benefits_discounts and advantage_rule.benefits_discounts.name not in sorted_rules: amount, qty, rate = rule._compute_rule(localdict) previous_amount = rule.code in localdict and localdict[ rule.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[rule.code] = tot_rule rules_dict[rule.code] = rule localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results if amount != 0: result_dict[key1] = { 'salary_rule_id': rule.id, 'contract_id': contract.id, 'name': rule.name, 'code': rule.code, 'category_id': rule.category_id.id, 'amount_select': rule.amount_select, 'amount_fix': rule.amount_fix, 'amount_python_compute': rule.amount_python_compute, 'amount_percentage': rule.amount_percentage, 'register_id': rule.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} if advantage_rule.type == 'customize': amount = advantage_rule.amount qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif advantage_rule.type == 'exception': total = advantage_rule.benefits_discounts._compute_rule(localdict)[0] if total == advantage_rule.amount or total == 0.0: amount, qty, rate = 0.0, 0, 0.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif total <= advantage_rule.amount: raise UserError( _( 'The amount you put is greater than fact value of this Salary rule')) else: amount = total - advantage_rule.amount # update 21/04/2019 qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} advantage_rule.done = False else: amount, qty, rate = rule._compute_rule(localdict) previous_amount = rule.code in localdict and localdict[rule.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[rule.code] = tot_rule rules_dict[rule.code] = rule localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results if amount != 0: result_dict[key1] = { 'salary_rule_id': rule.id, 'contract_id': contract.id, 'name': rule.name, 'code': rule.code, 'category_id': rule.category_id.id, 'amount_select': rule.amount_select, 'amount_fix': rule.amount_fix, 'amount_python_compute': rule.amount_python_compute, 'amount_percentage': rule.amount_percentage, 'register_id': rule.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} else: if date2 <= datetime.strptime(str(payslip.date_from), "%Y-%m-%d"): amount, qty, rate = rule._compute_rule(localdict) previous_amount = rule.code in localdict and localdict[rule.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[rule.code] = tot_rule rules_dict[rule.code] = rule localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results if amount != 0: result_dict[key1] = { 'salary_rule_id': rule.id, 'contract_id': contract.id, 'name': rule.name, 'code': rule.code, 'category_id': rule.category_id.id, 'amount_select': rule.amount_select, 'amount_fix': rule.amount_fix, 'amount_python_compute': rule.amount_python_compute, 'amount_percentage': rule.amount_percentage, 'register_id': rule.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} else: if date1 <= datetime.strptime(str(payslip.date_from), "%Y-%m-%d") or date1 <= datetime.strptime( str(payslip.date_to), "%Y-%m-%d"): if advantage_rule.benefits_discounts.name not in sorted_rules: amount, qty, rate = rule._compute_rule(localdict) previous_amount = rule.code in localdict and localdict[rule.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[rule.code] = tot_rule rules_dict[rule.code] = rule localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results if amount != 0: result_dict[key1] = { 'salary_rule_id': rule.id, 'contract_id': contract.id, 'name': rule.name, 'code': rule.code, 'category_id': rule.category_id.id, 'amount_select': rule.amount_select, 'amount_fix': rule.amount_fix, 'amount_python_compute': rule.amount_python_compute, 'amount_percentage': rule.amount_percentage, 'register_id': rule.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} # To Doooooooooooooo #if # if rule.name == advantage_rule.benefits_discounts.name: if advantage_rule.type == 'customize': amount = advantage_rule.amount qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif advantage_rule.type == 'exception': total = advantage_rule.benefits_discounts._compute_rule(localdict)[ 0] if total == advantage_rule.amount or total == 0.0: amount, qty, rate = 0.0, 0, 0.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[ advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif total <= advantage_rule.amount: raise UserError( _( 'The amount you put is greater than fact value of this Salary rule')) else: amount = total - advantage_rule.amount # update 21/04/2019 qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[ advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} else: amount, qty, rate = rule._compute_rule(localdict) previous_amount = rule.code in localdict and localdict[rule.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[rule.code] = tot_rule rules_dict[rule.code] = rule localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results if amount != 0: result_dict[key1] = { 'salary_rule_id': rule.id, 'contract_id': contract.id, 'name': rule.name, 'code': rule.code, 'category_id': rule.category_id.id, 'amount_select': rule.amount_select, 'amount_fix': rule.amount_fix, 'amount_python_compute': rule.amount_python_compute, 'amount_percentage': rule.amount_percentage, 'register_id': rule.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} advantage_rule.write({'done': True}) else: amount, qty, rate = rule._compute_rule(localdict) previous_amount = rule.code in localdict and localdict[rule.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[rule.code] = tot_rule rules_dict[rule.code] = rule localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results if amount != 0: result_dict[key1] = { 'salary_rule_id': rule.id, 'contract_id': contract.id, 'name': rule.name, 'code': rule.code, 'category_id': rule.category_id.id, 'amount_select': rule.amount_select, 'amount_fix': rule.amount_fix, 'amount_python_compute': rule.amount_python_compute, 'amount_percentage': rule.amount_percentage, 'register_id': rule.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} else: blacklist += [id for id, seq in rule._recursive_search_of_rules()] if payslip.contract_id.salary_level.benefits_discounts_ids: level_structure_ids = list(set(payslip.contract_id.salary_level.ids)) level_rule_ids = self.env['hr.payroll.structure'].browse(level_structure_ids).get_all_rules() level_sorted_rule_ids = [id for id, sequence in sorted(level_rule_ids, key=lambda x: x[1])] level_sorted_rules = self.env['hr.salary.rule'].browse(level_sorted_rule_ids) for rule in level_sorted_rules: key = rule.code + '-' + str(contract.id) localdict['result'] = None localdict['result_qty'] = 1.0 localdict['result_rate'] = 100 # check if the rule can be applied if rule._satisfy_condition(localdict) and rule.id not in blacklist: amount, qty, rate = rule._compute_rule(localdict) if qty == 0: qty = 1 previous_amount = rule.code in localdict and localdict[rule.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[rule.code] = tot_rule rules_dict[rule.code] = rule localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': rule.id, 'contract_id': contract.id, 'name': rule.name, 'code': rule.code, 'category_id': rule.category_id.id, 'amount_select': rule.amount_select, 'amount_fix': rule.amount_fix, 'amount_python_compute': rule.amount_python_compute, 'amount_percentage': rule.amount_percentage, 'register_id': rule.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} for advantage_rule in payslip.contract_id.advantages: if advantage_rule.benefits_discounts.name == rule.name: if advantage_rule.type == 'customize': amount = advantage_rule.amount + amount qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} if advantage_rule.type == 'exception': total = advantage_rule.benefits_discounts._compute_rule(localdict)[0] if total == advantage_rule.amount or total == 0.0: amount, qty, rate = 0.0, 0, 0.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif total <= advantage_rule.amount: raise UserError( _( 'The amount you put is greater than fact value of this Salary rule')) else: amount = total - advantage_rule.amount # update 21/04/2019 qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} else: blacklist += [id for id, seq in rule._recursive_search_of_rules()] if payslip.contract_id.salary_group.benefits_discounts_ids: group_structure_ids = list(set(payslip.contract_id.salary_group.ids)) group_rule_ids = self.env['hr.payroll.structure'].browse(group_structure_ids).get_all_rules() group_sorted_rule_ids = [id for id, sequence in sorted(group_rule_ids, key=lambda x: x[1])] group_sorted_rules = self.env['hr.salary.rule'].browse(group_sorted_rule_ids) for rule in group_sorted_rules: key = rule.code + '-' + str(contract.id) localdict['result'] = None localdict['result_qty'] = 1.0 localdict['result_rate'] = 100 # check if the rule can be applied if rule._satisfy_condition(localdict) and rule.id not in blacklist: amount, qty, rate = rule._compute_rule(localdict) previous_amount = rule.code in localdict and localdict[rule.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[rule.code] = tot_rule rules_dict[rule.code] = rule localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': rule.id, 'contract_id': contract.id, 'name': rule.name, 'code': rule.code, 'category_id': rule.category_id.id, 'amount_select': rule.amount_select, 'amount_fix': rule.amount_fix, 'amount_python_compute': rule.amount_python_compute, 'amount_percentage': rule.amount_percentage, 'register_id': rule.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} for advantage_rule in payslip.contract_id.advantages: if advantage_rule.benefits_discounts.name == rule.name: if advantage_rule.type == 'customize': amount = advantage_rule.amount + amount qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} if advantage_rule.type == 'exception': total = advantage_rule.benefits_discounts._compute_rule(localdict)[0] if total == advantage_rule.amount or total == 0.0: amount, qty, rate = 0.0, 0, 0.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif total <= advantage_rule.amount: raise UserError( _( 'The amount you put is greater than fact value of this Salary rule')) else: amount = total - advantage_rule.amount # update 21/04/2019 qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} else: blacklist += [id for id, seq in rule._recursive_search_of_rules()] else: advantage_list = [] for advantage_rule in payslip.contract_id.advantages: advantage_list.append(advantage_rule.benefits_discounts.id) for rule in sorted_rules: key1 = rule.code + '-' + str(contract.id) localdict['result'] = None localdict['result_qty'] = 1.0 localdict['result_rate'] = 100 # check if the rule can be applied if rule._satisfy_condition(localdict) and rule.id not in blacklist: if payslip.contract_id.advantages: for advantage_rule in payslip.contract_id.advantages: key = advantage_rule.benefits_discounts.code + '-' + str(contract.id) date1 = datetime.strptime(str(advantage_rule.date_from), "%Y-%m-%d") if advantage_rule.benefits_discounts.name == rule.name: if advantage_rule.date_to: date2 = datetime.strptime(str(advantage_rule.date_to), "%Y-%m-%d") if (datetime.strptime(str(payslip.date_from), "%Y-%m-%d") >= date1 and date2 >= datetime.strptime( str(payslip.date_to), "%Y-%m-%d")) \ or date2 >= datetime.strptime(str(payslip.date_from), "%Y-%m-%d") >= date1 \ or date2 >= datetime.strptime(str(payslip.date_to), "%Y-%m-%d") >= date1 \ or (datetime.strptime(str(payslip.date_to), "%Y-%m-%d") >= date1 and date2 >= datetime.strptime( str(payslip.date_from), "%Y-%m-%d")): if advantage_rule.type == 'customize': amount = advantage_rule.amount qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif advantage_rule.type == 'exception': total = advantage_rule.benefits_discounts._compute_rule(localdict)[ 0] # update 21/04/2019 if total == advantage_rule.amount or total == 0.0: amount, qty, rate = 0.0, 0, 0.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif total <= advantage_rule.amount: raise UserError( _( 'The amount you put is greater than fact value of this Salary rule')) else: amount = total - advantage_rule.amount # update 21/04/2019 qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} else: amount, qty, rate = rule._compute_rule(localdict) previous_amount = rule.code in localdict and localdict[rule.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[rule.code] = tot_rule rules_dict[rule.code] = rule localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results if amount != 0: result_dict[key1] = { 'salary_rule_id': rule.id, 'contract_id': contract.id, 'name': rule.name, 'code': rule.code, 'category_id': rule.category_id.id, 'amount_select': rule.amount_select, 'amount_fix': rule.amount_fix, 'amount_python_compute': rule.amount_python_compute, 'amount_percentage': rule.amount_percentage, 'register_id': rule.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} else: if date1 <= datetime.strptime(str(payslip.date_from), "%Y-%m-%d"): if advantage_rule.benefits_discounts.name in sorted_rules: if advantage_rule.type == 'customize': amount = advantage_rule.amount qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif advantage_rule.type == 'exception': total = advantage_rule.benefits_discounts._compute_rule(localdict)[ 0] if total == advantage_rule.amount or total == 0.0: amount, qty, rate = 0.0, 0, 0.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[ advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif total <= advantage_rule.amount: raise UserError( _( 'The amount you put is greater than fact value of this Salary rule')) else: amount = total - advantage_rule.amount # update 21/04/2019 qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[ advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} else: if advantage_rule.benefits_discounts.name not in sorted_rules: amount, qty, rate = rule._compute_rule(localdict) previous_amount = rule.code in localdict and localdict[ rule.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[rule.code] = tot_rule rules_dict[rule.code] = rule localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results if amount != 0: result_dict[key1] = { 'salary_rule_id': rule.id, 'contract_id': contract.id, 'name': rule.name, 'code': rule.code, 'category_id': rule.category_id.id, 'amount_select': rule.amount_select, 'amount_fix': rule.amount_fix, 'amount_python_compute': rule.amount_python_compute, 'amount_percentage': rule.amount_percentage, 'register_id': rule.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} if advantage_rule.type == 'customize': amount = advantage_rule.amount qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[ advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif advantage_rule.type == 'exception': total = \ advantage_rule.benefits_discounts._compute_rule(localdict)[ 0] if total == advantage_rule.amount or total == 0.0: amount, qty, rate = 0.0, 0, 0.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[ advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif total <= advantage_rule.amount: raise UserError( _( 'The amount you put is greater than fact value of this Salary rule')) else: amount = total - advantage_rule.amount # update 21/04/2019 qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[ advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} else: amount, qty, rate = rule._compute_rule(localdict) previous_amount = rule.code in localdict and localdict[rule.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[rule.code] = tot_rule rules_dict[rule.code] = rule localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results if amount != 0: result_dict[key1] = { 'salary_rule_id': rule.id, 'contract_id': contract.id, 'name': rule.name, 'code': rule.code, 'category_id': rule.category_id.id, 'amount_select': rule.amount_select, 'amount_fix': rule.amount_fix, 'amount_python_compute': rule.amount_python_compute, 'amount_percentage': rule.amount_percentage, 'register_id': rule.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} else: if rule.id not in advantage_list: # compute the amount of the rule amount, qty, rate = rule._compute_rule(localdict) # check if there is already a rule computed with that code previous_amount = rule.code in localdict and localdict[rule.code] or 0.0 # set/overwrite the amount computed for this rule in the localdict tot_rule = amount * qty * rate / 100.0 localdict[rule.code] = tot_rule rules_dict[rule.code] = rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results if amount != 0: result_dict[key1] = { 'salary_rule_id': rule.id, 'contract_id': contract.id, 'name': rule.name, 'code': rule.code, 'category_id': rule.category_id.id, 'amount_select': rule.amount_select, 'amount_fix': rule.amount_fix, 'amount_python_compute': rule.amount_python_compute, 'amount_percentage': rule.amount_percentage, 'register_id': rule.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} if advantage_rule.type == 'customize': amount = advantage_rule.amount qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif advantage_rule.type == 'exception': total = advantage_rule.benefits_discounts._compute_rule( localdict)[0] # update 21/04/2019 if total == advantage_rule.amount or total == 0.0: amount, qty, rate = 0.0, 0, 0.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[ advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} elif total <= advantage_rule.amount: raise UserError( _( 'The amount you put is greater than fact value of this Salary rule')) else: amount = total - advantage_rule.amount # update 21/04/2019 qty, rate = 1, 100.0 previous_amount = advantage_rule.benefits_discounts.code in localdict and \ localdict[advantage_rule.benefits_discounts.code] or 0.0 tot_rule = amount * qty * rate / 100.0 localdict[advantage_rule.benefits_discounts.code] = tot_rule rules_dict[advantage_rule.benefits_discounts.code] = advantage_rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, advantage_rule.benefits_discounts.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results result_dict[key] = { 'salary_rule_id': advantage_rule.benefits_discounts.id, 'contract_id': contract.id, 'name': advantage_rule.benefits_discounts.name, 'code': advantage_rule.benefits_discounts.code, 'category_id': advantage_rule.benefits_discounts.category_id.id, 'amount_select': advantage_rule.benefits_discounts.amount_select, 'amount_fix': advantage_rule.benefits_discounts.amount_fix, 'amount_python_compute': advantage_rule.benefits_discounts.amount_python_compute, 'amount_percentage': advantage_rule.benefits_discounts.amount_percentage, 'register_id': advantage_rule.benefits_discounts.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} advantage_rule.write({'done': True}) else: # compute the amount of the rule amount, qty, rate = rule._compute_rule(localdict) # check if there is already a rule computed with that code previous_amount = rule.code in localdict and localdict[rule.code] or 0.0 # set/overwrite the amount computed for this rule in the localdict tot_rule = amount * qty * rate / 100.0 localdict[rule.code] = tot_rule rules_dict[rule.code] = rule # sum the amount for its salary category localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount) # create/overwrite the rule in the temporary results if amount != 0: result_dict[key1] = { 'salary_rule_id': rule.id, 'contract_id': contract.id, 'name': rule.name, 'code': rule.code, 'category_id': rule.category_id.id, 'amount_select': rule.amount_select, 'amount_fix': rule.amount_fix, 'amount_python_compute': rule.amount_python_compute, 'amount_percentage': rule.amount_percentage, 'register_id': rule.register_id.id, 'amount': amount, 'employee_id': contract.employee_id.id, 'quantity': qty, 'rate': rate} else: blacklist += [id for id, seq in rule._recursive_search_of_rules()] return list(result_dict.values()) class HrPayslipLine(models.Model): _inherit = 'hr.payslip.line' leave_request_case = fields.Boolean() # Relational fields payslip_allowance = fields.Many2one('hr.payslip', ondelete='cascade', index=True) payslip_deduction = fields.Many2one('hr.payslip', ondelete='cascade', index=True) related_benefits_discounts = fields.Many2many(comodel_name='hr.salary.rule', relation='payslip_line_benefit_discount_rel', column1='rule_id', column2='sub_rule_id', string='Related Benefits and Discount') percentage = fields.Float(string='Percentage', related='slip_id.percentage') # override compute function in payslip lines @api.depends('quantity', 'amount', 'rate') def _compute_total(self): # payslip = self.env['hr.payslip'].search([('id', '=', self.slip_id.id)]) #print("payslip######################### ", self) start_time = time.time() for line in self: #print('--------------------------hr.payslip.line-------------------', line.id) if line.slip_id.worked_days_line_ids: total_days = 0 per = 0 days_number = sum(line.number_of_days for line in line.slip_id.worked_days_line_ids) for wo in line.slip_id.worked_days_line_ids: ####################################################### Holidays Unpaid ###################################### if wo.name == "Unpaid Holidays For this month": work_days = wo.number_of_days if total_days: line.slip_id.total_allowances = 0.0 line.slip_id.total_deductions = 0.0 total_days_after_holiday = total_days - work_days total_days = total_days_after_holiday else: total_days_after_holiday = 30 - work_days total_days = total_days_after_holiday if line.salary_rule_id.reduce_with_leaves == True and line.salary_rule_id.min_leave_days_to_deduct <= days_number: line.total = round(((line.amount / 30) * total_days_after_holiday) * line.percentage / 100,2) else: line.total = round(((line.amount) * line.percentage / 100),2) # line.total = ((line.amount / 30) * total_days_after_holiday) * line.percentage / 100 #################################################### Holidays percentage ####################################### elif wo.name == "Paid Holidays By percentage": work_days = wo.number_of_days percentage = wo.number_of_hours if total_days: line.slip_id.total_allowances = 0.0 line.slip_id.total_deductions = 0.0 total_days_after_holiday = total_days - work_days total_days = total_days_after_holiday else: total_days_after_holiday = 30 - work_days total_days = total_days_after_holiday allow = (line.amount / 30) * work_days per += (allow * percentage / 100) actual_allow_tot = (line.amount / 30) * total_days_after_holiday if line.salary_rule_id.reduce_with_leaves == True and line.salary_rule_id.min_leave_days_to_deduct <= days_number: line.total = round((actual_allow_tot + per) * line.percentage / 100,2) else: line.total = round(((line.amount) * line.percentage / 100),2) # line.total = (actual_allow_tot + per) * line.percentage / 100 ##################################################### Holidays Additional ######################################## elif wo.name == "Additional Paid Holidays": work_days = wo.number_of_days if total_days: line.slip_id.total_allowances = 0.0 line.slip_id.total_deductions = 0.0 total_days_after_holiday = total_days - work_days total_days = total_days_after_holiday else: total_days_after_holiday = 30 - work_days total_days = total_days_after_holiday if line.leave_request_case or line.salary_rule_id.reduce_with_leaves == False or line.salary_rule_id.min_leave_days_to_deduct > days_number: line.total = round((line.amount) * line.percentage / 100,2) else: line.total = round(((line.amount / 30) * total_days_after_holiday) * line.percentage / 100,2) ################################################### Holidays Reconcile and Exclusion ############################### elif wo.name == "Exclusion or Reconcile Paid Holidays": work_days = wo.number_of_days if total_days: line.slip_id.total_allowances = 0.0 line.slip_id.total_deductions = 0.0 total_days_after_holiday = total_days - work_days total_days = total_days_after_holiday else: total_days_after_holiday = 30 - work_days total_days = total_days_after_holiday if not line.leave_request_case or line.salary_rule_id.reduce_with_leaves == False or line.salary_rule_id.min_leave_days_to_deduct > days_number: line.total = round((line.amount) * line.percentage / 100,2) else: line.total = round(((line.amount / 30) * total_days_after_holiday) * line.percentage / 100,2) ################################################### Working days for this month ###################################### else: work_days = wo.number_of_days total_days = work_days if line.leave_request_case or line.salary_rule_id.reduce_with_leaves == False or line.salary_rule_id.min_leave_days_to_deduct > days_number: line.total = round((line.amount) * line.percentage / 100,2) else: line.total = round(((line.amount / 30) * work_days) * line.percentage / 100,2) ################################################### End IF Then else ################################################# else: total = Decimal(line.amount * line.percentage / 100) rounded = total.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) line.total = round(rounded,2) #print("compute_shee_computee_total payslips_Run %s" % (time.time() - start_time)) class HrPayslipRun(models.Model): _inherit = 'hr.payslip.run' required_condition = fields.Boolean(string='Required Condition', compute='compute_type') state = fields.Selection(selection_add=[('computed', 'Computed'), ('confirmed', 'Confirmed'), ('transfered', 'Transfer'), ('close', 'Close')], tracking=True) # Relational fields salary_scale = fields.Many2one('hr.payroll.structure', string='Salary Scale') employee_ids = fields.Many2many('hr.employee', 'hr_employee_payslip_rel', 'payslip_id', 'employee_id', 'Employees', index=True,domain="[('id', 'in', employee_value_ids)]") department_ids = fields.Many2many('hr.department', 'hr_department_payslip_rel', 'payslip_id', 'department_id', 'Departments') journal_id = fields.Many2one('account.journal', 'Salary Journal') percentage = fields.Float(string='Percentage', default=100) move_id = fields.Many2one('account.move', string="Move Number") company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.company) employee_value_ids = fields.Many2many(comodel_name="hr.employee", compute="_compute_allowed_value_ids") holiday_start_date = fields.Date(string="Holiday Start Date") holiday_end_date = fields.Date(string="Holiday End Date") @api.onchange('date_start') def check_date_start(self): if self.date_start : self.date_end = fields.Date.from_string(self.date_start)+relativedelta(months=+1, day=1, days=-1) @api.onchange('date_end') def check_date_end(self): if self.date_start and self.date_end and self.date_start > self.date_end: raise UserError(_('Date From must be less than or equal Date To')) month_current_from = datetime.strptime(str(self.date_start), '%Y-%m-%d').strftime('%m') year_current_from = datetime.strptime(str(self.date_start), '%Y-%m-%d').strftime('%y') month_current_to = datetime.strptime(str(self.date_end), '%Y-%m-%d').strftime('%m') year_current_to = datetime.strptime(str(self.date_end), '%Y-%m-%d').strftime('%y') if month_current_from != month_current_to or year_current_from != year_current_to: raise UserError(_('Sorry, The Pyroll period Must be During the same Month')) @api.depends('salary_scale.transfer_type') def compute_type(self): if self.salary_scale.transfer_type == 'all' or self.salary_scale.transfer_type == 'per_analytic_account': self.required_condition = True else: self.required_condition = False # domain the employee to compute salary @api.depends('salary_scale','department_ids','date_start') def _compute_allowed_value_ids(self): for item in self: date_from = str(item.date_start) date_to = str(item.date_end) if item.salary_scale: if item.department_ids: depart = item.department_ids._origin #for dep in item.department_ids._origin: employee_contracts = self.env['hr.contract'].search( [('salary_scale', '=', item.salary_scale.id), ('state', '=', 'program_directory')]).filtered( lambda item: item.employee_id.department_id in depart and item.employee_id.state == 'open' and str(item.employee_id.first_hiring_date) <= date_to) item.employee_value_ids = employee_contracts.mapped("employee_id") else: employee_contracts = self.env['hr.contract'].search( [('salary_scale', '=', item.salary_scale.id), ('state', '=', 'program_directory')]).filtered( lambda item: item.employee_id.state == 'open' and str(item.employee_id.first_hiring_date) <= date_to) item.employee_value_ids = employee_contracts.mapped("employee_id") else: item.employee_value_ids = False @api.onchange('salary_scale') def _onchange_salary_scale_id(self): for item in self: if item.salary_scale: item.employee_ids = False item.department_ids = False @api.onchange('department_ids','date_start') def _onchange_department_ids(self): for item in self: item.employee_ids = False '''@api.onchange('salary_scale') def onchange_salary_scale_id(self): for item in self: if item.salary_scale: item.employee_ids = False item.department_ids = False if item.department_ids: for dep in item.department_ids: employee_contracts = self.env['hr.contract'].search( [('salary_scale', '=', item.salary_scale.id), ('state', '=', 'program_directory')]).filtered( lambda item: item.employee_id.department_id == dep and item.employee_id.state == 'open') emps = [] for contract in employee_contracts: emps.append(contract.employee_id.id) return {'domain': {'employee_ids': [('id', 'in', emps)]}} else: employee_contracts = self.env['hr.contract'].search( [('salary_scale', '=', item.salary_scale.id), ('state', '=', 'program_directory')]).filtered( lambda item: item.employee_id.state == 'open') emps = [] for contract in employee_contracts: emps.append(contract.employee_id.id) return {'domain': {'employee_ids': [('id', 'in', emps)]}} else: return {'domain': {'employee_ids': [('id', 'in', [])]}}''' # Override function compute sheet in Payslip Batches def compute_sheet(self): payslips = self.env['hr.payslip'] [data] = self.read() from_date = str(self.date_start) to_date = str(self.date_end) holiday_start_date = str(self.holiday_start_date) if self.holiday_start_date else False holiday_end_date = str(self.holiday_end_date) if self.holiday_end_date else False start_time = time.time() #worked_days, emps, dictionary = [], [], [] worked_days, emps, dictionary,emp_last_payslip,emp_priv_payslip = [], [], [], [],[] if datetime.strptime(str(from_date), "%Y-%m-%d").date().month == datetime.strptime(str(to_date),"%Y-%m-%d").date().month: month_date = datetime.strptime(str(from_date), "%Y-%m-%d").date() if self.department_ids: for dep in self.department_ids: employee_contracts = self.env['hr.contract'].search( [('salary_scale', '=', self.salary_scale.id), ('state', '=', 'program_directory')]).filtered( lambda item: item.employee_id.department_id == dep and item.employee_id.state == 'open' and str(item.employee_id.first_hiring_date) <= to_date) for contract in employee_contracts: emps.append(contract.employee_id.id) else: employee_contracts = self.env['hr.contract'].search( [('salary_scale', '=', self.salary_scale.id), ('state', '=', 'program_directory')]).filtered( lambda item: item.employee_id.state == 'open' and str(item.employee_id.first_hiring_date) <= to_date) for contract in employee_contracts: emps.append(contract.employee_id.id) emps = self.env['hr.employee'].browse(emps) employees = self.env['hr.employee'].browse(data['employee_ids']) ################### Employee run payslip one in month and previously month ####### last_payslips = self.env['hr.payslip'].search([('date_from', '>=', self.date_start),('date_from', '<=', self.date_end), ('payslip_run_id', '!=', self.id)]) if last_payslips: for priv_pay in last_payslips: if employees: for emp in employees: if emp.id == priv_pay.employee_id.id: emp_last_payslip.append(emp.name) else : for emp in emps: if emp.id == priv_pay.employee_id.id: emp_last_payslip.append(emp.name) if emp_last_payslip: raise UserError( _("Sorry, Salary has already been calculated This Month for Employees \n %s") % (emp_last_payslip)) ######################################################################################## last_month = self.date_start - relativedelta(months=1) end_last_month = self.date_start - relativedelta(days=1) priv_payslips_month = self.env['hr.payslip'].search([('date_from', '>=', last_month),('date_from', '<=', end_last_month), ('payslip_run_id', '!=', self.id)]).employee_id old_payslips = self.env['hr.payslip'].search([('date_from', '<', self.date_start), ('payslip_run_id', '!=', self.id)]).employee_id if employees: diff_employee= employees-priv_payslips_month else: diff_employee= emps-priv_payslips_month #if diff_employee and diff_employee in old_payslips : if diff_employee : for emp in diff_employee: if emp in old_payslips: emp_priv_payslip.append(emp.name) if emp_priv_payslip: raise UserError( _("Sorry, The Previous month's salary has Not been calculated for Employees \n %s") % (emp_priv_payslip)) ################### End ################################################################ if employees: locale = self.env.context.get('lang') or 'en_US' for employee in employees: slip_data = self.env['hr.payslip'].onchange_employee_id(from_date, to_date, employee.id, contract_id=False) # pays = self.env['hr.payslip'].search([('contract_id', '=', employee.contract_id.id)]) ################### Rename Slip and Date####### ttyme = datetime.fromtimestamp(time.mktime(time.strptime(str(from_date), "%Y-%m-%d"))) slip_data['value'].update({ '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, }) ########### employee_slip_line = self.slip_ids.filtered(lambda item: item.employee_id.id == employee.id) if to_date >= str(employee.first_hiring_date) >= from_date: contract_start_date = datetime.strptime(str(employee.first_hiring_date), "%Y-%m-%d").date() if to_date >= str(employee.leaving_date) >= str(employee.first_hiring_date): contract_end_date = datetime.strptime(str(employee.leaving_date), "%Y-%m-%d").date() + timedelta( days=1) duration = relativedelta(contract_end_date, contract_start_date).days hours = (float((contract_end_date - contract_start_date).seconds) / 86400) * 24 if not employee_slip_line: res = { 'employee_id': employee.id, 'name': slip_data['value'].get('name'), 'struct_id': self.salary_scale.id, 'contract_id': employee.contract_id.id, 'input_line_ids': [(0, 0, x) for x in slip_data['value'].get('input_line_ids')], 'worked_days_line_ids': worked_days, 'date_from': str(employee.first_hiring_date) or from_date, 'date_to': employee.leaving_date or to_date, 'holiday_start_date': holiday_start_date, 'holiday_end_date': holiday_end_date, 'credit_note': self.credit_note, 'company_id': employee.company_id.id, 'percentage': self.percentage} item_payslip = self.env['hr.payslip'].create(res) payslips += item_payslip # if pays: # for p in pays: # if p.employee_id != employee and p not in payslips: # payslips += item_payslip # else: # payslips += item_payslip if item_payslip: days = {'name': "Working days for this month", 'sequence': 1, 'payslip_id': item_payslip.id, 'code': 2, 'number_of_days': duration, 'number_of_hours': hours, 'contract_id': employee.contract_id.id} worked_days += self.env['hr.payslip.worked_days'].create(days) else: item_payslip = employee_slip_line payslips += item_payslip # if pays: # for p in pays: # if p.employee_id != employee and p not in payslips: # payslips += item_payslip # else: # payslips += item_payslip else: from calendar import monthrange month_range = monthrange(datetime.now().date().year, month_date.month)[1] contract_end_date = datetime.strptime(str(to_date), "%Y-%m-%d").date() if month_range == 30 and contract_end_date.day == 30: duration = relativedelta(contract_end_date, contract_start_date).days + 1 elif month_range > 30 and contract_end_date.day > 30: duration = relativedelta(contract_end_date, contract_start_date).days if duration == 0: duration = duration + 1 elif month_range == 28 and contract_end_date.day == 28: duration = relativedelta(contract_end_date, contract_start_date).days + 3 elif month_range == 29 and contract_end_date.day == 29: duration = relativedelta(contract_end_date, contract_start_date).days + 2 else: duration = relativedelta(contract_end_date, contract_start_date).days + 1 hours = (float((contract_end_date - contract_start_date).seconds) / 86400) * 24 if not employee_slip_line: res = { 'employee_id': employee.id, 'name': slip_data['value'].get('name'), 'struct_id': self.salary_scale.id, 'contract_id': employee.contract_id.id, 'input_line_ids': [(0, 0, x) for x in slip_data['value'].get('input_line_ids')], # 'worked_days_line_ids': worked_days , 'date_from': str(employee.first_hiring_date) or from_date, 'date_to': to_date, 'holiday_start_date': holiday_start_date, 'holiday_end_date': holiday_end_date, 'credit_note': self.credit_note, 'company_id': employee.company_id.id, 'percentage': self.percentage} item_payslip = self.env['hr.payslip'].create(res) payslips += item_payslip # if pays: # for p in pays: # if p.employee_id != employee and p not in payslips: # payslips += item_payslip # else: # payslips += item_payslip if item_payslip: # print("22222222222222222222222222222222222222222222222", employee.english_name) days = {'name': "Working days for this month", 'sequence': 1, 'payslip_id': item_payslip.id, 'code': 2, 'number_of_days': duration, 'number_of_hours': hours, 'contract_id': employee.contract_id.id} worked_days += self.env['hr.payslip.worked_days'].create(days) else: item_payslip = employee_slip_line payslips += item_payslip # if pays: # for p in pays: # if p.employee_id != employee and p not in payslips: # payslips += item_payslip # else: # payslips += item_payslip elif to_date >= str(employee.leaving_date) >= from_date: contract_start_date = datetime.strptime(str(from_date), "%Y-%m-%d").date() contract_end_date = datetime.strptime(str(employee.leaving_date), "%Y-%m-%d").date() + timedelta( days=1) duration = relativedelta(contract_end_date, contract_start_date).days hours = (float((contract_end_date - contract_start_date).seconds) / 86400) * 24 employee_slip_line = self.slip_ids.filtered(lambda item: item.employee_id.id == employee.id) if not employee_slip_line: res = { 'employee_id': employee.id, 'name': slip_data['value'].get('name'), 'struct_id': self.salary_scale.id, 'contract_id': employee.contract_id.id, 'input_line_ids': [(0, 0, x) for x in slip_data['value'].get('input_line_ids')], 'worked_days_line_ids': worked_days, 'date_from': from_date, 'date_to': employee.leaving_date or to_date, 'holiday_start_date': holiday_start_date, 'holiday_end_date': holiday_end_date, 'credit_note': self.credit_note, 'company_id': employee.company_id.id, 'percentage': self.percentage} item_payslip = self.env['hr.payslip'].create(res) payslips += item_payslip # if pays: # for p in pays: # if p.employee_id != employee and p not in payslips: # payslips += item_payslip # else: # payslips += item_payslip if item_payslip: days = {'name': "Working days for this month", 'sequence': 1, 'payslip_id': item_payslip.id, 'code': 2, 'number_of_days': duration, 'number_of_hours': hours, 'contract_id': employee.contract_id.id} worked_days += self.env['hr.payslip.worked_days'].create(days) else: item_payslip = employee_slip_line payslips += item_payslip # if pays: # for p in pays: # if p.employee_id != employee and p not in payslips: # payslips += item_payslip # else: # payslips += item_payslip else: if not employee_slip_line and str(employee.first_hiring_date) < from_date: if employee.leaving_date: if str(employee.leaving_date) <= from_date: pass else: res = { 'employee_id': employee.id, 'name': slip_data['value'].get('name'), 'struct_id': self.salary_scale.id, 'contract_id': employee.contract_id.id, 'input_line_ids': [(0, 0, x) for x in slip_data['value'].get('input_line_ids')], 'worked_days_line_ids': [(0, 0, x) for x in slip_data['value'].get('worked_days_line_ids')], 'date_from': from_date, 'date_to': to_date, 'holiday_start_date': holiday_start_date, 'holiday_end_date': holiday_end_date, 'credit_note': self.credit_note, 'company_id': employee.company_id.id, 'percentage': self.percentage} payslips += self.env['hr.payslip'].create(res) else: res = { 'employee_id': employee.id, 'name': slip_data['value'].get('name'), 'struct_id': self.salary_scale.id, 'contract_id': employee.contract_id.id, 'input_line_ids': [(0, 0, x) for x in slip_data['value'].get('input_line_ids')], 'worked_days_line_ids': [(0, 0, x) for x in slip_data['value'].get('worked_days_line_ids')], 'date_from': from_date, 'date_to': to_date, 'holiday_start_date': holiday_start_date, 'holiday_end_date': holiday_end_date, 'credit_note': self.credit_note, 'company_id': employee.company_id.id, 'percentage': self.percentage} payslips += self.env['hr.payslip'].create(res) else: if employee.leaving_date and str(employee.first_hiring_date) < from_date: if str(employee.leaving_date) <= from_date: pass else: payslips += employee_slip_line else: payslips += employee_slip_line else: for emp in emps: slip_data = self.env['hr.payslip'].onchange_employee_id(from_date, to_date, emp.id, contract_id=False) # pays = self.env['hr.payslip'].search( # [('contract_id', '=', emp.contract_id.id), ('date_from', '>=', self.date_start)]) ################### Rename Slip and Date####### ttyme = datetime.fromtimestamp(time.mktime(time.strptime(str(from_date), "%Y-%m-%d"))) slip_data['value'].update({ 'name': _('Salary Slip of %s for %s') % ( emp.name, tools.ustr(babel.dates.format_date(date=ttyme, format='MMMM-y'))), 'company_id': emp.company_id.id, }) ########### employee_slip_line = self.slip_ids.filtered(lambda item: item.employee_id.id == emp.id) if to_date >= str(emp.first_hiring_date) >= from_date: if to_date >= str(emp.leaving_date) >= str(emp.first_hiring_date): contract_start_date = datetime.strptime(str(emp.first_hiring_date), "%Y-%m-%d").date() contract_end_date = datetime.strptime(str(emp.leaving_date), "%Y-%m-%d").date() + timedelta( days=1) duration = relativedelta(contract_end_date, contract_start_date).days hours = (float((contract_end_date - contract_start_date).seconds) / 86400) * 24 if not employee_slip_line: res = { 'employee_id': emp.id, 'name': slip_data['value'].get('name'), 'struct_id': self.salary_scale.id, 'contract_id': emp.contract_id.id, 'input_line_ids': [(0, 0, x) for x in slip_data['value'].get('input_line_ids')], # 'worked_days_line_ids': worked_days, 'date_from': emp.first_hiring_date or from_date, 'date_to': emp.leaving_date or to_date, 'holiday_start_date': holiday_start_date, 'holiday_end_date': holiday_end_date, 'credit_note': self.credit_note, 'company_id': emp.company_id.id, 'percentage': self.percentage} item_payslip = self.env['hr.payslip'].create(res) payslips += item_payslip # if pays: # for p in pays: # if p.employee_id != emp and p not in payslips: # payslips += item_payslip # else: # payslips += item_payslip if item_payslip: days = {'name': "Working days for this month", 'sequence': 1, 'payslip_id': item_payslip.id, 'code': 2, 'number_of_days': duration, 'number_of_hours': hours, 'contract_id': emp.contract_id.id} worked_days += self.env['hr.payslip.worked_days'].create(days) else: item_payslip = employee_slip_line payslips += item_payslip # if pays: # for p in pays: # if p.employee_id != emp and p not in payslips: # payslips += item_payslip # else: # payslips += item_payslip else: contract_start_date = datetime.strptime(str(emp.first_hiring_date), "%Y-%m-%d").date() from calendar import monthrange month_range = monthrange(datetime.now().date().year, month_date.month)[1] contract_end_date = datetime.strptime(str(to_date), "%Y-%m-%d").date() if month_range == 30 and contract_end_date.day == 30: duration = relativedelta(contract_end_date, contract_start_date).days + 1 elif month_range > 30 and contract_end_date.day > 30: duration = relativedelta(contract_end_date, contract_start_date).days if duration == 0: duration = duration + 1 elif month_range == 28 and contract_end_date.day == 28: duration = relativedelta(contract_end_date, contract_start_date).days + 3 elif month_range == 29 and contract_end_date.day == 29: duration = relativedelta(contract_end_date, contract_start_date).days + 2 else: duration = relativedelta(contract_end_date, contract_start_date).days + 1 hours = (float((contract_end_date - contract_start_date).seconds) / 86400) * 24 if not employee_slip_line: res = { 'employee_id': emp.id, 'name': slip_data['value'].get('name'), 'struct_id': self.salary_scale.id, 'contract_id': emp.contract_id.id, 'input_line_ids': [(0, 0, x) for x in slip_data['value'].get('input_line_ids')], # 'worked_days_line_ids': worked_days, 'date_from': emp.first_hiring_date or from_date, 'date_to': to_date, 'holiday_start_date': holiday_start_date, 'holiday_end_date': holiday_end_date, 'credit_note': self.credit_note, 'company_id': emp.company_id.id, 'percentage': self.percentage} item_payslip = self.env['hr.payslip'].create(res) payslips += item_payslip # if pays: # for p in pays: # if p.employee_id != emp and p not in payslips: # payslips += item_payslip # else: # payslips += item_payslip if item_payslip: days = {'name': "Working days for this month", 'sequence': 1, 'payslip_id': item_payslip.id, 'code': 2, 'number_of_days': duration, 'number_of_hours': hours, 'contract_id': emp.contract_id.id} worked_days += self.env['hr.payslip.worked_days'].create(days) else: item_payslip = employee_slip_line payslips += item_payslip # if pays: # for p in pays: # if p.employee_id != emp and p not in payslips: # payslips += item_payslip # else: # payslips += item_payslip elif to_date >= str(emp.leaving_date) >= from_date: contract_start_date = datetime.strptime(str(from_date), "%Y-%m-%d").date() contract_end_date = datetime.strptime(str(emp.leaving_date), "%Y-%m-%d").date() + timedelta(days=1) duration = relativedelta(contract_end_date, contract_start_date).days hours = (float((contract_end_date - contract_start_date).seconds) / 86400) * 24 if not employee_slip_line: res = { 'employee_id': emp.id, 'name': slip_data['value'].get('name'), 'struct_id': self.salary_scale.id, 'contract_id': emp.contract_id.id, 'input_line_ids': [(0, 0, x) for x in slip_data['value'].get('input_line_ids')], 'worked_days_line_ids': worked_days, 'date_from': from_date, 'date_to': emp.leaving_date, 'holiday_start_date': holiday_start_date, 'holiday_end_date': holiday_end_date, 'credit_note': self.credit_note, 'company_id': emp.company_id.id, 'percentage': self.percentage} item_payslip = self.env['hr.payslip'].create(res) payslips += item_payslip # if pays: # for p in pays: # if p.employee_id != emp and p not in payslips: # payslips += item_payslip # else: # payslips += item_payslip if item_payslip: days = {'name': "Working days for this month", 'sequence': 1, 'payslip_id': item_payslip.id, 'code': 2, 'number_of_days': duration, 'number_of_hours': hours, 'contract_id': emp.contract_id.id} worked_days += self.env['hr.payslip.worked_days'].create(days) else: item_payslip = employee_slip_line payslips += item_payslip # if pays: # for p in pays: # if p.employee_id != emp and p not in payslips: # payslips += item_payslip # else: # payslips += item_payslip else: if not employee_slip_line and str(emp.first_hiring_date) < from_date: if emp.leaving_date: if str(emp.leaving_date) <= from_date: pass else: res = { 'employee_id': emp.id, 'name': slip_data['value'].get('name'), 'struct_id': self.salary_scale.id, 'contract_id': emp.contract_id.id, 'input_line_ids': [(0, 0, x) for x in slip_data['value'].get('input_line_ids')], 'worked_days_line_ids': [(0, 0, x) for x in slip_data['value'].get('worked_days_line_ids')], 'date_from': from_date, 'date_to': to_date, 'holiday_start_date': holiday_start_date, 'holiday_end_date': holiday_end_date, 'credit_note': self.credit_note, 'company_id': emp.company_id.id, 'percentage': self.percentage} # if pays: # for p in pays: # if p.employee_id != emp and p not in payslips: # payslips += self.env['hr.payslip'].create(res) # else: payslips += self.env['hr.payslip'].create(res) else: res = { 'employee_id': emp.id, 'name': slip_data['value'].get('name'), 'struct_id': self.salary_scale.id, 'contract_id': emp.contract_id.id, 'input_line_ids': [(0, 0, x) for x in slip_data['value'].get('input_line_ids')], 'worked_days_line_ids': [(0, 0, x) for x in slip_data['value'].get('worked_days_line_ids')], 'date_from': from_date, 'date_to': to_date, 'holiday_start_date': holiday_start_date, 'holiday_end_date': holiday_end_date, 'credit_note': self.credit_note, 'company_id': emp.company_id.id, 'percentage': self.percentage} # if pays: # for p in pays: # if p.employee_id != emp and p not in payslips: # payslips += self.env['hr.payslip'].create(res) # else: payslips += self.env['hr.payslip'].create(res) else: if emp.leaving_date and str(emp.first_hiring_date) < from_date: if str(emp.leaving_date) <= from_date: pass else: payslips += employee_slip_line else: payslips += employee_slip_line payslips.compute_sheet() self.env['hr.payslip.line']._compute_total() for pay in payslips: if pay.total_sum < 0: dictionary.append(pay.employee_id.name) if dictionary: raise UserError( _("Salary is less than 0 this month for the following employees \n %s") % (dictionary)) self.slip_ids = payslips self.write({'state': 'computed'}) def withdraw(self): for line in self.slip_ids: payslip = self.env['hr.payslip'].search([('number', '=', line.number)]) if 'hr.loan.salary.advance' in self.env: loans = self.env['hr.loan.salary.advance'].search([('employee_id', '=', line.employee_id.id)]) if line.number == payslip.number: if line.loan_ids: for loan in line.loan_ids: loan.paid = False if loans: for i in loans: if i.id == loan.loan_id.id: for l in i.deduction_lines: if loan.date == l.installment_date and loan.paid is False: l.paid = False l.payment_date = False #i.remaining_loan_amount += l.installment_amount i.get_remaining_loan_amount() # check remaining loan and change state to pay if i.state == 'closed' and i.remaining_loan_amount > 0.0: i.state = 'pay' elif i.remaining_loan_amount == 0.0 and i.gm_propos_amount > 0.0: i.state = 'closed' for record in payslip: record.write({'state': 'draft'}) record.unlink() self.write({'slip_ids': [fields.Command.clear()]}) self.write({'state': 'draft'}) def unlink(self): if any(self.filtered(lambda payslip: payslip.state != 'draft')): raise UserError(_('You cannot delete a payslip which is not draft!')) return super(HrPayslipRun, self).unlink() def return_button(self): for line in self.slip_ids: payslip = self.env['hr.payslip'].search([('state', '=', line.state)]) if payslip: if self.move_id: if self.move_id.state == 'posted': raise UserError( _('You can not Return account move %s in state not draft') % self.move_id.name) else: self.move_id.unlink() self.move_id = False if line.move_id: if line.move_id.state == 'posted': raise UserError( _('You can not Return account move %s in state not draft') % line.move_id.name) else: line.move_id.unlink() line.move_id = False line.write({'state': 'computed'}) self.write({'state': 'computed'}) def confirm(self): for line in self.slip_ids: payslip = self.env['hr.payslip'].search([('state', '=', line.state)]) if payslip: line.write({'state': 'confirmed'}) self.write({'state': 'confirmed'}) def merge_lists(self, l1, key, key2): grupos = it.groupby(sorted(l1, key=itemgetter(key,key2)), key=itemgetter(key, key2)) res = [] for v, items in grupos: new_items = list(items) analytic_account_id = None if round(sum(dicc['debit'] for dicc in new_items),2) > 0: analytic_account_id = self.salary_scale.analytic_account_id.id res.append({ 'name': v[0], 'account_id': v[1], 'debit': round(sum(dicc['debit'] for dicc in new_items),2), 'credit': round(sum(dicc2['credit'] for dicc2 in new_items),2), 'analytic_account_id': analytic_account_id , }) return res def new_merge_lists(self, l1, key1, key2, key3): # groups = it.groupby(sorted(l1, key=itemgetter(key)), key=itemgetter(key, key2, key3)) groups = it.groupby(sorted(l1, key=itemgetter(key1, key2, key3)), key=itemgetter(key1, key2, key3)) res = [] for v, items in groups: new_items = list(items) res.append({ 'name': v[0], 'account_id': v[1], 'analytic_account_id': v[2], 'debit': sum(dicc['debit'] for dicc in new_items), 'credit': sum(dicc2['credit'] for dicc2 in new_items) }) return res def transfer(self): list_of_vals = [] if self.salary_scale.transfer_type == 'all': total_of_list = [] for line in self.slip_ids: emp_type = line.employee_id.employee_type_id.id total_allow, total_ded, total_loan = 0.0, 0.0, 0.0 total_list = [] total_loan_list = [] move_vals = dict() journal = self.journal_id if list_of_vals: for item in list_of_vals: if item.get('move') == journal.id: move_vals = item break for l in line.allowance_ids: amount_allow = l.total # account = l.salary_rule_id.rule_debit_account_id account = l.salary_rule_id.get_debit_account_id(emp_type) if not account: raise UserError( _('Sorry The Allowance %s is Not account Set') % l.name) total_list.append({ 'name': l.name, 'debit': amount_allow, 'journal_id': journal.id, 'credit': 0, 'account_id': account, }) total_allow += amount_allow for ded in line.deduction_ids: amount_ded = -ded.total # account = ded.salary_rule_id.rule_credit_account_id account = ded.salary_rule_id.get_credit_account_id(emp_type) if not account: raise UserError( _('Sorry The Deduction %s is Not account Set') % ded.name) total_list.append({ 'name': ded.name, 'credit': amount_ded, 'journal_id': journal.id, 'debit': 0, 'account_id': account, }) total_ded += amount_ded for lo in line.loan_ids: amount_loans = -lo.amount if not lo.account_id: raise UserError( _('Sorry The Loan %s is Not account Set') % lo.name) loan_line_vals = { 'name': lo.name, 'credit': amount_loans, 'debit': 0, 'journal_id': journal.id, 'account_id': lo.account_id.id, 'partner_id': line.employee_id.user_id.partner_id.id, } total_loan_list.append(loan_line_vals) total_loan += amount_loans # credit_loans_vals = { # 'name': lo.name, # 'credit': amount_loans, # 'journal_id': journal.id, # 'debit': 0, # 'account_id': lo.account_id.id, # } # total_list.append(credit_loans_vals) # create line for total of all allowance, deduction, loans of all employees total_of_list.append({ 'name': "Total", 'journal_id': journal.id, 'partner_id': line.employee_id.user_id.partner_id.id, 'account_id': journal.default_account_id.id, 'credit': round(total_allow, 2) - round(total_ded, 2) - round(total_loan, 2), 'debit': 0, }) if not move_vals: move_vals.update({'move': journal.id, 'list_ids': total_list, 'loans': total_loan_list}) list_of_vals.append(move_vals) else: new_list = move_vals.get('list_ids') new_list.extend(total_list) new_loan_list = move_vals.get('loans') new_loan_list.extend(total_loan_list) move_vals.update({'list_ids': new_list, 'loans': new_loan_list}) for record in list_of_vals: new_record_list = record.get('list_ids') + [d for d in total_of_list if d['journal_id'] == record.get('move')] new_rec_loan_list = record.get('loans') merged_list = self.merge_lists(new_record_list, 'name', 'account_id') record_final_item = merged_list + new_rec_loan_list if not self.move_id: move = self.env['account.move'].create({ 'state': 'draft', 'journal_id': record.get('move'), # 'date': fields.Date.context_today(self), 'date': self.date_end, 'ref': self.name, 'line_ids': [(0, 0, item) for item in record_final_item], 'res_model': 'hr.payslip.run', 'res_id': self.id }) self.move_id = move.id ########################## per_analytic_account ########### elif self.salary_scale.transfer_type == 'per_analytic_account': total_of_list = [] journal = self.journal_id department_totals = {} # Dictionary to store department-wise totals total_allow, total_ded, total_loan = 0.0, 0.0, 0.0 for line in self.slip_ids: emp_type = line.employee_id.employee_type_id.id total_list = [] total_loan_list = [] move_vals = dict() journal = self.journal_id if list_of_vals: for item in list_of_vals: if item.get('move') == journal.id: move_vals = item break for l in line.allowance_ids: amount_allow = l.total # account = l.salary_rule_id.rule_debit_account_id account = l.salary_rule_id.get_debit_account_id(emp_type) if not account: raise UserError( _('Sorry The Allowance %s is Not account Set') % l.name) total_list.append({ 'name': l.name, 'debit': amount_allow, 'journal_id': journal.id, 'credit': 0, 'account_id': account, 'analytic_account_id': line.employee_id.department_id.analytic_account_id.id, }) total_allow += amount_allow for ded in line.deduction_ids: amount_ded = -ded.total account = ded.salary_rule_id.get_credit_account_id(emp_type) # account = ded.salary_rule_id.rule_credit_account_id if not account: raise UserError( _('Sorry The Deduction %s is Not account Set') % ded.name) total_list.append({ 'name': ded.name, 'credit': amount_ded, 'journal_id': journal.id, 'debit': 0, 'account_id': account, 'analytic_account_id': None, }) total_ded += amount_ded for lo in line.loan_ids: amount_loans = -lo.amount if not lo.account_id: raise UserError( _('Sorry The Loan %s is Not account Set') % lo.name) credit_loans_vals = { 'name': lo.name, 'credit': amount_loans, 'journal_id': journal.id, 'debit': 0, 'account_id': lo.account_id.id, 'analytic_account_id': None, 'partner_id': line.employee_id.user_id.partner_id.id, } total_loan += amount_loans total_loan_list.append(credit_loans_vals) # Get the department of the employee department = line.employee_id.department_id # Add allowance amount to the department total if department in department_totals: department_totals[department] += total_allow else: department_totals[department] = total_allow if not move_vals: move_vals.update({'move': journal.id, 'list_ids': total_list, 'loans': total_loan_list}) list_of_vals.append(move_vals) else: new_list = move_vals.get('list_ids') new_list.extend(total_list) new_loan_list = move_vals.get('loans') new_loan_list.extend(total_loan_list) move_vals.update({'list_ids': new_list, 'loans': new_loan_list}) total_of_list.append({ 'name': "Total", 'journal_id': journal.id, 'account_id': journal.default_account_id.id, 'credit': total_allow - total_ded - total_loan, 'debit': 0, 'analytic_account_id': None, }) # for department, allowance_total in department_totals.items(): # total_of_list.append({ # 'name': f"Total ({department.analytic_account_id.name})", # 'journal_id': journal.id, # 'account_id': journal.default_credit_account_id.id, # 'credit': allowance_total - total_ded - total_loan, # 'analytic_account_id': department.analytic_account_id.id, # 'debit': 0, # }) for record in list_of_vals: new_record_list = record.get('list_ids') + [d for d in total_of_list if d['journal_id'] == record.get('move')] new_rec_loan_list = record.get('loans') merged_list = self.new_merge_lists(new_record_list, 'name', 'account_id', 'analytic_account_id') record_final_item = merged_list + new_rec_loan_list if not self.move_id: move = self.env['account.move'].create({ 'state': 'draft', 'journal_id': record.get('move'), 'date': self.date_end, 'ref': self.name, 'line_ids': [(0, 0, item) for item in record_final_item], 'res_model': 'hr.payslip.run', 'res_id': self.id }) self.move_id = move.id # import pdb # pdb.set_trace() ##################################### elif self.salary_scale.transfer_type == 'one_by_one': for line in self.slip_ids: emp_type = line.employee_id.employee_type_id.id total_allow, total_ded, total_loan = 0.0, 0.0, 0.0 total_list = [] move_vals = dict() journal = line.contract_id.journal_id if not journal: raise UserError( _('Sorry The Contract Employee %s is Not Journal Set') % line.employee_id.name) for l in line.allowance_ids: amount_allow = l.total # account = l.salary_rule_id.rule_debit_account_id account = l.salary_rule_id.get_debit_account_id(emp_type) if not account: raise UserError( _('Sorry The Allowance %s is Not account Set') % l.name) total_list.append({ 'name': l.name, 'debit': amount_allow, 'partner_id': line.employee_id.user_id.partner_id.id, 'credit': 0, 'account_id': account, 'analytic_account_id': line.employee_id.contract_id.analytic_account_id.id, }) total_allow += amount_allow for ded in line.deduction_ids: amount_ded = -ded.total # account = ded.salary_rule_id.rule_credit_account_id account = ded.salary_rule_id.get_credit_account_id(emp_type) if not account: raise UserError( _('Sorry The Deduction %s is Not account Set') % ded.name) total_list.append({ 'name': ded.name, 'credit': amount_ded, 'partner_id': line.employee_id.user_id.partner_id.id, 'debit': 0, 'account_id': account, }) total_ded += amount_ded for lo in line.loan_ids: amount_loans = -lo.amount if not lo.account_id: raise UserError( _('Sorry The Loan %s is Not account Set') % lo.name) credit_loans_vals = { 'name': lo.name, 'credit': amount_loans, 'partner_id': line.employee_id.user_id.partner_id.id, 'debit': 0, 'account_id': lo.account_id.id, } total_loan += amount_loans total_list.append(credit_loans_vals) # create line for total of all allowance, deduction, loans of all employees total = total_allow - total_ded - total_loan total_list.append({ 'name': line.name, 'partner_id': line.employee_id.user_id.partner_id.id, 'account_id': line.contract_id.journal_id.default_account_id.id, 'credit': total, 'debit': 0, }) # print('total list', total_list) if not move_vals: move_vals.update({'move': journal.id, 'list_ids': total_list}) list_of_vals.append(move_vals) else: new_list = move_vals.get('list_ids') new_list.extend(total_list) move_vals.update({'list_ids': new_list}) for record in list_of_vals: new_record_list = record.get('list_ids') # merged_list = self.merge_lists(new_record_list, 'name', 'account_id') # record_final_item = merged_list if not line.move_id: move = self.env['account.move'].create({ 'state': 'draft', 'partner_id': line.employee_id.user_id.partner_id.id, 'journal_id': line.contract_id.journal_id.id, # 'date': fields.Date.context_today(self), 'date': self.date_end, 'ref': line.name, 'line_ids': [(0, 0, item) for item in new_record_list], 'res_model': 'hr.payslip.run', 'res_id': self.id }) line.move_id = move.id else: bank_id = '' for line in self.slip_ids: emp_type = line.employee_id.employee_type_id.id total_allow, total_ded, total_loan = 0.0, 0.0, 0.0 total_list = [] total_loan_list = [] move_vals = dict() if line.employee_id.payment_method == 'bank': journal = self.env['account.journal'].search([('type', '=', line.employee_id.payment_method), ], limit=1) if not journal: raise UserError(' There is no journal For that Bank..' ' Please define a sale journal') if list_of_vals: for item in list_of_vals: if item.get('move') == journal.id: move_vals = item break for l in line.allowance_ids: amount_allow = l.total # account = l.salary_rule_id.rule_debit_account_id account = l.salary_rule_id.get_debit_account_id(emp_type) if not account: raise UserError( _('Sorry The Allowance %s is Not account Set') % l.name) total_list.append({ 'name': l.name, 'debit': amount_allow, 'journal_id': journal.id, 'credit': 0, 'account_id': account, }) total_allow += amount_allow for ded in line.deduction_ids: amount_ded = -ded.total # account = ded.salary_rule_id.rule_credit_account_id account = ded.salary_rule_id.get_credit_account_id(emp_type) if not account: raise UserError( _('Sorry The Deduction %s is Not account Set') % ded.name) total_list.append({ 'name': ded.name, 'credit': amount_ded, 'journal_id': journal.id, 'debit': 0, 'account_id': account, }) total_ded += amount_ded for lo in line.loan_ids: amount_loans = -lo.amount if not lo.account_id: raise UserError( _('Sorry The Loan %s is Not account Set') % lo.name) credit_loans_vals = { 'name': lo.name, 'credit': amount_loans, 'journal_id': journal.id, 'debit': 0, 'account_id': lo.account_id.id, 'partner_id': line.employee_id.user_id.partner_id.id, } total_loan += amount_loans total_loan_list.append(credit_loans_vals) # create line for total of all allowance, deduction, loans of all employees total_list.append({ 'name': "Total", 'journal_id': journal.id, 'account_id': journal.default_account_id.id, 'credit': total_allow - total_ded - total_loan, 'debit': 0, }) if not move_vals: move_vals.update({'move': journal.id, 'list_ids': total_list, 'loans': total_loan_list}) list_of_vals.append(move_vals) else: new_list = move_vals.get('list_ids') new_list.extend(total_list) new_loan_list = move_vals.get('loans') new_loan_list.extend(total_loan_list) move_vals.update({'list_ids': new_list, 'loans': new_loan_list}) bank_id = line.employee_id.bank_account_id.bank_id.name elif line.employee_id.payment_method == 'cash': amount, amount1, amount2 = 0.0, 0.0, 0.0 for l in line.allowance_ids: amount_allow = l.total # account = l.salary_rule_id.rule_debit_account_id account = l.salary_rule_id.get_debit_account_id(emp_type) if not account: raise UserError( _('Sorry The Allowance %s is Not account Set') % l.name) total_list.append({ 'name': l.name, 'account_id': account, 'debit': amount_allow, 'credit': 0, 'partner_id': line.employee_id.user_id.partner_id.id }) amount += amount_allow total_allow += amount for ded in line.deduction_ids: amount_ded = -ded.total # account = ded.salary_rule_id.rule_credit_account_id account = ded.salary_rule_id.get_credit_account_id(emp_type) if not account: raise UserError( _('Sorry The Deduction %s is Not account Set') % ded.name) total_list.append({ 'name': ded.name, 'account_id': account, 'credit': amount_ded, 'debit': 0, 'partner_id': line.employee_id.user_id.partner_id.id }) amount1 += amount_ded total_ded += amount1 for lo in line.loan_ids: amount_loans = -lo.amount if not lo.account_id: raise UserError( _('Sorry The Loan %s is Not account Set') % lo.name) total_list.append({ 'name': lo.name, 'account_id': lo.account_id.id, 'credit': amount_loans, 'debit': 0, 'partner_id': line.employee_id.user_id.partner_id.id }) amount2 += amount_loans total_loan += amount2 # create line for total of all allowance, deduction, loans of one employee total = total_allow - total_ded - total_loan total_list.append({ 'name': "Total", 'account_id': line.contract_id.journal_id.default_account_id.id, 'partner_id': line.employee_id.user_id.partner_id.id, 'credit': round(total, 1), 'debit': 0, }) move = self.env['account.move'].create({ 'journal_id': line.contract_id.journal_id.id, # 'date': fields.Date.context_today(self), 'date': self.date_end, 'ref': "Cash", 'line_ids': [(0, 0, item) for item in total_list] }) for record in list_of_vals: new_record_list = record.get('list_ids') new_rec_loan_list = record.get('loans') merged_list = self.merge_lists(new_record_list, 'name', 'account_id') record_final_item = merged_list + new_rec_loan_list if not line.move_id: move = self.env['account.move'].create({ 'state': 'draft', 'journal_id': record.get('move'), # 'date': fields.Date.context_today(self), 'date': self.date_end, 'ref': bank_id, 'line_ids': [(0, 0, item) for item in record_final_item], 'res_model': 'hr.payslip.run', 'res_id': self.id }) line.move_id = move.id for line in self.slip_ids: payslip = self.env['hr.payslip'].search([('state', '=', line.state)]) if payslip: line.write({'state': 'transfered'}) self.write({'state': 'transfered'})