make scal stages

This commit is contained in:
mohammed-alkhazrji 2025-07-15 23:51:14 +03:00
parent 62acf4e8b8
commit 8182ef9c76
8 changed files with 522 additions and 8 deletions

View File

@ -187,3 +187,99 @@ msgstr ""
msgid "محجوب"
msgstr ""
#. module: helpdesk_employee_request
#: code:addons/helpdesk_employee_request/models/helpdesk.py:0
msgid "No previous stage is configured for this ticket!"
msgstr "لا توجد مرحلة سابقة مهيئة لهذه التذكرة!"
#. module: helpdesk_employee_request
#: code:addons/helpdesk_employee_request/models/helpdesk.py:0
#, python-format
msgid "Only members of the '%s' group can approve this stage."
msgstr "فقط أعضاء مجموعة '%s' يمكنهم اعتماد هذه المرحلة."
#. module: helpdesk_employee_request
#: code:addons/helpdesk_employee_request/models/helpdesk.py:0
msgid "Only the employee's manager can approve this stage."
msgstr "فقط مدير الموظف يمكنه اعتماد هذه المرحلة."
#. module: helpdesk_employee_request
#: code:addons/helpdesk_employee_request/models/helpdesk.py:0
#, python-format
msgid "Only '%s' can approve this stage."
msgstr "فقط '%s' يمكنه اعتماد هذه المرحلة."
#. module: helpdesk_employee_request
#: code:addons/helpdesk_employee_request/models/helpdesk.py:0
msgid "Employee not found based on partner_id."
msgstr "الموظف غير موجود بناءً على partner_id."
#. module: helpdesk_employee_request
#: code:addons/helpdesk_employee_request/models/helpdesk.py:0
msgid "You cannot proceed to the previous stage because you are not the employee linked to this ticket."
msgstr "لا يمكنك الانتقال إلى المرحلة السابقة لأنك لست الموظف المرتبط بهذه التذكرة."
#. module: helpdesk_employee_request
#: code:addons/helpdesk_employee_request/models/helpdesk.py:0
msgid "No final rejection stage is defined within the team's stages."
msgstr "لا توجد مرحلة رفض نهائي محددة ضمن مراحل الفريق."
#. module: helpdesk_employee_request
#: code:addons/helpdesk_employee_request/models/helpdesk.py:0
msgid "No next stage is configured for this ticket!"
msgstr "لا توجد مرحلة تالية مهيئة لهذه التذكرة!"
#. module: helpdesk_employee_request
#: code:addons/helpdesk_employee_request/models/helpdesk.py:0
msgid "You cannot proceed to the next stage because you are not the employee linked to this ticket."
msgstr "لا يمكنك الانتقال إلى المرحلة التالية لأنك لست الموظف المرتبط بهذه التذكرة."
#. module: helpdesk_employee_request
#: model_terms:ir.ui.view,arch_db:helpdesk_employee_request.odex25_helpdesk_ticket_vip_view_form
#: model_terms:ir.ui.view,arch_db:helpdesk_employee_request.ticket_request_view_form
msgid "Send"
msgstr "إرسال"
#. module: helpdesk_employee_request
#: model_terms:ir.ui.view,arch_db:helpdesk_employee_request.odex25_helpdesk_ticket_vip_view_form
#: model_terms:ir.ui.view,arch_db:helpdesk_employee_request.ticket_request_view_form
msgid "Previous"
msgstr "السابق"
#. module: helpdesk_employee_request
#: model_terms:ir.ui.view,arch_db:helpdesk_employee_request.odex25_helpdesk_ticket_vip_view_form
#: model_terms:ir.ui.view,arch_db:helpdesk_employee_request.ticket_request_view_form
msgid "Rejection"
msgstr "رفض"

View File

