Initial commit: Hr packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:50 +02:00
commit 62531cd146
2820 changed files with 1432848 additions and 0 deletions

View file

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import hr_plan_wizard
from . import hr_departure_wizard

View file

@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class HrDepartureWizard(models.TransientModel):
_name = 'hr.departure.wizard'
_description = 'Departure Wizard'
def _get_employee_departure_date(self):
return self.env['hr.employee'].browse(self.env.context['active_id']).departure_date
def _get_default_departure_date(self):
departure_date = False
if self.env.context.get('active_id'):
departure_date = self._get_employee_departure_date()
return departure_date or fields.Date.today()
departure_reason_id = fields.Many2one("hr.departure.reason", default=lambda self: self.env['hr.departure.reason'].search([], limit=1), required=True)
departure_description = fields.Html(string="Additional Information")
departure_date = fields.Date(string="Departure Date", required=True, default=_get_default_departure_date)
employee_id = fields.Many2one(
'hr.employee', string='Employee', required=True,
default=lambda self: self.env.context.get('active_id', None),
)
archive_private_address = fields.Boolean('Archive Private Address', default=True)
def action_register_departure(self):
employee = self.employee_id
if self.env.context.get('toggle_active', False) and employee.active:
employee.with_context(no_wizard=True).toggle_active()
employee.departure_reason_id = self.departure_reason_id
employee.departure_description = self.departure_description
employee.departure_date = self.departure_date
if self.archive_private_address:
# ignore contact links to internal users
private_address = employee.address_home_id
if private_address and private_address.active and not self.env['res.users'].search([('partner_id', '=', private_address.id)]):
private_address.sudo().toggle_active()

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="hr_departure_wizard_view_form" model="ir.ui.view">
<field name="name">hr.departure.wizard.view.form</field>
<field name="model">hr.departure.wizard</field>
<field name="arch" type="xml">
<form>
<sheet>
<h1><field name="employee_id" readonly="1" options="{'no_open': True}"/></h1>
<group>
<group id="info">
<field name="departure_reason_id" options="{'no_edit': True, 'no_create': True, 'no_open': True}"/>
<field name="departure_date"/>
</group>
<group id="action">
<!-- Override invisible="1" when inheriting -->
<div class="o_td_label" id="activities_label" invisible="1">
<span class="o_form_label o_hr_form_label cursor-default">Close Activities</span>
</div>
<!-- Override invisible="1" when inheriting -->
<div class="column" id="activities" invisible="1">
</div>
<separator colspan="2"/>
<div class="o_td_label" id="label_info">
<span class="o_form_label o_hr_form_label cursor-default">HR Info</span>
</div>
<div class="column" id="info">
<div><field name="archive_private_address"/><label for="archive_private_address"/></div>
</div>
</group>
</group>
<group>
<div id="detailed_reason" colspan="2">
<span class="o_form_label o_hr_form_label cursor-default">Detailed Reason</span>
<field name="departure_description"/>
</div>
</group>
</sheet>
<footer>
<button name="action_register_departure" string="Apply" type="object" class="oe_highlight" data-hotkey="q"/>
<button string="Discard" class="btn-secondary" special="cancel" data-hotkey="z"/>
</footer>
</form>
</field>
</record>
<record id="hr_departure_wizard_action" model="ir.actions.act_window">
<field name="name">Register Departure</field>
<field name="res_model">hr.departure.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</odoo>

View file

