manage career from contract

This commit is contained in:
Florian du Garage Num 2024-03-19 20:55:51 +01:00
parent f9b8002b8e
commit 5bd07b645b
6 changed files with 86 additions and 36 deletions

View File

@ -10,7 +10,7 @@ Addons for Odoo 16.
| gn_l10n_fr_pcg_asso | 16.0.0.0.3 | French chart of account and fiscal position for NGO's |
| gn_cc | 16.0.0.0.2 | Configuration for French convention collective, with data for IDCC3442 |
| gn_holidays | 16.0.0.0.1 | French configuration for Publics Holidays and Leave Management |
| gn_career | 16.0.0.0.10 | Fiche de poste et évolution de carrière |
| gn_career | 16.0.0.0.11 | Fiche de poste et évolution de carrière |
| gn_contract | 16.0.0.0.4 | Amendements to Hr Contracts |
## ToDo

View File

@ -10,6 +10,8 @@ Module de gestion des fiches de postes et des évolutions de carrière
## Changelog
- v16.0.0.0.11 (2024/03/19):
- clean gn_contract.py code and create action_manage_career_button
- v16.0.0.0.10 (2024/03/18):
- constrains task selection in mission detail
- v16.0.0.0.9 (2024/03/17):
@ -37,4 +39,6 @@ Module de gestion des fiches de postes et des évolutions de carrière
- [] Review total_percentage constraints
- [] Review domains and unicity for tasks and missions in models (constraints)
- [] clean and prune methods
- [] ensure cascade deletion
- [] ensure cascade deletion
- [] create gn_career.career.tree view
- [] find some mechanisms to ensure career's state is updated. It is neccesary for contract's method action_manage_career.

View File

@ -1,6 +1,6 @@
{
"name": "France - Fiche de poste",
"version": "16.0.0.0.10",
"version": "16.0.0.0.11",
"category": "HR",
"summary": "Configuration de la fiche de poste et de son évolution conventionnelle",
"author": "Le Garage Numérique",

View File

@ -14,7 +14,7 @@ class GnCareer(models.Model):
name = fields.Char("Nom", compute='_compute_name')
start_date = fields.Date('From', required=True, default=lambda self: fields.Date.today())
contract_id = fields.Many2one('hr.contract', string="Contrat ou Avenant associé")
contract_id = fields.Many2one('hr.contract', string="Contrat ou Avenant associé", ondelete='cascade')
employee_id = fields.Many2one(string="Employee", related='contract_id.employee_id', readonly=True, store=True)
associated_careers_count = fields.Integer(compute='_compute_associated_careers_count', store=True)
@ -25,7 +25,7 @@ class GnCareer(models.Model):
('wait_employee_approval', "En attente de signature par le salarié"),
('ready', 'Prête'),
('active', 'Active'),
], string="État", default='draft')
], string="État", default='draft', required=True)
mission_ids = fields.Many2many('gn_career.mission', 'career_ids', compute='_compute_mission_ids', string="Missions effectuées", store=True)
mission_detail_ids = fields.One2many('gn_career.mission.detail', 'career_id', string="Détail de la mission")

View File

