exp_payroll_custom
This commit is contained in:
parent
1906c6e115
commit
d6e0892e98
|
|
@ -0,0 +1,5 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import models
|
||||||
|
from . import wizard
|
||||||
|
from . import report
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
{
|
||||||
|
'name': 'HR Advance Payroll',
|
||||||
|
'version': '18.0.1.0.0',
|
||||||
|
'category': 'Odex25-HR/Odex25-HR',
|
||||||
|
'sequence': 4,
|
||||||
|
'website': 'http://exp-sa.com',
|
||||||
|
'license': 'GPL-3',
|
||||||
|
'author': 'Expert Co. Ltd.',
|
||||||
|
'summary': 'Advance Payroll In HR',
|
||||||
|
'description': """
|
||||||
|
Helps you to manage All Payroll Requests of your company's staff.
|
||||||
|
""",
|
||||||
|
'depends': [
|
||||||
|
'exp_hr_payroll',
|
||||||
|
'hr_holidays_community',
|
||||||
|
'account',
|
||||||
|
'hr_contract',
|
||||||
|
'hr_base',
|
||||||
|
'report_xlsx',
|
||||||
|
'hr_contract_custom'
|
||||||
|
],
|
||||||
|
'data': [
|
||||||
|
'security/security.xml',
|
||||||
|
'security/ir.model.access.csv',
|
||||||
|
'security/ir_rule.xml',
|
||||||
|
|
||||||
|
'data/data.xml',
|
||||||
|
|
||||||
|
'views/salary_structure.xml',
|
||||||
|
# 'views/salary_advance.xml',
|
||||||
|
'views/payslip_view.xml',
|
||||||
|
'views/employee_promotions_view.xml',
|
||||||
|
'views/hr_salary_rules.xml',
|
||||||
|
'views/hr_salary_scale.xml',
|
||||||
|
'views/salary_scale_level_group.xml',
|
||||||
|
'views/hr_salary_scale_level.xml',
|
||||||
|
'views/hr_salary_scale_level_degree.xml',
|
||||||
|
'views/hr_recontract.xml',
|
||||||
|
'views/hr_employee.xml',
|
||||||
|
'views/hr_contract.xml',
|
||||||
|
'views/employee_reward_view.xml',
|
||||||
|
'views/payroll_report.xml',
|
||||||
|
'views/contract_advantage.xml',
|
||||||
|
'views/bank_pdf_report.xml',
|
||||||
|
'views/company_custom.xml',
|
||||||
|
'views/menu_security_cus.xml',
|
||||||
|
|
||||||
|
# menus
|
||||||
|
'views/payroll_menus.xml',
|
||||||
|
'views/hr_salary_menus.xml',
|
||||||
|
'wizard/payslip_monthly_report_view.xml',
|
||||||
|
'wizard/payroll_bank_report_view.xml',
|
||||||
|
'wizard/employee_selection_wizard.xml',
|
||||||
|
|
||||||
|
|
||||||
|
# reports templates
|
||||||
|
'templates/payroll_bank_text.xml',
|
||||||
|
'templates/hr_payslip_run_template.xml',
|
||||||
|
'templates/payslip_monthly_report.xml',
|
||||||
|
'templates/report_payslip_details.xml',
|
||||||
|
'templates/report_payslip.xml',
|
||||||
|
'templates/employee_cost_template.xml',
|
||||||
|
|
||||||
|
],
|
||||||
|
'installable': True,
|
||||||
|
'auto_install': False,
|
||||||
|
'application': True,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<odoo>
|
||||||
|
<data noupdate="1">
|
||||||
|
<!--Level sequence-->
|
||||||
|
<record id="level_sequence" model="ir.sequence">
|
||||||
|
<field name="name">level_sequence_name</field>
|
||||||
|
<field name="code">hr.salary.scale.level</field>
|
||||||
|
<field name="prefix">LO</field>
|
||||||
|
<field name="padding">5</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!--Degree sequence-->
|
||||||
|
<record id="degree_sequence" model="ir.sequence">
|
||||||
|
<field name="name">degree_sequence_name</field>
|
||||||
|
<field name="code">hr.salary.scale.level.degree</field>
|
||||||
|
<field name="prefix">DO</field>
|
||||||
|
<field name="padding">5</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!--Group sequence-->
|
||||||
|
<record id="group_sequence" model="ir.sequence">
|
||||||
|
<field name="name">group_sequence_name</field>
|
||||||
|
<field name="code">hr.salary.scale.level.group</field>
|
||||||
|
<field name="prefix">GO</field>
|
||||||
|
<field name="padding">5</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!--Salary sequence-->
|
||||||
|
<record id="salary_scale_sequence" model="ir.sequence">
|
||||||
|
<field name="name">salary_sequence_name</field>
|
||||||
|
<field name="code">hr.payroll.structure</field>
|
||||||
|
<field name="prefix">SO</field>
|
||||||
|
<field name="padding">5</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,16 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import hr_salary_rules
|
||||||
|
from . import hr_salary_scale
|
||||||
|
from . import hr_salary_scale_level_group
|
||||||
|
from . import hr_salary_scale_level
|
||||||
|
from . import hr_salary_scale_level_degree
|
||||||
|
from . import hr_recontract
|
||||||
|
from . import hr_employee
|
||||||
|
from . import hr_contract
|
||||||
|
from . import salary_advance
|
||||||
|
from . import hr_advance_payslip
|
||||||
|
from . import employee_promotions
|
||||||
|
from . import employee_reward
|
||||||
|
from . import company_costum
|
||||||
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class CompanyCustom(models.Model):
|
||||||
|
_inherit = 'res.company'
|
||||||
|
|
||||||
|
company_hr_no = fields.Char(string="Number Of Company For HR")
|
||||||
|
company_pay_no = fields.Char(string="Company Pay Number")
|
||||||
|
|
@ -0,0 +1,172 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from odoo import models, fields, api, _, exceptions
|
||||||
|
|
||||||
|
|
||||||
|
class EmployeePromotions(models.Model):
|
||||||
|
_name = 'employee.promotions'
|
||||||
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||||
|
_rec_name = 'employee_id'
|
||||||
|
_description = 'Employee Promotions'
|
||||||
|
|
||||||
|
date = fields.Date(required=True)
|
||||||
|
comment = fields.Text()
|
||||||
|
state = fields.Selection(selection=[('draft', _('Draft')),
|
||||||
|
('confirm', _('HR Officer')),
|
||||||
|
('hr_manager', _('HR Manager')),
|
||||||
|
('approved', _('Approved')), ('refuse', 'Refused')],
|
||||||
|
default='draft', tracking=True)
|
||||||
|
|
||||||
|
# relational fields
|
||||||
|
employee_id = fields.Many2one('hr.employee', domain=[('state', '=', 'open')])
|
||||||
|
old_scale = fields.Many2one('hr.payroll.structure')
|
||||||
|
old_level = fields.Many2one('hr.payroll.structure')
|
||||||
|
old_group = fields.Many2one('hr.payroll.structure')
|
||||||
|
old_degree = fields.Many2one('hr.payroll.structure')
|
||||||
|
old_level_2 = fields.Many2one('hr.payroll.structure')
|
||||||
|
old_group_2 = fields.Many2one('hr.payroll.structure')
|
||||||
|
old_degree_2 = fields.Many2one('hr.payroll.structure')
|
||||||
|
new_level = fields.Many2one('hr.payroll.structure', domain=[('id', 'in', [])])
|
||||||
|
new_group = fields.Many2one('hr.payroll.structure', domain=[('id', 'in', [])])
|
||||||
|
new_degree = fields.Many2one('hr.payroll.structure', domain=[('id', 'in', [])])
|
||||||
|
company_id = fields.Many2one('res.company', string='Company',default=lambda self: self.env.company)
|
||||||
|
|
||||||
|
@api.onchange('employee_id')
|
||||||
|
def store_level_group_and_degree_values(self):
|
||||||
|
if self.employee_id:
|
||||||
|
self.old_scale = self.employee_id.salary_scale
|
||||||
|
self.old_level = self.employee_id.salary_level
|
||||||
|
self.old_group = self.employee_id.salary_group
|
||||||
|
self.old_degree = self.employee_id.salary_degree
|
||||||
|
self.old_level_2 = self.employee_id.salary_level
|
||||||
|
self.old_group_2 = self.employee_id.salary_group
|
||||||
|
self.old_degree_2 = self.employee_id.salary_degree
|
||||||
|
|
||||||
|
# dynamic domain to get new level and new group domain
|
||||||
|
|
||||||
|
@api.onchange('old_scale')
|
||||||
|
def _get_new_level_and_new_group_domain(self):
|
||||||
|
for item in self:
|
||||||
|
if item.old_scale:
|
||||||
|
level_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_id', '=', item.old_scale.id), ('type', '=', 'level')])
|
||||||
|
group_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_id', '=', item.old_scale.id), ('type', '=', 'group')])
|
||||||
|
degree_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_id', '=', item.old_scale.id), ('type', '=', 'degree')])
|
||||||
|
domain = {'new_level': [('id', 'in', level_ids.ids)],
|
||||||
|
'new_group': [('id', 'in', group_ids.ids)],
|
||||||
|
'new_degree': [('id', 'in', degree_ids.ids)]}
|
||||||
|
return {'domain': domain}
|
||||||
|
else:
|
||||||
|
domain = {'new_level': [('id', 'in', [])],
|
||||||
|
'new_group': [('id', 'in', [])],
|
||||||
|
'new_degree': [('id', 'in', [])]}
|
||||||
|
return {'domain': domain}
|
||||||
|
|
||||||
|
# filter depend on salary_level
|
||||||
|
|
||||||
|
@api.onchange('new_level')
|
||||||
|
def onchange_salary_level(self):
|
||||||
|
for item in self:
|
||||||
|
if item.new_level:
|
||||||
|
group_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_level_id', '=', item.new_level.id), ('type', '=', 'group')])
|
||||||
|
return {'domain': {'new_group': [('id', 'in', group_ids.ids)],
|
||||||
|
'new_degree': [('id', 'in', [])]}}
|
||||||
|
else:
|
||||||
|
return {'domain': {'new_group': [('id', 'in', [])],
|
||||||
|
'new_degree': [('id', 'in', [])]}}
|
||||||
|
|
||||||
|
# dynamic domain to get new degree domain
|
||||||
|
|
||||||
|
@api.onchange('new_group')
|
||||||
|
def _get_new_degree_domain(self):
|
||||||
|
for item in self:
|
||||||
|
if item.new_group:
|
||||||
|
# item.new_degree = False
|
||||||
|
degree_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_group_id', '=', item.new_group.id), ('type', '=', 'degree')])
|
||||||
|
domain = {'new_degree': [('id', 'in', degree_ids.ids)]}
|
||||||
|
return {'domain': domain}
|
||||||
|
else:
|
||||||
|
domain = {'new_degree': [('id', 'in', [])]}
|
||||||
|
return {'domain': domain}
|
||||||
|
|
||||||
|
def confirm(self):
|
||||||
|
module_obj = self.env['ir.module.module'].sudo()
|
||||||
|
modules = module_obj.search([('state', '=', 'installed'), ('name', '=', 'hr_disciplinary_tracking')])
|
||||||
|
year_promotion = datetime.strptime(str(self.date), '%Y-%m-%d').strftime('%y')
|
||||||
|
if modules:
|
||||||
|
employee_penalty = self.env['hr.penalty.register'].search([('employee_id', '=', self.employee_id.id),
|
||||||
|
('state', 'not in', ['draft', 'refuse'])])
|
||||||
|
if employee_penalty:
|
||||||
|
for penalty in employee_penalty:
|
||||||
|
year_penalty = datetime.strptime(str(penalty.date), '%Y-%m-%d').strftime('%y')
|
||||||
|
if year_promotion == year_penalty:
|
||||||
|
for punish in penalty.punishment_id:
|
||||||
|
if punish.type == "deprivation":
|
||||||
|
raise exceptions.Warning(_('You can not promotions Employee has Penalty %s in this '
|
||||||
|
'Period.') % punish.name)
|
||||||
|
self.state = 'confirm'
|
||||||
|
|
||||||
|
def hr_manager(self):
|
||||||
|
self.confirm()
|
||||||
|
self.state = 'hr_manager'
|
||||||
|
|
||||||
|
def approved(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.employee_id.contract_id.write({
|
||||||
|
'salary_level': rec.new_level.id,
|
||||||
|
'salary_group': rec.new_group.id,
|
||||||
|
'salary_degree': rec.new_degree.id,
|
||||||
|
'salary': rec.new_degree.base_salary,
|
||||||
|
'salary_insurnce': rec.new_degree.base_salary,
|
||||||
|
})
|
||||||
|
rec.state = 'approved'
|
||||||
|
|
||||||
|
def act_refuse(self):
|
||||||
|
self.state = 'refuse'
|
||||||
|
|
||||||
|
# change state to draft
|
||||||
|
def re_draft(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.employee_id.contract_id.write({
|
||||||
|
'salary_level': rec.old_level_2.id,
|
||||||
|
'salary_group': rec.old_group_2.id,
|
||||||
|
'salary_degree': rec.old_degree_2.id,
|
||||||
|
'salary': rec.old_degree_2.base_salary,
|
||||||
|
'salary_insurnce': rec.old_degree_2.base_salary,
|
||||||
|
})
|
||||||
|
|
||||||
|
rec.state = 'draft'
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def create(self, values):
|
||||||
|
result = super(EmployeePromotions, self).create(values)
|
||||||
|
result.old_level_2 = result.old_level
|
||||||
|
result.old_group_2 = result.old_group
|
||||||
|
result.old_degree_2 = result.old_degree
|
||||||
|
return result
|
||||||
|
|
||||||
|
def unlink(self):
|
||||||
|
for item in self:
|
||||||
|
if item.state != 'draft':
|
||||||
|
raise exceptions.Warning(_(
|
||||||
|
'You can not delete employee promotions for "%s" in state not in draft.') % item.employee_id.name)
|
||||||
|
return super(EmployeePromotions, self).unlink()
|
||||||
|
|
||||||
|
|
||||||
|
class HrEmployee(models.Model):
|
||||||
|
_inherit = 'hr.employee'
|
||||||
|
|
||||||
|
promotions_count = fields.Integer(compute='get_employee_promotions')
|
||||||
|
|
||||||
|
def get_employee_promotions(self):
|
||||||
|
for item in self:
|
||||||
|
promotions = item.sudo().env['employee.promotions'].search([
|
||||||
|
('state', '=', 'approved'), ('employee_id', '=', item.id)])
|
||||||
|
item.sudo().promotions_count = len(promotions)
|
||||||
|
return promotions
|
||||||
|
|
@ -0,0 +1,477 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import calendar
|
||||||
|
from datetime import date, datetime
|
||||||
|
|
||||||
|
from odoo import models, fields, api, _, exceptions
|
||||||
|
|
||||||
|
|
||||||
|
class EmployeeReward(models.Model):
|
||||||
|
_name = 'hr.employee.reward'
|
||||||
|
_rec_name = 'allowance_name'
|
||||||
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||||
|
|
||||||
|
line_ids_reward = fields.One2many(comodel_name='lines.ids.reward', inverse_name='employee_reward_id',
|
||||||
|
string="Reward Line")
|
||||||
|
date = fields.Date(default=lambda self: fields.Date.today(), string="Date Request",
|
||||||
|
required=True, tracking=True)
|
||||||
|
date_from = fields.Date(string="Date From", tracking=True)
|
||||||
|
date_to = fields.Date(string="Date To", tracking=True)
|
||||||
|
allowance_reason = fields.Text(string="Reward Reason", required=True)
|
||||||
|
allowance_name = fields.Many2one('hr.salary.rule', string="Allowance Name")
|
||||||
|
percentage = fields.Float(string="Percentage%", default=100)
|
||||||
|
amount = fields.Float(string="Amount")
|
||||||
|
account_id = fields.Many2one('account.account')
|
||||||
|
journal_id = fields.Many2one('account.journal', string='Payment Method')
|
||||||
|
next_approve = fields.Text(string="Next Required Approval", compute="_get_nxt_approve")
|
||||||
|
reward_type = fields.Selection(
|
||||||
|
[('allowance', 'Allowance'), ('amount', 'Amount')], default='allowance')
|
||||||
|
transfer_type = fields.Selection(
|
||||||
|
[('accounting', 'Accounting'), ('payroll', 'Payroll')], default='accounting')
|
||||||
|
state = fields.Selection(
|
||||||
|
[('draft', 'Draft'), ('submitted', 'Submit'), ('hrm', 'HRM Approval'),
|
||||||
|
('done', 'GM Approval'), ('refused', 'Refused')], default='draft', tracking=True)
|
||||||
|
benefits_discounts = fields.Many2one(comodel_name='hr.salary.rule', string='Rewards/Benefits')
|
||||||
|
|
||||||
|
check_appraisal = fields.Boolean(string='Appraisal Percentage', default=False)
|
||||||
|
reward_once = fields.Boolean(string='Reward Once Yearly', default=False)
|
||||||
|
|
||||||
|
company_id = fields.Many2one('res.company', string='Company',
|
||||||
|
default=lambda self: self.env.company)
|
||||||
|
|
||||||
|
def action_add_employees(self):
|
||||||
|
self.ensure_one()
|
||||||
|
ctx = dict(self.env.context)
|
||||||
|
if not self.id:
|
||||||
|
ctx.update({
|
||||||
|
'default_reward_vals': {
|
||||||
|
'name': self.name,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
ctx['default_employee_reward_id'] = self.id
|
||||||
|
|
||||||
|
if self.percentage:
|
||||||
|
ctx['default_percentage'] = self.percentage
|
||||||
|
|
||||||
|
ctx['default_employee_id'] = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'name': _('Add Employees to Reward'),
|
||||||
|
'view_mode': 'form',
|
||||||
|
'res_model': 'employee.selection.wizard',
|
||||||
|
'type': 'ir.actions.act_window',
|
||||||
|
'target': 'new',
|
||||||
|
'context': ctx,
|
||||||
|
}
|
||||||
|
|
||||||
|
@api.onchange('amount')
|
||||||
|
def chick_amount_positive(self):
|
||||||
|
for item in self:
|
||||||
|
if item.amount < 0:
|
||||||
|
raise exceptions.Warning(_('The Amount Must Be Greater Than Zero'))
|
||||||
|
|
||||||
|
|
||||||
|
@api.depends('state')
|
||||||
|
def _get_nxt_approve(self):
|
||||||
|
for record in self:
|
||||||
|
if record.state == "draft":
|
||||||
|
record.next_approve = "Submit"
|
||||||
|
for line in record.line_ids_reward:
|
||||||
|
line.reward_state = "draft"
|
||||||
|
elif record.state == "submitted":
|
||||||
|
record.next_approve = "HRM Approval"
|
||||||
|
for line in record.line_ids_reward:
|
||||||
|
line.reward_state = "submitted"
|
||||||
|
elif record.state == "hrm":
|
||||||
|
record.next_approve = "GM Approval"
|
||||||
|
for line in record.line_ids_reward:
|
||||||
|
line.reward_state = "hrm"
|
||||||
|
elif record.state == "done":
|
||||||
|
for line in record.line_ids_reward:
|
||||||
|
line.reward_state = "done"
|
||||||
|
elif record.state == "refused":
|
||||||
|
for line in record.line_ids_reward:
|
||||||
|
line.reward_state = "refused"
|
||||||
|
|
||||||
|
def action_submit(self):
|
||||||
|
if not self.line_ids_reward:
|
||||||
|
raise exceptions.Warning(_('Sorry, Can Not Request without The Employees'))
|
||||||
|
self.state = "submitted"
|
||||||
|
for line in self.line_ids_reward:
|
||||||
|
line.check_reward_once()
|
||||||
|
line.reward_state = "submitted"
|
||||||
|
|
||||||
|
def recalculate(self):
|
||||||
|
for line in self.line_ids_reward:
|
||||||
|
# line.amount = line.amount
|
||||||
|
# line.percentage = line.percentage
|
||||||
|
line._compute_calculate_amount()
|
||||||
|
|
||||||
|
def action_hrm(self):
|
||||||
|
self.state = "hrm"
|
||||||
|
for line in self.line_ids_reward:
|
||||||
|
line.check_reward_once()
|
||||||
|
line.reward_state = "hrm"
|
||||||
|
|
||||||
|
def action_done(self):
|
||||||
|
if self.transfer_type == 'accounting':
|
||||||
|
for item in self:
|
||||||
|
for record in item.line_ids_reward:
|
||||||
|
debit_line_vals = {
|
||||||
|
'name': record.employee_id.name,
|
||||||
|
'debit': record.amount,
|
||||||
|
'account_id': item.account_id.id,
|
||||||
|
'partner_id': record.employee_id.user_id.partner_id.id,
|
||||||
|
'analytic_account_id': record.employee_id.department_id.analytic_account_id.id
|
||||||
|
}
|
||||||
|
credit_line_vals = {
|
||||||
|
'name': record.employee_id.name,
|
||||||
|
'credit': record.amount,
|
||||||
|
'account_id': item.journal_id.default_account_id.id
|
||||||
|
#'partner_id': record.employee_id.user_id.partner_id.id
|
||||||
|
}
|
||||||
|
if not record.move_id:
|
||||||
|
move = record.env['account.move'].create({
|
||||||
|
'state': 'draft',
|
||||||
|
'journal_id': item.journal_id.id,
|
||||||
|
'date': item.date,
|
||||||
|
'ref': record.employee_id.name,
|
||||||
|
'line_ids': [(0, 0, debit_line_vals), (0, 0, credit_line_vals)],
|
||||||
|
'res_model': 'hr.employee.reward',
|
||||||
|
'res_id': self.id
|
||||||
|
})
|
||||||
|
|
||||||
|
record.move_id = move.id
|
||||||
|
self.state = "done"
|
||||||
|
for line in self.line_ids_reward:
|
||||||
|
line.reward_state = "done"
|
||||||
|
if self.transfer_type == 'payroll':
|
||||||
|
last_day_of_current_month = date.today().replace(
|
||||||
|
day=calendar.monthrange(date.today().year, date.today().month)[1])
|
||||||
|
first_day_of_current_month = date.today().replace(day=1)
|
||||||
|
for item in self:
|
||||||
|
for record in item.line_ids_reward:
|
||||||
|
if record.employee_id.contract_id:
|
||||||
|
|
||||||
|
advantage_arc = record.env['contract.advantage'].create({
|
||||||
|
'benefits_discounts': item.benefits_discounts.id,
|
||||||
|
'type': 'customize',
|
||||||
|
'date_from': item.date_from,
|
||||||
|
'date_to': item.date_to,
|
||||||
|
'amount': record.amount,
|
||||||
|
'reward_id': True,
|
||||||
|
'employee_id': record.employee_id.id,
|
||||||
|
'contract_advantage_id': record.employee_id.contract_id.id,
|
||||||
|
'out_rule': True,
|
||||||
|
'state': 'confirm',
|
||||||
|
'comments': item.allowance_reason})
|
||||||
|
record.advantage_id = advantage_arc.id
|
||||||
|
else:
|
||||||
|
raise exceptions.Warning(_(
|
||||||
|
'Employee "%s" has no contract Please create contract to add line to advantages')
|
||||||
|
% record.employee_id.name)
|
||||||
|
|
||||||
|
self.state = "done"
|
||||||
|
for line in self.line_ids_reward:
|
||||||
|
line.reward_state = "done"
|
||||||
|
|
||||||
|
def action_refuse(self):
|
||||||
|
self.state = "refused"
|
||||||
|
for line in self.line_ids_reward:
|
||||||
|
line.reward_state = "refused"
|
||||||
|
|
||||||
|
def re_draft(self):
|
||||||
|
# when redraft cancel the created account move
|
||||||
|
if self.transfer_type == 'payroll':
|
||||||
|
for record in self.line_ids_reward:
|
||||||
|
record.advantage_id.draft()
|
||||||
|
record.advantage_id.unlink()
|
||||||
|
record.reward_state = "draft"
|
||||||
|
self.state = "draft"
|
||||||
|
|
||||||
|
if self.transfer_type == 'accounting':
|
||||||
|
if self.transfer_type == 'accounting':
|
||||||
|
if self.line_ids_reward and self.line_ids_reward[0].move_id:
|
||||||
|
move_id_not_draft = False
|
||||||
|
for line in self.line_ids_reward:
|
||||||
|
if line.move_id.state == 'posted':
|
||||||
|
move_id_not_draft_name = line.move_id.name
|
||||||
|
move_id_not_draft = True
|
||||||
|
if move_id_not_draft:
|
||||||
|
raise exceptions.Warning(_(
|
||||||
|
'You can not cancel account move "%s" in state not draft') % move_id_not_draft_name)
|
||||||
|
else:
|
||||||
|
for record in self.line_ids_reward:
|
||||||
|
# record.move_id.write({'state': 'canceled'})
|
||||||
|
record.move_id.unlink()
|
||||||
|
record.write({'move_id': False, })
|
||||||
|
#record.account_id = False
|
||||||
|
#record.journal_id = False
|
||||||
|
record.reward_state = "draft"
|
||||||
|
self.write({'state': 'draft'})
|
||||||
|
#self.account_id = False
|
||||||
|
#self.journal_id = False
|
||||||
|
else:
|
||||||
|
self.write({
|
||||||
|
'state': 'draft',
|
||||||
|
#'account_id': False,
|
||||||
|
#'journal_id': False
|
||||||
|
})
|
||||||
|
for record in self.line_ids_reward:
|
||||||
|
record.write({
|
||||||
|
'move_id': False,
|
||||||
|
#'account_id': False,
|
||||||
|
#'journal_id': False,
|
||||||
|
'reward_state': 'draft'
|
||||||
|
})
|
||||||
|
|
||||||
|
def unlink(self):
|
||||||
|
for i in self:
|
||||||
|
if i.state != 'draft':
|
||||||
|
raise exceptions.Warning(_('You can not delete record in state not in draft'))
|
||||||
|
i.line_ids_reward.unlink()
|
||||||
|
return super(EmployeeReward, self).unlink()
|
||||||
|
|
||||||
|
@api.onchange('transfer_type', 'account_id', 'journal_id', 'line_ids_reward')
|
||||||
|
def onchange_transfer_type(self):
|
||||||
|
if self.transfer_type == 'payroll':
|
||||||
|
self.account_id = False
|
||||||
|
self.journal_id = False
|
||||||
|
for line in self.line_ids_reward:
|
||||||
|
line.account_id = False
|
||||||
|
line.journal_id = False
|
||||||
|
if self.transfer_type == 'accounting':
|
||||||
|
for line in self.line_ids_reward:
|
||||||
|
if self.state == 'hrm':
|
||||||
|
if not line.account_id:
|
||||||
|
line.account_id = self.account_id
|
||||||
|
if not line.journal_id:
|
||||||
|
line.journal_id = self.journal_id
|
||||||
|
else:
|
||||||
|
line.account_id = False
|
||||||
|
line.journal_id = False
|
||||||
|
|
||||||
|
@api.onchange('account_id')
|
||||||
|
def onchange_account_id(self):
|
||||||
|
for line in self.line_ids_reward:
|
||||||
|
self.recalculate()
|
||||||
|
line.account_id = self.account_id
|
||||||
|
|
||||||
|
@api.onchange('journal_id')
|
||||||
|
def onchange_journal_id(self):
|
||||||
|
for line in self.line_ids_reward:
|
||||||
|
self.recalculate()
|
||||||
|
line.journal_id = self.journal_id
|
||||||
|
|
||||||
|
|
||||||
|
class HrEmployee(models.Model):
|
||||||
|
_name = 'lines.ids.reward'
|
||||||
|
|
||||||
|
def _domain_get_employee(self):
|
||||||
|
return [('id', '!=', self.employee_id.id), ('state', '=', 'open')]
|
||||||
|
|
||||||
|
employee_reward_id = fields.Many2one('hr.employee.reward', string='Employee', required=True)
|
||||||
|
employee_id = fields.Many2one('hr.employee', string='Employee', required=True,
|
||||||
|
domain=lambda self: self._domain_get_employee())
|
||||||
|
amount = fields.Float(string="Amount", compute='_compute_calculate_amount', store=True)
|
||||||
|
account_id = fields.Many2one('account.account', string='Account')
|
||||||
|
journal_id = fields.Many2one('account.journal', string='Payment Method')
|
||||||
|
percentage = fields.Float(string="Percentage%")
|
||||||
|
move_id = fields.Many2one('account.move')
|
||||||
|
contract_advantage_id = fields.Many2one('hr.contract')
|
||||||
|
reward_state = fields.Selection(
|
||||||
|
[('draft', 'Draft'), ('submitted', 'Submit'), ('hrm', 'HRM Approval'),
|
||||||
|
('done', 'GM Approval'), ('refused', 'Refused')], default='draft')
|
||||||
|
|
||||||
|
amount_base = fields.Float(string="Amount Base", store=True)
|
||||||
|
check_appraisal = fields.Boolean('Appraisal Percentage', related='employee_reward_id.check_appraisal', store=True)
|
||||||
|
transfer_type = fields.Selection(related='employee_reward_id.transfer_type', string='Transfer type')
|
||||||
|
|
||||||
|
reward_once = fields.Boolean(related='employee_reward_id.reward_once', store=True)
|
||||||
|
date = fields.Date(related='employee_reward_id.date', string='Reward Once Yearly', tracking=True, store=True)
|
||||||
|
|
||||||
|
advantage_id = fields.Many2one(comodel_name='contract.advantage', string='Allowance Employee')
|
||||||
|
|
||||||
|
reward_type = fields.Selection(related='employee_reward_id.reward_type', string='Reward Type', store=True)
|
||||||
|
|
||||||
|
@api.onchange('amount_base')
|
||||||
|
def chick_amount_base_positive(self):
|
||||||
|
for item in self:
|
||||||
|
if item.amount_base < 0:
|
||||||
|
raise exceptions.Warning(_('The Employee %s Amount Must Be Greater Than Zero')% item.employee_id.name)
|
||||||
|
|
||||||
|
|
||||||
|
# Select employee once in reward Line
|
||||||
|
@api.onchange('employee_id')
|
||||||
|
def select_employee_once(self):
|
||||||
|
employee_ids = self.env['hr.employee'].search([('state', '=', 'open')]).ids
|
||||||
|
|
||||||
|
for line in self.employee_reward_id.line_ids_reward:
|
||||||
|
if line.employee_id:
|
||||||
|
if line.employee_id.id in employee_ids:
|
||||||
|
employee_ids.remove(line.employee_id.id)
|
||||||
|
|
||||||
|
return {'domain': {'employee_id': [('id', 'in', employee_ids)]}}
|
||||||
|
|
||||||
|
def get_salary_rules_account(self, record_id, amount, items):
|
||||||
|
record = self.env['hr.salary.rule.line'].create({
|
||||||
|
'salary_rule_id': record_id.id,
|
||||||
|
'amount': amount,
|
||||||
|
})
|
||||||
|
items.append(record.id)
|
||||||
|
|
||||||
|
def compute_salary_rule(self, record_id, item, items):
|
||||||
|
for record in self:
|
||||||
|
if not record.employee_id.id: continue
|
||||||
|
contract = self.env['hr.contract'].search([('employee_id', '=', record.employee_id.id)])
|
||||||
|
localdict = dict(employee=record.employee_id.id, contract=contract)
|
||||||
|
amount, total = 0.0, 0.0
|
||||||
|
|
||||||
|
if item.amount_select == 'fix':
|
||||||
|
if contract.advantages:
|
||||||
|
for con in contract.advantages:
|
||||||
|
if item.id == con.benefits_discounts.id:
|
||||||
|
if con.type == 'exception':
|
||||||
|
if con.amount > item._compute_rule(localdict)[0] or con.amount == \
|
||||||
|
item._compute_rule(localdict)[0]:
|
||||||
|
pass
|
||||||
|
elif con.amount < item._compute_rule(localdict)[0]:
|
||||||
|
total = item._compute_rule(localdict)[0] - con.amount
|
||||||
|
elif con.type == 'customize':
|
||||||
|
total = con.amount
|
||||||
|
amount = 0
|
||||||
|
amount += total
|
||||||
|
else:
|
||||||
|
amount = 0
|
||||||
|
amount += item._compute_rule(localdict)[0]
|
||||||
|
else:
|
||||||
|
amount += item._compute_rule(localdict)[0]
|
||||||
|
|
||||||
|
elif item.amount_select == 'percentage':
|
||||||
|
if contract and contract.advantages:
|
||||||
|
for con in contract.advantages:
|
||||||
|
if item.id == con.benefits_discounts.id:
|
||||||
|
if con.type == 'exception':
|
||||||
|
if con.amount > item._compute_rule(localdict)[0] or con.amount == \
|
||||||
|
item._compute_rule(localdict)[0]:
|
||||||
|
pass
|
||||||
|
elif con.amount < item._compute_rule(localdict)[0]:
|
||||||
|
total = item._compute_rule(localdict)[0] - con.amount
|
||||||
|
elif con.type == 'customize':
|
||||||
|
total = con.amount
|
||||||
|
amount = 0
|
||||||
|
amount += total
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if amount:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
amount += item._compute_rule(localdict)[0]
|
||||||
|
else:
|
||||||
|
amount += item._compute_rule(localdict)[0]
|
||||||
|
|
||||||
|
else:
|
||||||
|
if contract.advantages:
|
||||||
|
for con in contract.advantages:
|
||||||
|
if item.id == con.benefits_discounts.id:
|
||||||
|
if con.type == 'exception':
|
||||||
|
if con.amount > item._compute_rule(localdict)[0] or con.amount == \
|
||||||
|
item._compute_rule(localdict)[0]:
|
||||||
|
pass
|
||||||
|
elif con.amount < item._compute_rule(localdict)[0]:
|
||||||
|
total = item._compute_rule(localdict)[0] - con.amount
|
||||||
|
elif con.type == 'customize':
|
||||||
|
total = con.amount
|
||||||
|
amount = 0
|
||||||
|
amount += total
|
||||||
|
else:
|
||||||
|
if amount:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
amount = 0
|
||||||
|
amount += item._compute_rule(localdict)[0]
|
||||||
|
else:
|
||||||
|
amount += item._compute_rule(localdict)[0]
|
||||||
|
|
||||||
|
return amount
|
||||||
|
|
||||||
|
@api.depends('percentage', 'employee_reward_id', 'employee_id', 'account_id', 'journal_id','amount_base')
|
||||||
|
def _compute_calculate_amount(self):
|
||||||
|
for line in self:
|
||||||
|
if line.check_appraisal == True:
|
||||||
|
self.get_percentage_appraisal()
|
||||||
|
percentage = line.percentage
|
||||||
|
if line.employee_reward_id.reward_type == 'allowance':
|
||||||
|
if line.employee_reward_id.allowance_name:
|
||||||
|
items = []
|
||||||
|
for item in line.employee_reward_id.allowance_name:
|
||||||
|
total = 0.0
|
||||||
|
record_id = self.env['hr.salary.rule'].search([('id', '=', item.id)])
|
||||||
|
total = self.compute_salary_rule(record_id, item, items) or 0
|
||||||
|
amount = (total * percentage) / 100
|
||||||
|
line.amount = amount
|
||||||
|
amount_base = total
|
||||||
|
line.amount_base = amount_base
|
||||||
|
elif line.employee_reward_id.reward_type == 'amount':
|
||||||
|
amount_up = line.employee_reward_id.amount
|
||||||
|
if amount_up > 0:
|
||||||
|
amount = (amount_up * percentage) / 100
|
||||||
|
line.amount = amount
|
||||||
|
amount_base = amount_up
|
||||||
|
line.amount_base = amount_base
|
||||||
|
else:
|
||||||
|
line.amount = (line.amount_base * percentage) / 100
|
||||||
|
|
||||||
|
else:
|
||||||
|
line.amount = 0
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def default_get(self, fields):
|
||||||
|
res = super(HrEmployee, self).default_get(fields)
|
||||||
|
if self._context.get('percentage'):
|
||||||
|
res['percentage'] = self._context.get('percentage')
|
||||||
|
if self._context.get('account_id') and self._context.get('journal_id'):
|
||||||
|
res['account_id'] = self._context.get('account_id')
|
||||||
|
res['journal_id'] = self._context.get('journal_id')
|
||||||
|
return res
|
||||||
|
|
||||||
|
# get percentage from performance appraisal
|
||||||
|
def get_percentage_appraisal(self):
|
||||||
|
Module = self.env['ir.module.module'].sudo()
|
||||||
|
modules = Module.search([('state', '=', 'installed'), ('name', '=', 'exp_hr_appraisal')])
|
||||||
|
|
||||||
|
for line in self:
|
||||||
|
if modules:
|
||||||
|
emp_appraisal = self.env['hr.employee.appraisal'].search([('employee_id', '=', line.employee_id.id),
|
||||||
|
('state', '!=', 'draft'),
|
||||||
|
('appraisal_type', '=', 'performance')],
|
||||||
|
order='appraisal_date desc', limit=1)
|
||||||
|
level_achieved = emp_appraisal.level_achieved
|
||||||
|
if line.check_appraisal:
|
||||||
|
if emp_appraisal:
|
||||||
|
line.percentage = level_achieved
|
||||||
|
else:
|
||||||
|
line.percentage = 0
|
||||||
|
|
||||||
|
# To Cannot Take More Than Once Reward In The Same Year
|
||||||
|
|
||||||
|
@api.constrains('employee_id', 'date', 'reward_once')
|
||||||
|
def check_reward_once(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.date:
|
||||||
|
current_year = datetime.strptime(str(rec.date), "%Y-%m-%d").date().year
|
||||||
|
last_reward = rec.search([('id', '!=', rec.id), ('employee_id', '=', rec.employee_id.id),
|
||||||
|
('reward_state', 'not in', ('draft', 'refused')),
|
||||||
|
('reward_once', '=', True)], order='date desc', limit=1).date
|
||||||
|
if last_reward:
|
||||||
|
last_year = datetime.strptime(str(last_reward), "%Y-%m-%d").date().year
|
||||||
|
if current_year == last_year and rec.reward_once:
|
||||||
|
raise exceptions.Warning(_('Sorry, The Employee %s Cannot be Taking More Than Once Reward '
|
||||||
|
'In The Same Year %s') % (rec.employee_id.name, current_year))
|
||||||
|
|
||||||
|
def unlink(self):
|
||||||
|
for i in self:
|
||||||
|
if i.reward_state != 'draft':
|
||||||
|
raise exceptions.Warning(_('You can not delete record in state not in draft'))
|
||||||
|
return super(HrEmployee, self).unlink()
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,349 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
|
class HrContractSalaryScale(models.Model):
|
||||||
|
_inherit = 'hr.contract'
|
||||||
|
|
||||||
|
salary_level = fields.Many2one(comodel_name='hr.payroll.structure', domain=[('id', 'in', [])])
|
||||||
|
salary_scale = fields.Many2one(comodel_name='hr.payroll.structure', domain=[('id', 'in', [])], index=True)
|
||||||
|
salary_group = fields.Many2one(comodel_name='hr.payroll.structure', domain=[('id', 'in', [])])
|
||||||
|
salary_degree = fields.Many2one(comodel_name='hr.payroll.structure', domain=[('id', 'in', [])])
|
||||||
|
hide = fields.Boolean(string='Hide', compute="compute_type")
|
||||||
|
required_condition = fields.Boolean(string='Required Condition', compute='compute_move_type')
|
||||||
|
total_allowance = fields.Float(string='Total Allowance', compute='compute_function',store=True)
|
||||||
|
total_deduction = fields.Float(string='Total Deduction', compute='compute_function',store=True)
|
||||||
|
total_net = fields.Float(string='Total Net', compute='compute_function',store=True)
|
||||||
|
advantages = fields.One2many('contract.advantage', 'contract_advantage_id', string='Advantages')
|
||||||
|
house_allowance_temp = fields.Float(string='House Allowance', compute='compute_function',store=True)
|
||||||
|
transport_allowance = fields.Float(string='Transport Allowance', compute='compute_function',store=True)
|
||||||
|
|
||||||
|
@api.constrains('advantages', 'salary', 'salary_group')
|
||||||
|
def amount_constrains(self):
|
||||||
|
for rec in self:
|
||||||
|
localdict = dict(employee=rec.employee_id.id, contract=rec.env['hr.contract'].search([
|
||||||
|
('employee_id', '=', rec.employee_id.id)]))
|
||||||
|
if rec.salary_group.gread_max > 0 and rec.salary_group.gread_min > 0:
|
||||||
|
if rec.salary > rec.salary_group.gread_max or rec.salary < rec.salary_group.gread_min:
|
||||||
|
raise UserError(_('The Basic Salary Is Greater Than Group Gread Max Or less than Gread Min'))
|
||||||
|
for item in self.advantages:
|
||||||
|
item.to_get_contract_id()
|
||||||
|
if item.benefits_discounts._compute_rule(localdict)[0] < item.amount and item.type == 'exception':
|
||||||
|
raise UserError(_(
|
||||||
|
'The amount you put is greater than fact value of this Salary rule %s (%s).') % (
|
||||||
|
item.benefits_discounts.name, item.benefits_discounts.code))
|
||||||
|
|
||||||
|
@api.depends('salary_scale.transfer_type')
|
||||||
|
def compute_move_type(self):
|
||||||
|
self.compute_function()
|
||||||
|
if self.salary_scale.transfer_type == 'one_by_one':
|
||||||
|
self.required_condition = True
|
||||||
|
else:
|
||||||
|
self.required_condition = False
|
||||||
|
|
||||||
|
@api.depends('salary_scale', 'salary_level', 'salary_group', 'salary_degree','salary','advantages','house_allowance_temp','transport_allowance','total_deduction','salary_insurnce','total_allowance','state')
|
||||||
|
def compute_function(self):
|
||||||
|
for item in self:
|
||||||
|
item.house_allowance_temp = 0
|
||||||
|
item.transport_allowance = 0
|
||||||
|
item.total_net = 0
|
||||||
|
contract = self.env['hr.contract'].search([('employee_id', '=', item.employee_id.id)])
|
||||||
|
localdict = dict(employee=item.employee_id.id, contract=contract)
|
||||||
|
current_date = datetime.now().date()
|
||||||
|
|
||||||
|
# customize type in advantages
|
||||||
|
allowance_customize_items = item.advantages.filtered(
|
||||||
|
lambda key: key.type == 'customize' and key.out_rule is False and
|
||||||
|
key.benefits_discounts.category_id.rule_type == 'allowance' and
|
||||||
|
(datetime.strptime(str(key.date_to), "%Y-%m-%d").date() if key.date_to else current_date)
|
||||||
|
>= current_date >= datetime.strptime(str(key.date_from), "%Y-%m-%d").date())
|
||||||
|
|
||||||
|
allow_sum_custom = sum(x.amount for x in allowance_customize_items)
|
||||||
|
for x in allowance_customize_items:
|
||||||
|
if x.benefits_discounts.rules_type == 'house':
|
||||||
|
item.house_allowance_temp += x.amount
|
||||||
|
|
||||||
|
if x.benefits_discounts.rules_type == 'transport':
|
||||||
|
item.transport_allowance += x.amount
|
||||||
|
# allow_custom_ids = [record.benefits_discounts.id for record in allowance_customize_items]
|
||||||
|
|
||||||
|
deduction_customize_items = item.advantages.filtered(
|
||||||
|
lambda key: key.type == 'customize' and key.out_rule is False and
|
||||||
|
key.benefits_discounts.category_id.rule_type == 'deduction' and
|
||||||
|
(datetime.strptime(str(key.date_to), "%Y-%m-%d").date() if key.date_to else current_date)
|
||||||
|
>= current_date >= datetime.strptime(str(key.date_from), "%Y-%m-%d").date())
|
||||||
|
|
||||||
|
ded_sum_custom = sum(x.amount for x in deduction_customize_items)
|
||||||
|
ded_custom_ids = [record.benefits_discounts.id for record in deduction_customize_items]
|
||||||
|
|
||||||
|
# exception type in advantages
|
||||||
|
exception_items = item.advantages.filtered(lambda key: key.type == 'exception')
|
||||||
|
total_rule_result, sum_except, sum_customize_expect = 0.0, 0.0, 0.0
|
||||||
|
|
||||||
|
for x in exception_items:
|
||||||
|
rule_result = x.benefits_discounts._compute_rule(localdict)[0]
|
||||||
|
if x.date_from >= str(current_date):
|
||||||
|
total_rule_result = rule_result
|
||||||
|
elif str(current_date) > x.date_from:
|
||||||
|
if x.date_to and str(current_date) <= x.date_to:
|
||||||
|
total_rule_result = rule_result - x.amount
|
||||||
|
elif x.date_to and str(current_date) >= x.date_to:
|
||||||
|
total_rule_result = 0 # rule_result
|
||||||
|
elif not x.date_to:
|
||||||
|
total_rule_result = rule_result - x.amount
|
||||||
|
else:
|
||||||
|
if rule_result > x.amount:
|
||||||
|
total_rule_result = rule_result - x.amount
|
||||||
|
|
||||||
|
if total_rule_result:
|
||||||
|
if x.benefits_discounts.category_id.rule_type == 'allowance':
|
||||||
|
sum_customize_expect += total_rule_result
|
||||||
|
if x.benefits_discounts.rules_type == 'house':
|
||||||
|
item.house_allowance_temp += total_rule_result - x.amount
|
||||||
|
else:
|
||||||
|
sum_except += total_rule_result
|
||||||
|
|
||||||
|
if exception_items:
|
||||||
|
exception_items = item.advantages.filtered(
|
||||||
|
lambda key: (datetime.strptime(str(key.date_to),
|
||||||
|
"%Y-%m-%d").date().month if key.date_to else current_date.month)
|
||||||
|
>= current_date.month >= datetime.strptime(str(key.date_from), "%Y-%m-%d").date().month)
|
||||||
|
|
||||||
|
except_ids = [record.benefits_discounts.id for record in exception_items]
|
||||||
|
|
||||||
|
rule_ids = item.salary_scale.rule_ids.filtered(
|
||||||
|
lambda key: key.id not in ded_custom_ids and key.id not in except_ids)
|
||||||
|
|
||||||
|
level_rule_ids = item.salary_level.benefits_discounts_ids.filtered(lambda key: key.id not in except_ids)
|
||||||
|
# key.id not in allow_custom_ids and key.id not in ded_custom_ids and
|
||||||
|
|
||||||
|
group_rule_ids = item.salary_group.benefits_discounts_ids.filtered(lambda key: key.id not in except_ids)
|
||||||
|
# key.id not in allow_custom_ids and key.id not in ded_custom_ids and
|
||||||
|
|
||||||
|
total_allowance = 0
|
||||||
|
total_ded = 0
|
||||||
|
for line in rule_ids:
|
||||||
|
if line.category_id.rule_type == 'allowance':
|
||||||
|
try:
|
||||||
|
total_allowance += line._compute_rule(localdict)[0]
|
||||||
|
except:
|
||||||
|
total_allowance += 0
|
||||||
|
|
||||||
|
if line.category_id.rule_type == 'deduction':
|
||||||
|
try:
|
||||||
|
total_ded += line._compute_rule(localdict)[0]
|
||||||
|
except:
|
||||||
|
total_ded += 0
|
||||||
|
|
||||||
|
|
||||||
|
if line.rules_type == 'house':
|
||||||
|
item.house_allowance_temp += line._compute_rule(localdict)[0]
|
||||||
|
if line.rules_type == 'transport':
|
||||||
|
item.transport_allowance += line._compute_rule(localdict)[0]
|
||||||
|
|
||||||
|
item.total_allowance = total_allowance
|
||||||
|
item.total_deduction = -total_ded
|
||||||
|
|
||||||
|
if item.salary_level:
|
||||||
|
total_allowance = 0
|
||||||
|
total_deduction = 0
|
||||||
|
for line in level_rule_ids:
|
||||||
|
if line.category_id.rule_type == 'allowance':
|
||||||
|
try:
|
||||||
|
total_allowance += line._compute_rule(localdict)[0]
|
||||||
|
except:
|
||||||
|
total_allowance += 0
|
||||||
|
elif line.category_id.rule_type == 'deduction':
|
||||||
|
try:
|
||||||
|
total_deduction += line._compute_rule(localdict)[0]
|
||||||
|
except:
|
||||||
|
total_deduction += 0
|
||||||
|
|
||||||
|
item.total_allowance += total_allowance
|
||||||
|
item.total_deduction += -total_deduction
|
||||||
|
|
||||||
|
if item.salary_group:
|
||||||
|
total_allowance = 0
|
||||||
|
total_deduction = 0
|
||||||
|
for line in group_rule_ids:
|
||||||
|
if line.category_id.rule_type == 'allowance':
|
||||||
|
total_allowance += line._compute_rule(localdict)[0]
|
||||||
|
elif line.category_id.rule_type == 'deduction':
|
||||||
|
total_deduction += line._compute_rule(localdict)[0]
|
||||||
|
|
||||||
|
item.total_allowance += total_allowance
|
||||||
|
item.total_deduction += -total_deduction
|
||||||
|
|
||||||
|
item.total_allowance += allow_sum_custom
|
||||||
|
item.total_allowance += sum_customize_expect
|
||||||
|
item.total_deduction += -ded_sum_custom
|
||||||
|
item.total_deduction += -sum_except
|
||||||
|
item.total_net = item.total_allowance + item.total_deduction
|
||||||
|
|
||||||
|
# filter salary_level,salary_group,salary_degree
|
||||||
|
|
||||||
|
@api.onchange('salary_scale')
|
||||||
|
def onchange_salary_scale(self):
|
||||||
|
for item in self:
|
||||||
|
if item.salary_scale:
|
||||||
|
level_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_id', '=', item.salary_scale.id), ('type', '=', 'level')])
|
||||||
|
group_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_id', '=', item.salary_scale.id), ('type', '=', 'group')])
|
||||||
|
degree_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_id', '=', item.salary_scale.id), ('type', '=', 'degree')])
|
||||||
|
return {'domain': {'salary_level': [('id', 'in', level_ids.ids)],
|
||||||
|
'salary_group': [('id', 'in', group_ids.ids)],
|
||||||
|
'salary_degree': [('id', 'in', degree_ids.ids)]}}
|
||||||
|
else:
|
||||||
|
item.total_allowance = 0.0
|
||||||
|
item.total_deduction = 0.0
|
||||||
|
item.total_net = 0.0
|
||||||
|
return {'domain': {'salary_level': [('id', 'in', [])],
|
||||||
|
'salary_group': [('id', 'in', [])],
|
||||||
|
'salary_degree': [('id', 'in', [])]}}
|
||||||
|
|
||||||
|
# filter depend on salary_level
|
||||||
|
|
||||||
|
@api.onchange('salary_level')
|
||||||
|
def onchange_salary_level(self):
|
||||||
|
for item in self:
|
||||||
|
if item.salary_level:
|
||||||
|
group_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_level_id', '=', item.salary_level.id), ('type', '=', 'group')])
|
||||||
|
return {'domain': {'salary_group': [('id', 'in', group_ids.ids)],
|
||||||
|
'salary_degree': [('id', 'in', [])]}}
|
||||||
|
else:
|
||||||
|
return {'domain': {'salary_group': [('id', 'in', [])],
|
||||||
|
'salary_degree': [('id', 'in', [])]}}
|
||||||
|
|
||||||
|
# filter depend on salary_group
|
||||||
|
|
||||||
|
@api.onchange('salary_group')
|
||||||
|
def onchange_salary_group(self):
|
||||||
|
for item in self:
|
||||||
|
if item.salary_group:
|
||||||
|
degree_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_group_id', '=', item.salary_group.id), ('type', '=', 'degree')])
|
||||||
|
return {'domain': {'salary_degree': [('id', 'in', degree_ids.ids)]}}
|
||||||
|
else:
|
||||||
|
return {'domain': {'salary_degree': [('id', 'in', [])]}}
|
||||||
|
|
||||||
|
@api.depends('salary_degree')
|
||||||
|
def _get_amount(self):
|
||||||
|
for record in self:
|
||||||
|
record.transport_allowance_temp = record.transport_allowance * record.wage / 100 \
|
||||||
|
if record.transport_allowance_type == 'perc' else record.transport_allowance
|
||||||
|
record.house_allowance_temp = record.house_allowance * record.wage / 100 \
|
||||||
|
if record.house_allowance_type == 'perc' else record.house_allowance
|
||||||
|
record.communication_allowance_temp = record.communication_allowance * record.wage / 100 \
|
||||||
|
if record.communication_allowance_type == 'perc' else record.communication_allowance
|
||||||
|
record.field_allowance_temp = record.field_allowance * record.wage / 100 \
|
||||||
|
if record.field_allowance_type == 'perc' else record.field_allowance
|
||||||
|
record.special_allowance_temp = record.special_allowance * record.wage / 100 \
|
||||||
|
if record.special_allowance_type == 'perc' else record.special_allowance
|
||||||
|
record.other_allowance_temp = record.other_allowance * record.wage / 100 \
|
||||||
|
if record.other_allowance_type == 'perc' else record.other_allowance
|
||||||
|
|
||||||
|
@api.depends('contractor_type.salary_type')
|
||||||
|
def compute_type(self):
|
||||||
|
if self.contractor_type.salary_type == 'scale':
|
||||||
|
self.hide = True
|
||||||
|
else:
|
||||||
|
self.hide = False
|
||||||
|
|
||||||
|
|
||||||
|
class Advantages(models.Model):
|
||||||
|
_name = 'contract.advantage'
|
||||||
|
_rec_name = 'benefits_discounts'
|
||||||
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||||
|
|
||||||
|
date_from = fields.Date(string='Date From')
|
||||||
|
date_to = fields.Date(string='Date To')
|
||||||
|
amount = fields.Float(string='Amount', tracking=True)
|
||||||
|
type = fields.Selection(selection=[('customize', _('Customize')),
|
||||||
|
('exception', _('Exception'))], string='Type', default="customize")
|
||||||
|
# to link employee move line from official mission to advantages line in contract
|
||||||
|
official_mission_id = fields.Boolean(string="Official Mission", default=False)
|
||||||
|
# To link employee move line from over time to advantages line in contract
|
||||||
|
over_time_id = fields.Boolean(string="OverTime", default=False)
|
||||||
|
# To link employee move line from employee reward to advantages line in contract
|
||||||
|
reward_id = fields.Boolean(string="Reward", default=False)
|
||||||
|
penalty_id = fields.Boolean(string='Penalty Name', default=False)
|
||||||
|
|
||||||
|
# Relational fields
|
||||||
|
benefits_discounts = fields.Many2one(comodel_name='hr.salary.rule', string='Benefits/Discounts')
|
||||||
|
contract_advantage_id = fields.Many2one('hr.contract')
|
||||||
|
done = fields.Boolean(string="Done in Payroll")
|
||||||
|
out_rule = fields.Boolean(string="Out of Payroll", default=True)
|
||||||
|
|
||||||
|
employee_id = fields.Many2one('hr.employee', 'Employee Name', domain=[('state', '=', 'open')], tracking=True)
|
||||||
|
state = fields.Selection(selection=[('draft', _('Draft')), ('confirm', _('Confirmed')),
|
||||||
|
('refused', _('Refused'))],
|
||||||
|
default='draft', tracking=True)
|
||||||
|
|
||||||
|
comments = fields.Text(string='Comments')
|
||||||
|
payroll_month = fields.Text(string='Payroll Month', tracking=True)
|
||||||
|
company_id = fields.Many2one('res.company', string='Company', related='employee_id.company_id', store=True)
|
||||||
|
|
||||||
|
@api.constrains('date_from', 'date_to', 'amount')
|
||||||
|
def _chick_date(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.date_to:
|
||||||
|
if rec.date_to <= rec.date_from:
|
||||||
|
raise UserError(_('The Date Form Must be Less than Date To'))
|
||||||
|
if rec.amount <= 0:
|
||||||
|
raise UserError(_('The Amount Must be Greater Than Zero The Employee %s')% rec.employee_id.name)
|
||||||
|
|
||||||
|
def confirm(self):
|
||||||
|
self.state = 'confirm'
|
||||||
|
|
||||||
|
def refused(self):
|
||||||
|
self.state = 'refused'
|
||||||
|
|
||||||
|
def draft(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.state = 'draft'
|
||||||
|
|
||||||
|
@api.onchange('employee_id')
|
||||||
|
def to_get_contract_id(self):
|
||||||
|
contract_id = self.employee_id.contract_id
|
||||||
|
self.employee_id = self.contract_advantage_id.employee_id.id
|
||||||
|
if contract_id:
|
||||||
|
self.contract_advantage_id = contract_id.id
|
||||||
|
self.employee_id = self.contract_advantage_id.employee_id.id
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def unlink(self):
|
||||||
|
for item in self:
|
||||||
|
if item.state != 'draft':
|
||||||
|
raise UserError(_('You cannot delete The Salary rule %s For the Employee %s is Not Draft') % (
|
||||||
|
item.benefits_discounts.name, item.employee_id.name))
|
||||||
|
# if item.done == True:
|
||||||
|
# raise UserError(_('Sorry, The Salary rule %s For the Employee %s is Already Computed in Payroll') % (
|
||||||
|
# item.benefits_discounts.name, item.employee_id.name))
|
||||||
|
return super(Advantages, self).unlink()
|
||||||
|
|
||||||
|
@api.constrains('employee_id', 'date_from', 'date_to', 'benefits_discounts')
|
||||||
|
def check_rule_dates(self):
|
||||||
|
""" Function Can Not add Same Advantage at The Same Month
|
||||||
|
same employee.
|
||||||
|
"""
|
||||||
|
for rec in self:
|
||||||
|
domain = [
|
||||||
|
('date_from', '<=', rec.date_to),
|
||||||
|
('date_to', '>=', rec.date_from),
|
||||||
|
('employee_id', '=', rec.employee_id.id),
|
||||||
|
('id', '!=', rec.id),
|
||||||
|
('benefits_discounts', '=', rec.benefits_discounts.id), ]
|
||||||
|
advantages_id = self.search_count(domain)
|
||||||
|
if advantages_id:
|
||||||
|
# for adv in advantages_id:
|
||||||
|
raise UserError(
|
||||||
|
_('You Can Not add Same Allowance/Deduction at The Same Employee %s For The Same Month!')
|
||||||
|
% rec.employee_id.name)
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from odoo import models, fields
|
||||||
|
|
||||||
|
|
||||||
|
class HrEmployeeSalaryScale(models.Model):
|
||||||
|
_inherit = 'hr.employee'
|
||||||
|
|
||||||
|
salary_scale = fields.Many2one(related='contract_id.salary_scale', string='Salary scale', store=True)
|
||||||
|
salary_level = fields.Many2one(related='contract_id.salary_level', string='Salary Level', store=True)
|
||||||
|
salary_group = fields.Many2one(related='contract_id.salary_group', string='Salary Group', store=True)
|
||||||
|
salary_degree = fields.Many2one(related='contract_id.salary_degree', string='Salary Degree', store=True)
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from odoo import models, fields, api
|
||||||
|
|
||||||
|
|
||||||
|
class HrReContract(models.Model):
|
||||||
|
_inherit = 'hr.re.contract'
|
||||||
|
|
||||||
|
salary_scale = fields.Many2one('hr.payroll.structure', string='Salary Scale', compute='_get_employee_data')
|
||||||
|
salary_group = fields.Many2one('hr.payroll.structure', string='Salary Group', compute='_get_employee_data')
|
||||||
|
salary_level = fields.Many2one('hr.payroll.structure', string='Salary Level', compute='_get_employee_data')
|
||||||
|
salary_degree = fields.Many2one('hr.payroll.structure', string='Salary Degree', compute='_get_employee_data')
|
||||||
|
new_salary_scale = fields.Many2one(comodel_name='hr.payroll.structure')
|
||||||
|
new_salary_level = fields.Many2one(comodel_name='hr.payroll.structure')
|
||||||
|
new_salary_group = fields.Many2one(comodel_name='hr.payroll.structure')
|
||||||
|
new_salary_degree = fields.Many2one(comodel_name='hr.payroll.structure')
|
||||||
|
|
||||||
|
@api.onchange('new_salary_scale')
|
||||||
|
def onchange_new_salary_scale(self):
|
||||||
|
for item in self:
|
||||||
|
if item.new_salary_scale:
|
||||||
|
level_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_id', '=', item.new_salary_scale.id), ('type', '=', 'level')])
|
||||||
|
group_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_id', '=', item.new_salary_scale.id), ('type', '=', 'group')])
|
||||||
|
degree_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_id', '=', item.new_salary_scale.id), ('type', '=', 'degree')])
|
||||||
|
return {'domain': {'new_salary_level': [('id', 'in', level_ids.ids)],
|
||||||
|
'new_salary_group': [('id', 'in', group_ids.ids)],
|
||||||
|
'new_salary_degree': [('id', 'in', degree_ids.ids)]}}
|
||||||
|
else:
|
||||||
|
item.new_salary = 0.0
|
||||||
|
return {'domain': {'new_salary_level': [('id', 'in', [])],
|
||||||
|
'new_salary_group': [('id', 'in', [])],
|
||||||
|
'new_salary_degree': [('id', 'in', [])]}}
|
||||||
|
|
||||||
|
# filter depend on new_salary_level
|
||||||
|
|
||||||
|
@api.onchange('new_salary_level')
|
||||||
|
def onchange_new_salary_level(self):
|
||||||
|
for item in self:
|
||||||
|
if item.new_salary_level:
|
||||||
|
group_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_level_id', '=', item.new_salary_level.id), ('type', '=', 'group')])
|
||||||
|
return {'domain': {'new_salary_group': [('id', 'in', group_ids.ids)],
|
||||||
|
'new_salary_degree': [('id', 'in', [])]}}
|
||||||
|
else:
|
||||||
|
return {'domain': {'new_salary_group': [('id', 'in', [])],
|
||||||
|
'new_salary_degree': [('id', 'in', [])]}}
|
||||||
|
|
||||||
|
# filter depend on salary_group
|
||||||
|
|
||||||
|
@api.onchange('new_salary_group')
|
||||||
|
def onchange_salary_group(self):
|
||||||
|
for item in self:
|
||||||
|
if item.new_salary_group:
|
||||||
|
degree_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_group_id', '=', item.new_salary_group.id), ('type', '=', 'degree')])
|
||||||
|
return {'domain': {'new_salary_degree': [('id', 'in', degree_ids.ids)]}}
|
||||||
|
else:
|
||||||
|
return {'domain': {'new_salary_degree': [('id', 'in', [])]}}
|
||||||
|
|
||||||
|
@api.onchange('new_salary_degree')
|
||||||
|
def onchange_degree(self):
|
||||||
|
if self.new_salary_degree:
|
||||||
|
self.new_salary = self.new_salary_degree.base_salary
|
||||||
|
|
||||||
|
@api.depends('employee_id')
|
||||||
|
def _get_employee_data(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.hire_date = False
|
||||||
|
rec.contract_id = False
|
||||||
|
rec.start_date = False
|
||||||
|
rec.eoc_date = False
|
||||||
|
rec.job_id = False
|
||||||
|
rec.department_id = False
|
||||||
|
rec.salary_scale = False
|
||||||
|
rec.salary_level = False
|
||||||
|
rec.salary_group = False
|
||||||
|
rec.salary_degree = False
|
||||||
|
if rec.employee_id:
|
||||||
|
rec.hire_date = rec.employee_id.first_hiring_date
|
||||||
|
rec.contract_id = rec.employee_id.contract_id.id
|
||||||
|
rec.start_date = rec.employee_id.contract_id.date_start
|
||||||
|
rec.eoc_date = rec.employee_id.contract_id.date_end
|
||||||
|
rec.job_id = rec.employee_id.job_id.id
|
||||||
|
rec.department_id = rec.employee_id.department_id.id
|
||||||
|
rec.salary_scale = rec.employee_id.contract_id.salary_scale.id
|
||||||
|
rec.salary_level = rec.employee_id.contract_id.salary_level.id
|
||||||
|
rec.salary_group = rec.employee_id.contract_id.salary_group.id
|
||||||
|
rec.salary_degree = rec.employee_id.contract_id.salary_degree.id
|
||||||
|
|
||||||
|
def _get_default_category(self):
|
||||||
|
return self.env['hr.salary.rule.category'].search([('code', '=', 'NET')], limit=1)
|
||||||
|
|
@ -0,0 +1,390 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from odoo import api, fields, models, _
|
||||||
|
|
||||||
|
from odoo.exceptions import UserError,ValidationError
|
||||||
|
|
||||||
|
from odoo.tools.safe_eval import safe_eval
|
||||||
|
|
||||||
|
class HrSalaryRuleAccount(models.Model):
|
||||||
|
_name = 'hr.salary.rule.account'
|
||||||
|
_description = 'Salary Rule Account Mapping'
|
||||||
|
|
||||||
|
rule_id = fields.Many2one('hr.salary.rule', string="Salary Rule", required=True, ondelete="cascade")
|
||||||
|
emp_type_id = fields.Many2one('hr.contract.type', string="Employee Type", required=True)
|
||||||
|
credit_account_id = fields.Many2one('account.account', string="Credit Account", required=True)
|
||||||
|
debit_account_id = fields.Many2one('account.account', string="Debit Account", required=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class HrSalaryRules(models.Model):
|
||||||
|
_inherit = 'hr.salary.rule'
|
||||||
|
|
||||||
|
start_date = fields.Date(string='Start Date', default=fields.date.today())
|
||||||
|
end_date = fields.Date(string='End Date')
|
||||||
|
salary_type = fields.Selection([('fixed', _('Fixed for all')),
|
||||||
|
('related_levels', _('Related with Levels')),
|
||||||
|
('related_groups', _('Related with Groups')),
|
||||||
|
('related_degrees', _('Related with Degrees'))], default="fixed",
|
||||||
|
string='Type Scale')
|
||||||
|
related_qualifications = fields.Boolean(string='Related with qualifications')
|
||||||
|
special = fields.Boolean(string='Special')
|
||||||
|
reduce_with_leaves = fields.Boolean(string='Reduce With Leaves',default=True)
|
||||||
|
min_leave_days_to_deduct = fields.Integer(string='Min Leave Days To Deduct')
|
||||||
|
company_id = fields.Many2one(comodel_name='res.company', string='Company', required=True,
|
||||||
|
default=lambda self: self.env.user.company_id)
|
||||||
|
discount_absence = fields.Selection([('by_day', _('By Day')),
|
||||||
|
('by_hour', _('By Hour')),
|
||||||
|
('no_discount', _('No discount'))],
|
||||||
|
default="no_discount", string='Discount Absence')
|
||||||
|
fixed_amount = fields.Integer(string='Fixed Amount')
|
||||||
|
|
||||||
|
# relational fields
|
||||||
|
related_benefits_discounts = fields.Many2many(comodel_name='hr.salary.rule',
|
||||||
|
relation='salary_rule_benefit_discount_rel',
|
||||||
|
column1='rule_id', column2='sub_rule_id',
|
||||||
|
string='Related Benefits and Discount')
|
||||||
|
salary_amount_ids = fields.One2many('related.salary.amount', 'salary_rule_id')
|
||||||
|
rule_credit_account_id = fields.Many2one('account.account')
|
||||||
|
rule_debit_account_id = fields.Many2one('account.account')
|
||||||
|
rules_type = fields.Selection([('salary', _('Salary Allowance')),
|
||||||
|
('house', _('House Allowance')),
|
||||||
|
('overtime', _('Overtime Allowance')),
|
||||||
|
('mandate', _('Mandate Allowance')),
|
||||||
|
('transport', _('Transport Allowance')),
|
||||||
|
('termination', _('End Of Services')),
|
||||||
|
('insurnce', _('Insurnce Deduction')),
|
||||||
|
('other', _('Other'))
|
||||||
|
], string='Rules Type')
|
||||||
|
|
||||||
|
account_ids = fields.One2many('hr.salary.rule.account', 'rule_id')
|
||||||
|
transfer_by_emp_type = fields.Boolean('Transfer By Employee Type')
|
||||||
|
|
||||||
|
def get_debit_account_id(self, emp_type):
|
||||||
|
if not self.transfer_by_emp_type: return self.rule_debit_account_id.id
|
||||||
|
account_mapping = self.sudo().account_ids.filtered(lambda a: a.emp_type_id.id == emp_type)
|
||||||
|
return account_mapping[0].debit_account_id.id if account_mapping else False
|
||||||
|
|
||||||
|
def get_credit_account_id(self, emp_type):
|
||||||
|
if not self.transfer_by_emp_type: return self.rule_credit_account_id.id
|
||||||
|
account_mapping = self.sudo().account_ids.filtered(lambda a: a.emp_type_id.id == emp_type)
|
||||||
|
return account_mapping[0].credit_account_id.id if account_mapping else False
|
||||||
|
|
||||||
|
@api.constrains('rules_type', 'category_id')
|
||||||
|
def _check_dates(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.category_id.rule_type != 'deduction' and rec.rules_type == 'insurnce':
|
||||||
|
raise UserError(_("The Salary Rule is Not Deduction"))
|
||||||
|
|
||||||
|
# Override function compute rule in hr salary rule
|
||||||
|
|
||||||
|
def _compute_rule(self, localdict):
|
||||||
|
payslip = localdict.get('payslip')
|
||||||
|
contract = localdict.get('contract')
|
||||||
|
if self.amount_select == 'percentage':
|
||||||
|
total_percent, total = 0, 0
|
||||||
|
if self.related_benefits_discounts:
|
||||||
|
for line in self.related_benefits_discounts:
|
||||||
|
calc_line = line._compute_rule(localdict)[0]
|
||||||
|
|
||||||
|
if line.amount_select == 'fix':
|
||||||
|
if contract.advantages:
|
||||||
|
for con in contract.advantages:
|
||||||
|
if line.id == con.benefits_discounts.id:
|
||||||
|
if payslip:
|
||||||
|
if con.date_from > payslip.date_from:
|
||||||
|
total_percent = calc_line
|
||||||
|
elif con.date_to is not None and str(
|
||||||
|
con.date_to) >= payslip.date_to or con.date_to is None:
|
||||||
|
if con.type == 'exception':
|
||||||
|
if con.amount > calc_line or con.amount == calc_line:
|
||||||
|
pass
|
||||||
|
elif con.amount < calc_line:
|
||||||
|
total = calc_line - con.amount
|
||||||
|
elif con.type == 'customize':
|
||||||
|
total = con.amount
|
||||||
|
total_percent += total
|
||||||
|
else:
|
||||||
|
if str(con.date_from) < str(datetime.now().date()):
|
||||||
|
if con.date_to:
|
||||||
|
if datetime.strptime(str(con.date_to), "%Y-%m-%d").date().month \
|
||||||
|
>= datetime.now().date().month or not con.date_to:
|
||||||
|
if con.type == 'exception':
|
||||||
|
if con.amount > calc_line or con.amount == calc_line:
|
||||||
|
pass
|
||||||
|
elif con.amount < calc_line:
|
||||||
|
total = calc_line - con.amount
|
||||||
|
elif con.type == 'customize':
|
||||||
|
total = con.amount
|
||||||
|
total_percent += total
|
||||||
|
else:
|
||||||
|
total_percent = calc_line
|
||||||
|
else:
|
||||||
|
total_percent += calc_line
|
||||||
|
|
||||||
|
elif line.amount_select == 'percentage':
|
||||||
|
if contract.advantages:
|
||||||
|
for con in contract.advantages:
|
||||||
|
if line.id == con.benefits_discounts.id:
|
||||||
|
if payslip:
|
||||||
|
if con.date_from > payslip.date_from:
|
||||||
|
total_percent = calc_line
|
||||||
|
elif con.date_to is not None and str(
|
||||||
|
con.date_to) >= payslip.date_to or con.date_to is None:
|
||||||
|
if con.type == 'exception':
|
||||||
|
if con.amount > calc_line or con.amount == calc_line:
|
||||||
|
pass
|
||||||
|
elif con.amount < calc_line:
|
||||||
|
total = calc_line - con.amount
|
||||||
|
elif con.type == 'customize':
|
||||||
|
total = con.amount
|
||||||
|
total_percent -= calc_line
|
||||||
|
total_percent += total
|
||||||
|
else:
|
||||||
|
if str(con.date_from) < str(datetime.now().date()):
|
||||||
|
if con.date_to:
|
||||||
|
if datetime.strptime(str(con.date_to), "%Y-%m-%d").date().month \
|
||||||
|
>= datetime.now().date().month or not con.date_to:
|
||||||
|
if con.type == 'exception':
|
||||||
|
if con.amount > calc_line or con.amount == calc_line:
|
||||||
|
pass
|
||||||
|
elif con.amount < calc_line:
|
||||||
|
total = calc_line - con.amount
|
||||||
|
elif con.type == 'customize':
|
||||||
|
total = con.amount
|
||||||
|
total_percent -= calc_line
|
||||||
|
total_percent += total
|
||||||
|
else:
|
||||||
|
if con.type != 'exception':
|
||||||
|
total_percent += calc_line
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
total_percent += calc_line
|
||||||
|
|
||||||
|
else:
|
||||||
|
if contract.advantages:
|
||||||
|
for con in contract.advantages:
|
||||||
|
if line.id == con.benefits_discounts.id:
|
||||||
|
if payslip:
|
||||||
|
if con.date_from > payslip.date_from:
|
||||||
|
total_percent = calc_line
|
||||||
|
elif con.date_to is not None and con.date_to >= payslip.date_to or con.date_to is None:
|
||||||
|
if con.type == 'exception':
|
||||||
|
if con.amount > calc_line or con.amount == calc_line:
|
||||||
|
pass
|
||||||
|
elif con.amount < calc_line:
|
||||||
|
total = calc_line - con.amount
|
||||||
|
elif con.type == 'customize':
|
||||||
|
total = con.amount
|
||||||
|
total_percent = 0
|
||||||
|
total_percent += total
|
||||||
|
else:
|
||||||
|
if con.date_from < (datetime.now().date()):
|
||||||
|
if con.date_to:
|
||||||
|
if datetime.strptime(str(con.date_to), "%Y-%m-%d").date().month \
|
||||||
|
>= datetime.now().date().month or not con.date_to:
|
||||||
|
if con.type == 'exception':
|
||||||
|
if con.amount > calc_line or con.amount == calc_line:
|
||||||
|
pass
|
||||||
|
elif con.amount < calc_line:
|
||||||
|
total = calc_line - con.amount
|
||||||
|
elif con.type == 'customize':
|
||||||
|
total = con.amount
|
||||||
|
total_percent = 0
|
||||||
|
total_percent += total
|
||||||
|
else:
|
||||||
|
if datetime.strptime(str(con.date_from),
|
||||||
|
"%Y-%m-%d").date().month >= datetime.now().date().month:
|
||||||
|
if con.type == 'exception':
|
||||||
|
if con.amount > calc_line or con.amount == calc_line:
|
||||||
|
pass
|
||||||
|
elif con.amount < calc_line:
|
||||||
|
total = calc_line - con.amount
|
||||||
|
elif con.type == 'customize':
|
||||||
|
total = con.amount + calc_line
|
||||||
|
total_percent = 0
|
||||||
|
total_percent += total
|
||||||
|
|
||||||
|
else:
|
||||||
|
if not total_percent:
|
||||||
|
total_percent = calc_line
|
||||||
|
else:
|
||||||
|
total_percent += calc_line
|
||||||
|
if total_percent:
|
||||||
|
if self.salary_type == 'fixed':
|
||||||
|
try:
|
||||||
|
return float(total_percent * self.amount_percentage / 100), \
|
||||||
|
float(safe_eval(self.quantity, localdict)), self.amount_percentage
|
||||||
|
except:
|
||||||
|
raise UserError(
|
||||||
|
_('Wrong percentage base or quantity defined for salary rule %s (%s).') % (
|
||||||
|
self.name, self.code))
|
||||||
|
elif self.salary_type == 'related_levels':
|
||||||
|
levels_ids = self.salary_amount_ids.filtered(
|
||||||
|
lambda item: item.salary_scale_level.id == contract.salary_level.id)
|
||||||
|
if levels_ids:
|
||||||
|
for l in levels_ids:
|
||||||
|
try:
|
||||||
|
return float(l.salary * total_percent / 100), float(
|
||||||
|
safe_eval(self.quantity, localdict)), 100.0
|
||||||
|
except:
|
||||||
|
raise UserError(
|
||||||
|
_('Wrong quantity defined for salary rule %s (%s).') % (
|
||||||
|
self.name, self.code))
|
||||||
|
else:
|
||||||
|
return 0, 0, 0
|
||||||
|
elif self.salary_type == 'related_groups':
|
||||||
|
groups_ids = self.salary_amount_ids.filtered(
|
||||||
|
lambda item: item.salary_scale_group.id == contract.salary_group.id)
|
||||||
|
if groups_ids:
|
||||||
|
for g in groups_ids:
|
||||||
|
try:
|
||||||
|
return float(g.salary * total_percent / 100), float(
|
||||||
|
safe_eval(self.quantity, localdict)), 100.0
|
||||||
|
except:
|
||||||
|
raise UserError(
|
||||||
|
_('Wrong quantity defined for salary rule %s (%s).') % (
|
||||||
|
self.name, self.code))
|
||||||
|
else:
|
||||||
|
return 0, 0, 0
|
||||||
|
elif self.salary_type == 'related_degrees':
|
||||||
|
degrees_ids = self.salary_amount_ids.filtered(
|
||||||
|
lambda item: item.salary_scale_degree.id == contract.salary_degree.id)
|
||||||
|
if degrees_ids:
|
||||||
|
for d in degrees_ids:
|
||||||
|
try:
|
||||||
|
return float(d.salary * total_percent / 100), float(
|
||||||
|
safe_eval(self.quantity, localdict)), 100.0
|
||||||
|
except:
|
||||||
|
raise UserError(
|
||||||
|
_('Wrong quantity defined for salary rule %s (%s).') % (
|
||||||
|
self.name, self.code))
|
||||||
|
else:
|
||||||
|
return 0, 0, 0
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
return 0, 0, 0
|
||||||
|
except:
|
||||||
|
raise UserError(_('There is no total for rule : %s') % self.name)
|
||||||
|
|
||||||
|
elif self.amount_select == 'fix':
|
||||||
|
if self.salary_type == 'fixed':
|
||||||
|
try:
|
||||||
|
return self.fixed_amount, float(safe_eval(self.quantity, localdict)), 100.0
|
||||||
|
except:
|
||||||
|
raise UserError(_('Wrong quantity defined for salary rule %s (%s).') % (self.name, self.code))
|
||||||
|
elif self.salary_type == 'related_levels':
|
||||||
|
levels_ids = self.salary_amount_ids.filtered(
|
||||||
|
lambda item: item.salary_scale_level.id == contract.salary_level.id)
|
||||||
|
if levels_ids:
|
||||||
|
for l in levels_ids:
|
||||||
|
try:
|
||||||
|
return l.salary, float(safe_eval(self.quantity, localdict)), 100.0
|
||||||
|
except:
|
||||||
|
raise UserError(
|
||||||
|
_('Wrong quantity defined for salary rule %s (%s).') % (self.name, self.code))
|
||||||
|
else:
|
||||||
|
return 0, 0, 0
|
||||||
|
elif self.salary_type == 'related_groups':
|
||||||
|
groups_ids = self.salary_amount_ids.filtered(
|
||||||
|
lambda item: item.salary_scale_group.id == contract.salary_group.id)
|
||||||
|
if groups_ids:
|
||||||
|
for g in groups_ids:
|
||||||
|
try:
|
||||||
|
return g.salary, float(safe_eval(self.quantity, localdict)), 100.0
|
||||||
|
except:
|
||||||
|
raise UserError(
|
||||||
|
_('Wrong quantity defined for salary rule %s (%s).') % (self.name, self.code))
|
||||||
|
else:
|
||||||
|
return 0, 0, 0
|
||||||
|
elif self.salary_type == 'related_degrees':
|
||||||
|
degrees_ids = self.salary_amount_ids.filtered(
|
||||||
|
lambda item: item.salary_scale_degree.id == contract.salary_degree.id)
|
||||||
|
if degrees_ids:
|
||||||
|
for d in degrees_ids:
|
||||||
|
try:
|
||||||
|
return d.salary, float(safe_eval(self.quantity, localdict)), 100.0
|
||||||
|
except:
|
||||||
|
raise UserError(
|
||||||
|
_('Wrong quantity defined for salary rule %s (%s).') % (self.name, self.code))
|
||||||
|
else:
|
||||||
|
return 0, 0, 0
|
||||||
|
else:
|
||||||
|
raise UserError(_('Error, Select Salary type to calculate rule'))
|
||||||
|
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
safe_eval(self.amount_python_compute, localdict, mode='exec', nocopy=True)
|
||||||
|
return float(localdict['result']), 'result_qty' in localdict and localdict[
|
||||||
|
'result_qty'] or 1.0, 'result_rate' in localdict and localdict['result_rate'] or 100.0
|
||||||
|
except:
|
||||||
|
raise UserError(_('Wrong python code defined for salary rule %s (%s).') % (self.name, self.code))
|
||||||
|
|
||||||
|
|
||||||
|
class SalaryConfig(models.Model):
|
||||||
|
_name = 'related.salary.amount'
|
||||||
|
|
||||||
|
salary_scale = fields.Many2one('hr.payroll.structure')
|
||||||
|
salary_scale_level = fields.Many2one('hr.payroll.structure')
|
||||||
|
salary_scale_group = fields.Many2one('hr.payroll.structure')
|
||||||
|
salary_scale_degree = fields.Many2one('hr.payroll.structure')
|
||||||
|
salary = fields.Float(string='Salary / Percentage')
|
||||||
|
|
||||||
|
# relations fields
|
||||||
|
salary_rule_id = fields.Many2one(comodel_name='hr.salary.rule')
|
||||||
|
|
||||||
|
# filter salary_level,salary_group,salary_degree
|
||||||
|
|
||||||
|
@api.onchange('salary_scale')
|
||||||
|
def onchange_salary_scale(self):
|
||||||
|
for item in self:
|
||||||
|
if item.salary_scale:
|
||||||
|
level_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_id', '=', item.salary_scale.id), ('type', '=', 'level')])
|
||||||
|
group_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_id', '=', item.salary_scale.id), ('type', '=', 'group')])
|
||||||
|
degree_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_id', '=', item.salary_scale.id), ('type', '=', 'degree')])
|
||||||
|
return {'domain': {'salary_scale_level': [('id', 'in', level_ids.ids)],
|
||||||
|
'salary_scale_group': [('id', 'in', group_ids.ids)],
|
||||||
|
'salary_scale_degree': [('id', 'in', degree_ids.ids)]}}
|
||||||
|
else:
|
||||||
|
return {'domain': {'salary_scale_level': [('id', 'in', [])],
|
||||||
|
'salary_scale_group': [('id', 'in', [])],
|
||||||
|
'salary_scale_degree': [('id', 'in', [])]}}
|
||||||
|
|
||||||
|
# filter depend on salary_level
|
||||||
|
|
||||||
|
@api.onchange('salary_scale_level')
|
||||||
|
def onchange_salary_level(self):
|
||||||
|
for item in self:
|
||||||
|
if item.salary_scale_level:
|
||||||
|
group_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_level_id', '=', item.salary_scale_level.id), ('type', '=', 'group')])
|
||||||
|
return {'domain': {'salary_scale_group': [('id', 'in', group_ids.ids)],
|
||||||
|
'salary_scale_degree': [('id', 'in', [])]}}
|
||||||
|
else:
|
||||||
|
return {'domain': {'salary_scale_group': [('id', 'in', [])],
|
||||||
|
'salary_scale_degree': [('id', 'in', [])]}}
|
||||||
|
|
||||||
|
# filter depend on salary_group
|
||||||
|
|
||||||
|
@api.onchange('salary_scale_group')
|
||||||
|
def onchange_salary_group(self):
|
||||||
|
for item in self:
|
||||||
|
if item.salary_scale_group:
|
||||||
|
degree_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_group_id', '=', item.salary_scale_group.id), ('type', '=', 'degree')])
|
||||||
|
return {'domain': {'salary_scale_degree': [('id', 'in', degree_ids.ids)]}}
|
||||||
|
else:
|
||||||
|
return {'domain': {'salary_scale_degree': [('id', 'in', [])]}}
|
||||||
|
|
||||||
|
|
||||||
|
class SalaryRuleCategory(models.Model):
|
||||||
|
_inherit = 'hr.salary.rule.category'
|
||||||
|
|
||||||
|
rule_type = fields.Selection(selection=[('allowance', _('Allowance')), ('deduction', _('Deduction')),
|
||||||
|
('base', _('Base')), ('gross', _('Gross')),
|
||||||
|
('net', _('Net')), ('end_of_service', _('End of Service'))], string='Type')
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
|
||||||
|
|
||||||
|
class HrSalaryScale(models.Model):
|
||||||
|
_inherit = 'hr.payroll.structure'
|
||||||
|
|
||||||
|
active = fields.Boolean(string='Active', default=True)
|
||||||
|
start_date = fields.Date(string='Start Date')
|
||||||
|
end_date = fields.Date(string='End Date')
|
||||||
|
level_num = fields.Integer(string='Number Of Levels')
|
||||||
|
retirement_age = fields.Integer('Retirement Age', default=60)
|
||||||
|
type = fields.Selection(selection=[('scale', _('Scale')), ('level', _('Level')),
|
||||||
|
('group', _('Group')), ('degree', _('Degree'))], default='scale', string='Type')
|
||||||
|
transfer_type = fields.Selection(selection=[('all', _('All Employee')),
|
||||||
|
('per_analytic_account', _('Per Analytic Account')),
|
||||||
|
('one_by_one', _('Per Employee')),
|
||||||
|
('per_bank', _('Per Bank'))], string='Transfer type')
|
||||||
|
|
||||||
|
# relation fields
|
||||||
|
salary_scale_levels_ids = fields.One2many('hr.payroll.structure', 'salary_scale_id',
|
||||||
|
domain=[('type', '=', 'level')], store=True)
|
||||||
|
salary_scale_level_degrees_ids = fields.One2many('hr.payroll.structure', 'salary_scale_id',
|
||||||
|
domain=[('type', '=', 'degree')], store=True)
|
||||||
|
salary_scale_level_groups_ids = fields.One2many('hr.payroll.structure', 'salary_scale_id',
|
||||||
|
domain=[('type', '=', 'group')], store=True)
|
||||||
|
|
||||||
|
salary_scale_id = fields.Many2one('hr.payroll.structure', string='Salary Scale', index=True) # salary scale
|
||||||
|
|
||||||
|
#Percentage_increase = fields.Float('Percentage Increase %',default=0.05)
|
||||||
|
|
||||||
|
analytic_account_id = fields.Many2one(comodel_name='account.analytic.account')
|
||||||
|
|
||||||
|
# Override Function
|
||||||
|
|
||||||
|
def get_all_rules(self):
|
||||||
|
"""
|
||||||
|
@return: returns a list of tuple (id, sequence) of rules that are maybe to apply
|
||||||
|
"""
|
||||||
|
all_rules = []
|
||||||
|
for struct in self:
|
||||||
|
if struct.benefits_discounts_ids:
|
||||||
|
all_rules += struct.benefits_discounts_ids._recursive_search_of_rules()
|
||||||
|
else:
|
||||||
|
all_rules += struct.rule_ids._recursive_search_of_rules()
|
||||||
|
|
||||||
|
return all_rules
|
||||||
|
|
||||||
|
# filter salary_level,salary_group
|
||||||
|
|
||||||
|
@api.onchange('salary_scale_id')
|
||||||
|
def onchange_salary_scale_id(self):
|
||||||
|
for item in self:
|
||||||
|
if item.salary_scale_id:
|
||||||
|
level_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_id', '=', item.salary_scale_id.id), ('type', '=', 'level')])
|
||||||
|
item.salary_scale_level_id = []
|
||||||
|
item.salary_scale_group_id = []
|
||||||
|
return {'domain': {'salary_scale_level_id': [('id', 'in', level_ids.ids)]}}
|
||||||
|
|
||||||
|
# filter depend on salary_level
|
||||||
|
|
||||||
|
@api.onchange('salary_scale_level_id')
|
||||||
|
def onchange_salary_scale_level_id(self):
|
||||||
|
for item in self:
|
||||||
|
if item.salary_scale_level_id:
|
||||||
|
group_ids = self.env['hr.payroll.structure'].search(
|
||||||
|
[('salary_scale_level_id', '=', item.salary_scale_level_id.id), ('type', '=', 'group')])
|
||||||
|
item.salary_scale_group_id = []
|
||||||
|
return {'domain': {'salary_scale_group_id': [('id', 'in', group_ids.ids)]}}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from odoo import models, fields
|
||||||
|
|
||||||
|
|
||||||
|
class HrSalaryScaleLevel(models.Model):
|
||||||
|
_inherit = 'hr.payroll.structure'
|
||||||
|
|
||||||
|
groups_number = fields.Integer(string='Number Of Groups')
|
||||||
|
salary_scale_id = fields.Many2one('hr.payroll.structure', string='Salary Scale', index=True)
|
||||||
|
benefits_discounts_ids = fields.Many2many('hr.salary.rule', string='Benefits and discounts')
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
|
class HrSalaryScaleDegree(models.Model):
|
||||||
|
_inherit = 'hr.payroll.structure'
|
||||||
|
|
||||||
|
base_salary = fields.Float(string='Base Salary')
|
||||||
|
interval_time = fields.Integer(string='Interval Time')
|
||||||
|
salary_scale_group_id = fields.Many2one(comodel_name='hr.payroll.structure', index=True)
|
||||||
|
|
||||||
|
@api.constrains('base_salary', 'salary_scale_group_id')
|
||||||
|
def base_salary_constrains(self):
|
||||||
|
if self.salary_scale_group_id.gread_max > 0 and self.salary_scale_group_id.gread_min > 0:
|
||||||
|
if self.base_salary > self.salary_scale_group_id.gread_max or \
|
||||||
|
self.base_salary < self.salary_scale_group_id.gread_min:
|
||||||
|
raise UserError(_('The Basic Salary Is Greater Than Group Gread Max Or less than Gread Min'))
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
|
class HrSalaryScaleLevel(models.Model):
|
||||||
|
_inherit = 'hr.payroll.structure'
|
||||||
|
|
||||||
|
degree_number = fields.Integer(string='Number of Degrees')
|
||||||
|
salary_scale_level_id = fields.Many2one(comodel_name='hr.payroll.structure', string='Salary Scale Level',
|
||||||
|
index=True)
|
||||||
|
gread_min = fields.Float(string='Gread Min')
|
||||||
|
gread_max = fields.Float(string='Gread Max')
|
||||||
|
|
||||||
|
@api.constrains('gread_min', 'gread_max')
|
||||||
|
def zero_constrains(self):
|
||||||
|
|
||||||
|
if self.gread_max < 0 or self.gread_min < 0:
|
||||||
|
raise UserError(_('The Gread Max Or Gread Min is not Negative'))
|
||||||
|
|
||||||
|
if self.gread_max < self.gread_min:
|
||||||
|
raise UserError(_('The Gread Max Is Greater Than Gread Min'))
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from odoo import exceptions
|
||||||
|
from odoo import fields, models, api, _
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SalaryAdvancePayment(models.Model):
|
||||||
|
_name = "salary.advance"
|
||||||
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||||
|
|
||||||
|
name = fields.Char(string='Name', readonly=True, default=lambda self: 'Adv/')
|
||||||
|
employee_id = fields.Many2one(comodel_name='hr.employee', string='Employee', required=True, index=True)
|
||||||
|
date = fields.Date(string='Date', required=True, default=lambda self: fields.Date.today())
|
||||||
|
reason = fields.Text(string='Reason')
|
||||||
|
currency_id = fields.Many2one(comodel_name='res.currency', string='Currency', required=True,
|
||||||
|
default=lambda self: self.env.user.company_id.currency_id)
|
||||||
|
company_id = fields.Many2one(comodel_name='res.company', string='Company', required=True,
|
||||||
|
default=lambda self: self.env.user.company_id)
|
||||||
|
advance = fields.Float(string='Advance', required=True)
|
||||||
|
payment_method = fields.Many2one(comodel_name='account.journal', string='Payment Method')
|
||||||
|
exceed_condition = fields.Boolean(string='Exceed than maximum',
|
||||||
|
help="The Advance is greater than the maximum percentage in salary structure")
|
||||||
|
department = fields.Many2one(comodel_name='hr.department', string='Department')
|
||||||
|
state = fields.Selection(selection=[('draft', 'Draft'),
|
||||||
|
('submit', 'Submitted'),
|
||||||
|
('waiting_approval', 'Waiting Approval'),
|
||||||
|
('approve', 'Approved'),
|
||||||
|
('cancel', 'Cancelled'),
|
||||||
|
('reject', 'Rejected')], string='Status', default='draft', tracking=True)
|
||||||
|
debit = fields.Many2one(comodel_name='account.account', string='Debit Account')
|
||||||
|
credit = fields.Many2one(comodel_name='account.account', string='Credit Account')
|
||||||
|
journal = fields.Many2one(comodel_name='account.journal', string='Journal')
|
||||||
|
employee_contract_id = fields.Many2one(comodel_name='hr.contract', string='Contract')
|
||||||
|
|
||||||
|
@api.onchange('employee_id')
|
||||||
|
def onchange_employee_id(self):
|
||||||
|
department_id = self.employee_id.department_id.id
|
||||||
|
domain = [('employee_id', '=', self.employee_id.id)]
|
||||||
|
return {'value': {'department': department_id}, 'domain': {
|
||||||
|
'employee_contract_id': domain,
|
||||||
|
}}
|
||||||
|
|
||||||
|
@api.onchange('company_id')
|
||||||
|
def onchange_company_id(self):
|
||||||
|
company = self.company_id
|
||||||
|
domain = [('company_id.id', '=', company.id)]
|
||||||
|
result = {
|
||||||
|
'domain': {
|
||||||
|
'journal': domain,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
|
||||||
|
def submit_to_manager(self):
|
||||||
|
self.state = 'submit'
|
||||||
|
|
||||||
|
def cancel(self):
|
||||||
|
self.state = 'cancel'
|
||||||
|
|
||||||
|
def reject(self):
|
||||||
|
self.state = 'reject'
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def create(self, vals):
|
||||||
|
vals['name'] = self.env['ir.sequence'].get('salary.advance.seq') or ' '
|
||||||
|
res_id = super(SalaryAdvancePayment, self).create(vals)
|
||||||
|
return res_id
|
||||||
|
|
||||||
|
def approve_request(self):
|
||||||
|
"""This Approve the employee salary advance request.
|
||||||
|
"""
|
||||||
|
emp_obj = self.env['hr.employee']
|
||||||
|
address = emp_obj.browse([self.employee_id.id]).address_home_id
|
||||||
|
if not address.id:
|
||||||
|
raise UserError('Error!', 'Define home address for employee')
|
||||||
|
salary_advance_search = self.search([('employee_id', '=', self.employee_id.id), ('id', '!=', self.id),
|
||||||
|
('state', '=', 'approve')])
|
||||||
|
current_month = datetime.strptime(str(self.date), '%Y-%m-%d').date().month
|
||||||
|
for each_advance in salary_advance_search:
|
||||||
|
existing_month = datetime.strptime(str(each_advance.date), '%Y-%m-%d').date().month
|
||||||
|
if current_month == existing_month:
|
||||||
|
raise UserError('Error!', 'Advance can be requested once in a month')
|
||||||
|
if not self.employee_contract_id:
|
||||||
|
raise UserError('Error!', 'Define a contract for the employee')
|
||||||
|
struct_id = self.employee_contract_id.struct_id
|
||||||
|
if not struct_id.max_percent or not struct_id.advance_date:
|
||||||
|
raise UserError('Error!', 'Max percentage or advance days are not provided in Contract')
|
||||||
|
adv = self.advance
|
||||||
|
amt = (self.employee_contract_id.struct_id.max_percent * self.employee_contract_id.wage) / 100
|
||||||
|
if adv > amt and not self.exceed_condition:
|
||||||
|
raise UserError('Error!', 'Advance amount is greater than allotted')
|
||||||
|
|
||||||
|
if not self.advance:
|
||||||
|
raise UserError('Warning', 'You must Enter the Salary Advance amount')
|
||||||
|
payslip_obj = self.env['hr.payslip'].search([('employee_id', '=', self.employee_id.id),
|
||||||
|
('state', '=', 'done'), ('date_from', '<=', self.date),
|
||||||
|
('date_to', '>=', self.date)])
|
||||||
|
if payslip_obj:
|
||||||
|
raise UserError('Warning', "This month salary already calculated")
|
||||||
|
|
||||||
|
for slip in self.env['hr.payslip'].search([('employee_id', '=', self.employee_id.id)]):
|
||||||
|
slip_moth = datetime.strptime(str(slip.date_from), '%Y-%m-%d').date().month
|
||||||
|
if current_month == slip_moth + 1:
|
||||||
|
slip_day = datetime.strptime(str(slip.date_from), '%Y-%m-%d').date().day
|
||||||
|
current_day = datetime.strptime(str(self.date), '%Y-%m-%d').date().day
|
||||||
|
if current_day - slip_day < struct_id.advance_date:
|
||||||
|
raise exceptions.Warning(
|
||||||
|
_('Request can be done after "%s" Days From previous month salary') % struct_id.advance_date)
|
||||||
|
self.state = 'waiting_approval'
|
||||||
|
|
||||||
|
def approve_request_acc_dept(self):
|
||||||
|
"""This Approve the employee salary advance request from accounting department.
|
||||||
|
"""
|
||||||
|
salary_advance_search = self.search([('employee_id', '=', self.employee_id.id), ('id', '!=', self.id),
|
||||||
|
('state', '=', 'approve')])
|
||||||
|
current_month = datetime.strptime(str(self.date), '%Y-%m-%d').date().month
|
||||||
|
for each_advance in salary_advance_search:
|
||||||
|
existing_month = datetime.strptime(str(each_advance.date), '%Y-%m-%d').date().month
|
||||||
|
if current_month == existing_month:
|
||||||
|
raise UserError('Error!', 'Advance can be requested once in a month')
|
||||||
|
if not self.debit or not self.credit or not self.journal:
|
||||||
|
raise UserError('Warning', "You must enter Debit & Credit account and journal to approve ")
|
||||||
|
if not self.advance:
|
||||||
|
raise UserError('Warning', 'You must Enter the Salary Advance amount')
|
||||||
|
|
||||||
|
move_obj = self.env['account.move']
|
||||||
|
timenow = time.strftime('%Y-%m-%d')
|
||||||
|
line_ids = []
|
||||||
|
debit_sum = 0.0
|
||||||
|
credit_sum = 0.0
|
||||||
|
for request in self:
|
||||||
|
amount = request.advance
|
||||||
|
request_name = request.employee_id.name
|
||||||
|
reference = request.name
|
||||||
|
journal_id = request.journal.id
|
||||||
|
move = {
|
||||||
|
'narration': 'Salary Advance Of ' + request_name,
|
||||||
|
'ref': reference,
|
||||||
|
'journal_id': journal_id,
|
||||||
|
'date': timenow,
|
||||||
|
'state': 'posted',
|
||||||
|
}
|
||||||
|
|
||||||
|
debit_account_id = request.debit.id
|
||||||
|
credit_account_id = request.credit.id
|
||||||
|
|
||||||
|
if debit_account_id:
|
||||||
|
debit_line = (0, 0, {
|
||||||
|
'name': request_name,
|
||||||
|
'account_id': debit_account_id,
|
||||||
|
'journal_id': journal_id,
|
||||||
|
'date': timenow,
|
||||||
|
'debit': amount > 0.0 and amount or 0.0,
|
||||||
|
'credit': amount < 0.0 and -amount or 0.0,
|
||||||
|
'currency_id': self.currency_id.id,
|
||||||
|
})
|
||||||
|
line_ids.append(debit_line)
|
||||||
|
debit_sum += debit_line[2]['debit'] - debit_line[2]['credit']
|
||||||
|
|
||||||
|
if credit_account_id:
|
||||||
|
credit_line = (0, 0, {
|
||||||
|
'name': request_name,
|
||||||
|
'account_id': credit_account_id,
|
||||||
|
'journal_id': journal_id,
|
||||||
|
'date': timenow,
|
||||||
|
'debit': amount < 0.0 and -amount or 0.0,
|
||||||
|
'credit': amount > 0.0 and amount or 0.0,
|
||||||
|
'currency_id': self.currency_id.id,
|
||||||
|
})
|
||||||
|
line_ids.append(credit_line)
|
||||||
|
credit_sum += credit_line[2]['credit'] - credit_line[2]['debit']
|
||||||
|
|
||||||
|
move.update({'line_ids': line_ids})
|
||||||
|
move_obj.create(move)
|
||||||
|
self.state = 'approve'
|
||||||
|
return True
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import payslip_monthly_report
|
||||||
|
from . import bank_pdf_report
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,188 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from odoo import models, api, _
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
|
class PayslipMonthlyReport(models.AbstractModel):
|
||||||
|
_name = 'report.exp_payroll_custom.payslip_monthly_report'
|
||||||
|
_description = 'Payslip Monthly Report'
|
||||||
|
|
||||||
|
def get_rule_values(self, data=None, context={}):
|
||||||
|
docs = []
|
||||||
|
payslip_line = self.env['hr.payslip.line']
|
||||||
|
count = 0
|
||||||
|
exception = False
|
||||||
|
if data['delist'] == 'ff':
|
||||||
|
ftotal = 0
|
||||||
|
title = _('Allowances and deduction Totals')
|
||||||
|
docs.append({'count': '#', 'rule': _('Name'), 'type': _('Type'), 'amount': _('Amount'), })
|
||||||
|
rules = self.env[data['model']].browse(data['ids']).sorted('sequence')
|
||||||
|
for rule in rules:
|
||||||
|
count += 1
|
||||||
|
total = sum(payslip_line.browse(data['payslip_line_ids']).filtered(
|
||||||
|
lambda r: r.salary_rule_id.id == rule.id).mapped('total'))
|
||||||
|
ftotal += total
|
||||||
|
docs.append({
|
||||||
|
'count': count,
|
||||||
|
'rule': rule.name,
|
||||||
|
'type': _(dict(rule.category_id._fields['rule_type'].selection, context={}).get(
|
||||||
|
rule.category_id.rule_type)),
|
||||||
|
'amount': "{:.2f}".format(total),
|
||||||
|
})
|
||||||
|
docs.append({'count': '', 'rule': _('Total'), 'type': '', 'amount': "{:.2f}".format(ftotal), })
|
||||||
|
elif data['delist'] == 'tt':
|
||||||
|
# TODO review bellow raise
|
||||||
|
if not data['payslip_line_ids'] or not data['rule_ids']: raise ValidationError(
|
||||||
|
_('Sorry No Data To Be Printed'))
|
||||||
|
title = _('Employees Paysheet')
|
||||||
|
rule_dict = {}
|
||||||
|
sorted_rules = self.env['hr.salary.rule'].browse(data['rule_ids']).sorted('sequence')
|
||||||
|
for line in sorted_rules:
|
||||||
|
rule_dict.setdefault(line.category_id.rule_type, [])
|
||||||
|
rule_dict[line.category_id.rule_type] += line
|
||||||
|
tdict = {'count': '#', 'emp_no':_('EMP #'),'emp': _('Name'), }
|
||||||
|
ndict = {'count': '', 'emp_no': _('Nets'),'emp':'' }
|
||||||
|
for key, value in rule_dict.items():
|
||||||
|
for x in value:
|
||||||
|
tdict[x.id], ndict[x.id] = x.name, 0
|
||||||
|
rule_type_name = dict(
|
||||||
|
x.category_id._fields['rule_type']._description_selection(self.env)
|
||||||
|
).get(key)
|
||||||
|
tdict[key], ndict[key] = _('%s %s') % (_('Total'), rule_type_name), 0
|
||||||
|
tdict['net'], ndict['net'], = _('Net'), 0
|
||||||
|
if self.env.context.get('track_emp', False): tdict['track_id'] = 'track_id'
|
||||||
|
docs.append(tdict)
|
||||||
|
fnet = 0
|
||||||
|
for emp in self.env[data['model']].browse(data['ids']):
|
||||||
|
emp_dict = {}
|
||||||
|
count += 1
|
||||||
|
net = 0
|
||||||
|
for key, value in tdict.items():
|
||||||
|
if value == _('#'):
|
||||||
|
emp_dict[key] = count
|
||||||
|
continue
|
||||||
|
elif value == _('EMP #'):
|
||||||
|
emp_dict[key] = emp.emp_no
|
||||||
|
continue
|
||||||
|
elif value == _('Name'):
|
||||||
|
emp_dict[key] = emp.name
|
||||||
|
continue
|
||||||
|
elif value == 'track_id':
|
||||||
|
emp_dict['track_id'] = emp.id
|
||||||
|
continue
|
||||||
|
elif isinstance(key, int):
|
||||||
|
total = sum(payslip_line.browse(data['payslip_line_ids']).filtered(
|
||||||
|
lambda r: r.employee_id.id == emp.id and r.salary_rule_id.id == key).mapped('total'))
|
||||||
|
emp_dict[key] = "{:.2f}".format(total)
|
||||||
|
net += total
|
||||||
|
fnet += total
|
||||||
|
ndict[key] += total
|
||||||
|
elif isinstance(key, str):
|
||||||
|
total = sum(payslip_line.browse(data['payslip_line_ids']).filtered(
|
||||||
|
lambda
|
||||||
|
r: r.employee_id.id == emp.id and r.salary_rule_id.category_id.rule_type == key).mapped(
|
||||||
|
'total'))
|
||||||
|
emp_dict[key] = "{:.2f}".format(total)
|
||||||
|
ndict[key] += total
|
||||||
|
elif isinstance(key, bool):
|
||||||
|
total = sum(payslip_line.browse(data['payslip_line_ids']).filtered(
|
||||||
|
lambda
|
||||||
|
r: r.employee_id.id == emp.id and r.salary_rule_id.category_id.rule_type == False).mapped(
|
||||||
|
'total'))
|
||||||
|
emp_dict[key] = "{:.2f}".format(total)
|
||||||
|
ndict[key] += total
|
||||||
|
if value == _('Net'):
|
||||||
|
emp_dict[key] = "{:.2f}".format(net)
|
||||||
|
continue
|
||||||
|
docs.append(emp_dict)
|
||||||
|
for key in ndict:
|
||||||
|
if isinstance(ndict[key], (int, float)) and key not in ['count', 'emp_no', 'emp']:
|
||||||
|
ndict[key] = "{:.2f}".format(ndict[key])
|
||||||
|
ndict['net'] = "{:.2f}".format(fnet)
|
||||||
|
docs.append(ndict)
|
||||||
|
else:
|
||||||
|
title = _('Specific Allowance and deduction Report')
|
||||||
|
exception = True
|
||||||
|
rules = self.env[data['model']].browse(data['ids']).sorted('sequence')
|
||||||
|
for rule in rules:
|
||||||
|
count = 0
|
||||||
|
ftotal = 0
|
||||||
|
inner_doc = {'rule': rule.name, 'lines': [], }
|
||||||
|
inner_doc['lines'].append({'count': '#', 'emp_no': _('EMP #'), 'emp': _('Employee'), 'amount': _('Amount'), })
|
||||||
|
for emp in set(payslip_line.browse(data['payslip_line_ids']).filtered(
|
||||||
|
lambda r: r.salary_rule_id.id == rule.id).mapped('employee_id')):
|
||||||
|
count += 1
|
||||||
|
total = sum(payslip_line.browse(data['payslip_line_ids']).filtered(
|
||||||
|
lambda r: r.employee_id.id == emp.id and r.salary_rule_id.id == rule.id).mapped('total'))
|
||||||
|
ftotal += total
|
||||||
|
inner_doc['lines'].append({'count': count, 'emp_no': emp.emp_no, 'emp': emp.name, 'amount': "{:.2f}".format(total), })
|
||||||
|
inner_doc['lines'].append({'count': '', 'emp_no': _('Total'),'emp':'', 'amount': "{:.2f}".format(ftotal), })
|
||||||
|
docs.append(inner_doc)
|
||||||
|
return title, exception, docs
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _get_report_values(self, docids, data=None):
|
||||||
|
title, exception, docs = self.get_rule_values(data)
|
||||||
|
return {
|
||||||
|
'exception': exception,
|
||||||
|
'title': title,
|
||||||
|
'date_from': data['form']['date_from'],
|
||||||
|
'date_to': data['form']['date_to'],
|
||||||
|
'docs': docs,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PayslipMonthlyReportXlsx(models.AbstractModel):
|
||||||
|
_name = "report.exp_payroll_custom.payslip_monthly_report_xlsx"
|
||||||
|
_inherit = 'report.report_xlsx.abstract'
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def generate_xlsx_report(self, workbook, data, objs):
|
||||||
|
title, exception, docs = self.env['report.exp_payroll_custom.payslip_monthly_report'].get_rule_values(data)
|
||||||
|
sheet = workbook.add_worksheet('Proll Monthly report')
|
||||||
|
format1 = workbook.add_format({'bottom': True, 'right': True, 'left': True, 'top': True, 'align': 'center', })
|
||||||
|
format2 = workbook.add_format({'font_size': 14, 'bottom': True, 'right': True, 'left': True, 'top': True,
|
||||||
|
'align': 'center', 'bold': True})
|
||||||
|
format2.set_align('center')
|
||||||
|
format2.set_align('vcenter')
|
||||||
|
format3 = workbook.add_format({'bottom': True, 'align': 'center', 'bold': True, })
|
||||||
|
format_amount = workbook.add_format({
|
||||||
|
'bottom': True, 'right': True, 'left': True, 'top': True, 'align': 'center',
|
||||||
|
'num_format': '#,##0.00',
|
||||||
|
})
|
||||||
|
if data['delist'] != 'tf':
|
||||||
|
sheet.merge_range('C5:F5', title, format2)
|
||||||
|
sheet.merge_range('C6:F6', data['form']['date_from'] + ' - ' + data['form']['date_to'], format2)
|
||||||
|
else:
|
||||||
|
sheet.merge_range('C5:E5', title, format2)
|
||||||
|
sheet.merge_range('C6:E6', data['form']['date_from'] + ' - ' + data['form']['date_to'], format2)
|
||||||
|
sheet.set_column('C:C', 10)
|
||||||
|
sheet.set_column('D:D', 40)
|
||||||
|
# sheet.set_column('E:Z', 20)
|
||||||
|
row = 6
|
||||||
|
for line in docs:
|
||||||
|
if data['delist'] != 'tf':
|
||||||
|
row += 1
|
||||||
|
clm = 1
|
||||||
|
for k, v in line.items():
|
||||||
|
clm += 1
|
||||||
|
if isinstance(v, (int, float)):
|
||||||
|
sheet.write(row, clm, v, format_amount)
|
||||||
|
else:
|
||||||
|
sheet.write(row, clm, v, format1)
|
||||||
|
#sheet.write(row, clm, line[k], format1)
|
||||||
|
else:
|
||||||
|
row += 1
|
||||||
|
clm = 2
|
||||||
|
sheet.write(row, clm, line['rule'], format3)
|
||||||
|
for ln in line['lines']:
|
||||||
|
row += 1
|
||||||
|
clm = 1
|
||||||
|
for k, v in ln.items():
|
||||||
|
clm += 1
|
||||||
|
if isinstance(v, (int, float)):
|
||||||
|
sheet.write(row, clm, v, format_amount)
|
||||||
|
else:
|
||||||
|
sheet.write(row, clm, v, format1)
|
||||||
|
#sheet.write(row, clm, ln[k], format1)
|
||||||
|
row += 1
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
access_salary_advance_user,salary.advance,model_salary_advance,base.group_user,1,1,1,0
|
||||||
|
access_salary_advance_officer,salary.advance,model_salary_advance,hr.group_hr_user,1,1,1,1
|
||||||
|
access_salary_advance_manager,salary.advance,model_salary_advance,hr.group_hr_manager,1,1,1,1
|
||||||
|
access_account_manager,salary.advance,model_salary_advance,account.group_account_manager,1,1,1,1
|
||||||
|
access_hr_salary_rule_emp,hr.salary.rule.emp,model_hr_salary_rule,base.group_user,1,0,0,0
|
||||||
|
access_hr_salary_rule_category_emp,hr.salary.rule.category.emp,model_hr_salary_rule_category,base.group_user,1,0,0,0
|
||||||
|
access_hr_payroll_structure_emp,hr.payroll.structure.emp,model_hr_payroll_structure,base.group_user,1,0,0,0
|
||||||
|
access_hr_reward_line_officer,hr.reward.line.officer,model_lines_ids_reward,hr.group_hr_user,1,0,0,0
|
||||||
|
access_hr_reward_line_hr_manager,hr.reward.line.hr.manager,model_lines_ids_reward,hr.group_hr_manager,1,1,1,0
|
||||||
|
access_hr_reward_line_division,hr.reward.line.division,model_lines_ids_reward,hr_base.group_division_manager,1,1,1,1
|
||||||
|
access_hr_reward_line_general_manager,hr.reward.line.gm,model_lines_ids_reward,hr_base.group_general_manager,1,1,0,0
|
||||||
|
access_hr_reward_line_department,hr.reward.department,model_lines_ids_reward,hr_base.group_department_manager,1,0,0,0
|
||||||
|
access_hr_reward_hr_user,hr.reward.hr.user,model_hr_employee_reward,hr.group_hr_user,1,1,0,0
|
||||||
|
access_hr_reward_hr_manager,hr.reward.hr.manager,model_hr_employee_reward,hr.group_hr_manager,1,1,1,0
|
||||||
|
access_hr_reward_division,hr.reward.division,model_hr_employee_reward,hr_base.group_division_manager,1,1,1,1
|
||||||
|
access_hr_reward_general_manager,hr.reward.gm,model_hr_employee_reward,hr_base.group_general_manager,1,1,0,0
|
||||||
|
access_hr_reward_department,hr.reward.department,model_hr_employee_reward,hr_base.group_department_manager,1,0,0,0
|
||||||
|
access_hr_employee_reward,access_hr_employee_reward,model_hr_employee_reward,base.group_user,1,0,0,0
|
||||||
|
access_hr_contract_advantage_officer,hr_contract_advantage_officer,model_contract_advantage,hr.group_hr_user,1,1,1,0
|
||||||
|
access_hr_contract_advantage_manager,hr_contract_advantage_manager,model_contract_advantage,hr.group_hr_manager,1,1,1,1
|
||||||
|
access_hr_contract_advantage_executive,hr_contract_advantage_executive,model_contract_advantage,hr_base.group_executive_manager,1,1,0,0
|
||||||
|
access_hr_contract_advantage_general_manager,hr_contract_advantage_gm,model_contract_advantage,hr_base.group_general_manager,1,0,0,0
|
||||||
|
access_hr_contract_advantage_employee,hr_contract_advantage_employee,model_contract_advantage,base.group_user,1,0,0,0
|
||||||
|
access_payslip_loans_user,payslip.loans.payroll.user,model_payslip_loans,exp_hr_payroll.group_hr_payroll_user,1,1,1,1
|
||||||
|
access_hr_payslip_payroll_contributor,hr.payslip.line.payroll.contributor,model_hr_payslip,exp_payroll_custom.group_hr_payroll_contributor,1,1,0,0
|
||||||
|
access_hr_payslip_line_payroll_contributor,hr.payslip.line.payroll.contributor,model_hr_payslip_line,exp_payroll_custom.group_hr_payroll_contributor,1,1,0,0
|
||||||
|
exp_hr_payroll.access_hr_payslip_run,hr.payslip.run,model_hr_payslip_run,exp_hr_payroll.group_hr_payroll_user,1,1,1,1
|
||||||
|
access_employee_promotions_contributor,employee.promotions.contributor,model_employee_promotions,exp_payroll_custom.group_hr_payroll_contributor,1,1,0,0
|
||||||
|
access_employee_promotions_payroll_user,employee.promotions.payroll.user,model_employee_promotions,exp_hr_payroll.group_hr_payroll_user,1,1,1,1
|
||||||
|
access_hr_payslip_emp,hr.payslip.emp,model_hr_payslip,base.group_user,1,0,0,0
|
||||||
|
access_hr_payslip_line_emp,hr.payslip.line.emp,model_hr_payslip_line,base.group_user,1,0,0,0
|
||||||
|
access_payslip_loans_emp,payslip.loans.emp,model_payslip_loans,base.group_user,1,0,0,0
|
||||||
|
access_related_salary_amount_officer,related_salary_amount_officer,model_related_salary_amount,hr.group_hr_user,1,1,1,1
|
||||||
|
access_related_salary_amount_emp,related_salary_amount_emp,model_related_salary_amount,base.group_user,1,0,0,0
|
||||||
|
access_payroll_bank_wiz_user,access_payroll_bank_wiz_user,model_payroll_bank_wiz,hr.group_hr_user,1,1,1,0
|
||||||
|
access_payslip_monthly_report_user,access_payslip_monthly_report_user,model_payslip_monthly_report,hr.group_hr_user,1,1,1,0
|
||||||
|
access_employee_selection_wizard_hr_manager,employee.selection.wizard.hr.manager,model_employee_selection_wizard,,1,1,1,1
|
||||||
|
access_hr_salary_rule_account_emp,hr_salary_rule_account_emp,model_hr_salary_rule_account,base.group_user,1,0,0,0
|
||||||
|
access_hr_salary_rule_account_hr_user,hr_salary_rule_account_hr_user,model_hr_salary_rule_account,hr.group_hr_user,1,1,1,1
|
||||||
|
access_hr_payslip_finance_review,access_hr_payslip_finance_review,model_hr_payslip,exp_payroll_custom.group_payroll_finance_review,1,1,0,0
|
||||||
|
access_hr_payslip_expense_manger,access_hr_payslip_expense_manger,model_hr_payslip,exp_payroll_custom.group_payroll_expense_manger,1,1,0,0
|
||||||
|
access_hr_payslip_account_manager,access_hr_payslip_account_manager,model_hr_payslip,hr_base.group_account_manager,1,1,0,0
|
||||||
|
access_hr_payslip_hr_manager,access_hr_payslip_hr_manager,model_hr_payslip,hr.group_hr_manager,1,1,0,0
|
||||||
|
access_hr_payslip_general_manager,access_hr_payslip_general_manager,model_hr_payslip,hr_base.group_general_manager,1,1,0,0
|
||||||
|
access_hr_payslip_run_finance_review,access_hr_payslip_finance_review,model_hr_payslip_run,exp_payroll_custom.group_payroll_finance_review,1,1,0,0
|
||||||
|
access_hr_payslip_run_expense_manger,access_hr_payslip_expense_manger,model_hr_payslip_run,exp_payroll_custom.group_payroll_expense_manger,1,1,0,0
|
||||||
|
access_hr_payslip_run_account_manager,access_hr_payslip_account_manager,model_hr_payslip_run,hr_base.group_account_manager,1,1,0,0
|
||||||
|
access_hr_payslip_run_hr_manager,access_hr_payslip_hr_manager,model_hr_payslip_run,hr.group_hr_manager,1,1,0,0
|
||||||
|
access_hr_payslip_run_general_manager,access_hr_payslip_general_manager,model_hr_payslip_run,hr_base.group_general_manager,1,1,0,0
|
||||||
|
access_hr_payslip_line_finance_review,access_hr_payslip_finance_review,model_hr_payslip_line,exp_payroll_custom.group_payroll_finance_review,1,1,0,0
|
||||||
|
access_hr_payslip_line_expense_manger,access_hr_payslip_expense_manger,model_hr_payslip_line,exp_payroll_custom.group_payroll_expense_manger,1,1,0,0
|
||||||
|
access_hr_payslip_line_account_manager,access_hr_payslip_account_manager,model_hr_payslip_line,hr_base.group_account_manager,1,1,0,0
|
||||||
|
access_hr_payslip_line_hr_manager,access_hr_payslip_hr_manager,model_hr_payslip_line,hr.group_hr_manager,1,1,0,0
|
||||||
|
access_hr_payslip_line_general_manager,access_hr_payslip_general_manager,model_hr_payslip_line,hr_base.group_general_manager,1,1,0,0
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<record id="employee_promotion_rule_comp_rule" model="ir.rule">
|
||||||
|
<field name="name">Employee promotions multi company rule</field>
|
||||||
|
<field name="model_id" ref="model_employee_promotions" />
|
||||||
|
<field name="domain_force">['|', ('company_id','=',False), ('company_id', 'in',
|
||||||
|
company_ids)]</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="employee_reward_rule_comp_rule" model="ir.rule">
|
||||||
|
<field name="name">Employee reward multi company rule</field>
|
||||||
|
<field name="model_id" ref="model_hr_employee_reward" />
|
||||||
|
<field name="domain_force">['|', ('company_id','=',False), ('company_id', 'in',
|
||||||
|
company_ids)]</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_payslip_run_rule_comp_rule" model="ir.rule">
|
||||||
|
<field name="name">Employee hr payslip run multi company rule</field>
|
||||||
|
<field name="model_id" ref="model_hr_payslip_run" />
|
||||||
|
<field name="domain_force">['|', ('company_id','=',False), ('company_id', 'in',
|
||||||
|
company_ids)]</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="salary_rule_comp_rule" model="ir.rule">
|
||||||
|
<field name="name">Employee hr_salary_rule multi company rule</field>
|
||||||
|
<field name="model_id" ref="model_hr_salary_rule" />
|
||||||
|
<field name="domain_force">['|', ('company_id','=',False), ('company_id', 'in',
|
||||||
|
company_ids)]</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_payroll_structure_comp_rule" model="ir.rule">
|
||||||
|
<field name="name">Employee hr_salary_rule multi company rule</field>
|
||||||
|
<field name="model_id" ref="model_hr_payroll_structure" />
|
||||||
|
<field name="domain_force">['|', ('company_id','=',False), ('company_id', 'in',
|
||||||
|
company_ids)]</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="rule_advance_salary_multi_company" model="ir.rule">
|
||||||
|
<field name="name">Advance Request Multi Company</field>
|
||||||
|
<field name="model_id" ref="model_salary_advance" />
|
||||||
|
<field eval="True" name="global" />
|
||||||
|
<field name="domain_force">['|', ('company_id','=',False), ('company_id', 'in',company_ids)]
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_payslip_rule_comp_rule" model="ir.rule">
|
||||||
|
<field name="name">Employee hr payslip multi company rule</field>
|
||||||
|
<field name="model_id" ref="model_hr_payslip" />
|
||||||
|
<field name="domain_force">['|', ('company_id','=',False), ('company_id', 'in',
|
||||||
|
company_ids)]</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="contract_advantage_rule_comp_rule" model="ir.rule">
|
||||||
|
<field name="name">Employee contract advantage multi company rule</field>
|
||||||
|
<field name="model_id" ref="model_contract_advantage" />
|
||||||
|
<field name="domain_force">['|', ('company_id','=',False), ('company_id', 'in',
|
||||||
|
company_ids)]</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_salary_advance_manager_rule" model="ir.rule">
|
||||||
|
<field name="name">Salary Advance</field>
|
||||||
|
<field name="model_id" ref="model_salary_advance" />
|
||||||
|
<field name="groups"
|
||||||
|
eval="[(4, ref('hr.group_hr_user')),(4, ref('account.group_account_user'))]" />
|
||||||
|
<field name="perm_write" eval="True" />
|
||||||
|
<field name="perm_read" eval="True" />
|
||||||
|
<field name="perm_create" eval="True" />
|
||||||
|
<field name="perm_unlink" eval="True" />
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_salary_advance_employee_rule" model="ir.rule">
|
||||||
|
<field name="name">Salary Advance Rule For Employee</field>
|
||||||
|
<field name="domain_force">[('employee_id.user_id','=',user.id)]</field>
|
||||||
|
<field name="global" eval="True" />
|
||||||
|
<field name="model_id" ref="model_salary_advance" />
|
||||||
|
<field name="groups" eval="[(4,ref('base.group_user'))]" />
|
||||||
|
<field name="perm_write" eval="True" />
|
||||||
|
<field name="perm_read" eval="True" />
|
||||||
|
<field name="perm_create" eval="True" />
|
||||||
|
<field name="perm_unlink" eval="True" />
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_payroll_rule_employee" model="ir.rule">
|
||||||
|
<field name="name">Employee Payslip</field>
|
||||||
|
<field name="model_id" ref="model_hr_payslip" />
|
||||||
|
<field name="domain_force">[('employee_id.user_id.id', '=', user.id),('state', '=',
|
||||||
|
'transfered')]</field>
|
||||||
|
<field name="groups" eval="[(4, ref('base.group_user'))]" />
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_payslip_contributor_rule" model="ir.rule">
|
||||||
|
<field name="name">All Payslip</field>
|
||||||
|
<field name="model_id" ref="model_hr_payslip" />
|
||||||
|
<field name="domain_force">[(1,'=',1)]</field>
|
||||||
|
<field name="groups"
|
||||||
|
eval="[(4, ref('exp_payroll_custom.group_hr_payroll_contributor')),
|
||||||
|
(4, ref('hr_base.group_general_manager')),
|
||||||
|
(4, ref('exp_hr_payroll.group_hr_payroll_user')),
|
||||||
|
(4, ref('hr_base.group_executive_manager')),
|
||||||
|
(4, ref('hr.group_hr_manager')),
|
||||||
|
(4, ref('hr_base.group_account_manager')),
|
||||||
|
(4, ref('exp_payroll_custom.group_payroll_expense_manger')),
|
||||||
|
(4, ref('exp_payroll_custom.group_payroll_finance_review'))]" />
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="employee_promotion_employee_rule" model="ir.rule">
|
||||||
|
<field name="name">Employee: views its promotions only</field>
|
||||||
|
<field name="model_id" ref="model_employee_promotions" />
|
||||||
|
<field name="domain_force">[('employee_id.user_id','=',user.id)]</field>
|
||||||
|
<field name="groups" eval="[(4, ref('base.group_user'))]" />
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="employee_promotion_division_manager_rule" model="ir.rule">
|
||||||
|
<field name="name">Division/Dep Manager: views promotions of its subordinates</field>
|
||||||
|
<field name="model_id" ref="model_employee_promotions" />
|
||||||
|
<field name="domain_force">['|','|',('employee_id.department_id.manager_id','=',False),
|
||||||
|
('employee_id.department_id.manager_id.user_id','=', user.id),
|
||||||
|
('employee_id.department_id.parent_id.manager_id.user_id','=', user.id)]
|
||||||
|
</field>
|
||||||
|
<field name="groups"
|
||||||
|
eval="[(4, ref('hr_base.group_department_manager')),(4, ref('hr_base.group_division_manager'))]" />
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="employee_promotion_all_rule" model="ir.rule">
|
||||||
|
<field name="name">Manager: views promotions of all employee</field>
|
||||||
|
<field name="model_id" ref="model_employee_promotions" />
|
||||||
|
<field name="domain_force">[(1 ,'=', 1)]</field>
|
||||||
|
<field name="groups"
|
||||||
|
eval="[(3, ref('hr_base.group_account_manager')),
|
||||||
|
(4, ref('hr_base.group_executive_manager')),
|
||||||
|
(4, ref('hr_base.group_general_manager')),
|
||||||
|
(4, ref('hr.group_hr_manager'))]" />
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<data noupdate="1">
|
||||||
|
|
||||||
|
<record id="group_hr_payroll_contributor" model="res.groups">
|
||||||
|
<field name="name">Contributor</field>
|
||||||
|
<field name="comment">This user is a participant in payroll related processes.</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="group_payroll_finance_review" model="res.groups">
|
||||||
|
<field name="name">Finance Review</field>
|
||||||
|
<field name="category_id" ref="base.module_category_payroll_localization"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="group_payroll_expense_manger" model="res.groups">
|
||||||
|
<field name="name">Expense Manager</field>
|
||||||
|
<field name="category_id" ref="base.module_category_payroll_localization"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
|
|
@ -0,0 +1,22 @@
|
||||||
|
@media (min-width: 768px){
|
||||||
|
.rtl .navbar-right{
|
||||||
|
float: left !important;
|
||||||
|
}
|
||||||
|
.rtl .navbar-right .dropdown .dropdown-menu{
|
||||||
|
right: auto !important;
|
||||||
|
left: 0 !important;
|
||||||
|
}
|
||||||
|
.rtl .navbar-left{
|
||||||
|
float: right !important;
|
||||||
|
}
|
||||||
|
.rtl .navbar-left .dropdown .dropdown-menu{
|
||||||
|
left: auto !important;
|
||||||
|
right: 0 !important;
|
||||||
|
}
|
||||||
|
.navbar-nav.navbar-right:last-child{
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
.rtl .pull-left{
|
||||||
|
float: right !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<template id="report_payroll_bank_pdf">
|
||||||
|
<t t-call="web.html_container">
|
||||||
|
<t t-call="web.external_layout" t-att-data-oe-lang="data['form'].get('create_uid.lang')">
|
||||||
|
<div class="page">
|
||||||
|
<h5 class="text-center">Salary Bank Payslip Report</h5>
|
||||||
|
<h5 class="text-center">
|
||||||
|
<span t-esc="date_from"/>
|
||||||
|
---
|
||||||
|
<span t-esc="date_to"/>
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
|
||||||
|
<t t-foreach="data" t-as="v">
|
||||||
|
<h5 class="text-left">
|
||||||
|
<span t-esc="v['bank']"/>
|
||||||
|
</h5>
|
||||||
|
<table class="table table-condensed table-bordered"
|
||||||
|
style="background-color:#0f80d6;width:100%;">
|
||||||
|
<thead style="background: #3e5d7f;text-align: center;color: #ffffff;font-family:verdana;valign: middle;"
|
||||||
|
class="text-center">
|
||||||
|
<th style="text-align:center;">Employee Number</th>
|
||||||
|
<th style="text-align:center;">Employee Name</th>
|
||||||
|
<th style="text-align:center;">Account #</th>
|
||||||
|
<th style="text-align:center;">Bank</th>
|
||||||
|
<th style="text-align:center;">Amount</th>
|
||||||
|
<th style="text-align:center;">Legal #</th>
|
||||||
|
<th style="text-align:center;">Basic Salary</th>
|
||||||
|
<th style="text-align:center;">Housing Allowance</th>
|
||||||
|
<th style="text-align:center;">Other Earnings</th>
|
||||||
|
<th style="text-align:center;">Deduction</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr t-foreach="v['docs']" t-as="o">
|
||||||
|
<td>
|
||||||
|
<span t-esc="o['ID']"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o['Name']"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o['Account #']"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o['Bank']"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o['Salary']"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o['National']"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o['Basic']"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o['Housing']"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o['Other']"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o['Deduction']"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</template>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<template id="employee_cost_report">
|
||||||
|
<t t-call="web.html_container">
|
||||||
|
<t t-call="web.external_layout">
|
||||||
|
<div class="page">
|
||||||
|
<!-- <h1 class="text-center"> Employee Cost </h1>-->
|
||||||
|
<!-- <h3 class="text-center"><span t-esc="date_from"/> - <span t-esc="date_to"/></h3>-->
|
||||||
|
<table class="table table-condensed table-bordered">
|
||||||
|
<thead class="text-center">
|
||||||
|
<tr style="background-color:#0f80d6;width:100%;">
|
||||||
|
<th colspan="12" class="text-center" style="color:#f7f7f7;font-size:20px"> Employee Cost Report <span t-esc="date_from"/> - <span t-esc="date_to"/></th>
|
||||||
|
</tr>
|
||||||
|
<tr style="background-color: #b8bcbf;width:100%;">
|
||||||
|
<th >#</th>
|
||||||
|
<th >Department</th>
|
||||||
|
<th >Employee ID</th>
|
||||||
|
<th >Employee Name</th>
|
||||||
|
<th >Employee Basic Wage</th>
|
||||||
|
<th >House Allowance</th>
|
||||||
|
<th >Other Benefits</th>
|
||||||
|
<th >Employee GOSI</th>
|
||||||
|
<th >Employer GOSI</th>
|
||||||
|
<th >Daily Wage</th>
|
||||||
|
<th >Total</th>
|
||||||
|
<th>Annual Cost</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="text-center">
|
||||||
|
<t t-set="sequence" t-value="0"/>
|
||||||
|
<t t-foreach="docs" t-as="o">
|
||||||
|
<t t-set="salary_value" t-value="o.get_employee_data_report(o.contract_id,date_from,date_to)"/>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<t t-set="sequence" t-value="sequence +1"/>
|
||||||
|
<t t-esc="sequence"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<t t-esc="o.department_id.name"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o.emp_no"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o.name"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o.contract_id.salary"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o.contract_id.house_allowance_temp"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<t t-esc="salary_value[1]"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o.contract_id.gosi_deduction"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o.contract_id.gosi_employer_deduction"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="salary_value[0]"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o.contract_id.total_net"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="salary_value[2]"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</t>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<record id ="employee_cost_report_act" model="ir.actions.report">
|
||||||
|
<field name="model">hr.contract</field>
|
||||||
|
<field name="name">Employee Cost Report</field>
|
||||||
|
<field name="report_type">qweb-pdf</field>
|
||||||
|
<field name="report_name">exp_payroll_custom.employee_cost_report</field>
|
||||||
|
<field name="report_file">exp_payroll_custom.employee_cost_report</field>
|
||||||
|
</record>
|
||||||
|
<record id ="employee_cost_report_act_xlsx" model="ir.actions.report">
|
||||||
|
<field name="model">hr.contract</field>
|
||||||
|
<field name="name">Employee Cost Report</field>
|
||||||
|
<field name="report_type">xlsx</field>
|
||||||
|
<field name="report_name">exp_payroll_custom.employee_cost_report_xlsx</field>
|
||||||
|
<field name="report_file">exp_payroll_custom.employee_cost_report_xlsx</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<record model="report.paperformat" id="paperformat_payslips_batches_recap_report">
|
||||||
|
<field name="name">paperformat.payslips.batches.recap.report</field>
|
||||||
|
<field name="default" eval="True"/>
|
||||||
|
<field name="format">A3</field>
|
||||||
|
<field name="page_width">0</field>
|
||||||
|
<field name="page_width">0</field>
|
||||||
|
<field name="orientation">Portrait</field>
|
||||||
|
<field name="margin_top">30</field>
|
||||||
|
<field name="margin_right">5</field>
|
||||||
|
<field name="margin_bottom">10</field>
|
||||||
|
<field name="margin_left">5</field>
|
||||||
|
<field name="header_line" eval="False"/>
|
||||||
|
<field name="header_spacing">20</field>
|
||||||
|
<field name="dpi">90</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<template id="hr_payslip_run_report_pdf_template">
|
||||||
|
<t t-call="web.html_container">
|
||||||
|
<t t-call="web.internal_layout">
|
||||||
|
<t t-call="web.external_layout">
|
||||||
|
<table class="table table-condensed table-bordered" style="width: 100%">
|
||||||
|
<thead>
|
||||||
|
<thead>
|
||||||
|
<th class="text-center" style="width: 2%;background:#e9ebee;color:#003c79">
|
||||||
|
#
|
||||||
|
</th>
|
||||||
|
<th class="text-center" style="width: 4%;background:#e9ebee;color:#003c79">
|
||||||
|
Employee No
|
||||||
|
</th>
|
||||||
|
<th class="text-center" style="width: 4%;background:#e9ebee;color:#003c79">
|
||||||
|
Employee
|
||||||
|
</th>
|
||||||
|
<th class="text-center" style="width: 4%;background:#e9ebee;color:#003c79">
|
||||||
|
Total Allowance
|
||||||
|
</th>
|
||||||
|
<th class="text-center" style="width: 4%;background:#e9ebee;color:#003c79">
|
||||||
|
Total Deduction
|
||||||
|
</th>
|
||||||
|
<th class="text-center" style="width: 4%;background:#e9ebee;color:#003c79">
|
||||||
|
Total Net
|
||||||
|
</th>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<t t-set="sequence" t-value="0"/>
|
||||||
|
<t t-foreach="docs" t-as="doc">
|
||||||
|
<t t-foreach="doc['slip_ids']" t-as='o'>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<t t-set="sequence" t-value="sequence +1"/>
|
||||||
|
<t t-esc="sequence"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o.employee_id.emp_no"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o.employee_id.name"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o.total_allowances"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o.total_deductions"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-esc="o.total_sum"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- QWeb Reports -->
|
||||||
|
<!-- NAME & FILE_NAME should be the same -->
|
||||||
|
<record id="hr_payslip_run_report_pdf" model="ir.actions.report">
|
||||||
|
<field name="model">hr.payslip.run</field>
|
||||||
|
<field name="name">Payslips Batches Report</field>
|
||||||
|
<field name="report_type">qweb-pdf</field>
|
||||||
|
<field name="report_name">exp_payroll_custom.hr_payslip_run_report_pdf_template</field>
|
||||||
|
<field name="report_file">exp_payroll_custom.hr_payslip_run_report_pdf_template</field>
|
||||||
|
<field name="paperformat_id" ref="paperformat_payslips_batches_recap_report"/>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<template id="report_payroll_bank_pdf_docx"><t t-foreach="data" t-as="v"><t>IFH,IFILE,CSV,ABCD5953001,SASABBGSA003888815,<t><t t-esc="random_char"/></t><t t-set="date_value" t-value="pay_date"/><t t-esc="date_value.replace('-', '').replace('/', '').replace(':', '')"/>00,</t><t t-esc="datestamp" widget="datetime"></t>,<t><t t-esc="timestamp" widget="datetime"></t></t><t>,P,1.0,</t><t><t t-esc="number_of_records"/></t>
|
||||||
|
<t>BATHDR,ACH-CR,<t><t t-esc="counter"/></t>,,,,<t><t t-esc="salary_type"/></t>,Salary,,@1ST@,<t t-set="date_value" t-value="pay_date"/><t t-esc="date_value.replace('-', '').replace('/', '')"/>,00<t t-esc="company_pay_no"></t>,<t t-esc="currency"></t>,<t t-esc="round(total_amount_salary,2)"></t>,,,,,,,<t t-esc="company_id"></t>,<t><t t-esc="company_hr_no"/></t>,<t><t t-esc="company_registry"/></t>,,,,<t><t t-esc="random_char2"/></t><t t-set="date_value" t-value="timestamp" widget="datetime"/><t t-esc="date_value.replace('-', '').replace('/', '').replace(':', '')"/>00</t><t t-if="bank_type=='rajhi'"><t t-foreach="v['docs']" t-as="o"><t></t>
|
||||||
|
<t>SECPTY,</t><t><t t-esc="o['Account #']"/></t>,<t><t t-esc="o['Name']"/></t>,<t><t t-esc="o['ID']"/></t>,<t><t t-esc="o['Bank']"/></t>,,,<t><t t-esc="'%.2f'% o['Salary']"/></t>,,,,,,,N,N,,,,,,@SACH@,<t><t t-esc="o['National']"/></t>,<t><t t-esc="'%.2f'% o['Basic']"/></t>,<t><t t-esc="'%.2f'% o['Housing']"/></t><t>,<t t-esc="'%.2f'% o['Other']"/></t>,<t><t t-esc="'%.2f'% o['Deduction']"/></t>,<t>salary of <t t-esc="pay_slip"/></t></t></t>
|
||||||
|
<t t-elif="bank_type=='alahli'"><t t-foreach="v['docs']" t-as="o"><t></t>
|
||||||
|
<t>SECPTY,</t><t><t t-esc="o['Account #']"/></t>,<t><t t-esc="o['Name']"/></t>,<t><t t-esc="o['ID']"/></t>,<t><t t-esc="o['Bank']"/></t>,,,<t><t t-esc="'%.2f'% o['Salary']"/></t>,,,,,,,N,N,,,,,,@SACH@,<t><t t-esc="o['National']"/></t>,<t><t t-esc="'%.2f'% o['Basic']"/></t>,<t><t t-esc="'%.2f'% o['Housing']"/></t><t>,<t t-esc="'%.2f'% o['Other']"/></t>,<t><t t-esc="'%.2f'% o['Deduction']"/></t>,<t>salary of <t t-esc="pay_slip"/></t></t></t>
|
||||||
|
<t t-elif="bank_type=='riyadh'"><t t-foreach="v['docs']" t-as="o"><t></t>
|
||||||
|
<t>SECPTY,</t><t><t t-esc="o+['Account #']"/></t>,<t><t t-esc="o['Name']"/></t>,<t><t t-esc="o['ID']"/></t>,<t><t t-esc="o['Bank']"/></t>,,,<t><t t-esc="'%.2f'% o['Salary']"/></t>,,,,,,,N,N,,,,,,@SACH@,<t><t t-esc="o['National']"/></t>,<t><t t-esc="'%.2f'% o['Basic']"/></t>,<t><t t-esc="'%.2f'% o['Housing']"/></t><t>,<t t-esc="'%.2f'% o['Other']"/></t>,<t><t t-esc="'%.2f'% o['Deduction']"/></t>,<t>salary of <t t-esc="pay_slip"/></t></t></t></t>
|
||||||
|
</template>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<template id="payslip_monthly_report">
|
||||||
|
<t t-call="web.html_container">
|
||||||
|
<t t-call="hr_base.hr_layout">
|
||||||
|
<style>
|
||||||
|
@font-face {font-family: "Sakkal Majalla"; src:
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.eot"); src:
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.eot?#iefix")
|
||||||
|
format("embedded-opentype"),
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.woff2") format("woff2"),
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.woff") format("woff"),
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.ttf") format("truetype");
|
||||||
|
}
|
||||||
|
table td {
|
||||||
|
font-size: 12pt;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="page" style="font-family: 'Sakkal Majalla'!important;font-size:15pt;">
|
||||||
|
<t t-if="exception==False">
|
||||||
|
<h3 class="text-center">
|
||||||
|
<span t-esc="title"/>
|
||||||
|
</h3>
|
||||||
|
<h4 class="text-center">
|
||||||
|
<span t-esc="date_from"/>
|
||||||
|
-
|
||||||
|
<span t-esc="date_to"/>
|
||||||
|
</h4>
|
||||||
|
<br/>
|
||||||
|
<table class="table table-condensed table-bordered" style="width: 100%">
|
||||||
|
<t t-foreach="docs" t-as="doc">
|
||||||
|
<t t-if="doc['count']=='#'">
|
||||||
|
<thead style="background: #3e5d7f;text-align: center;
|
||||||
|
color: #ffffff;font-family:'Sakkal Majalla'!important: middle;">
|
||||||
|
<span t-foreach="doc" t-as="clm">
|
||||||
|
<th>
|
||||||
|
<span t-esc="doc[clm]"/>
|
||||||
|
</th>
|
||||||
|
</span>
|
||||||
|
</thead>
|
||||||
|
</t>
|
||||||
|
<t t-if="doc['count']!='#'">
|
||||||
|
<tbody style="text-align: justify; padding: 0.7em;font-family:'Sakkal Majalla'!important;">
|
||||||
|
<span t-foreach="doc" t-as="clm">
|
||||||
|
<t t-if="doc_last">
|
||||||
|
<td style="font-weight: bold; ">
|
||||||
|
<t t-if=" isinstance(doc[clm] , float) ">
|
||||||
|
<span t-esc="'%.2f'%doc[clm]"/>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<span t-esc="doc[clm]"/>
|
||||||
|
</t>
|
||||||
|
</td>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<td>
|
||||||
|
<t t-if=" isinstance(doc[clm] , float) ">
|
||||||
|
<span t-esc="'%.2f'%doc[clm]"/>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<span t-esc="doc[clm]"/>
|
||||||
|
</t>
|
||||||
|
</td>
|
||||||
|
</t>
|
||||||
|
</span>
|
||||||
|
</tbody>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</table>
|
||||||
|
</t>
|
||||||
|
<t t-if="exception==True">
|
||||||
|
<h3 class="text-center">
|
||||||
|
<span t-esc="title"/>
|
||||||
|
</h3>
|
||||||
|
<h4 class="text-center">
|
||||||
|
<span t-esc="date_from"/>
|
||||||
|
-
|
||||||
|
<span t-esc="date_to"/>
|
||||||
|
</h4>
|
||||||
|
<t t-foreach="docs" t-as="doc">
|
||||||
|
<h4 class="text-center">
|
||||||
|
<span t-esc="doc['rule']"/>
|
||||||
|
</h4>
|
||||||
|
<table class="table table-condensed table-bordered" style="width: 100%">
|
||||||
|
<t t-foreach="doc['lines']" t-as="line">
|
||||||
|
<t t-if="line['count']=='#'">
|
||||||
|
<thead style="text-align:center; background: #3e5d7f;color: #ffffff;
|
||||||
|
font-family:'Sakkal Majalla'!important;">
|
||||||
|
<span t-foreach="line" t-as="clm">
|
||||||
|
<th>
|
||||||
|
<span t-esc="line[clm]"/>
|
||||||
|
</th>
|
||||||
|
</span>
|
||||||
|
</thead>
|
||||||
|
</t>
|
||||||
|
<t t-if="line['count']!='#'">
|
||||||
|
<tbody style="text-align: justify; padding: 0.7em;font-family:'Sakkal Majalla'!important;">
|
||||||
|
<t t-if="line_last">
|
||||||
|
<span t-foreach="line" t-as="clm">
|
||||||
|
<td style="font-weight: bold;">
|
||||||
|
<t t-if=" isinstance(line[clm] , float) ">
|
||||||
|
<span t-esc="'%.2f'%line[clm]"/>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<span t-esc="line[clm]"/>
|
||||||
|
</t>
|
||||||
|
</td>
|
||||||
|
</span>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<span t-foreach="line" t-as="clm">
|
||||||
|
<td>
|
||||||
|
<t t-if=" isinstance(line[clm] , float) ">
|
||||||
|
<span t-esc="'%.2f'%line[clm]"/>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<span t-esc="line[clm]"/>
|
||||||
|
</t>
|
||||||
|
</td>
|
||||||
|
</span>
|
||||||
|
</t>
|
||||||
|
</tbody>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</table>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</template>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<template id="report_payslip_inherit" inherit_id="exp_hr_payroll.report_payslip">
|
||||||
|
|
||||||
|
<xpath expr="//span[@t-field='o.employee_id.identification_id']" position="replace">
|
||||||
|
<span t-field="o.employee_id.identity_number"/>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//div/table[2]/tbody" position="inside">
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<strong>Total Allowances</strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>
|
||||||
|
<span t-esc="sum([s.amount for s in o.allowance_ids])"
|
||||||
|
t-esc-options='{"widget": "monetary", "display_currency": o.company_id.currency_id}'/>
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>
|
||||||
|
<span t-esc="sum([s.total for s in o.allowance_ids])"
|
||||||
|
t-esc-options='{"widget": "monetary", "display_currency": o.company_id.currency_id}'/>
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<strong>Total Deductions</strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>
|
||||||
|
<span t-esc="sum([s.amount for s in o.deduction_ids])"
|
||||||
|
t-esc-options='{"widget": "monetary", "display_currency": o.company_id.currency_id}'/>
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>
|
||||||
|
<span t-esc="sum([s.total for s in o.deduction_ids])"
|
||||||
|
t-esc-options='{"widget": "monetary", "display_currency": o.company_id.currency_id}'/>
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<strong>Total Loans</strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>
|
||||||
|
<span t-esc="sum([s.amount for s in o.loan_ids])"
|
||||||
|
t-esc-options='{"widget": "monetary", "display_currency": o.company_id.currency_id}'/>
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<!-- <strong>-->
|
||||||
|
<!-- <span t-esc="sum([s.amount for s in o.loan_ids])"-->
|
||||||
|
<!-- t-esc-options='{"widget": "monetary", "display_currency": o.company_id.currency_id}'/>-->
|
||||||
|
<!-- </strong>-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<strong>NET</strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>
|
||||||
|
<span t-esc="round( sum([s.amount for s in o.line_ids.filtered(lambda line: line.appears_on_payslip)]) + sum([s.amount for s in o.loan_ids]), 2)"
|
||||||
|
t-esc-options='{"widget": "monetary", "display_currency": o.company_id.currency_id}'/>
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>
|
||||||
|
<span t-esc="round(sum([s.total for s in o.line_ids.filtered(lambda line: line.appears_on_payslip)]) + sum([s.amount for s in o.loan_ids]), 2)"
|
||||||
|
t-esc-options='{"widget": "monetary", "display_currency": o.company_id.currency_id}'/>
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<template id="report_payslip_details_inherit"
|
||||||
|
inherit_id="exp_hr_payroll.report_payslip_details">
|
||||||
|
|
||||||
|
<xpath expr="//div/table[2]/tbody" position="after">
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<strong>NET</strong>
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<strong>
|
||||||
|
<span t-esc="sum([h['total'] for h in get_details_by_rule_category.get(o.id, []) if not h['level']==0 ])"
|
||||||
|
t-esc-options='{"widget": "monetary", "display_currency": o.company_id.currency_id}'/>
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
<xpath expr="//div/table[3]/tbody/tr" position="after">
|
||||||
|
<tr >
|
||||||
|
<td colspan="3"><strong>NET</strong></td>
|
||||||
|
<td class="text-right">
|
||||||
|
<strong><span t-esc="sum([p['total'] for p in get_lines_by_contribution_register.get(o.id, []) ])"
|
||||||
|
t-esc-options='{"widget": "monetary", "display_currency": o.company_id.currency_id}'/>
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<strong><span t-esc="sum([p['total'] for p in get_lines_by_contribution_register.get(o.id, []) ])"
|
||||||
|
t-esc-options='{"widget": "monetary", "display_currency": o.company_id.currency_id}'/>
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,612 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<template id="report_payroll_bank_pdf_docx">
|
||||||
|
<t t-call="web.html_container">
|
||||||
|
<t t-call="hr_base.hr_layout" translation="off">
|
||||||
|
<style>
|
||||||
|
@font-face {font-family: "Sakkal Majalla"; src:
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.eot"); src:
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.eot?#iefix")
|
||||||
|
format("embedded-opentype"),
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.woff2") format("woff2"),
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.woff") format("woff"),
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.ttf") format("truetype");
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<div class="page" style="font-family: 'Sakkal Majalla'!important;font-size:14pt;direction:rtl">
|
||||||
|
<t t-set="sequence" t-value="0"/>
|
||||||
|
<t t-foreach="data" t-as="v">
|
||||||
|
<h3 style="text-align: center;color: font-weight: bold;">
|
||||||
|
<strong t-if="v['report_type']=='salary'">مسير البنك للرواتب</strong>
|
||||||
|
<strong t-if="v['report_type']=='allowance'">مسير البنك للحوافز</strong>
|
||||||
|
<strong t-if="v['report_type']=='overtime'">مسير البنك للعمل الإضافي</strong>
|
||||||
|
<strong t-if="v['report_type']=='training'">مسير البنك للتدريب</strong>
|
||||||
|
<strong t-if="v['report_type']=='mission'">مسير البنك لمهام العمل</strong>
|
||||||
|
<br/>
|
||||||
|
<span t-esc="date_from"/>
|
||||||
|
---
|
||||||
|
<span t-esc="date_to"/>
|
||||||
|
</h3>
|
||||||
|
<p t-if="v['no_details']==False"
|
||||||
|
style="text-align:right;font-weight:bold;padding:0px; line-height: 1.1;">
|
||||||
|
<span>بنك :</span>
|
||||||
|
<span t-esc="v['bank']"/>
|
||||||
|
</p>
|
||||||
|
<t t-if="bank_type=='rajhi'">
|
||||||
|
<table class="table table-condensed table-bordered">
|
||||||
|
<thead style="margin-top:0px;background: #3e5d7f;text-align: center;color: #ffffff;valign: middle;"
|
||||||
|
class="text-center">
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
رقم الموظف
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
إسم الموظف
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
رقم الحساب
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
البنك
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
المبلغ
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
الهوية
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
الراتب الأساسي
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
بدل السكن
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
بدلات أخرى
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
الخصم
|
||||||
|
</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr t-foreach="v['docs']" t-as="o">
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['ID']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Name']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Account #']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Bank']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="'%.2f'% o['Salary']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['National']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Basic']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Housing']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Other']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Deduction']"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p style="page-break-after:always"></p>
|
||||||
|
</t>
|
||||||
|
<t t-elif="bank_type=='alahli'">
|
||||||
|
<table class="table table-condensed table-bordered">
|
||||||
|
<thead style="margin-top:0px;background: #3e5d7f;text-align: center;color: #ffffff;valign: middle;"
|
||||||
|
class="text-center">
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Bank
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Account Number
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Total Salary
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Transaction Reference
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Employee Name
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
National ID/Iqama ID
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Employee Address
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Basic Salary
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Housing Allowance
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Other Earnings
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Deductions
|
||||||
|
</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr t-foreach="v['docs']" t-as="o">
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Bank']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Account #']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="'%.2f'% o['Salary']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['ID']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Name']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['National']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Address']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Basic']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Housing']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Other']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Deduction']"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p style="page-break-after:always"></p>
|
||||||
|
</t>
|
||||||
|
<t t-elif="bank_type=='riyadh'">
|
||||||
|
<table class="table table-condensed table-bordered">
|
||||||
|
<thead style="margin-top:0px;background: #3e5d7f;text-align: center;color: #ffffff;valign: middle;"
|
||||||
|
class="text-center">
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
SN
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
هوية المستفيد/ المرجع
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
المستفيد / اسم الموظف
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
رقم الحساب
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
رمز البنك
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
إجمالي المبلغ
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
الراتب الأساسي
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
بدل السكن
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
دخل آخر
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
الخصومات
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
العنوان
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
العملة
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
الحالة
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
وصف الدفع
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
مرجع الدفع
|
||||||
|
</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr t-foreach="v['docs']" t-as="o">
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<t t-set="sequence" t-value="sequence +1"/>
|
||||||
|
<t t-esc="sequence"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['National']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Name']"/>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['ID']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Bank']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="'%.2f'% o['Salary']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Basic']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Basic']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Housing']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Housing']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Other']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Deduction']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Address']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['currency']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Pay Description']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['ID']"/>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p style="page-break-after:always"></p>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</template>
|
||||||
|
<template id="report_payroll_bank_pdf">
|
||||||
|
<t t-call="web.html_container">
|
||||||
|
<t t-call="hr_base.hr_layout" translation="off">
|
||||||
|
<style>
|
||||||
|
@font-face {font-family: "Sakkal Majalla"; src:
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.eot"); src:
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.eot?#iefix")
|
||||||
|
format("embedded-opentype"),
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.woff2") format("woff2"),
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.woff") format("woff"),
|
||||||
|
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.ttf") format("truetype");
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<div class="page" style="font-family: 'Sakkal Majalla'!important;font-size:14pt;direction:rtl">
|
||||||
|
<t t-set="sequence" t-value="0"/>
|
||||||
|
<t t-foreach="data" t-as="v">
|
||||||
|
<h3 style="text-align: center;color: font-weight: bold;">
|
||||||
|
<strong t-if="v['report_type']=='salary'">مسير البنك للرواتب</strong>
|
||||||
|
<strong t-if="v['report_type']=='allowance'">مسير البنك للحوافز</strong>
|
||||||
|
<strong t-if="v['report_type']=='overtime'">مسير البنك للعمل الإضافي</strong>
|
||||||
|
<strong t-if="v['report_type']=='training'">مسير البنك للتدريب</strong>
|
||||||
|
<strong t-if="v['report_type']=='mission'">مسير البنك لمهام العمل</strong>
|
||||||
|
<br/>
|
||||||
|
<span t-esc="date_from"/>
|
||||||
|
---
|
||||||
|
<span t-esc="date_to"/>
|
||||||
|
</h3>
|
||||||
|
<p t-if="v['no_details']==False"
|
||||||
|
style="text-align:right;font-weight:bold;padding:0px; line-height: 1.1;">
|
||||||
|
<span>بنك :</span>
|
||||||
|
<span t-esc="v['bank']"/>
|
||||||
|
</p>
|
||||||
|
<t t-if="bank_type=='rajhi'">
|
||||||
|
<table class="table table-condensed table-bordered">
|
||||||
|
<thead style="margin-top:0px;background: #3e5d7f;text-align: center;color: #ffffff;valign: middle;"
|
||||||
|
class="text-center">
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
رقم الموظف
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
إسم الموظف
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
رقم الحساب
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
البنك
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
المبلغ
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
الهوية
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
الراتب الأساسي
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
بدل السكن
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
بدلات أخرى
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
الخصم
|
||||||
|
</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr t-foreach="v['docs']" t-as="o">
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['ID']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Name']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Account #']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Bank']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="'%.2f'% o['Salary']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['National']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Basic']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Housing']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Other']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Deduction']"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p style="page-break-after:always"></p>
|
||||||
|
</t>
|
||||||
|
<t t-elif="bank_type=='alahli'">
|
||||||
|
<table class="table table-condensed table-bordered">
|
||||||
|
<thead style="margin-top:0px;background: #3e5d7f;text-align: center;color: #ffffff;valign: middle;"
|
||||||
|
class="text-center">
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Bank
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Account Number
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Total Salary
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Transaction Reference
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Employee Name
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
National ID/Iqama ID
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Employee Address
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Basic Salary
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Housing Allowance
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Other Earnings
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
Deductions
|
||||||
|
</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr t-foreach="v['docs']" t-as="o">
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Bank']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Account #']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="'%.2f'% o['Salary']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['ID']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Name']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['National']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Address']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Basic']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Housing']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Other']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Deduction']"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p style="page-break-after:always"></p>
|
||||||
|
</t>
|
||||||
|
<t t-elif="bank_type=='riyadh'">
|
||||||
|
<table class="table table-condensed table-bordered">
|
||||||
|
<thead style="margin-top:0px;background: #3e5d7f;text-align: center;color: #ffffff;valign: middle;"
|
||||||
|
class="text-center">
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
SN
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
هوية المستفيد/ المرجع
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
المستفيد / اسم الموظف
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
رقم الحساب
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
رمز البنك
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
إجمالي المبلغ
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
الراتب الأساسي
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
بدل السكن
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
دخل آخر
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
الخصومات
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
العنوان
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
العملة
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
الحالة
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
وصف الدفع
|
||||||
|
</th>
|
||||||
|
<th style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;text-align:center;">
|
||||||
|
مرجع الدفع
|
||||||
|
</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr t-foreach="v['docs']" t-as="o">
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<t t-set="sequence" t-value="sequence +1"/>
|
||||||
|
<t t-esc="sequence"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['National']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Name']"/>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['ID']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Bank']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="'%.2f'% o['Salary']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Basic']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Basic']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Housing']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Housing']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Other']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Deduction']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Address']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['currency']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['Pay Description']"/>
|
||||||
|
</td>
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">
|
||||||
|
<span t-esc="o['ID']"/>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p style="page-break-after:always"></p>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<record id="res_company_form_inherit" model="ir.ui.view">
|
||||||
|
<field name="name">res.company.form.inherit</field>
|
||||||
|
<field name="model">res.company</field>
|
||||||
|
<field name="inherit_id" ref="base.view_company_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='phone']" position="after">
|
||||||
|
<field name="company_hr_no"/>
|
||||||
|
<field name="company_pay_no"/>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<!-- Action -->
|
||||||
|
<record model="ir.actions.act_window" id="employee_advantage_list_action">
|
||||||
|
<field name="name">Employee Allowances and Deductions</field>
|
||||||
|
<field name="res_model">contract.advantage</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Form View -->
|
||||||
|
<record id="employee_advantage_form_view" model="ir.ui.view">
|
||||||
|
<field name="name">Employee Allowances and Deductions</field>
|
||||||
|
<field name="model">contract.advantage</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Employee Allowances and Deductions">
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<button name="confirm" string="Confirm" type="object"
|
||||||
|
class="oe_highlight"
|
||||||
|
invisible="state != 'draft'"
|
||||||
|
groups="hr.group_hr_user,hr.group_hr_manager" />
|
||||||
|
|
||||||
|
<button name="refused" string="Refused" type="object"
|
||||||
|
class="oe_highlight"
|
||||||
|
invisible="state != 'confirm'"
|
||||||
|
groups="hr.group_hr_user,hr.group_hr_manager" />
|
||||||
|
|
||||||
|
<button name="draft" string="Re-Draft" type="object"
|
||||||
|
class="oe_highlight"
|
||||||
|
invisible="state != 'refused'"
|
||||||
|
groups="hr.group_hr_user,hr.group_hr_manager" />
|
||||||
|
|
||||||
|
<field name="state" widget="statusbar" />
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="employee_id" string="Employee Name"
|
||||||
|
required="True"
|
||||||
|
readonly="state != 'draft'" />
|
||||||
|
<field name="contract_advantage_id" readonly="True"
|
||||||
|
force_save="1" store="1" />
|
||||||
|
<field name="type" required="True"
|
||||||
|
readonly="state != 'draft'"
|
||||||
|
invisible="True" />
|
||||||
|
<field name="benefits_discounts" required="True"
|
||||||
|
readonly="state != 'draft'" />
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<field name="date_from" required="True"
|
||||||
|
readonly="state != 'draft'" />
|
||||||
|
<field name="date_to"
|
||||||
|
readonly="state != 'draft'" />
|
||||||
|
<field name="amount" required="True"
|
||||||
|
readonly="state != 'draft'" />
|
||||||
|
<field name="out_rule"
|
||||||
|
readonly="state != 'draft'" />
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group string="Allowances Or Deductions Types">
|
||||||
|
<field name="over_time_id" readonly="True" />
|
||||||
|
<field name="official_mission_id" readonly="True" />
|
||||||
|
<field name="reward_id" readonly="True" />
|
||||||
|
<field name="penalty_id" readonly="True" />
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group string="Comments">
|
||||||
|
<field name="comments"
|
||||||
|
readonly="state != 'draft'" />
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
|
||||||
|
<div class="oe_chatter">
|
||||||
|
<field name="message_follower_ids" widget="mail_followers" />
|
||||||
|
<field name="activity_ids" widget="mail_activity" />
|
||||||
|
<field name="message_ids" widget="mail_thread" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Tree View -->
|
||||||
|
<record model="ir.ui.view" id="employee_advantage_tree_view">
|
||||||
|
<field name="name">Employee Allowances and Deductions</field>
|
||||||
|
<field name="model">contract.advantage</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list string="Employee Allowances and Deductions"
|
||||||
|
decoration-info="state == 'draft'"
|
||||||
|
decoration-danger="state == 'refused'">
|
||||||
|
<field name="employee_id" string="Employee Name" />
|
||||||
|
<field name="type" invisible="True" />
|
||||||
|
<field name="benefits_discounts" />
|
||||||
|
<field name="date_from" />
|
||||||
|
<field name="date_to" />
|
||||||
|
<field name="amount" />
|
||||||
|
<field name="state" string="State" />
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Search View -->
|
||||||
|
<record id="view_employee_filter_advantage" model="ir.ui.view">
|
||||||
|
<field name="name">Employee Allowances and Deductions</field>
|
||||||
|
<field name="model">contract.advantage</field>
|
||||||
|
<field name="type">search</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<search string="Employee Allowances and Deductions">
|
||||||
|
<field name="employee_id" />
|
||||||
|
<field name="benefits_discounts" />
|
||||||
|
<field name="date_from" />
|
||||||
|
</search>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Menu Item -->
|
||||||
|
<menuitem id="employee_advantage_menu"
|
||||||
|
name="Employee Allowances and Deductions"
|
||||||
|
parent="exp_hr_payroll.menu_hr_payroll_root"
|
||||||
|
action="employee_advantage_list_action"
|
||||||
|
sequence="10"
|
||||||
|
groups="hr_base.group_executive_manager,hr_base.group_general_manager,exp_hr_payroll.group_hr_payroll_user" />
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<record id="employee_promotions_action" model="ir.actions.act_window">
|
||||||
|
<field name="name">Employee promotions</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">employee.promotions</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p class="oe_view_nocontent_create">
|
||||||
|
Create Requests.
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="employee_promotions_form_view" model="ir.ui.view">
|
||||||
|
<field name="name">employee.promotions.form</field>
|
||||||
|
<field name="model">employee.promotions</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Employee promotions">
|
||||||
|
<header>
|
||||||
|
<button name="confirm" string="HR Officer" type="object"
|
||||||
|
invisible="state != 'draft'"
|
||||||
|
class="oe_highlight"
|
||||||
|
groups="hr.group_hr_user,exp_hr_payroll.group_hr_payroll_user" />
|
||||||
|
|
||||||
|
<button name="hr_manager" string="HR Manager" type="object"
|
||||||
|
invisible="state != 'confirm'"
|
||||||
|
class="oe_highlight" groups="hr.group_hr_manager" />
|
||||||
|
<button string="Refused" name="act_refuse" type="object"
|
||||||
|
invisible="state != 'confirm'"
|
||||||
|
class="oe_highlight" groups="hr.group_hr_manager" />
|
||||||
|
|
||||||
|
<button name="approved" string="Approved" type="object"
|
||||||
|
invisible="state != 'hr_manager'"
|
||||||
|
class="oe_highlight"
|
||||||
|
groups="hr_base.group_executive_manager,hr_base.group_general_manager" />
|
||||||
|
<button string="Refused" name="act_refuse" type="object"
|
||||||
|
invisible="state != 'hr_manager'"
|
||||||
|
class="oe_highlight"
|
||||||
|
groups="hr_base.group_general_manager,hr_base.group_executive_manager" />
|
||||||
|
|
||||||
|
<button name="re_draft" string="Re-Draft" type="object"
|
||||||
|
invisible="state not in ['refuse', 'approved']"
|
||||||
|
class="oe_highlight" groups="hr.group_hr_manager"
|
||||||
|
confirm="Are you sure to Reset To Draft This Record?" />
|
||||||
|
<field name="state" widget="statusbar" />
|
||||||
|
</header>
|
||||||
|
<sheet>
|
||||||
|
<div class="oe_title">
|
||||||
|
<h1>
|
||||||
|
<field name="employee_id"
|
||||||
|
placeholder="Employee Name"
|
||||||
|
string="Employee" required="1"
|
||||||
|
readonly="state != 'draft'" />
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="new_level" string="Promotion Level"
|
||||||
|
domain="[('type','=','level')]"
|
||||||
|
readonly="state != 'draft'" required="1" widget="selection"
|
||||||
|
context="{'default_type': 'level'}" />
|
||||||
|
<field name="new_group" string="Promotion Group"
|
||||||
|
domain="[('type','=','group')]"
|
||||||
|
context="{'default_type': 'group'}"
|
||||||
|
readonly="state != 'draft'"
|
||||||
|
required="1" widget="selection" />
|
||||||
|
<field name="new_degree" string="Promotion Degree"
|
||||||
|
domain="[('type','=','degree')]"
|
||||||
|
context="{'default_type': 'degree'}"
|
||||||
|
readonly="state != 'draft'" required="1" widget="selection" />
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="date" string="Promotion Date"
|
||||||
|
readonly="state != 'draft'" />
|
||||||
|
<field name="company_id" groups="base.group_multi_company"
|
||||||
|
readonly="1" />
|
||||||
|
<field name="old_scale" string="Current Scale" readonly="1"
|
||||||
|
force_save="1" />
|
||||||
|
<field name="old_level" string="Current Level" invisible="1" />
|
||||||
|
<field name="old_group" string="Current Group" invisible="1" />
|
||||||
|
<field name="old_degree" string="Current Degree" invisible="1" />
|
||||||
|
<field name="old_level_2" string="Current Level" readonly="1"
|
||||||
|
force_save="1" />
|
||||||
|
<field name="old_group_2" string="Current Group" readonly="1"
|
||||||
|
force_save="1" />
|
||||||
|
<field name="old_degree_2" string="Current Degree" readonly="1"
|
||||||
|
force_save="1" />
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
<separator string="Comment" />
|
||||||
|
<field name="comment" string="" readonly="state != 'draft'" />
|
||||||
|
</sheet>
|
||||||
|
<!-- Discuss widgets for history and communication -->
|
||||||
|
<div class="oe_chatter">
|
||||||
|
<field name="message_follower_ids" widget="mail_followers" />
|
||||||
|
<field name="activity_ids" widget="mail_activity" />
|
||||||
|
<field name="message_ids" widget="mail_thread" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="employee_promotions_tree_view">
|
||||||
|
<field name="name">employee.promotions.tree</field>
|
||||||
|
<field name="model">employee.promotions</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list decoration-success="state=='approved'" decoration-info="state == 'draft'"
|
||||||
|
decoration-danger="state == 'refuse'" string="Employee promotions">
|
||||||
|
<field name="employee_id" string="Employee" />
|
||||||
|
<field name="date" string="Date" />
|
||||||
|
<field name="new_level" string="New level" />
|
||||||
|
<field name="new_group" string="New group" />
|
||||||
|
<field name="new_degree" string="New degree" />
|
||||||
|
<field name="state" string="State" />
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem id="employee_promotions_view" name="Employee Promotions"
|
||||||
|
parent="exp_hr_payroll.menu_hr_payroll_root"
|
||||||
|
action="employee_promotions_action"
|
||||||
|
sequence="11" />
|
||||||
|
|
||||||
|
<!--#########################
|
||||||
|
Smart button employee promotions #######-->
|
||||||
|
<record id="employee_promotions_action_hr_employee" model="ir.actions.act_window">
|
||||||
|
<field name="name">Promotions Action</field>
|
||||||
|
<field name="res_model">employee.promotions</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
<field name="context">{'search_default_employee_id': active_id, 'default_employee_id':
|
||||||
|
active_id}</field>
|
||||||
|
<field name="domain">[('state','=','approved'), ('employee_id','=',active_id)]</field>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p class="oe_view_nocontent_create">
|
||||||
|
Click to add a Promotions...
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_employee_promotions_inherit" model="ir.ui.view">
|
||||||
|
<field name="name">hr.employee</field>
|
||||||
|
<field name="model">hr.employee</field>
|
||||||
|
<field name="inherit_id" ref="hr.view_employee_form" />
|
||||||
|
<field name="priority">14</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//div[hasclass('oe_button_box')]" position="inside">
|
||||||
|
<button name="%(employee_promotions_action_hr_employee)d"
|
||||||
|
class="oe_stat_button"
|
||||||
|
type="action" icon="fa-book">
|
||||||
|
<field name="promotions_count" widget="statinfo" string="Promotions" />
|
||||||
|
</button>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,171 @@
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<!-- Action -->
|
||||||
|
<record model="ir.actions.act_window" id="employee_reward_list_action">
|
||||||
|
<field name="name">Employee Reward and Allowances</field>
|
||||||
|
<field name="res_model">hr.employee.reward</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Form View -->
|
||||||
|
<record id="employee_reward_form_view" model="ir.ui.view">
|
||||||
|
<field name="name">Employee Reward and Allowances</field>
|
||||||
|
<field name="model">hr.employee.reward</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Employee Reward and Allowances">
|
||||||
|
<header>
|
||||||
|
<button string="Direct Manager" type="object" name="action_submit"
|
||||||
|
invisible="state != 'draft'"
|
||||||
|
class="oe_highlight"
|
||||||
|
groups="hr_base.group_division_manager" />
|
||||||
|
|
||||||
|
<button string="HRM Approval" type="object" name="action_hrm"
|
||||||
|
invisible="state != 'submitted'"
|
||||||
|
class="oe_highlight"
|
||||||
|
groups="hr.group_hr_manager" />
|
||||||
|
|
||||||
|
<button string="GM Approval" type="object" name="action_done"
|
||||||
|
invisible="state != 'hrm'"
|
||||||
|
class="oe_highlight"
|
||||||
|
groups="hr_base.group_executive_manager,hr_base.group_general_manager" />
|
||||||
|
|
||||||
|
<button string="Recalculate" type="object" name="recalculate"
|
||||||
|
invisible="state not in ['draft', 'submitted']"
|
||||||
|
class="oe_highlight"
|
||||||
|
groups="hr.group_hr_user, hr.group_hr_manager" />
|
||||||
|
|
||||||
|
<button string="Add Employees" type="object" name="action_add_employees"
|
||||||
|
invisible="state != 'draft'"
|
||||||
|
class="oe_highlight"
|
||||||
|
groups="hr.group_hr_user, hr.group_hr_manager" />
|
||||||
|
|
||||||
|
<button string="Refuse" type="object" name="action_refuse"
|
||||||
|
invisible="state not in ['submitted', 'hrm']"
|
||||||
|
class="oe_highlight"
|
||||||
|
groups="hr.group_hr_manager, hr_base.group_general_manager" />
|
||||||
|
|
||||||
|
<button string="Re-Draft" type="object" name="re_draft"
|
||||||
|
invisible="state not in ['refused', 'done']"
|
||||||
|
class="oe_highlight"
|
||||||
|
confirm="Are you sure to Reset To Draft This Record?"
|
||||||
|
groups="hr.group_hr_manager" />
|
||||||
|
|
||||||
|
<field name="state" widget="statusbar" />
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="transfer_type"
|
||||||
|
readonly="state not in ['draft', 'submitted']"
|
||||||
|
required="True" />
|
||||||
|
|
||||||
|
<field name="reward_type"
|
||||||
|
readonly="state != 'draft'"
|
||||||
|
required="True" />
|
||||||
|
|
||||||
|
<field name="allowance_name"
|
||||||
|
invisible="reward_type != 'allowance'"
|
||||||
|
readonly="state not in ['draft', 'submitted']"
|
||||||
|
required="reward_type == 'allowance'" />
|
||||||
|
|
||||||
|
<field name="account_id" string="Account"
|
||||||
|
invisible="transfer_type != 'accounting'"
|
||||||
|
readonly="state != 'hrm'"
|
||||||
|
required="transfer_type == 'accounting' and state == 'hrm'" />
|
||||||
|
|
||||||
|
<field name="journal_id" string="Journal"
|
||||||
|
invisible="transfer_type != 'accounting'"
|
||||||
|
readonly="state != 'hrm'"
|
||||||
|
required="transfer_type == 'accounting' and state == 'hrm'" />
|
||||||
|
|
||||||
|
<field name="benefits_discounts"
|
||||||
|
invisible="transfer_type != 'payroll'"
|
||||||
|
readonly="state != 'submitted'"
|
||||||
|
required="transfer_type == 'payroll' and state == 'submitted'" />
|
||||||
|
|
||||||
|
<field name="date_from"
|
||||||
|
invisible="transfer_type != 'payroll'"
|
||||||
|
readonly="state != 'submitted'"
|
||||||
|
required="transfer_type == 'payroll' and state == 'submitted'" />
|
||||||
|
|
||||||
|
<field name="date_to"
|
||||||
|
invisible="transfer_type != 'payroll'"
|
||||||
|
readonly="state != 'submitted'"
|
||||||
|
required="transfer_type == 'payroll' and state == 'submitted'" />
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<field name="date" widget="date"
|
||||||
|
readonly="state != 'draft'" />
|
||||||
|
<field name="allowance_reason"
|
||||||
|
readonly="state != 'draft'" />
|
||||||
|
<field name="amount"
|
||||||
|
invisible="reward_type != 'amount'"
|
||||||
|
readonly="state != 'draft'"
|
||||||
|
required="True" />
|
||||||
|
|
||||||
|
<field name="check_appraisal"
|
||||||
|
readonly="state not in ['draft', 'submitted']"
|
||||||
|
groups="hr.group_hr_user, hr.group_hr_manager" />
|
||||||
|
|
||||||
|
<field name="percentage"
|
||||||
|
readonly="state != 'draft'"
|
||||||
|
invisible="check_appraisal == True" />
|
||||||
|
|
||||||
|
<field name="reward_once"
|
||||||
|
readonly="state not in ['draft', 'submitted']"
|
||||||
|
groups="hr.group_hr_user, hr.group_hr_manager" />
|
||||||
|
|
||||||
|
<field name="company_id"
|
||||||
|
groups="base.group_multi_company"
|
||||||
|
readonly="True" />
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<field name="line_ids_reward"
|
||||||
|
context="{'percentage': percentage, 'account_id': account_id, 'journal_id': journal_id}"
|
||||||
|
readonly="state in ['submitted', 'done', 'refused']"
|
||||||
|
required="state == 'hrm'">
|
||||||
|
<list string="Employee Reward and Allowances" editable="bottom">
|
||||||
|
<field name="amount"
|
||||||
|
groups="hr_base.group_executive_manager,hr.group_hr_user" />
|
||||||
|
<field name="percentage" />
|
||||||
|
<field name="reward_state" invisible="True" />
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</sheet>
|
||||||
|
|
||||||
|
<div class="oe_chatter">
|
||||||
|
<field name="message_follower_ids" widget="mail_followers" />
|
||||||
|
<field name="activity_ids" widget="mail_activity" />
|
||||||
|
<field name="message_ids" widget="mail_thread" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Tree View -->
|
||||||
|
<record model="ir.ui.view" id="employee_reward_tree_view">
|
||||||
|
<field name="name">Employee Reward and Allowances</field>
|
||||||
|
<field name="model">hr.employee.reward</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list decoration-success="state == 'done'" decoration-info="state == 'draft'"
|
||||||
|
string="Employee Reward and Allowances">
|
||||||
|
<field name="date" widget="date" />
|
||||||
|
<field name="allowance_reason" />
|
||||||
|
<field name="reward_type" />
|
||||||
|
<field name="state" />
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Menu Item -->
|
||||||
|
<menuitem id="employee_reward_menu"
|
||||||
|
name="Employee Reward and Allowances"
|
||||||
|
parent="exp_hr_payroll.menu_hr_payroll_root"
|
||||||
|
action="employee_reward_list_action"
|
||||||
|
sequence="10"
|
||||||
|
groups="hr_base.group_executive_manager,hr_base.group_general_manager,exp_hr_payroll.group_hr_payroll_user" />
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<!--inheriting hr_employee form view-->
|
||||||
|
<record id="hr_contract_salary_form_view" model="ir.ui.view">
|
||||||
|
<field name="name">hr.contract.salary.form.inherit</field>
|
||||||
|
<field name="model">hr.contract</field>
|
||||||
|
<field name="inherit_id" ref="hr_contract.hr_contract_view_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
|
||||||
|
<xpath expr="//group[@name='salary']" position="before">
|
||||||
|
<group invisible="1">
|
||||||
|
<field name="hide" invisible="1" />
|
||||||
|
<field name="required_condition" invisible="1" />
|
||||||
|
</group>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//group[@name='salary']" position="after">
|
||||||
|
<group>
|
||||||
|
<field name="total_allowance" readonly="1"
|
||||||
|
invisible="[('consultants', '==', True)]"
|
||||||
|
groups="hr.group_hr_user,hr.group_hr_manager" />
|
||||||
|
<field name="total_deduction" readonly="1"
|
||||||
|
invisible="[('consultants', '==', True)]"
|
||||||
|
groups="hr.group_hr_user,hr.group_hr_manager" />
|
||||||
|
<field name="total_net" readonly="1"
|
||||||
|
invisible="[('consultants', '==', True)]"
|
||||||
|
groups="hr.group_hr_user,hr.group_hr_manager" />
|
||||||
|
</group>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
<xpath expr="//field[@name='salary_insurnce']" position="after">
|
||||||
|
<field name="house_allowance_temp" readonly="[('state', '!=', 'draft')]"
|
||||||
|
groups="hr.group_hr_user,hr.group_hr_manager" />
|
||||||
|
<field name="transport_allowance" readonly="[('state', '!=', 'draft')]"
|
||||||
|
groups="hr.group_hr_user,hr.group_hr_manager" />
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
<xpath expr="//group[@name='salary_info']" position="after">
|
||||||
|
<group name="advantage" groups="hr.group_hr_user,hr.group_hr_manager">
|
||||||
|
<separator colspan="2" string="Advantages" />
|
||||||
|
<field name="advantages" nolabel="1" readonly="[('state', '!=', 'draft')]">
|
||||||
|
<list>
|
||||||
|
<!-- <field name="benefits_discounts" required="1" />-->
|
||||||
|
<field name="type" invisible="1" />
|
||||||
|
<field name="date_from" required="1" />
|
||||||
|
<field name="date_to" />
|
||||||
|
<field name="amount" required="1" />
|
||||||
|
<field name="done" readonly="1" />
|
||||||
|
<field name="out_rule" invisible="[('type', '!=', 'customize')]" />
|
||||||
|
<!--To
|
||||||
|
link employee move line from official mission to advantages line in
|
||||||
|
contract-->
|
||||||
|
<field name="official_mission_id" invisible="1" />
|
||||||
|
<!--To
|
||||||
|
link employee move line from over time to advantages line in
|
||||||
|
contract-->
|
||||||
|
<field name="over_time_id" invisible="1" />
|
||||||
|
<!--To
|
||||||
|
link employee move line from employee reward to advantages line in
|
||||||
|
contract-->
|
||||||
|
<field name="reward_id" invisible="1" />
|
||||||
|
<field name="penalty_id" invisible="1" />
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</group>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
<xpath expr="//group[@name='duration_group']" position="after">
|
||||||
|
<group name="accounting_info" string="Accounting">
|
||||||
|
<field name="journal_id" required="[('required_condition', '=', True)]"
|
||||||
|
readonly="[('state', '!=', 'draft')]" widget="selection" />
|
||||||
|
|
||||||
|
<field name="analytic_account_id"
|
||||||
|
required="[('required_condition', '=', True)]"
|
||||||
|
readonly="[('state', '!=', 'draft')]" widget="selection" />
|
||||||
|
|
||||||
|
</group>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
<xpath expr="//group[@name='salary_scale_group']" position="inside">
|
||||||
|
<field name="salary_scale" required="1" widget="selection"
|
||||||
|
domain="[('type', '=', 'scale')]"
|
||||||
|
context="{'default_type': 'scale'}" readonly="[('state', '!=', 'draft')]" />
|
||||||
|
|
||||||
|
<field name="salary_level" string="Salary Level" widget="selection"
|
||||||
|
context="{'default_type': 'level'}"
|
||||||
|
invisible="[('hide', '==', False)]"
|
||||||
|
readonly="[('state', '!=', 'draft')]"
|
||||||
|
required="[('hide', '==', True)]"
|
||||||
|
domain="[('type', '=', 'level')]" />
|
||||||
|
|
||||||
|
<field name="salary_group" string="Salary Group" widget="selection"
|
||||||
|
domain="[('type', '=', 'group')]"
|
||||||
|
invisible="[('hide', '==', False)]"
|
||||||
|
readonly="[('state', '!=', 'draft')]"
|
||||||
|
required="[('hide', '==', True)]"
|
||||||
|
context="{'default_type': 'group'}" />
|
||||||
|
|
||||||
|
<field name="salary_degree" string="Salary Degree" widget="selection"
|
||||||
|
domain="[('type', '=', 'degree')]"
|
||||||
|
invisible="[('hide', '==', False)]"
|
||||||
|
readonly="[('state', '!=', 'draft')]"
|
||||||
|
required="[('hide', '==', True)]"
|
||||||
|
context="{'default_type': 'degree'}" />
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
inheriting hr_employee form view
|
||||||
|
<record model="ir.ui.view" id="hr_employee_salary_scale_inherited_form_view">
|
||||||
|
<field name="name">hr.employee.form.view</field>
|
||||||
|
<field name="model">hr.employee</field>
|
||||||
|
<field name="inherit_id" ref="hr.view_employee_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//group[@name='bank_info']" position="after">
|
||||||
|
<group col="2">
|
||||||
|
<group string="Salary Scale" name="salary_scale">
|
||||||
|
<field name="salary_scale" widget="selection" readonly="1"/>
|
||||||
|
<field name="salary_level" widget="selection" readonly="1"/>
|
||||||
|
<field name="salary_group" widget="selection" readonly="1"/>
|
||||||
|
<field name="salary_degree" widget="selection" readonly="1"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<!--inheriting re-contract form view-->
|
||||||
|
<record model="ir.ui.view" id="re_contract_inherited_form_view">
|
||||||
|
<field name="name">hr.re.contract.inherited.form.view</field>
|
||||||
|
<field name="model">hr.re.contract</field>
|
||||||
|
<field name="inherit_id" ref="hr_contract_custom.view_re-contracting_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='contract_id']" position="after">
|
||||||
|
<field name="salary_scale" invisible="1" readonly="1"/>
|
||||||
|
<field name="salary_level" invisible="1" readonly="1"/>
|
||||||
|
<field name="salary_group" invisible="1" readonly="1"/>
|
||||||
|
<field name="salary_degree" invisible="1" readonly="1"/>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
<!--xpath expr="//field[@name='increase_salary']" position="after">
|
||||||
|
<field name="new_salary_scale" widget="selection" domain="[('type','=','scale')]"
|
||||||
|
string="New Salary Scale" context="{'default_type': 'scale'}"
|
||||||
|
attrs="{'invisible':[('state','=','draft'),('increase_salary','in',['no',''])],
|
||||||
|
'required':[('state','!=','draft'),('increase_salary','=','yes')],'readonly':[('state','!=','submitted')]}"/>
|
||||||
|
|
||||||
|
<field name="new_salary_level" widget="selection"
|
||||||
|
domain="[('type','=','level'),('salary_scale_id', '=',new_salary_scale)]"
|
||||||
|
string="New Salary Level" context="{'default_type': 'level'}"
|
||||||
|
attrs="{'invisible':[('state','=','draft'),('increase_salary','in',['no',''])],
|
||||||
|
'required':[('state','!=','draft'),('increase_salary','=','yes')],'readonly':[('state','!=','submitted')]}"/>
|
||||||
|
|
||||||
|
<field name="new_salary_group" widget="selection"
|
||||||
|
domain="[('type','=','group'),('salary_scale_level_id', '=', new_salary_level)]"
|
||||||
|
string="New Salary Group" context="{'default_type': 'group'}"
|
||||||
|
attrs="{'invisible':[('state','=','draft'),('increase_salary','in',['no',''])],
|
||||||
|
'required':[('state','!=','draft'),('increase_salary','=','yes')],'readonly':[('state','!=','submitted')]}"/>
|
||||||
|
|
||||||
|
<field name="new_salary_degree" widget="selection"
|
||||||
|
domain="[('type','=','degree'),('salary_scale_group_id', '=', new_salary_group)]"
|
||||||
|
string="New Salary Degree" context="{'default_type': 'degree'}"
|
||||||
|
attrs="{'invisible':[('state','=','draft'),('increase_salary','in',['no',''])],
|
||||||
|
'required':[('state','!=','draft'),('increase_salary','=','yes')],'readonly':[('state','!=','submitted')]}"/>
|
||||||
|
</xpath-->
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<!--MENU ITEM SALARY SCALE main-->
|
||||||
|
<menuitem
|
||||||
|
id="salary_scale_main_menu"
|
||||||
|
name="Salary Scale"
|
||||||
|
parent="exp_hr_payroll.menu_hr_payroll_configuration"
|
||||||
|
sequence="1"
|
||||||
|
/>
|
||||||
|
<!--MENU ITEM SALARY SCALE child-->
|
||||||
|
<menuitem
|
||||||
|
id="salary_scale_menu"
|
||||||
|
name="Salary Scale"
|
||||||
|
parent="salary_scale_main_menu"
|
||||||
|
sequence="1"
|
||||||
|
action="salary_scale_record_action"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!--MENU ITEM SALARY SCALE level degree child-->
|
||||||
|
<menuitem
|
||||||
|
id="salary_scale_level_degree_menu"
|
||||||
|
name="Scale degree"
|
||||||
|
parent="salary_scale_main_menu"
|
||||||
|
sequence="4"
|
||||||
|
action="salary_scale_level_degree_record_action"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!--MENU ITEM SALARY SCALE level group -->
|
||||||
|
<menuitem
|
||||||
|
id="salary_scale_level_group_menu"
|
||||||
|
name="Scale Group"
|
||||||
|
parent="salary_scale_main_menu"
|
||||||
|
sequence="3"
|
||||||
|
action="salary_scale_level_group_record_action"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<!--MENU ITEM SALARY SCALE level -->
|
||||||
|
<menuitem
|
||||||
|
id="salary_scale_level_menu"
|
||||||
|
name="Scale Levels"
|
||||||
|
parent="salary_scale_main_menu"
|
||||||
|
sequence="2"
|
||||||
|
action="salary_scale_level_action"
|
||||||
|
/>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,189 @@
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<record id="hr_salary_rule_view_form_inherit" model="ir.ui.view">
|
||||||
|
<field name="name">hr.salary.rule.form.inherit</field>
|
||||||
|
<field name="model">hr.salary.rule</field>
|
||||||
|
<field name="inherit_id" ref="exp_hr_payroll.hr_salary_rule_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//label[@for='category_id']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='category_id']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//group[1]" position="replace">
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="category_id" />
|
||||||
|
<field name="code" />
|
||||||
|
<field name="sequence" />
|
||||||
|
<field name="company_id" options="{'no_create': True}"
|
||||||
|
groups="base.group_multi_company" />
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="start_date" />
|
||||||
|
<field name="end_date" />
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//page[1]" position="replace">
|
||||||
|
<field name="active" invisible="1" />
|
||||||
|
<page string="General">
|
||||||
|
<separator colspan="4" string="Computation" />
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="amount_select" />
|
||||||
|
<newline />
|
||||||
|
<field colspan="4" name="amount_python_compute"
|
||||||
|
invisible="amount_select != 'code'"
|
||||||
|
required="amount_select == 'code'" />
|
||||||
|
<newline />
|
||||||
|
<field name="salary_type" invisible="amount_select == 'code'" />
|
||||||
|
<field name="fixed_amount"
|
||||||
|
invisible="salary_type != 'fixed' or amount_select in ('percentage', 'code')"
|
||||||
|
required="salary_type == 'fixed'" />
|
||||||
|
<field name="related_benefits_discounts" widget="many2many_tags"
|
||||||
|
invisible="amount_select != 'percentage'"
|
||||||
|
required="amount_select == 'percentage'" />
|
||||||
|
<newline />
|
||||||
|
<field name="amount_percentage"
|
||||||
|
invisible="amount_select != 'percentage' or salary_type in ('related_levels', 'related_groups', 'related_degrees')"
|
||||||
|
required="amount_select == 'percentage'" />
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="special" />
|
||||||
|
<field name="rules_type" required="1" />
|
||||||
|
<field name="reduce_with_leaves" />
|
||||||
|
<field name="min_leave_days_to_deduct"
|
||||||
|
invisible="reduce_with_leaves == False" />
|
||||||
|
<!--field
|
||||||
|
name="related_qualifications"/-->
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<!--group
|
||||||
|
col="2">
|
||||||
|
<group>
|
||||||
|
<separator colspan="2" string="Conditions"/>
|
||||||
|
<field name="condition_select"/>
|
||||||
|
<newline/>
|
||||||
|
<field name="condition_python"
|
||||||
|
invisible="condition_select != 'python'"
|
||||||
|
required="condition_select == 'python'"
|
||||||
|
colspan="4"/>
|
||||||
|
<newline/>
|
||||||
|
<field name="condition_range"
|
||||||
|
invisible="condition_select != 'range'"
|
||||||
|
required="condition_select == 'range'"/>
|
||||||
|
<newline/>
|
||||||
|
<field name="condition_range_min" colspan="2"
|
||||||
|
invisible="condition_select != 'range'"
|
||||||
|
required="condition_select == 'range'"/>
|
||||||
|
<newline/>
|
||||||
|
<field name="condition_range_max" colspan="2"
|
||||||
|
invisible="condition_select != 'range'"
|
||||||
|
required="condition_select == 'range'"/>
|
||||||
|
<newline/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<separator colspan="2" string="Company Contribution"/>
|
||||||
|
<field name="register_id"/>
|
||||||
|
</group>
|
||||||
|
</group-->
|
||||||
|
</page>
|
||||||
|
|
||||||
|
</xpath>
|
||||||
|
<!--[add]
|
||||||
|
adding accounting info in salary rule -->
|
||||||
|
<xpath expr="//page[1]" position="after">
|
||||||
|
<page string="Accounting Info">
|
||||||
|
<group>
|
||||||
|
<field name="transfer_by_emp_type" string="Transfer By Employee Type" />
|
||||||
|
<field name="rule_debit_account_id" string="Debit Account"
|
||||||
|
invisible="transfer_by_emp_type == True" />
|
||||||
|
<field name="rule_credit_account_id" string="Credit Account"
|
||||||
|
invisible="transfer_by_emp_type == True" />
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<field name="account_ids" invisible="transfer_by_emp_type == False">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="emp_type_id" string="Employee Type" />
|
||||||
|
<field name="debit_account_id" string="Debit Account" />
|
||||||
|
<field name="credit_account_id" string="Credit Account" />
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//notebook/page[1]" position="after">
|
||||||
|
<page name="related_salary" string="Related Salary Configuration"
|
||||||
|
invisible="salary_type in (False, 'fixed')">
|
||||||
|
<field name="salary_amount_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="salary_scale" required="1"
|
||||||
|
domain="[('type','=','scale')]"
|
||||||
|
context="{'default_type': 'scale'}" />
|
||||||
|
<field name="salary_scale_level" required="1"
|
||||||
|
domain="[('type','=','level')]"
|
||||||
|
context="{'default_type': 'level'}" />
|
||||||
|
<field name="salary_scale_group" required="1"
|
||||||
|
domain="[('type','=','group')]"
|
||||||
|
context="{'default_type': 'group'}"
|
||||||
|
column_invisible="parent.salary_type not in ('related_groups', 'related_degrees')" />
|
||||||
|
<field name="salary_scale_degree" required="1"
|
||||||
|
domain="[('type','=','degree')]"
|
||||||
|
context="{'default_type': 'degree'}"
|
||||||
|
column_invisible="parent.salary_type != 'related_degrees'" />
|
||||||
|
<field name="salary" required="1" />
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
</xpath>
|
||||||
|
<!-- page invisible-->
|
||||||
|
|
||||||
|
<xpath expr="//page[@name='rules']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//page[5]" position="replace">
|
||||||
|
<page string="Inputs" invisible="1">
|
||||||
|
<field name="input_ids" mode="list">
|
||||||
|
<list string="Input Data" editable="bottom">
|
||||||
|
<field name="name" />
|
||||||
|
<field name="code" />
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
</xpath>
|
||||||
|
<!-- page-->
|
||||||
|
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Salary Category-->
|
||||||
|
<record id="hr_salary_rule_category__inherited_form" model="ir.ui.view">
|
||||||
|
<field name="name">hr.salary.rule.category.inherited.form</field>
|
||||||
|
<field name="model">hr.salary.rule.category</field>
|
||||||
|
<field name="inherit_id" ref="exp_hr_payroll.hr_salary_rule_category_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='code']" position="after">
|
||||||
|
<field name="rule_type" required="1" />
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Salary rule tree-->
|
||||||
|
<record id="hr_salary_rule_list2" model="ir.ui.view">
|
||||||
|
<field name="name">hr.salary.rule.list</field>
|
||||||
|
<field name="model">hr.salary.rule</field>
|
||||||
|
<field name="inherit_id" ref="exp_hr_payroll.hr_salary_rule_list" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='register_id']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='code']" position="after">
|
||||||
|
<field name="company_id" />
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<!-- Search View -->
|
||||||
|
<record id="salary_scale_filter_view" model="ir.ui.view">
|
||||||
|
<field name="name">salary.scale.filter.view</field>
|
||||||
|
<field name="model">hr.payroll.structure</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<search string="Search Salary Scale">
|
||||||
|
<field name="name" filter_domain="[('name','ilike',self)]" />
|
||||||
|
<separator />
|
||||||
|
<filter string="Scale" name="scale" domain="[('type','=', 'scale')]" />
|
||||||
|
<filter string="Level" name="level" domain="[('type','=', 'level')]" />
|
||||||
|
<filter string="Group" name="group" domain="[('type','=', 'group')]" />
|
||||||
|
<filter string="Degree" name="degree" domain="[('type','=', 'degree')]" />
|
||||||
|
</search>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Action -->
|
||||||
|
<record id="salary_scale_record_action" model="ir.actions.act_window">
|
||||||
|
<field name="name">Salary Scale</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">hr.payroll.structure</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
<field name="domain">[('type','=','scale')]</field>
|
||||||
|
<field name="context">{'default_type':'scale', 'search_default_scale': 1}</field>
|
||||||
|
<field name="search_view_id" ref="salary_scale_filter_view" />
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Form View -->
|
||||||
|
<record id="salary_scale_form_view" model="ir.ui.view">
|
||||||
|
<field name="name">Salary Scale</field>
|
||||||
|
<field name="model">hr.payroll.structure</field>
|
||||||
|
<field name="inherit_id" ref="exp_hr_payroll.view_hr_employee_grade_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//group[1]" position="replace">
|
||||||
|
<div class="oe_button_box" name="button_box">
|
||||||
|
<button name="toggle_active" type="object" class="oe_stat_button"
|
||||||
|
icon="fa-archive">
|
||||||
|
<field name="active" widget="boolean_button"
|
||||||
|
options="{'terminology': 'archive'}" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="oe_title oe_left">
|
||||||
|
<div class="oe_edit_only">
|
||||||
|
<label for="name" />
|
||||||
|
</div>
|
||||||
|
<h1>
|
||||||
|
<field name="name" default_focus="1" />
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<group>
|
||||||
|
<field name="code" />
|
||||||
|
<field name="salary_scale_id"
|
||||||
|
invisible="type == 'scale'"
|
||||||
|
required="type != 'scale'"
|
||||||
|
domain="[('type', '=', 'scale')]"
|
||||||
|
context="{'default_type': 'scale'}" />
|
||||||
|
<field name="salary_scale_level_id"
|
||||||
|
invisible="type in ['level', 'scale']"
|
||||||
|
required="type not in ['level', 'scale']"
|
||||||
|
domain="[('type', '=', 'level')]"
|
||||||
|
context="{'default_type': 'level'}" />
|
||||||
|
<field name="salary_scale_group_id"
|
||||||
|
invisible="type != 'degree'"
|
||||||
|
required="type == 'degree'"
|
||||||
|
domain="[('type', '=', 'group')]"
|
||||||
|
context="{'default_type': 'group'}" />
|
||||||
|
<field name="company_id" groups="base.group_multi_company" readonly="1"
|
||||||
|
options="{'no_create': True}" />
|
||||||
|
</group>
|
||||||
|
<group name="salary_scale">
|
||||||
|
<group>
|
||||||
|
<field name="base_salary"
|
||||||
|
invisible="type != 'degree'"
|
||||||
|
required="type == 'degree'" />
|
||||||
|
<field name="level_num"
|
||||||
|
invisible="type != 'scale'"
|
||||||
|
required="type == 'scale'" />
|
||||||
|
<field name="retirement_age"
|
||||||
|
invisible="type != 'scale'"
|
||||||
|
required="type == 'scale'" />
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="start_date"
|
||||||
|
invisible="type != 'scale'" />
|
||||||
|
<field name="end_date"
|
||||||
|
invisible="type != 'scale'" />
|
||||||
|
<field name="transfer_type"
|
||||||
|
invisible="type != 'scale'"
|
||||||
|
required="type == 'scale'" />
|
||||||
|
<field name="analytic_account_id" string="Analytic Account"
|
||||||
|
invisible="type != 'scale'" />
|
||||||
|
<field name="groups_number"
|
||||||
|
invisible="type != 'level'"
|
||||||
|
required="type == 'level'" />
|
||||||
|
<field name="degree_number"
|
||||||
|
invisible="type != 'group'"
|
||||||
|
required="type == 'group'" />
|
||||||
|
<field name="gread_min"
|
||||||
|
invisible="type != 'group'" />
|
||||||
|
<field name="gread_max"
|
||||||
|
invisible="type != 'group'" />
|
||||||
|
<field name="interval_time"
|
||||||
|
invisible="type != 'degree'" />
|
||||||
|
<field name="type" invisible="1" />
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
<xpath expr="//notebook" position="replace">
|
||||||
|
<notebook invisible="type != 'scale'">
|
||||||
|
<page name="salary_scale_levels" string="Salary Scale Levels">
|
||||||
|
<field name="salary_scale_levels_ids"
|
||||||
|
readonly="1" required="1" />
|
||||||
|
</page>
|
||||||
|
<page name="salary_scale_level_groups" string="Salary Scale Level Groups">
|
||||||
|
<field name="salary_scale_level_groups_ids"
|
||||||
|
readonly="1" required="1" />
|
||||||
|
</page>
|
||||||
|
<page name="salary_scale_level_degrees" string="Salary Scale Level Degrees">
|
||||||
|
<field name="salary_scale_level_degrees_ids"
|
||||||
|
readonly="1" required="1" />
|
||||||
|
</page>
|
||||||
|
<page name="salary_rules" string="Benefits and discounts">
|
||||||
|
<field name="rule_ids">
|
||||||
|
<list>
|
||||||
|
<field name="name" />
|
||||||
|
<field name="code" />
|
||||||
|
<field name="company_id" />
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<record id="salary_scale_level_action" model="ir.actions.act_window">
|
||||||
|
<field name="name">Salary Scale Level</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">hr.payroll.structure</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
<field name="domain">[('type','=','level')]</field>
|
||||||
|
<field name="context">{'default_type':'level', 'search_default_level': 1}</field>
|
||||||
|
<field name="search_view_id" ref="salary_scale_filter_view" />
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="salary_scale_level_form_view" model="ir.ui.view">
|
||||||
|
<field name="name">Salary Scale Level</field>
|
||||||
|
<field name="model">hr.payroll.structure</field>
|
||||||
|
<field name="inherit_id" ref="exp_hr_payroll.view_hr_employee_grade_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//notebook" position="before">
|
||||||
|
<group>
|
||||||
|
<field name="benefits_discounts_ids" widget="many2many_tags"
|
||||||
|
invisible="[('type', 'not in', ['level', 'group'])]"
|
||||||
|
domain="[('category_id.rule_type','=',('allowance','deduction'))]" />
|
||||||
|
</group>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<record id="salary_scale_level_degree_record_action" model="ir.actions.act_window">
|
||||||
|
<field name="name">Salary Scale Level Degree</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">hr.payroll.structure</field>
|
||||||
|
<field name="view_mode">tree,form</field>
|
||||||
|
<field name="domain">[('type','=','degree')]</field>
|
||||||
|
<field name="context">{'default_type':'degree', 'search_default_degree': 1}</field>
|
||||||
|
<field name="search_view_id" ref="salary_scale_filter_view"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Customize menus security -->
|
||||||
|
<odoo>
|
||||||
|
<record model="ir.ui.menu" id="exp_hr_payroll.menu_hr_payroll_root">
|
||||||
|
<field name="groups_id" eval="[(4,ref('exp_hr_payroll.group_hr_payroll_user')),
|
||||||
|
(4,ref('hr_base.group_general_manager'))]"/>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<menuitem id="exp_hr_payroll.menu_hr_payroll_root" name="Payroll"
|
||||||
|
groups="exp_payroll_custom.group_hr_payroll_contributor,exp_hr_payroll.group_hr_payroll_user,exp_payroll_custom.group_payroll_finance_review,exp_payroll_custom.group_payroll_expense_manger,hr_base.group_account_manager,hr.group_hr_manager,hr_base.group_general_manager"/>
|
||||||
|
|
||||||
|
<menuitem id="exp_hr_payroll.menu_hr_payslip_run" sequence="1"
|
||||||
|
parent="exp_hr_payroll.menu_hr_payroll_root"
|
||||||
|
groups="hr_base.group_executive_manager,exp_payroll_custom.group_hr_payroll_contributor,exp_hr_payroll.group_hr_payroll_user,exp_payroll_custom.group_payroll_finance_review,exp_payroll_custom.group_payroll_expense_manger,hr_base.group_account_manager,hr.group_hr_manager,hr_base.group_general_manager"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<record model="ir.ui.menu" id="exp_hr_payroll.menu_department_tree">
|
||||||
|
<field name="groups_id"
|
||||||
|
eval="[(4,ref('exp_hr_payroll.group_hr_payroll_user')),
|
||||||
|
(4,ref('hr_base.group_general_manager'))]"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.ui.menu" id="exp_hr_payroll.menu_hr_payroll_configuration">
|
||||||
|
<field name="groups_id" eval="[(4, ref('exp_hr_payroll.group_hr_payroll_user'))]"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<record id="act_payslip_monthly_report" model="ir.actions.report">
|
||||||
|
<field name="model">hr.payslip</field>
|
||||||
|
<field name="name">Payslip PDF Report</field>
|
||||||
|
<field name="report_type">qweb-pdf</field>
|
||||||
|
<field name="report_name">exp_payroll_custom.payslip_monthly_report</field>
|
||||||
|
<field name="report_file">exp_payroll_custom.payslip_monthly_report</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="payslip_monthly_report_xlsx" model="ir.actions.report">
|
||||||
|
<field name="model">hr.payslip</field>
|
||||||
|
<field name="name">Payslip Xlsx Report</field>
|
||||||
|
<field name="report_type">xlsx</field>
|
||||||
|
<field name="report_name">exp_payroll_custom.payslip_monthly_report_xlsx</field>
|
||||||
|
<field name="report_file">exp_payroll_custom.payslip_monthly_report_xlsx</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="act_payslip_monthly_report" model="ir.actions.report">
|
||||||
|
<field name="model">hr.payslip</field>
|
||||||
|
<field name="name">Payslip PDF Report</field>
|
||||||
|
<field name="report_type">qweb-pdf</field>
|
||||||
|
<field name="report_name">exp_payroll_custom.payslip_monthly_report</field>
|
||||||
|
<field name="report_file">exp_payroll_custom.payslip_monthly_report</field>
|
||||||
|
<field name="binding_model_id" eval="False"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<record id="payslip_monthly_report_xlsx" model="ir.actions.report">
|
||||||
|
<field name="model">hr.payslip</field>
|
||||||
|
<field name="name">Payslip Xlsx Report</field>
|
||||||
|
<field name="report_type">xlsx</field>
|
||||||
|
<field name="report_name">exp_payroll_custom.payslip_monthly_report_xlsx</field>
|
||||||
|
<field name="report_file">exp_payroll_custom.payslip_monthly_report_xlsx</field>
|
||||||
|
<field name="binding_model_id" eval="False"/>
|
||||||
|
</record>
|
||||||
|
<record id="report_payroll_bank_xlsx" model="ir.actions.report">
|
||||||
|
<field name="model">payroll.bank.wiz</field>
|
||||||
|
<field name="name">Payroll Bank Report</field>
|
||||||
|
<field name="report_type">xlsx</field>
|
||||||
|
<field name="report_name">exp_payroll_custom.report_payroll_bank_xlsx</field>
|
||||||
|
<field name="report_file">Payroll Bank Report</field>
|
||||||
|
<field name="attachment_use">False</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="bank_payslip_report" model="ir.actions.report">
|
||||||
|
<field name="model">payroll.bank.wiz</field>
|
||||||
|
<field name="name">Payroll Bank Report</field>
|
||||||
|
<field name="report_type">qweb-pdf</field>
|
||||||
|
<field name="report_name">exp_payroll_custom.report_payroll_bank_pdf</field>
|
||||||
|
<field name="attachment_use">False</field>
|
||||||
|
</record>
|
||||||
|
<record id="payroll_bank_wiz_report_docx" model="ir.actions.report">
|
||||||
|
<field name="model">payroll.bank.wiz</field>
|
||||||
|
<field name="name">Print Text</field>
|
||||||
|
<field name="report_type">qweb-text</field>
|
||||||
|
<field name="report_name">exp_payroll_custom.report_payroll_bank_pdf_docx</field>
|
||||||
|
<field name="binding_type">report</field>
|
||||||
|
<field name="attachment_use">False</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,339 @@
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<record model="ir.ui.view" id="model_payslip_form_view">
|
||||||
|
<field name="name">hr.payslip.form</field>
|
||||||
|
<field name="model">hr.payslip</field>
|
||||||
|
<field name="inherit_id" ref="exp_hr_payroll.view_hr_payslip_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//header" position="replace">
|
||||||
|
<header>
|
||||||
|
<button string="Confirm" name="confirm" type="object"
|
||||||
|
invisible="state != 'computed'" class="oe_highlight"
|
||||||
|
groups="hr_base.group_executive_manager,hr_base.group_general_manager" />
|
||||||
|
<button string="Withdraw" name="withdraw" type="object"
|
||||||
|
invisible="state != 'computed'" class="oe_highlight"
|
||||||
|
confirm="Are you sure to Delete Compute Salaries?"
|
||||||
|
groups="hr.group_hr_manager" />
|
||||||
|
<button string="Recompute" name="compute_sheet" type="object"
|
||||||
|
invisible="state != 'computed'" class="oe_highlight"
|
||||||
|
confirm="Are you sure to Recompute Salaries?"
|
||||||
|
groups="exp_hr_payroll.group_hr_payroll_user" />
|
||||||
|
<button string="Transfer" name="transfer" type="object"
|
||||||
|
invisible="state != 'confirmed'" class="oe_highlight"
|
||||||
|
confirm="Are you sure to Transfer Accounting?"
|
||||||
|
groups="hr.group_hr_manager" />
|
||||||
|
<button string="Return" name="return_button" type="object"
|
||||||
|
invisible="state not in ['confirmed', 'transfered']"
|
||||||
|
class="oe_highlight" confirm="Are you sure to Return Compute Salaries?"
|
||||||
|
groups="hr_base.group_executive_manager,hr_base.group_general_manager" />
|
||||||
|
<button string="Compute Sheet" name="compute_sheet" type="object"
|
||||||
|
invisible="state != 'draft'" class="oe_highlight"
|
||||||
|
groups="exp_hr_payroll.group_hr_payroll_user" />
|
||||||
|
<field name="state" widget="statusbar"
|
||||||
|
statusbar_visible="draft,computed,confirmed,transfered" />
|
||||||
|
</header>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
<xpath expr="//form" position="attributes">
|
||||||
|
<attribute name="edit">0</attribute>
|
||||||
|
<attribute name="delete">0</attribute>
|
||||||
|
<attribute name="create">0</attribute>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
<xpath expr="//field[@name='name']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//group[1]" position="replace">
|
||||||
|
<group col="4">
|
||||||
|
<label for="date_from" string="Period" />
|
||||||
|
<div>
|
||||||
|
<field name="date_from" class="oe_inline" /> - <field name="date_to"
|
||||||
|
class="oe_inline" />
|
||||||
|
</div>
|
||||||
|
<field name="contract_id" context="{'default_employee_id': employee_id}" />
|
||||||
|
<field name="struct_id" domain="[('type','=','scale')]"
|
||||||
|
string="Salary Scale" />
|
||||||
|
<field name="move_id" readonly="1" />
|
||||||
|
</group>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//page[4]" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//page[3]" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//page[2]" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//notebook/page[1]" position="before">
|
||||||
|
<page string="Allowances">
|
||||||
|
<field name="allowance_ids" readonly="1">
|
||||||
|
<list>
|
||||||
|
<field name="name" />
|
||||||
|
<field name="category_id" string="Allowance" />
|
||||||
|
<field name="sequence" invisible="1" />
|
||||||
|
<field name="quantity" invisible="1" />
|
||||||
|
<field name="rate" />
|
||||||
|
<field name="salary_rule_id" invisible="1" />
|
||||||
|
<field name="amount" />
|
||||||
|
<field name="total" />
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page string="Deductions">
|
||||||
|
<field name="deduction_ids" readonly="1">
|
||||||
|
<list>
|
||||||
|
<field name="name" />
|
||||||
|
<field name="category_id" string="Deduction" />
|
||||||
|
<field name="sequence" invisible="1" />
|
||||||
|
<field name="quantity" invisible="1" />
|
||||||
|
<field name="rate" invisible="1" />
|
||||||
|
<field name="salary_rule_id" invisible="1" />
|
||||||
|
<field name="amount" />
|
||||||
|
<field name="total" />
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page name="loans" string="Loans"
|
||||||
|
groups="hr_loans_salary_advance.group_loan_manager">
|
||||||
|
<field name="loan_ids" readonly="1"
|
||||||
|
groups="hr_loans_salary_advance.group_loan_manager">
|
||||||
|
<list name="loans">
|
||||||
|
<field name="name" />
|
||||||
|
<field name="date" />
|
||||||
|
<field name="account_id" />
|
||||||
|
<field name="amount" />
|
||||||
|
<field name="paid" invisible="1" />
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//form/sheet/notebook" position="after">
|
||||||
|
<group col="4" colspan="4">
|
||||||
|
<field name="total_allowances" />
|
||||||
|
<field name="total_deductions" />
|
||||||
|
<field name="total_loans"
|
||||||
|
groups="hr_loans_salary_advance.group_loan_manager" />
|
||||||
|
<field name="total_sum" />
|
||||||
|
</group>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="hr_payslip_run_inherited_form_view">
|
||||||
|
<field name="name">hr.payslip.run.inherit.form</field>
|
||||||
|
<field name="model">hr.payslip.run</field>
|
||||||
|
<field name="inherit_id" ref="exp_hr_payroll.hr_payslip_run_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//header" position="replace">
|
||||||
|
<header>
|
||||||
|
<button name="compute_sheet" type="object" invisible="state != 'draft'"
|
||||||
|
string="Generate Payslip" class="oe_highlight"
|
||||||
|
groups="exp_hr_payroll.group_hr_payroll_user" />
|
||||||
|
<button name="confirm" type="object" invisible="state != 'computed'"
|
||||||
|
string="Confirm" class="oe_highlight"
|
||||||
|
groups="hr_base.group_executive_manager,hr_base.group_general_manager" />
|
||||||
|
<button name="withdraw" type="object" invisible="state != 'computed'"
|
||||||
|
string="Withdraw" class="oe_highlight" groups="hr.group_hr_manager"
|
||||||
|
confirm="Are you sure to Delete Compute Salaries?" />
|
||||||
|
<button name="compute_sheet" type="object" invisible="state != 'computed'"
|
||||||
|
string="Recompute" class="oe_highlight"
|
||||||
|
confirm="Are you sure to Recompute Salaries?"
|
||||||
|
groups="exp_hr_payroll.group_hr_payroll_user" />
|
||||||
|
<button string="Transfer" name="transfer" type="object"
|
||||||
|
invisible="state != 'confirmed'" class="oe_highlight"
|
||||||
|
confirm="Are you sure to Transfer Accounting?"
|
||||||
|
groups="hr.group_hr_manager" />
|
||||||
|
<button string="Return" name="return_button" type="object"
|
||||||
|
invisible="state not in ['confirmed', 'transfered']"
|
||||||
|
class="oe_highlight" confirm="Are you sure to Return Compute Salaries?"
|
||||||
|
groups="hr_base.group_executive_manager,hr_base.group_general_manager" />
|
||||||
|
<field name="state" widget="statusbar"
|
||||||
|
statusbar_visible="draft,computed,confirmed,transfered" />
|
||||||
|
</header>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='credit_note']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='credit_note']" position="before">
|
||||||
|
<label for="holiday_start_date" string="Holiday Period" />
|
||||||
|
<div>
|
||||||
|
<field name="holiday_start_date" class="oe_inline" /> - <field
|
||||||
|
name="holiday_end_date" class="oe_inline" />
|
||||||
|
</div>
|
||||||
|
<field name="salary_scale" domain="[('type', '=', 'scale')]"
|
||||||
|
readonly="state != 'draft'" required="1" />
|
||||||
|
<field name="journal_id" readonly="state != 'draft'"
|
||||||
|
required="required_condition == True" />
|
||||||
|
<field name="move_id" readonly="1" invisible="required_condition == False" />
|
||||||
|
<field name="company_id" groups="base.group_multi_company" readonly="1"
|
||||||
|
options="{'no_create': True}" />
|
||||||
|
<field name="required_condition" invisible="1" />
|
||||||
|
<field name="employee_value_ids" invisible="1" />
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='slip_ids']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//separator[1]" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//form/sheet" position="inside">
|
||||||
|
<notebook>
|
||||||
|
<page name="payslip_ids" string="Payslips">
|
||||||
|
<field name="slip_ids" />
|
||||||
|
</page>
|
||||||
|
<page name="employee_ids" string="Employees">
|
||||||
|
<field name="employee_ids" nolabel="1" widget="many2many"
|
||||||
|
readonly="state != 'draft'" />
|
||||||
|
</page>
|
||||||
|
<page name="department_ids" string="Departments">
|
||||||
|
<field name="department_ids" nolabel="1" widget="many2many"
|
||||||
|
readonly="state != 'draft'" />
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_payslip_run_tree_inherit" model="ir.ui.view">
|
||||||
|
<field name="name">hr.payslip.run.tree</field>
|
||||||
|
<field name="model">hr.payslip.run</field>
|
||||||
|
<field name="inherit_id" ref="exp_hr_payroll.hr_payslip_run_tree" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list position="replace">
|
||||||
|
<list decoration-success="state=='transfered'"
|
||||||
|
decoration-info="state == 'draft'">
|
||||||
|
<field name="name" />
|
||||||
|
<field name="date_start" />
|
||||||
|
<field name="date_end" />
|
||||||
|
<field name="credit_note" invisible="1" />
|
||||||
|
<field name="state" />
|
||||||
|
</list>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="inherited_hr_payslip_line_form" model="ir.ui.view">
|
||||||
|
<field name="name">hr.payslip.line.form.inherited</field>
|
||||||
|
<field name="model">hr.payslip.line</field>
|
||||||
|
<field name="inherit_id" ref="exp_hr_payroll.view_hr_payslip_line_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='employee_id']" position="after">
|
||||||
|
<field name="leave_request_case" />
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="inherited_view_hr_payslip_line_tree" model="ir.ui.view">
|
||||||
|
<field name="name">hr.payslip.line.tree.inherited</field>
|
||||||
|
<field name="model">hr.payslip.line</field>
|
||||||
|
<field name="inherit_id" ref="exp_hr_payroll.view_hr_payslip_line_tree" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='category_id']" position="attributes">
|
||||||
|
<attribute name="readonly">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='employee_id']" position="attributes">
|
||||||
|
<attribute name="invisible">0</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='employee_id']" position="attributes">
|
||||||
|
<attribute name="readonly">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='sequence']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='name']" position="attributes">
|
||||||
|
<attribute name="readonly">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='code']" position="attributes">
|
||||||
|
<attribute name="readonly">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='quantity']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='rate']" position="attributes">
|
||||||
|
<attribute name="readonly">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='amount']" position="attributes">
|
||||||
|
<attribute name="readonly">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='total']" position="attributes">
|
||||||
|
<attribute name="readonly">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_hr_payslip_inherit_tree" model="ir.ui.view">
|
||||||
|
<field name="name">hr.payslip.tree</field>
|
||||||
|
<field name="model">hr.payslip</field>
|
||||||
|
<field name="inherit_id" ref="exp_hr_payroll.view_hr_payslip_tree" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list position="replace">
|
||||||
|
<list decoration-success="state=='transfered'"
|
||||||
|
decoration-info="state == 'draft'" create="false" edit="false"
|
||||||
|
delete="false">
|
||||||
|
<field name="employee_no" string="Employee Number" />
|
||||||
|
<field name="employee_id" />
|
||||||
|
<field name="company_id" groups="base.group_multi_company"
|
||||||
|
options="{'no_create': True}" />
|
||||||
|
<field name="date_from" optional="hide" />
|
||||||
|
<field name="date_to" optional="hide" />
|
||||||
|
<field name="payslip_run_id" invisible="1" />
|
||||||
|
<field name="basic_allowances" sum="Basic Salary" />
|
||||||
|
<field name="house_allowances" sum="House Allowance" />
|
||||||
|
<field name="trans_allowances" sum="Transport Allowance" />
|
||||||
|
<field name="other_allowances" sum="Others Allowance" />
|
||||||
|
<field name="total_allowances" sum="Total Allowance" decoration-bf="1" />
|
||||||
|
<field name="employee_insurnce" sum="Employee Insurnce" />
|
||||||
|
<field name="total_deductions" sum="Total Deduction" decoration-bf="1"
|
||||||
|
decoration-danger="1" />
|
||||||
|
<field name="total_loans" sum="Total Loans"
|
||||||
|
groups="hr_loans_salary_advance.group_loan_manager" />
|
||||||
|
<field name="total_sum" sum="Total Net" decoration-bf="1"
|
||||||
|
decoration-success="1" />
|
||||||
|
<field name="state" optional="hide" />
|
||||||
|
</list>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_payslip_view_kanban_inherit" model="ir.ui.view">
|
||||||
|
<field name="name">hr.payslip.kanban</field>
|
||||||
|
<field name="model">hr.payslip</field>
|
||||||
|
<field name="inherit_id" ref="exp_hr_payroll.hr_payslip_view_kanban" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//kanban" position="attributes">
|
||||||
|
<attribute name="edit">0</attribute>
|
||||||
|
<attribute name="delete">0</attribute>
|
||||||
|
<attribute name="create">0</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='employee_id']" position="after">
|
||||||
|
<div class="col-12">
|
||||||
|
<span>
|
||||||
|
<field name="contract_id" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='name']" position="after">
|
||||||
|
<div class="col-12">
|
||||||
|
<span>
|
||||||
|
<field name="total_sum" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='name']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_hr_payslip_filter_inherit" model="ir.ui.view">
|
||||||
|
<field name="name">hr.payslip.select</field>
|
||||||
|
<field name="model">hr.payslip</field>
|
||||||
|
<field name="inherit_id" ref="exp_hr_payroll.view_hr_payslip_filter" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='employee_id']" position="after">
|
||||||
|
<field name="employee_no" string="Employee Number" />
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,165 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<record id="view_salary_advance_form" model="ir.ui.view">
|
||||||
|
<field name="name">salary.advance.form</field>
|
||||||
|
<field name="model">salary.advance</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Salary Advance">
|
||||||
|
<header>
|
||||||
|
<button name="submit_to_manager" string="Submit" type="object" states="draft"
|
||||||
|
class="oe_highlight"/>
|
||||||
|
<button name="approve_request" string="Approve" type="object" states="submit"
|
||||||
|
class="oe_highlight" groups="hr.group_hr_manager,hr.group_hr_user"/>
|
||||||
|
<button name="approve_request_acc_dept" string="Approve" type="object" states="waiting_approval"
|
||||||
|
class="oe_highlight" groups="account.group_account_manager,account.group_account_user"/>
|
||||||
|
<button name="cancel" string="Cancel" type="object" states="draft,submit"/>
|
||||||
|
<button name="reject" string="Reject" type="object" states="waiting_approval"/>
|
||||||
|
<field name="state" widget="statusbar"
|
||||||
|
statusbar_visible="draft,submit,waiting_approval,approve,cancel,reject"/>
|
||||||
|
</header>
|
||||||
|
<sheet>
|
||||||
|
<div class="oe_title oe_left">
|
||||||
|
<h2>
|
||||||
|
<field name="name" class="oe_inline" readonly="1"/>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="employee_id"/>
|
||||||
|
<field name="department"/>
|
||||||
|
<field name="date"/>
|
||||||
|
<field name="reason"/>
|
||||||
|
<field name="exceed_condition" groups="hr.group_hr_manager,hr.group_hr_user"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="advance"/>
|
||||||
|
<field name="currency_id" groups="base.group_multi_currency"/>
|
||||||
|
<field name="company_id" groups="base.group_multi_currency"/>
|
||||||
|
<field name="credit"
|
||||||
|
attrs="{'invisible':[('state', '=', 'draft'), ('state', '=', 'submit')]}"
|
||||||
|
groups="account.group_account_manager"/>
|
||||||
|
<field name="debit"
|
||||||
|
attrs="{'invisible':[('state', '=', 'draft'), ('state', '=', 'submit')]}"
|
||||||
|
groups="account.group_account_manager"/>
|
||||||
|
<field name="journal"
|
||||||
|
attrs="{'invisible': [('state', '=', 'draft'), ('state', '=', 'submit')]}"
|
||||||
|
groups="account.group_account_manager"/>
|
||||||
|
<field name="employee_contract_id"
|
||||||
|
attrs="{'invisible': ['|', ('state', '=', 'draft'), ('state', '=', 'approve')]}"
|
||||||
|
groups="hr.group_hr_manager,hr.group_hr_user"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="view_salary_advance_tree">
|
||||||
|
<field name="name">salary.advance.tree</field>
|
||||||
|
<field name="model">salary.advance</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<tree string="Salary Advance">
|
||||||
|
<field name="employee_id"/>
|
||||||
|
<field name="date"/>
|
||||||
|
<field name="advance"/>
|
||||||
|
<field name="state"/>
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_salary_advance_filter" model="ir.ui.view">
|
||||||
|
<field name="name">salary.advance.select</field>
|
||||||
|
<field name="model">salary.advance</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<search string="Search">
|
||||||
|
<field name="name" string="Salary Advance" filter_domain="['|',('name','ilike',self)]"/>
|
||||||
|
<field name="employee_id"/>
|
||||||
|
<field name="state"/>
|
||||||
|
<filter string="My Requests" domain="[('employee_id.user_id.id','=',uid)]"
|
||||||
|
name="my_requests_filter"/>
|
||||||
|
<filter domain="[('state', '=', 'draft')]" string="To Submit" name="to_report" help="New Requests"/>
|
||||||
|
<filter domain="[('state','in',('submit','waiting_approval'))]" string="To Approve" name="submitted"
|
||||||
|
help="Submitted Requests"/>
|
||||||
|
<filter domain="[('state', '=', 'approve')]" string="Approved" name="approved"
|
||||||
|
help="Approved Requests"/>
|
||||||
|
<separator/>
|
||||||
|
<filter string="Employee" name="employee_id" domain="[]" context="{'group_by':'employee_id'}"/>
|
||||||
|
<filter name="State" string="State" domain="[]" context="{'group_by':'state'}"/>
|
||||||
|
<filter string="Date" domain="[]" name="date" context="{'group_by':'date'}"/>
|
||||||
|
</search>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_my_salary_advance" model="ir.actions.act_window">
|
||||||
|
<field name="name">Salary Advance</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">salary.advance</field>
|
||||||
|
|
||||||
|
<field name="view_mode">tree,form</field>
|
||||||
|
<field name="search_view_id" ref="view_salary_advance_filter"/>
|
||||||
|
<field name="context">{'search_default_my_requests_filter':1}</field>
|
||||||
|
<field name="domain">[('employee_id.user_id', '=', uid)]</field>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p class="oe_view_nocontent_create">
|
||||||
|
Create Requests.
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_my_salary_advance_request_approved" model="ir.actions.act_window">
|
||||||
|
<field name="name">Salary Advance</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">salary.advance</field>
|
||||||
|
|
||||||
|
<field name="view_mode">tree,form</field>
|
||||||
|
<field name="search_view_id" ref="view_salary_advance_filter"/>
|
||||||
|
<field name="context">{'search_default_approved':1}</field>
|
||||||
|
<field name="domain">[('employee_id.user_id', '=', uid)]</field>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p class="oe_view_nocontent_create">
|
||||||
|
Create Requests.
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_salary_advance_to_approve" model="ir.actions.act_window">
|
||||||
|
<field name="name">Salary Advance</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">salary.advance</field>
|
||||||
|
|
||||||
|
<field name="view_mode">tree,form</field>
|
||||||
|
<field name="search_view_id" ref="view_salary_advance_filter"/>
|
||||||
|
<field name="context">{'search_default_submitted': 1}</field>
|
||||||
|
<field name="domain"></field>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p class="oe_view_nocontent_create">
|
||||||
|
Create Requests.
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ir_seq_hr_advance" model="ir.sequence">
|
||||||
|
<field name="name">Salary Advance Request</field>
|
||||||
|
<field name="code">salary.advance.seq</field>
|
||||||
|
<field name="prefix">SAR</field>
|
||||||
|
<field name="padding">4</field>
|
||||||
|
<field name="number_increment">1</field>
|
||||||
|
<field name="number_next_actual">1</field>
|
||||||
|
|
||||||
|
<field name="company_id" eval="False"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<menuitem id="parent_menu_salary_advance" name="Advance" parent="hr_loans.menu_hr_loans_and_advances"
|
||||||
|
sequence="7"/>
|
||||||
|
<menuitem id="menu_my_salary_advance" action="action_my_salary_advance" parent="parent_menu_salary_advance"
|
||||||
|
name="Request Salary Advance" sequence="1"/>
|
||||||
|
<menuitem id="menu_salary_advance" action="action_salary_advance_to_approve" parent="parent_menu_salary_advance"
|
||||||
|
name="Salary Advance To Approve" sequence="3"
|
||||||
|
groups="hr.group_hr_manager,hr.group_hr_user,account.group_account_manager"/>
|
||||||
|
<menuitem id="menu_my_salary_advance_approved" action="action_my_salary_advance_request_approved"
|
||||||
|
parent="parent_menu_salary_advance" name="My Approved Salary Advance" sequence="2"/>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<record id="salary_scale_level_group_record_action" model="ir.actions.act_window">
|
||||||
|
<field name="name">Salary Scale Group</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">hr.payroll.structure</field>
|
||||||
|
<field name="view_mode">tree,form</field>
|
||||||
|
<field name="domain">[('type','=','group')]</field>
|
||||||
|
<field name="context">{'default_type':'group', 'search_default_group': 1}</field>
|
||||||
|
<field name="search_view_id" ref="salary_scale_filter_view"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<odoo>
|
||||||
|
<data noupdate="1">
|
||||||
|
|
||||||
|
<!-- Salary Structure >
|
||||||
|
|
||||||
|
<record id="structure_base" model="hr.payroll.structure">
|
||||||
|
<field name="code">Scale</field>
|
||||||
|
<field name="name">Salary Scale</field>
|
||||||
|
<field name="transfer_type">all</field>
|
||||||
|
<field name="rule_ids" eval="[(6, 0, [ref('hr_rule_basic'), ref('hr_rule_house'),ref('hr_rule_transport'),ref('hr_rule_gosi')])]"/>
|
||||||
|
<field name="company_id" ref="base.main_company"/>
|
||||||
|
</record-->
|
||||||
|
<!-- advance salary rule -->
|
||||||
|
|
||||||
|
|
||||||
|
<!--record id="hr_rule_basic" model="hr.salary.rule">
|
||||||
|
<field name="name">Basic Salary</field>
|
||||||
|
<field name="sequence" eval="1"/>
|
||||||
|
<field name="code">BASIC Salary</field>
|
||||||
|
<field name="category_id" ref="exp_hr_payroll.ALW"/>
|
||||||
|
<field name="rules_type">salary</field>
|
||||||
|
<field name="condition_select">none</field>
|
||||||
|
<field name="amount_select">code</field>
|
||||||
|
<field name="amount_python_compute">result = contract.salary</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_rule_house" model="hr.salary.rule">
|
||||||
|
<field name="name">House Allowance</field>
|
||||||
|
<field name="sequence" eval="2"/>
|
||||||
|
<field name="code">House</field>
|
||||||
|
<field name="category_id" ref="exp_hr_payroll.ALW"/>
|
||||||
|
<field name="salary_type">fixed</field>
|
||||||
|
<field name="related_benefits_discounts" eval="[(6, 0, [ref('hr_rule_basic')])]"/>
|
||||||
|
<field name="rules_type">house</field>
|
||||||
|
<field name="condition_select">none</field>
|
||||||
|
<field name="amount_select">percentage</field>
|
||||||
|
<field name="amount_percentage">25</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_rule_transport" model="hr.salary.rule">
|
||||||
|
<field name="name">Transport Allowance</field>
|
||||||
|
<field name="sequence" eval="3"/>
|
||||||
|
<field name="code">Transport</field>
|
||||||
|
<field name="category_id" ref="exp_hr_payroll.ALW"/>
|
||||||
|
<field name="salary_type">fixed</field>
|
||||||
|
<field name="related_benefits_discounts" eval="[(6, 0, [ref('hr_rule_basic')])]"/>
|
||||||
|
<field name="rules_type">transport</field>
|
||||||
|
<field name="condition_select">none</field>
|
||||||
|
<field name="amount_select">percentage</field>
|
||||||
|
<field name="amount_percentage">10</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_rule_gosi" model="hr.salary.rule">
|
||||||
|
<field name="name">GOSI Deduction</field>
|
||||||
|
<field name="sequence" eval="4"/>
|
||||||
|
<field name="code">GOSI</field>
|
||||||
|
<field name="category_id" ref="exp_hr_payroll.DED"/>
|
||||||
|
<field name="rules_type">insurnce</field>
|
||||||
|
<field name="condition_select">none</field>
|
||||||
|
<field name="amount_select">code</field>
|
||||||
|
<field name="amount_python_compute">result=0
|
||||||
|
if contract.employee_id.check_nationality==True and contract.is_gosi_deducted=='yes':
|
||||||
|
result =contract.salary*0.0975
|
||||||
|
|
||||||
|
if result > 4387.5:
|
||||||
|
result= 4387.5
|
||||||
|
else:
|
||||||
|
result=result</field>
|
||||||
|
</record-->
|
||||||
|
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# LCT, Life Connection Technology
|
||||||
|
# Copyright (C) 2019-2020 LCT
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
from . import payslip_monthly_report
|
||||||
|
from . import payroll_bank_report
|
||||||
|
from . import employee_selection_wizard
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
from odoo import api, fields, models, _
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
|
class EmployeeSelectionWizard(models.TransientModel):
|
||||||
|
_name = 'employee.selection.wizard'
|
||||||
|
_description = 'Employee Selection Wizard'
|
||||||
|
|
||||||
|
|
||||||
|
employee_ids = fields.Many2many(
|
||||||
|
'hr.employee',
|
||||||
|
string='Employees',
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
employee_reward_id = fields.Many2one(comodel_name='hr.employee.reward',string='Employee_reward_id')
|
||||||
|
|
||||||
|
@api.onchange('employee_ids')
|
||||||
|
def _onchange_employee_ids(self):
|
||||||
|
return {
|
||||||
|
'domain': {
|
||||||
|
'employee_ids': [
|
||||||
|
('id', 'not in', self.employee_ids.ids),
|
||||||
|
('state','=','open'),
|
||||||
|
('active', '=', True)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def _get_active_employee_reward(self):
|
||||||
|
reward_id = self.env.context.get('default_employee_reward_id')
|
||||||
|
if not reward_id and self.env.context.get('active_model') == 'hr.employee.reward':
|
||||||
|
reward_id = self.env.context.get('active_id')
|
||||||
|
return reward_id
|
||||||
|
|
||||||
|
def action_confirm(self):
|
||||||
|
"""
|
||||||
|
Action to add employees to current employee reward record
|
||||||
|
"""
|
||||||
|
self.ensure_one()
|
||||||
|
|
||||||
|
# Get the current reward record or create a new one
|
||||||
|
reward = self.env['hr.employee.reward'].browse(self._get_active_employee_reward())
|
||||||
|
|
||||||
|
if not reward.exists():
|
||||||
|
# Get values from context
|
||||||
|
reward_vals = self.env.context.get('default_reward_vals', {})
|
||||||
|
reward = self.env['hr.employee.reward'].create(reward_vals)
|
||||||
|
|
||||||
|
print('percentage >>>>>>', self.env.context.get('default_reward_vals', {}))
|
||||||
|
|
||||||
|
# Prepare values for reward lines
|
||||||
|
vals_list = [
|
||||||
|
{
|
||||||
|
'employee_id': employee.id,
|
||||||
|
'employee_reward_id': reward.id,
|
||||||
|
}
|
||||||
|
for employee in self.employee_ids
|
||||||
|
]
|
||||||
|
existing_employees = reward.line_ids_reward.mapped('employee_id').ids
|
||||||
|
duplicate_employees = set(self.employee_ids.ids) & set(existing_employees)
|
||||||
|
|
||||||
|
if duplicate_employees:
|
||||||
|
duplicate_names = self.env['hr.employee'].browse(list(duplicate_employees)).mapped('name')
|
||||||
|
raise ValidationError(_(
|
||||||
|
"The following employees are already in reward lines: %s" % ', '.join(duplicate_names)
|
||||||
|
))
|
||||||
|
|
||||||
|
# Create all records in a single operation
|
||||||
|
reward.write({
|
||||||
|
'line_ids_reward': [(0, 0, vals) for vals in vals_list]
|
||||||
|
})
|
||||||
|
for line in reward.line_ids_reward:
|
||||||
|
fields = ['percentage', 'account_id', 'journal_id']
|
||||||
|
default_values = line.sudo().default_get(fields)
|
||||||
|
|
||||||
|
# Apply the default values to the line
|
||||||
|
line.write(default_values)
|
||||||
|
line.sudo().get_percentage_appraisal()
|
||||||
|
line.sudo()._compute_calculate_amount()
|
||||||
|
|
||||||
|
return {'type': 'ir.actions.act_window_close'}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<record id="view_employee_selection_wizard_form" model="ir.ui.view">
|
||||||
|
<field name="name">employee.selection.wizard.form</field>
|
||||||
|
<field name="model">employee.selection.wizard</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Select Employees">
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<field name="employee_ids"
|
||||||
|
options="{'no_create': True, 'no_create_edit': True}"/>
|
||||||
|
<field name="employee_reward_id" invisible="1"/>
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
<footer>
|
||||||
|
<button name="action_confirm"
|
||||||
|
string="Add"
|
||||||
|
type="object"
|
||||||
|
class="btn-primary"/>
|
||||||
|
<button string="Cancel"
|
||||||
|
class="btn-secondary"
|
||||||
|
special="cancel"/>
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Action to open the wizard -->
|
||||||
|
<record id="action_employee_selection_wizard" model="ir.actions.act_window">
|
||||||
|
<field name="name">Select Employees</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">employee.selection.wizard</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
<field name="target">new</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
# -*- coding:utf-8 -*-
|
||||||
|
|
||||||
|
from datetime import date, datetime
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
import datetime
|
||||||
|
import random
|
||||||
|
|
||||||
|
class BankPayslipReport(models.TransientModel):
|
||||||
|
_name = 'payroll.bank.wiz'
|
||||||
|
_description = "Bank Payslips Report"
|
||||||
|
|
||||||
|
date_from = fields.Date(string='Date From',required=True,
|
||||||
|
default=lambda self: date(date.today().year, date.today().month, 1))
|
||||||
|
date_to = fields.Date(string='Date To', required=True,
|
||||||
|
default=lambda self: date(date.today().year, date.today().month, 1)+relativedelta(months=1,days=-1))
|
||||||
|
pay_date = fields.Date(
|
||||||
|
string='Pay Date',
|
||||||
|
required=False)
|
||||||
|
salary_type= fields.Char(
|
||||||
|
string='',
|
||||||
|
required=False)
|
||||||
|
|
||||||
|
bank_ids = fields.Many2many('res.bank', string='Banks',required=True)
|
||||||
|
salary_ids = fields.Many2many('hr.payroll.structure', 'hrpayroll_rel', 'salary_id', 'colum2_id',string='Salary Structures')
|
||||||
|
level_ids = fields.Many2many('hr.payroll.structure','hrpayroll_rel_str', 'col1', 'col2', string='Salary Levels')
|
||||||
|
group_ids = fields.Many2many('hr.payroll.structure','hrpayroll_rel3', 'col11', 'colid2', string='Salary Degrees')
|
||||||
|
degree_ids = fields.Many2many('hr.payroll.structure','hrpayroll_rel4', 'colid1', 'col22' ,string='Salary Basice')
|
||||||
|
company_id = fields.Many2one('res.company', string="Company", default=lambda self:self.env.company.id)
|
||||||
|
employee_ids = fields.Many2many('hr.employee', string='Employees')
|
||||||
|
no_details = fields.Boolean('No Details' ,default=False)
|
||||||
|
report_type = fields.Selection(
|
||||||
|
[('salary', 'Salary'),
|
||||||
|
('overtime', 'Overtime'),
|
||||||
|
('mission', 'Mission'),
|
||||||
|
('training', 'Training'),
|
||||||
|
('allowance', 'Allowance'),
|
||||||
|
],default='salary', string='Report Type')
|
||||||
|
entry_type = fields.Selection(
|
||||||
|
[('all', 'ALL'),
|
||||||
|
('posted', 'Post'),
|
||||||
|
('unposted', 'Un Post'),
|
||||||
|
], default='all', string='Entry Type')
|
||||||
|
bank_type = fields.Selection(
|
||||||
|
[('rajhi', 'Al-Rajhi Bank'),
|
||||||
|
('alahli', 'Al-Ahli Bank'),
|
||||||
|
('riyadh', 'Al-Riyadh Bank'),
|
||||||
|
], default='rajhi', string='Select Bank')
|
||||||
|
|
||||||
|
@api.onchange('date_from')
|
||||||
|
def onchange_date_from(self):
|
||||||
|
if self.date_from :
|
||||||
|
self.date_to = fields.Date.from_string(self.date_from)+relativedelta(months=+1, day=1, days=-1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def print_pdf_report(self):
|
||||||
|
self.ensure_one()
|
||||||
|
[data] = self.read()
|
||||||
|
date_from = self.date_from
|
||||||
|
date_to = self.date_to
|
||||||
|
employees = self.env['hr.employee'].search([('id', 'in', self.employee_ids.ids)])
|
||||||
|
banks = self.env['res.bank'].search([('id', 'in', self.bank_ids.ids)])
|
||||||
|
salary = self.env['hr.payroll.structure'].search([('id', 'in', self.salary_ids.ids)])
|
||||||
|
no_details =self.no_details
|
||||||
|
report_type = self.report_type
|
||||||
|
entry_type = self.entry_type
|
||||||
|
bank_type = self.bank_type
|
||||||
|
company_id = self.env['res.company'].search([('id', '=', self.company_id.id)])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
datas = {
|
||||||
|
'employees': employees.ids,
|
||||||
|
'banks': banks.ids,
|
||||||
|
'salary': salary.ids,
|
||||||
|
'form': data,
|
||||||
|
'date_from': date_from,
|
||||||
|
'date_to': date_to,
|
||||||
|
'no_details': no_details,
|
||||||
|
'report_type': report_type,
|
||||||
|
'entry_type': entry_type,
|
||||||
|
'bank_type': bank_type,
|
||||||
|
'company_id': company_id,
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.env.ref('exp_payroll_custom.bank_payslip_report').report_action(self, data=datas)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def print_report(self):
|
||||||
|
[data] = self.read()
|
||||||
|
date_from = self.date_from
|
||||||
|
date_to = self.date_to
|
||||||
|
no_details=self.no_details
|
||||||
|
report_type=self.report_type
|
||||||
|
entry_type=self.entry_type
|
||||||
|
bank_type=self.bank_type
|
||||||
|
employees = self.env['hr.employee'].search([('id', 'in', self.employee_ids.ids)])
|
||||||
|
banks = self.env['res.bank'].search([('id', 'in', self.bank_ids.ids)])
|
||||||
|
salary = self.env['hr.payroll.structure'].search([('id', 'in', self.salary_ids.ids)])
|
||||||
|
company_id = self.env['res.company'].search([('id', '=', self.company_id.id)])
|
||||||
|
|
||||||
|
|
||||||
|
datas = {
|
||||||
|
'employees': employees.ids,
|
||||||
|
'banks': banks.ids,
|
||||||
|
'salary': salary.ids,
|
||||||
|
'form': data,
|
||||||
|
'date_from': date_from,
|
||||||
|
'date_to': date_to,
|
||||||
|
'no_details': no_details,
|
||||||
|
'report_type': report_type,
|
||||||
|
'entry_type': entry_type,
|
||||||
|
'bank_type': bank_type,
|
||||||
|
'company_id': company_id.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.env.ref('exp_payroll_custom.report_payroll_bank_xlsx').report_action(self,data=datas)
|
||||||
|
|
||||||
|
def print_report_text(self):
|
||||||
|
self.ensure_one()
|
||||||
|
[data] = self.read()
|
||||||
|
date_from = self.date_from.strftime("%B")
|
||||||
|
date_from = self.date_from
|
||||||
|
date_to = self.date_to
|
||||||
|
pay_slip = self.date_from.strftime("%B %Y")
|
||||||
|
employees = self.env['hr.employee'].search([('id', 'in', self.employee_ids.ids)])
|
||||||
|
banks = self.env['res.bank'].search([('id', 'in', self.bank_ids.ids)])
|
||||||
|
salary = self.env['hr.payroll.structure'].search([('id', 'in', self.salary_ids.ids)])
|
||||||
|
no_details = self.no_details
|
||||||
|
report_type = self.report_type
|
||||||
|
entry_type = self.entry_type
|
||||||
|
bank_type = self.bank_type
|
||||||
|
company_id = self.env['res.company'].search([('id', '=', self.company_id.id)])
|
||||||
|
company_hr_no = self.env['res.company'].search([('id', '=', self.company_id.id)]).company_hr_no
|
||||||
|
phone = self.env['res.company'].search([('id', '=', self.company_id.id)]).phone
|
||||||
|
company_pay_no = self.env['res.company'].search([('id', '=', self.company_id.id)]).company_pay_no
|
||||||
|
company_registry = self.env['res.company'].search([('id', '=', self.company_id.id)]).company_registry
|
||||||
|
datestamp = datetime.datetime.now().strftime("%Y/%m/%d")
|
||||||
|
timestamp = datetime.datetime.now().strftime("%H:%M:%S")
|
||||||
|
currency = self.env['res.company'].search([('id', '=', self.company_id.id)]).currency_id.name
|
||||||
|
if self.pay_date:
|
||||||
|
pay_date = self.pay_date
|
||||||
|
else:
|
||||||
|
pay_date = self.date_to
|
||||||
|
if report_type == 'salary':
|
||||||
|
self.salary_type = 'S'
|
||||||
|
elif report_type=='overtime':
|
||||||
|
self.salary_type = 'O'
|
||||||
|
else:
|
||||||
|
self.salary_type='B'
|
||||||
|
salary_type = self.salary_type
|
||||||
|
## Ranom vlaues in report
|
||||||
|
length_of_string = 5
|
||||||
|
length_of_string2 = 4
|
||||||
|
sample = "ABCDEFGHIJKLMNOPQURSTYWXZ0123456789"
|
||||||
|
generated_string1 = ''.join(random.choice(sample) for _ in range(length_of_string))
|
||||||
|
generated_string2 = ''.join(random.choice(sample) for _ in range(length_of_string2))
|
||||||
|
random_char = str(generated_string1)
|
||||||
|
random_char2 = str(generated_string2)
|
||||||
|
|
||||||
|
datas = {
|
||||||
|
'employees': employees.ids,
|
||||||
|
'banks': banks.ids,
|
||||||
|
'salary': salary.ids,
|
||||||
|
'form': data,
|
||||||
|
'date_from':date_from,
|
||||||
|
'date_to': date_to,
|
||||||
|
'no_details': no_details,
|
||||||
|
'report_type': report_type,
|
||||||
|
'entry_type': entry_type,
|
||||||
|
'bank_type': bank_type,
|
||||||
|
'company_id': company_id.english_name,
|
||||||
|
'timestamp': timestamp,
|
||||||
|
'datestamp': datestamp,
|
||||||
|
'currency': currency,
|
||||||
|
'pay_date': pay_date,
|
||||||
|
'salary_type': salary_type,
|
||||||
|
'company_hr_no': company_hr_no,
|
||||||
|
'phone': phone,
|
||||||
|
'company_pay_no': company_pay_no,
|
||||||
|
'company_registry': company_registry,
|
||||||
|
'pay_slip': pay_slip,
|
||||||
|
'random_char': random_char,
|
||||||
|
'random_char2': random_char2,
|
||||||
|
|
||||||
|
}
|
||||||
|
return self.env.ref('exp_payroll_custom.payroll_bank_wiz_report_docx').report_action(self, data=datas)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<!-- Wizard view -->
|
||||||
|
<record id="bank_payroll_report_form" model="ir.ui.view">
|
||||||
|
<field name="name">payroll.bank.wiz.form</field>
|
||||||
|
<field name="model">payroll.bank.wiz</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Bank Payroll Report">
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="date_from" />
|
||||||
|
<field name="no_details" />
|
||||||
|
<field name="bank_type" />
|
||||||
|
<field name="pay_date" />
|
||||||
|
<field name="company_id" groups="base.group_multi_company"
|
||||||
|
readonly="1" />
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="date_to" />
|
||||||
|
<!-- Odoo 18 declarative syntax -->
|
||||||
|
<field name="bank_ids"
|
||||||
|
widget="many2many_tags"
|
||||||
|
required="not no_details"
|
||||||
|
invisible="no_details" />
|
||||||
|
<field name="report_type" />
|
||||||
|
<field name="entry_type" required="1" />
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group col="4" colspan="4">
|
||||||
|
<notebook>
|
||||||
|
<page string="Salary Structures">
|
||||||
|
<group col="4" colspan="4">
|
||||||
|
<field name="salary_ids" domain="[('type','=','scale')]"
|
||||||
|
widget="many2many_tags" colspan="4" />
|
||||||
|
<field name="level_ids"
|
||||||
|
domain="[('type','=','level'),('salary_scale_id','in',salary_ids)]"
|
||||||
|
widget="many2many_tags" colspan="4" />
|
||||||
|
<field name="group_ids"
|
||||||
|
domain="[('type','=','group'),('salary_scale_level_id','in',level_ids)]"
|
||||||
|
widget="many2many_tags" colspan="4" />
|
||||||
|
<field name="degree_ids"
|
||||||
|
domain="[('type','=','degree'),('salary_scale_group_id','in',group_ids)]"
|
||||||
|
widget="many2many_tags" colspan="4" />
|
||||||
|
</group>
|
||||||
|
</page>
|
||||||
|
<page string="Employees">
|
||||||
|
<field name="employee_ids" />
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<button name="print_pdf_report" string="Print PDF" type="object"
|
||||||
|
class="btn-primary" />
|
||||||
|
<button name="print_report" string="Print Excel" type="object"
|
||||||
|
default_focus="1" class="btn-primary" />
|
||||||
|
<button name="print_report_text" string="Print Text" type="object"
|
||||||
|
default_focus="1" class="btn-primary" />
|
||||||
|
<button string="Cancel" class="btn-secondary" special="cancel" />
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Wizard action -->
|
||||||
|
<record id="action_bank_payroll_report" model="ir.actions.act_window">
|
||||||
|
<field name="name">Bank Payslip Report</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">payroll.bank.wiz</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
<field name="view_id" ref="bank_payroll_report_form" />
|
||||||
|
<field name="target">new</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Action placement -->
|
||||||
|
<menuitem action="action_bank_payroll_report"
|
||||||
|
id="menu_bank_payroll_report"
|
||||||
|
name="Bank Payslip Report"
|
||||||
|
parent="exp_payroll_custom.menu_hr_payroll_report" />
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
## -*- coding: utf-8 -*-
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# LCT, Life Connection Technology
|
||||||
|
# Copyright (C) 2019-2020 LCT
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
from odoo.exceptions import ValidationError, UserError
|
||||||
|
|
||||||
|
|
||||||
|
class PayslipMonthlyReport(models.TransientModel):
|
||||||
|
_name = 'payslip.monthly.report'
|
||||||
|
_description = "Payslips Monthly Report"
|
||||||
|
|
||||||
|
date_from = fields.Date(string='Date From', required=True,
|
||||||
|
default=lambda self: date(date.today().year, date.today().month, 1))
|
||||||
|
date_to = fields.Date(string='Date To', required=True,
|
||||||
|
default=lambda self: date(date.today().year, date.today().month, 1) + relativedelta(months=1,
|
||||||
|
days=-1))
|
||||||
|
detailed = fields.Boolean('Detail By Employees', default=False)
|
||||||
|
listed = fields.Boolean('List By Rules', default=False)
|
||||||
|
salary_ids = fields.Many2many('hr.payroll.structure', 'wiz_sal_rel', 'w_id', 'sal_id', string='Salary Structures')
|
||||||
|
level_ids = fields.Many2many('hr.payroll.structure', 'wiz_lvl_rel', 'w_id', 'lvl_id', string='Salary Levels')
|
||||||
|
group_ids = fields.Many2many('hr.payroll.structure', 'wiz_grp_rel', 'w_id', 'grp_id', string='Salary Groups')
|
||||||
|
degree_ids = fields.Many2many('hr.payroll.structure', 'wiz_dgr_rel', 'w_id', 'dgr_id', string='Salary Degrees')
|
||||||
|
rule_ids = fields.Many2many('hr.salary.rule', string='Rules')
|
||||||
|
allow = fields.Boolean('Allowances')
|
||||||
|
deduct = fields.Boolean('Deductions')
|
||||||
|
employee_ids = fields.Many2many('hr.employee', string='Employees')
|
||||||
|
no_rule = fields.Boolean('No Rules', default=False)
|
||||||
|
|
||||||
|
@api.onchange('date_from')
|
||||||
|
def onchange_date_from(self):
|
||||||
|
if self.date_from:
|
||||||
|
self.date_to = fields.Date.from_string(self.date_from) + relativedelta(months=+1, day=1, days=-1)
|
||||||
|
|
||||||
|
@api.onchange('allow', 'deduct')
|
||||||
|
def get_rule(self):
|
||||||
|
domain = (self.allow and self.deduct) and [('category_id.rule_type', 'in', ('allowance', 'deduction')), ] or \
|
||||||
|
self.allow and [('category_id.rule_type', '=', 'allowance'), ] or \
|
||||||
|
self.deduct and [('category_id.rule_type', '=', 'deduction'), ] or []
|
||||||
|
domain += [('appears_on_payslip', '=', True), ('active', '=', True)]
|
||||||
|
return {'domain': {'rule_ids': [('id', 'in', self.env['hr.salary.rule'].search(domain).ids)]}}
|
||||||
|
|
||||||
|
def get_payslip_line(self):
|
||||||
|
domain = [('slip_id.date_from', '>=', self.date_from), ('slip_id.date_to', '<=', self.date_to),
|
||||||
|
('slip_id.state', '!=', 'cancel'), ('appears_on_payslip', '=', True), ]
|
||||||
|
if self.rule_ids:
|
||||||
|
domain += [('salary_rule_id', 'in', self.rule_ids.ids)]
|
||||||
|
if self.allow and self.deduct:
|
||||||
|
domain += [('category_id.rule_type', 'in', ('allowance', 'deduction'))]
|
||||||
|
elif self.deduct:
|
||||||
|
domain += [('salary_rule_id.category_id.rule_type', '=', 'deduction')]
|
||||||
|
elif self.allow:
|
||||||
|
domain += [('salary_rule_id.category_id.rule_type', '=', 'allowance')]
|
||||||
|
if self.employee_ids:
|
||||||
|
domain += [('employee_id', 'in', self.employee_ids.ids)]
|
||||||
|
if self.salary_ids:
|
||||||
|
domain += [('slip_id.struct_id', 'in', self.salary_ids.ids)]
|
||||||
|
if self.level_ids:
|
||||||
|
domain += [('slip_id.level_id', 'in', self.level_ids.ids)]
|
||||||
|
if self.group_ids:
|
||||||
|
domain += [('slip_id.group_id', 'in', self.group_ids.ids)]
|
||||||
|
if self.degree_ids:
|
||||||
|
domain += [('slip_id.degree_id', 'in', self.degree_ids.ids)]
|
||||||
|
return self.env['hr.payslip.line'].search(domain)
|
||||||
|
|
||||||
|
def check_data(self):
|
||||||
|
landscape = False
|
||||||
|
if self.date_from > self.date_to:
|
||||||
|
raise UserError(_('Date From must be less than or equal Date To'))
|
||||||
|
payslip_lines = self.get_payslip_line()
|
||||||
|
if not payslip_lines:
|
||||||
|
raise ValidationError(_('Sorry No Data To Be Printed'))
|
||||||
|
rule_ids = self.no_rule and [0, ] or self.rule_ids and self.rule_ids.ids or \
|
||||||
|
self.env['hr.salary.rule'].search([('appears_on_payslip', '=', True), ('active', '=', True)]).ids
|
||||||
|
rule_ids = list(set(rule_ids) and set([r.id for r in payslip_lines.mapped('salary_rule_id')]))
|
||||||
|
datas = {
|
||||||
|
'ids': rule_ids,
|
||||||
|
'model': 'hr.salary.rule',
|
||||||
|
'payslip_line_ids': [pl.id for pl in payslip_lines],
|
||||||
|
'form': (self.read()[0]),
|
||||||
|
'rule_ids': rule_ids,
|
||||||
|
}
|
||||||
|
ctx = self.env.context.copy()
|
||||||
|
ctx.update({'active_model': 'hr.salary.rule', 'active_ids': rule_ids, })
|
||||||
|
if self.detailed and self.listed:
|
||||||
|
delist = 'tt'
|
||||||
|
emp_ids = self.employee_ids and self.employee_ids.ids or \
|
||||||
|
list(set(r['employee_id'][0] for r in self.env['hr.payslip'].search_read([
|
||||||
|
('date_from', '>=', self.date_from), ('date_to', '<=', self.date_to),
|
||||||
|
('state', '!=', 'cancel')], ['employee_id', ])))
|
||||||
|
emp_ids = list(set(emp_ids) and set([emp.id for emp in payslip_lines.mapped('employee_id')]))
|
||||||
|
datas['ids'] = emp_ids
|
||||||
|
datas['model'] = 'hr.employee'
|
||||||
|
ctx.update({'active_model': 'hr.employee', 'active_ids': emp_ids, })
|
||||||
|
landscape = True
|
||||||
|
elif self.detailed and not self.listed:
|
||||||
|
delist = 'tf'
|
||||||
|
else:
|
||||||
|
delist = 'ff'
|
||||||
|
datas['delist'] = delist
|
||||||
|
return datas, ctx, landscape
|
||||||
|
|
||||||
|
def print_report(self):
|
||||||
|
datas, ctx, lndkp = self.check_data()
|
||||||
|
return self.env.ref('exp_payroll_custom.act_payslip_monthly_report').with_context(
|
||||||
|
ctx, landscape=lndkp).report_action(self, data=datas)
|
||||||
|
|
||||||
|
def print_report_xlsx(self):
|
||||||
|
datas, ctx, lndkp = self.check_data()
|
||||||
|
return self.env.ref('exp_payroll_custom.payslip_monthly_report_xlsx').with_context(
|
||||||
|
ctx).report_action(self, data=datas)
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="payslip_xslx_report_form">
|
||||||
|
<field name="name">payslip.monthly.report.form</field>
|
||||||
|
<field name="model">payslip.monthly.report</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form>
|
||||||
|
<sheet>
|
||||||
|
<group col="4" colspan="2">
|
||||||
|
<field name="date_from" />
|
||||||
|
<field name="detailed" />
|
||||||
|
<field name="date_to" />
|
||||||
|
<!-- Odoo 18 declarative syntax -->
|
||||||
|
<field name="listed" invisible="not detailed" />
|
||||||
|
</group>
|
||||||
|
<group col="4" colspan="4">
|
||||||
|
<notebook>
|
||||||
|
<page string="Salary Structures">
|
||||||
|
<group col="4" colspan="4">
|
||||||
|
<field name="salary_ids" domain="[('type','=','scale')]"
|
||||||
|
widget="many2many_tags" colspan="4" />
|
||||||
|
<field name="level_ids"
|
||||||
|
domain="[('type','=','level'),('salary_scale_id','in',salary_ids)]"
|
||||||
|
widget="many2many_tags" colspan="4" />
|
||||||
|
<field name="group_ids"
|
||||||
|
domain="[('type','=','group'),('salary_scale_level_id','in',level_ids)]"
|
||||||
|
widget="many2many_tags" colspan="4" />
|
||||||
|
<field name="degree_ids"
|
||||||
|
domain="[('type','=','degree'),('salary_scale_group_id','in',group_ids)]"
|
||||||
|
widget="many2many_tags" colspan="4" />
|
||||||
|
</group>
|
||||||
|
</page>
|
||||||
|
<page string="Payroll Items">
|
||||||
|
<group col="6" colspan="2">
|
||||||
|
<field name="allow" />
|
||||||
|
<field name="deduct" />
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="rule_ids" colspan="4" nolabel="1" />
|
||||||
|
</group>
|
||||||
|
</page>
|
||||||
|
<page string="Employees">
|
||||||
|
<field name="employee_ids" />
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
<footer>
|
||||||
|
<button name="print_report" string="Print PDF" type="object"
|
||||||
|
class="btn-primary" />
|
||||||
|
<button name="print_report_xlsx" string="Print Excel" type="object"
|
||||||
|
class="btn-primary" />
|
||||||
|
<button string="Cancel" class="btn-secondary" special="cancel" />
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="payslip_xslx_report_action" model="ir.actions.act_window">
|
||||||
|
<field name="name">Payslips Report</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">payslip.monthly.report</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
<field name="target">new</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem
|
||||||
|
id="menu_hr_payroll_report"
|
||||||
|
name="Reporting"
|
||||||
|
parent="exp_hr_payroll.menu_hr_payroll_root"
|
||||||
|
sequence="90"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<menuitem
|
||||||
|
id="payslip_xslx_report_menu"
|
||||||
|
name="Payslips Report"
|
||||||
|
parent="exp_payroll_custom.menu_hr_payroll_report"
|
||||||
|
action="payslip_xslx_report_action"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
Loading…
Reference in New Issue