@ -0,0 +1,127 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class HrPlanWizard(models.TransientModel):
_name = 'hr.plan.wizard'
_description = 'Plan Wizard'
def _default_plan_id(self):
# We know that all employees belong to the same company
employees = self.env['hr.employee'].browse(self.env.context.get('active_ids') if self.env.context.get('active_ids') else [])
if not employees:
return None
if len(employees.department_id) > 1:
return self.env['hr.plan'].search([
('company_id', '=', employees[0].company_id.id),
('department_id', '=', False)
], limit=1)
else:
return self.env['hr.plan'].search([
('company_id', '=', employees[0].company_id.id),
'|',
('department_id', '=', employees[0].department_id.id),
('department_id', '=', False)
], limit=1)
plan_id = fields.Many2one('hr.plan', default=lambda self: self._default_plan_id(),
domain="[('company_id', 'in', [False, company_id]), '|', ('department_id', '=', department_id), ('department_id', '=', False)]")
department_id = fields.Many2one('hr.department', compute='_compute_department_id')
employee_ids = fields.Many2many(
'hr.employee', 'hr_employee_hr_plan_wizard_rel', 'employee_id', 'plan_wizard_id', string='Employee', required=True,
default=lambda self: self.env.context.get('active_ids', []),
)
company_id = fields.Many2one('res.company', 'Company', compute='_compute_company_id', required=True)
warning = fields.Html(compute='_compute_warning')
@api.depends('employee_ids')
def _compute_department_id(self):
for wizard in self:
all_departments = wizard.employee_ids.department_id
wizard.department_id = False if len(all_departments) > 1 else all_departments
@api.constrains('employee_ids')
def _check_employee_companies(self):
for wizard in self:
if len(wizard.employee_ids.mapped('company_id')) > 1:
raise ValidationError(_('The employees should belong to the same company.'))
@api.depends('employee_ids')
def _compute_company_id(self):
for wizard in self:
wizard.company_id = wizard.employee_ids and wizard.employee_ids[0].company_id or self.env.company
def _get_warnings(self):
self.ensure_one()
warnings = set()
for employee in self.employee_ids:
for activity_type in self.plan_id.plan_activity_type_ids:
warning = activity_type.get_responsible_id(employee)['warning']
if warning:
warnings.add(warning)
return warnings
@api.depends('employee_ids', 'plan_id')
def _compute_warning(self):
for wizard in self:
warnings = wizard._get_warnings()
if warnings:
warning_display = _('The plan %s cannot be launched: <br><ul>', wizard.plan_id.name)
for warning in warnings:
warning_display += '<li>%s</li>' % warning
warning_display += '</ul>'
else:
warning_display = False
wizard.warning = warning_display
def _get_activities_to_schedule(self):
return self.plan_id.plan_activity_type_ids
def action_launch(self):
self.ensure_one()
for employee in self.employee_ids:
body = _('The plan %s has been started', self.plan_id.name)
activities = set()
for activity_type in self._get_activities_to_schedule():
responsible = activity_type.get_responsible_id(employee)['responsible']
if self.env['hr.employee'].with_user(responsible).check_access_rights('read', raise_exception=False):
date_deadline = self.env['mail.activity']._calculate_date_deadline(activity_type.activity_type_id)
employee.activity_schedule(
activity_type_id=activity_type.activity_type_id.id,
summary=activity_type.summary,
note=activity_type.note,
user_id=responsible.id,
date_deadline=date_deadline
)
activity = _('%(activity)s, assigned to %(name)s, due on the %(deadline)s', activity=activity_type.summary, name=responsible.name, deadline=date_deadline)
activities.add(activity)
if activities:
body += '<ul>'
for activity in activities:
body += '<li>%s</li>' % activity
body += '</ul>'
employee.message_post(body=body)
if len(self.employee_ids) == 1:
return {
'type': 'ir.actions.act_window',
'res_model': 'hr.employee',
'res_id': self.employee_ids.id,
'name': self.employee_ids.display_name,
'view_mode': 'form',
'views': [(False, "form")],
}
return {
'type': 'ir.actions.act_window',
'res_model': 'hr.employee',
'name': _('Launch Plans'),
'view_mode': 'tree,form',
'target': 'current',
'domain': [('id', 'in', self.employee_ids.ids)],
}

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="plan_wizard" model="ir.ui.view">
<field name="name">plan wizard</field>
<field name="model">hr.plan.wizard</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="department_id" attrs="{'invisible': [('department_id', '=', False)]}"/>
<field name="plan_id"/>
<field name="employee_ids" invisible="1"/>
<field name="company_id" invisible="1"/>
</group>
<div role="alert" class="alert alert-danger mb8" attrs="{'invisible': [('warning', '=', False)]}">
<field name="warning"/>
</div>
</sheet>
<footer>
<button name="action_launch" string="Launch Plan" type="object" class="oe_highlight" attrs="{'invisible': [('warning', '!=', False)]}" groups="hr.group_hr_user" data-hotkey="q"/>
<button name="action_launch" string="Launch Plan" type="object" class="oe_highlight disabled" attrs="{'invisible': [('warning', '=', False)]}" groups="hr.group_hr_user" data-hotkey="q"/>
<button string="Cancel" class="btn-secondary" special="cancel" data-hotkey="z"/>
</footer>
</form>
</field>
</record>
<record id="plan_wizard_action" model="ir.actions.act_window">
<field name="name">Launch Plan</field>
<field name="res_model">hr.plan.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</odoo>