@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models, api
from datetime import datetime
from odoo.exceptions import ValidationError
import logging
@ -13,12 +14,6 @@ class GnCareerContract(models.Model):
career_ids = fields.One2many("gn_career.career", 'contract_id',
string="Analyses du poste")
@api.constrains('career_ids')
def _check_unique_career(self):
for record in self:
if len(record.career_ids) > 1:
raise ValidationError("Each contract can only have one career associated with it.")
def open_associated_careers(self):
_logger.warning("Open Active Career called on records: %s", self)
self.ensure_one() # Ensure that the method is called on a single record
@ -34,31 +29,77 @@ class GnCareerContract(models.Model):
}
return action
def action_open_career(self):
def action_manage_career(self):
self.ensure_one()
if self.career_ids:
active_careers = self.career_ids.filtered(lambda c: c.start_date <= fields.Date.today() and c.state != 'draft')
latest_career = active_careers.sorted(key=lambda c: c.start_date, reverse=True)[:1]
if latest_career:
action = {
'type': 'ir.actions.act_window',
"views": [[False, "form"]],
'res_model': 'gn_career.career',
'res_id': latest_career.id,
'target': 'current',
}
else:
latest_draft_career = self.career_ids.filtered(lambda c: c.state == 'draft').sorted(key=lambda c: c.start_date, reverse=True)[:1]
if latest_draft_career:
action = {
'type': 'ir.actions.act_window',
"views": [[False, "form"]],
'res_model': 'gn_career.career',
'res_id': latest_draft_career.id,
'target': 'current',
}
else:
raise UserError("Il semble y avoir un problème avec les fiches de poste associées au contrat. Accédez au menu 'Employés > Fiches de Poste' pour accéder manuellement à la fiche de poste")
else:
action = {
'type': 'ir.actions.act_window',
"views": [[False, "form"]],
'name': 'Définir la fiche de poste',
'view_mode': 'form',
'res_model': 'gn_career.career',
'res_id': self.career_ids[0].id, # ID of the career to open
'context': {
'default_contract_id': self.id,
'default_employee_id': self.employee_id.id,
'default_start_date': self.date_validity_start or self.date_start,
},
'target': 'current',
}
return action
}
return action
def action_define_career(self):
_logger.warning("Enter in action_define_career for contracts'id %s", self.id)
self.ensure_one()
action = {
'type': 'ir.actions.act_window',
'name': 'Définir la fiche de poste',
'view_mode': 'form',
'res_model': 'gn_career.career',
'context': {
'default_contract_id': self.id,
'default_employee_id': self.employee_id.id,
'default_start_date': self.date_validity_start or self.date_start,
},
'target': 'current',
}
return action
# def action_open_career(self):
# self.ensure_one()
# if self.career_ids:
# valid_careers = self.career_ids.filtered(lambda c: c.start_date and c.start_date <= fields.Date.today())
# latest_career = valid_careers.sorted(key=lambda c: c.start_date, reverse=True)[:1]
# if latest_career:
# action = {
# 'type': 'ir.actions.act_window',
# "views": [[False, "form"]],
# 'res_model': 'gn_career.career',
# 'res_id': latest_career.id,
# 'target': 'current',
# }
# return action
# def action_define_career(self):
# _logger.warning("Enter in action_define_career for contracts'id %s", self.id)
# self.ensure_one()
# action = {
# 'type': 'ir.actions.act_window',
# 'name': 'Définir la fiche de poste',
# 'view_mode': 'form',
# 'res_model': 'gn_career.career',
# 'context': {
# 'default_contract_id': self.id,
# 'default_employee_id': self.employee_id.id,
# 'default_start_date': self.date_validity_start or self.date_start,
# },
# 'target': 'current',
# }
# return action

View File

@ -7,17 +7,22 @@
<field name="inherit_id" ref="hr_contract.hr_contract_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='button_box']" position="inside">
<field name="career_ids" invisible="1"/>
<button name="action_open_career" type='object' class="oe_stat_button"
<!--<field name="career_ids" invisible="1"/>-->
<button name="action_manage_career" type="object" class="oe_stat_button"
icon="fa-pencil-square-o" groups="hr_contract.group_hr_contract_manager"
string="Gérer la fiche de poste"/>
<!--<button name="action_open_career" type='object' class="oe_stat_button"
icon="fa-money" groups="hr_contract.group_hr_contract_manager"
attrs="{'invisible': [('career_ids', '=', [])]}"
string="Voir la fiche de poste">
string="Fiche de poste active">
</button>
<button name="action_define_career" type="object" class="oe_stat_button"
icon="fa-pencil" groups="hr_contract.group_hr_contract_manager"
attrs="{'invisible': [('career_ids', '!=', [])]}"
string="Définir la fiche de poste">
</button>
</button> -->
</xpath>
</field>
</record>