@ -6,6 +6,7 @@ from lxml import etree
import json
import simplejson
import logging
from odoo.exceptions import UserError, ValidationError
_logger = logging.getLogger(__name__)
@ -38,7 +39,9 @@ class HelpdeskTicket(models.Model):
('vip', 'VIP'),
('request', 'Request'),
('secretary', 'Secretary')])
show_button_next = fields.Boolean(related='stage_id.show_button_next', store=True)
show_button_previous = fields.Boolean(related='stage_id.show_button_previous', store=True)
show_button_rejection = fields.Boolean(related='stage_id.final_rejection', store=True)
@api.model
def create(self, vals):
"""
@ -78,3 +81,113 @@ class HelpdeskTicket(models.Model):
self.partner_email = self.partner_id.email
res = {'domain': {'partner_id': [('id', '=', [self.requester_id.partner_id.id])]}}
return res
def _resolve_next_stage(self):
"""Return the best next stage according to the following order:
1) If `next_stage` is set and unique -> use it.
2) If there are multiple -> take the first one that intersects with the team's stages.
3) If not set -> use the first stage with a higher sequence than the current one within the team.
"""
self.ensure_one()
if self.stage_id.employee_created:
if self.partner_id != self.env.user.partner_id:
raise ValidationError(
_("You cannot proceed to the next stage because you are not the employee linked to this ticket."))
if self.stage_id.manager_approved:
employee = self.env['hr.employee'].search([('user_partner_id', '=', self.partner_id.id)], limit=1)
if not employee:
raise ValidationError(_("Employee not found based on partner_id."))
if employee.parent_id.user_id != self.env.user:
raise ValidationError(_("Only the employee's manager can approve this stage."))
if self.stage_id.needs_approval:
if self.stage_id.is_group_approver:
group_ext_id = self.env['ir.model.data'].search([
('model', '=', 'res.groups'),
('res_id', '=', self.stage_id.group_id.id)
], limit=1).complete_name
if not self.env.user.has_group(group_ext_id):
raise ValidationError(
_("Only members of the '%s' group can approve this stage.") % self.stage_id.group_id.name)
else:
if self.stage_id.user_id != self.env.user:
raise ValidationError(_("Only '%s' can approve this stage.") % self.stage_id.user_id.name)
stages = self.team_id.stage_ids.sorted(key=lambda s: s.sequence)
for st in stages:
if st.sequence > self.stage_id.sequence:
return st
return False
# --------------------------------------------------
# Action Buttons
# --------------------------------------------------
def action_confirm(self):
for ticket in self:
next_stage = ticket._resolve_next_stage()
if not next_stage:
raise ValidationError(_("No next stage is configured for this ticket!"))
ticket.stage_id = next_stage
def action_rejection(self):
self.ensure_one()
rejection_stage = self.team_id.stage_ids.filtered(lambda s: s.final_rejection_stage)
if rejection_stage:
self.stage_id = rejection_stage[0]
else:
raise ValidationError(_("No final rejection stage is defined within the team's stages."))
# --------------------------------------------------
# Override write to mark is_submitted when closing
# --------------------------------------------------
def write(self, vals):
if vals.get('stage_id'):
new_stage = self.env['odex25_helpdesk.stage'].browse(vals['stage_id'])
if new_stage.is_close:
vals['is_submitted'] = True
return super().write(vals)
def _resolve_previous_stage(self):
self.ensure_one()
if self.stage_id.employee_created:
if self.partner_id != self.env.user.partner_id:
raise ValidationError(
_("You cannot proceed to the Previous stage because you are not the employee linked to this ticket."))
if self.stage_id.manager_approved:
employee = self.env['hr.employee'].search([('user_partner_id', '=', self.partner_id.id)], limit=1)
if not employee:
raise ValidationError(_("Employee not found based on partner_id."))
if employee.parent_id.user_id != self.env.user:
raise ValidationError(_("Only the employee's manager can Previous this stage."))
if self.stage_id.needs_approval:
if self.stage_id.is_group_approver:
group_ext_id = self.env['ir.model.data'].search([
('model', '=', 'res.groups'),
('res_id', '=', self.stage_id.group_id.id)
], limit=1).complete_name
if not self.env.user.has_group(group_ext_id):
raise ValidationError(
_("Only members of the '%s' group can approve this stage.") % self.stage_id.group_id.name)
else:
if self.stage_id.user_id != self.env.user:
raise ValidationError(_("Only '%s' can approve this stage.") % self.stage_id.user_id.name)
stages = self.team_id.stage_ids.sorted(key=lambda s: s.sequence, reverse=True)
for st in stages:
if st.sequence < self.stage_id.sequence:
return st
return False
def action_back(self):
for ticket in self:
prev_stage = ticket._resolve_previous_stage()
if not prev_stage:
raise ValidationError(_("No previous stage is configured for this ticket!"))
ticket.stage_id = prev_stage

View File

@ -41,8 +41,17 @@
<field name="arch" type="xml">
<form string="Helpdesk Ticket">
<header>
<field name="stage_id" widget="statusbar" attrs="{'clickable':[('requester_id','!=',False)]}"
options="{'fold_field': 'fold'}"/>
<field name="show_button_next" invisible="1"/>
<field name="show_button_previous" invisible="1"/>
<field name="show_button_rejection" invisible="1"/>
<field name="stage_id" widget="statusbar" options="{'fold_field': 'fold'}" readonly="1"/>
<button name="action_confirm" string="Send" type="object" class="btn-primary"
attrs="{'invisible': [('show_button_next', '=', False)]}" />
<button name="action_back" string="Previous" type="object" class="btn-secondary" attrs="{'invisible': [('show_button_previous', '=', False)]}"/>
<button name="action_rejection" string="Rejection" type="object" class="btn-primary"
attrs="{'invisible': [('show_button_rejection', '=', False)]}" />
</header>
<sheet>
<div class="oe_title">
@ -83,8 +92,18 @@
<field name="arch" type="xml">
<form string="Helpdesk Ticket">
<header>
<field name="stage_id" widget="statusbar" attrs="{'clickable':[('requester_id','!=',False)]}"
options="{'fold_field': 'fold'}"/>
<field name="show_button_next" invisible="1"/>
<field name="show_button_previous" invisible="1"/>
<field name="show_button_rejection" invisible="1"/>
<field name="stage_id" widget="statusbar" options="{'fold_field': 'fold'}" readonly="1"/>
<button name="action_confirm" string="Send" type="object" class="btn-primary"
attrs="{'invisible': [('show_button_next', '=', False)]}" />
<button name="action_back" string="Previous" type="object" class="btn-secondary" attrs="{'invisible': [('show_button_previous', '=', False)]}"/>
<button name="action_rejection" string="Rejection" type="object" class="btn-primary"
attrs="{'invisible': [('show_button_rejection', '=', False)]}" />
</header>
<sheet>
<div class="oe_title">
@ -94,6 +113,7 @@
</div>
<group>
<group>
<field name="requester_id" invisible="1"/>
<field name="is_submitted" invisible="1"/>
<field name="active" invisible="1"/>

View File

@ -39,7 +39,7 @@ Features:
'data': [
'security/odex25_helpdesk_security.xml',
'security/ir.model.access.csv',
'data/digest_data.xml',
# 'data/digest_data.xml',
'data/mail_data.xml',
# 'data/odex25_helpdesk_data.xml',
'views/odex25_helpdesk_views.xml',

View File

@ -3487,3 +3487,120 @@ msgstr "نيابة عن المستخدم"
msgid "Phone Number"
msgstr "رقم الهاتف"
#. module: odex25_helpdesk
#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__manager_approved
msgid "Direct Manager Approved"
msgstr "إعتماد المدير المباشر"
#. module: odex25_helpdesk
#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__final_rejection
#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_ticket__show_button_rejection
msgid "Final Rejection"
msgstr "الرفض النهائي"
#. module: odex25_helpdesk
#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__final_rejection_stage
msgid "Final Rejection Stage"
msgstr "مرحلة الرفض النهائي"
#. module: odex25_helpdesk
#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__show_button_next
#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_ticket__show_button_next
msgid "Show Next Stage Button"
msgstr "إظهار زر المرحلة التالية"
#. module: odex25_helpdesk
#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__show_button_previous
#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_ticket__show_button_previous
msgid "Show Previous Stage Button"
msgstr "إظهار زر المرحلة السابقة"
#. module: odex25_helpdesk
#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__employee_created
msgid "Employee Created"
msgstr "تم إنشاء الموظف"
#. module: odex25_helpdesk
#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__group_id
msgid "Approver Group"
msgstr "مجموعة صاحب الصلاحية"
#. module: odex25_helpdesk
#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__user_id
msgid "Approver User"
msgstr "صاحب الاعتماد"
#. module: odex25_helpdesk
#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__is_group_approver
msgid "Is Group Approver?"
msgstr "هل صاحب الصلاحية مجموعة؟"
#. module: odex25_helpdesk
#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__needs_approval
msgid "Requires Approval?"
msgstr "هل تحتاج إلى موافقة؟"
#. module: odex25_helpdesk
#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0
msgid "No previous stage is configured for this ticket!"
msgstr "لا توجد مرحلة سابقة مهيئة لهذه التذكرة!"
#. module: odex25_helpdesk
#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0
#, python-format
msgid "Only members of the '%s' group can approve this stage."
msgstr "فقط أعضاء مجموعة '%s' يمكنهم اعتماد هذه المرحلة."
#. module: odex25_helpdesk
#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0
msgid "Only the employee's manager can approve this stage."
msgstr "فقط مدير الموظف يمكنه اعتماد هذه المرحلة."
#. module: odex25_helpdesk
#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0
#, python-format
msgid "Only '%s' can approve this stage."
msgstr "فقط '%s' يمكنه اعتماد هذه المرحلة."
#. module: odex25_helpdesk
#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0
msgid "Employee not found based on partner_id."
msgstr "الموظف غير موجود بناءً على partner_id."
#. module: odex25_helpdesk
#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0
msgid "You cannot proceed to the previous stage because you are not the employee linked to this ticket."
msgstr "لا يمكنك الانتقال إلى المرحلة السابقة لأنك لست الموظف المرتبط بهذه التذكرة."
#. module: odex25_helpdesk
#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0
msgid "No final rejection stage is defined within the team's stages."
msgstr "لا توجد مرحلة رفض نهائي محددة ضمن مراحل الفريق."
#. module: odex25_helpdesk
#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0
msgid "No next stage is configured for this ticket!"
msgstr "لا توجد مرحلة تالية مهيئة لهذه التذكرة!"
#. module: odex25_helpdesk
#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0
msgid "You cannot proceed to the next stage because you are not the employee linked to this ticket."
msgstr "لا يمكنك الانتقال إلى المرحلة التالية لأنك لست الموظف المرتبط بهذه التذكرة."
#. module: odex25_helpdesk
#: model_terms:ir.ui.view,arch_db:odex25_helpdesk.odex25_helpdesk_ticket_view_form
msgid "Send"
msgstr "إرسال"
#. module: odex25_helpdesk
#: model_terms:ir.ui.view,arch_db:odex25_helpdesk.odex25_helpdesk_ticket_view_form
msgid "Previous"
msgstr "السابق"
#. module: odex25_helpdesk
#: model_terms:ir.ui.view,arch_db:odex25_helpdesk.odex25_helpdesk_ticket_view_form
msgid "Rejection"
msgstr "رفض"

View File

@ -462,6 +462,25 @@ class odex25_helpdeskStage(models.Model):
'Grey Kanban Label', default=lambda s: _('In Progress'), translate=True, required=True,
help='Override the default value displayed for the normal state for kanban selection, when the task or issue is in that stage.')
needs_approval = fields.Boolean(string="Requires Approval?")
is_group_approver = fields.Boolean(string="Is Group Approver?")
user_id = fields.Many2one('res.users', string="Approver User")
group_id = fields.Many2one('res.groups', string="Approver Group")
show_button_next = fields.Boolean(string="Show Next Stage Button")
show_button_previous = fields.Boolean(string="Show Previous Stage Button")
employee_created = fields.Boolean(string="Employee Created")
manager_approved = fields.Boolean(string="Direct Manager Approved")
final_rejection = fields.Boolean(
string="Final Rejection",
default=False,
help="Indicates whether this stage represents the final rejection of the ticket."
)
final_rejection_stage = fields.Boolean(
string="Final Rejection Stage",
help="Mark this stage as the final rejection stage."
)
def unlink(self):
stages = self
default_team_id = self.env.context.get('default_team_id')

View File

@ -7,6 +7,7 @@ from random import randint
from odoo import api, fields, models, tools, _
from odoo.osv import expression
from odoo.exceptions import AccessError
from odoo.exceptions import UserError, ValidationError
TICKET_PRIORITY = [
('0', 'All'),
@ -318,6 +319,9 @@ class odex25_helpdeskTicket(models.Model):
on_behalf = fields.Many2one('hr.employee', string="On behalf of")
emp_req = fields.Boolean(default=False)
schedule_date = fields.Datetime("Scheduled Date")
show_button_next = fields.Boolean(related='stage_id.show_button_next', store=True)
show_button_previous = fields.Boolean(related='stage_id.show_button_previous', store=True)
show_button_rejection = fields.Boolean(related='stage_id.final_rejection', store=True)
@api.onchange('service_id')
def _onchange_invoice_date(self):
@ -968,3 +972,113 @@ class odex25_helpdeskTicket(models.Model):
def _rating_get_parent_field_name(self):
return 'team_id'
def _resolve_next_stage(self):
"""Return the best next stage according to the following order:
1) If `next_stage` is set and unique -> use it.
2) If there are multiple -> take the first one that intersects with the team's stages.
3) If not set -> use the first stage with a higher sequence than the current one within the team.
"""
self.ensure_one()
if self.stage_id.employee_created:
if self.partner_id != self.env.user.partner_id:
raise ValidationError(
_("You cannot proceed to the next stage because you are not the employee linked to this ticket."))
if self.stage_id.manager_approved:
employee = self.env['hr.employee'].search([('user_partner_id', '=', self.partner_id.id)], limit=1)
if not employee:
raise ValidationError(_("Employee not found based on partner_id."))
if employee.parent_id.user_id != self.env.user:
raise ValidationError(_("Only the employee's manager can approve this stage."))
if self.stage_id.needs_approval:
if self.stage_id.is_group_approver:
group_ext_id = self.env['ir.model.data'].search([
('model', '=', 'res.groups'),
('res_id', '=', self.stage_id.group_id.id)
], limit=1).complete_name
if not self.env.user.has_group(group_ext_id):
raise ValidationError(
_("Only members of the '%s' group can approve this stage.") % self.stage_id.group_id.name)
else:
if self.stage_id.user_id != self.env.user:
raise ValidationError(_("Only '%s' can approve this stage.") % self.stage_id.user_id.name)
stages = self.team_id.stage_ids.sorted(key=lambda s: s.sequence)
for st in stages:
if st.sequence > self.stage_id.sequence:
return st
return False
# --------------------------------------------------
# Action Buttons
# --------------------------------------------------
def action_confirm(self):
for ticket in self:
next_stage = ticket._resolve_next_stage()
if not next_stage:
raise ValidationError(_("No next stage is configured for this ticket!"))
ticket.stage_id = next_stage
def action_rejection(self):
self.ensure_one()
rejection_stage = self.team_id.stage_ids.filtered(lambda s: s.final_rejection_stage)
if rejection_stage:
self.stage_id = rejection_stage[0]
else:
raise ValidationError(_("No final rejection stage is defined within the team's stages."))
# --------------------------------------------------
# Override write to mark is_submitted when closing
# --------------------------------------------------
def write(self, vals):
if vals.get('stage_id'):
new_stage = self.env['odex25_helpdesk.stage'].browse(vals['stage_id'])
if new_stage.is_close:
vals['is_submitted'] = True
return super().write(vals)
def _resolve_previous_stage(self):
self.ensure_one()
if self.stage_id.employee_created:
if self.partner_id != self.env.user.partner_id:
raise ValidationError(
_("You cannot proceed to the Previous stage because you are not the employee linked to this ticket."))
if self.stage_id.manager_approved:
employee = self.env['hr.employee'].search([('user_partner_id', '=', self.partner_id.id)], limit=1)
if not employee:
raise ValidationError(_("Employee not found based on partner_id."))
if employee.parent_id.user_id != self.env.user:
raise ValidationError(_("Only the employee's manager can Previous this stage."))
if self.stage_id.needs_approval:
if self.stage_id.is_group_approver:
group_ext_id = self.env['ir.model.data'].search([
('model', '=', 'res.groups'),
('res_id', '=', self.stage_id.group_id.id)
], limit=1).complete_name
if not self.env.user.has_group(group_ext_id):
raise ValidationError(
_("Only members of the '%s' group can approve this stage.") % self.stage_id.group_id.name)
else:
if self.stage_id.user_id != self.env.user:
raise ValidationError(_("Only '%s' can approve this stage.") % self.stage_id.user_id.name)
stages = self.team_id.stage_ids.sorted(key=lambda s: s.sequence, reverse=True)
for st in stages:
if st.sequence < self.stage_id.sequence:
return st
return False
def action_back(self):
for ticket in self:
prev_stage = ticket._resolve_previous_stage()
if not prev_stage:
raise ValidationError(_("No previous stage is configured for this ticket!"))
ticket.stage_id = prev_stage

View File

@ -125,6 +125,32 @@
</p>
<field name="description" placeholder="Add a description..." nolabel="1" colspan="2"/>
</group>
<group string="Stage" >
<field name="final_rejection_stage"/>
</group>
<group string="Administrative Actions" attrs="{'invisible': [('final_rejection_stage', '=', True)]}" >
<field name="employee_created"/>
<field name="manager_approved"/>
<field name="show_button_next"/>
<field name="show_button_previous"/>
<field name="final_rejection"/>
</group>
<group string="You can control the stage navigation according to your needs."
attrs="{'invisible': ['|', ('final_rejection_stage', '=', True), '|', ('employee_created', '=', True), ('manager_approved', '=', True)]}">
<field name="needs_approval"/>
<field name="is_group_approver"
attrs="{'invisible': [('needs_approval', '=', False)]}"/>
<field name="user_id"
attrs="{'invisible': ['|', ('needs_approval', '=', False), ('is_group_approver', '=', True)]}"/>
<field name="group_id" attrs="{'invisible': [('is_group_approver', '=', False)]}"/>
</group>
</sheet>
</form>
</field>
@ -548,12 +574,21 @@
<field name="arch" type="xml">
<form string="Helpdesk Ticket">
<header>
<field name="show_button_next" invisible="1"/>
<field name="is_self_assigned" invisible="1"/>
<field name="show_button_previous" invisible="1"/>
<field name="show_button_rejection" invisible="1"/>
<field name="stage_id" widget="statusbar" options="{'fold_field': 'fold'}" readonly="1"/>
<button name="assign_ticket_to_self" string="Assign To Me" type="object" class="oe_highlight"
groups="odex25_helpdesk.group_odex25_helpdesk_user"
attrs="{'invisible': [('is_self_assigned', '=', True)]}"/>
<field name="stage_id" widget="statusbar"
options="{'clickable': '1', 'fold_field': 'fold'}"/>
<button name="action_confirm" string="Send" type="object" class="btn-primary"
attrs="{'invisible': [('show_button_next', '=', False)]}" />
<button name="action_back" string="Previous" type="object" class="btn-secondary" attrs="{'invisible': [('show_button_previous', '=', False)]}"/>
<button name="action_rejection" string="Rejection" type="object" class="btn-primary"
attrs="{'invisible': [('show_button_rejection', '=', False)]}" />
</header>
<sheet>
<field name="legend_blocked" invisible="1"/>