diff --git a/hr_holidays_usability/README.rst b/hr_holidays_usability/README.rst new file mode 100644 index 0000000..36891da --- /dev/null +++ b/hr_holidays_usability/README.rst @@ -0,0 +1,23 @@ +HR Holidays Usability +===================== + +This module adds what I consider the minimum usability level for the holiday management module in Odoo: + + * By default, if you only use the official *hr_holidays* module, there the number of days is not automatically computed from the start date and end date. This module fixes it : it counts the number of days following a computation method that is defined on the object hr.holiday.status. It also replaces the datetime field for start/end dates by a date field plus a selection field to indicated morning/noon/evening. + + * It depends on the OCA module *hr_public_holidays* to easily define the bank holidays per country. It takes those bank holidays into account when counting the number of days. + + * It sends an email to the manager when the employee submits a holiday requests (with the employee in Cc) and it sends an email to the employee (with the manager in Cc) when the holiday request is validated/refused. + +Known issues / Roadmap +====================== + + * Port to v8 + +Credits +======= + +Contributors +------------ + +* Alexis de Lattre diff --git a/hr_holidays_usability/__init__.py b/hr_holidays_usability/__init__.py new file mode 100644 index 0000000..dfa6080 --- /dev/null +++ b/hr_holidays_usability/__init__.py @@ -0,0 +1,23 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# HR Holidays Usability module for Odoo +# Copyright (C) 2015 Akretion (http://www.akretion.com) +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from . import hr_holidays diff --git a/hr_holidays_usability/__openerp__.py b/hr_holidays_usability/__openerp__.py new file mode 100644 index 0000000..73d60e0 --- /dev/null +++ b/hr_holidays_usability/__openerp__.py @@ -0,0 +1,39 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# HR Holidays Usability module for Odoo +# Copyright (C) 2015 Akretion (http://www.akretion.com) +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + 'name': 'HR Holidays Usability', + 'version': '0.1', + 'category': 'Human Resources', + 'license': 'AGPL-3', + 'summary': 'Better usability for the management of holidays', + 'description': '', + 'author': 'Akretion', + 'website': 'http://www.akretion.com', + 'depends': ['hr_holidays', 'hr_public_holidays'], + 'data': [ + 'hr_holidays_view.xml', + 'hr_holidays_mail.xml', + ], + 'installable': True, +} diff --git a/hr_holidays_usability/hr_holidays.py b/hr_holidays_usability/hr_holidays.py new file mode 100644 index 0000000..8fe1fd6 --- /dev/null +++ b/hr_holidays_usability/hr_holidays.py @@ -0,0 +1,262 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# HR Holidays Usability module for Odoo +# Copyright (C) 2015 Akretion (http://www.akretion.com) +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields, api, _ +from openerp.exceptions import ValidationError +from datetime import datetime +from dateutil.relativedelta import relativedelta +import pytz +import logging + +logger = logging.getLogger(__name__) + + +class HrHolidaysStatus(models.Model): + _inherit = 'hr.holidays.status' + + vacation_compute_method = fields.Selection([ + ('worked', u'Jours ouvrés'), + ('business', u'Jours ouvrables'), + # TODO find proper English translation + ], string='Vacation Compute Method', required=True, + default='worked') + + +class HrHolidays(models.Model): + _inherit = 'hr.holidays' + _order = 'type desc, date_from desc' + # by default : type desc, date_from asc + +# Idea : +# For allocation (type = add), we don't change anything: +# The user writes in the field number_of_days_temp and +# number_of_days = number_of_days_temp +# For leave (type = remove), we don't let users enter the number of days, +# we compute it for them +# -> new computed field "number_of_days_remove' that compute the number +# of days depending on the computation method defined on 'type' +# Redefine the field 'number_of_days' to take into accout +# 'number_of_days_remove' when type == remove (= number_of_days_remove * -1) +# change date time fields by date + selection morning/noon + +# How do we set the dates : +# from : premier jour d'absence (et non dernier jour de présence) +# + time : morning/noon +# to : date de fin de congés (et non date de retour au travail) +# + time : noon/evening + +# which computation methods on the 'hr.holidays.status': +# 1) jours ouvrés (sans compter les jours fériés) +# 2) jours ouvrables (quid des jours fériés ???) : +# il faut compter les samedis sauf les samedis fériés. +# Cas particulier : quand la personne prend le vendredi aprèm, +# il faut compter 1j (et non 0.5 ni 1.5) +# 3) malade : on compte tous les jours -> ptet pas nécessaire pour le moment +# 1 for 'unpaid leaves' + repos compensateur + congés conventionnels + maladie +# 1 or 2 for normal holidays + + @api.one + @api.depends( + 'vacation_date_from', 'vacation_time_from', 'vacation_date_to', + 'vacation_time_to', 'number_of_days_temp', 'type', 'holiday_type', + 'holiday_status_id.vacation_compute_method') + def _compute_number_of_days(self): + # depend on the holiday_status_id + hhpo = self.env['hr.holidays.public'] + days = 0.0 + if ( + self.type == 'remove' and + self.holiday_type == 'employee' and + self.vacation_date_from and + self.vacation_time_from and + self.vacation_date_to and + self.vacation_time_to): + if self.holiday_status_id.vacation_compute_method == 'business': + business = True + else: + business = False + date_dt = start_date_dt = fields.Date.from_string( + self.vacation_date_from) + end_date_dt = fields.Date.from_string( + self.vacation_date_to) + + while True: + # REGULAR COMPUTATION + # if it's a bank holidays, don't count + if hhpo.is_public_holiday(date_dt, self.employee_id.id): + logger.info( + "%s is a bank holiday, don't count", date_dt) + # it it's a saturday/sunday + elif date_dt.weekday() in (5, 6): + logger.info( + "%s is a saturday/sunday, don't count", date_dt) + else: + days += 1.0 + # special case for friday when compute_method = business + if ( + business and + date_dt.weekday() == 4 and + not hhpo.is_public_holiday( + date_dt + relativedelta(days=1), + self.employee_id.id)): + days += 1.0 + # PARTICULAR CASE OF THE FIRST DAY + if date_dt == start_date_dt: + if self.vacation_time_from == 'noon': + if ( + business and + date_dt.weekday() == 4 and + not hhpo.is_public_holiday( + date_dt + relativedelta(days=1), + self.employee_id.id)): + days -= 1.0 # result = 2 - 1 = 1 + else: + days -= 0.5 + # PARTICULAR CASE OF THE LAST DAY + if date_dt == end_date_dt: + if self.vacation_time_to == 'noon': + if ( + business and + date_dt.weekday() == 4 and + not hhpo.is_public_holiday( + date_dt + relativedelta(days=1), + self.employee_id.id)): + days -= 1.5 # 2 - 1.5 = 0.5 + else: + days -= 0.5 + break + date_dt += relativedelta(days=1) + + self.number_of_days_remove = days + + # PASTE + if self.type == 'remove': + # read number_of_days_remove instead of number_of_days_temp + number_of_days = -days + else: + # for allocations, we read the native field number_of_days_temp + number_of_days = self.number_of_days_temp + self.number_of_days = number_of_days + + vacation_date_from = fields.Date( + string='First Day of Vacation', track_visibility='onchange', + help="Enter the first day of vacation. For example, if " + "you leave one full calendar week, the first day of vacation " + "is Monday morning (and not Friday of the week before)") + vacation_time_from = fields.Selection([ + ('morning', 'Morning'), + ('noon', 'Noon'), + ], string="Start of Vacation", track_visibility='onchange', + default='morning', + help="For example, if you leave one full calendar week, " + "the first day of vacation is Monday Morning") + vacation_date_to = fields.Date( + string='Last Day of Vacation', track_visibility='onchange', + help="Enter the last day of vacation. For example, if you " + "leave one full calendar week, the last day of vacation is " + "Friday evening (and not Monday of the week after)") + vacation_time_to = fields.Selection([ + ('noon', 'Noon'), + ('evening', 'Evening'), + ], string="End of Vacation", track_visibility='onchange', + default='evening', + help="For example, if you leave one full calendar week, " + "the end of vacation is Friday Evening") + number_of_days_remove = fields.Float( + compute='_compute_number_of_days', + string="Number of Days of Vacation", readonly=True) + # number_of_days is a native field that I inherit + number_of_days = fields.Float(compute='_compute_number_of_days') + + @api.one + @api.constrains( + 'vacation_date_from', 'vacation_date_to', 'holiday_type', 'type') + def _check_vacation_dates(self): + hhpo = self.env['hr.holidays.public'] + if self.type == 'remove': + if self.vacation_date_from > self.vacation_date_to: + raise ValidationError( + _('The first day cannot be after the last day !')) + elif ( + self.vacation_date_from == self.vacation_date_to and + self.vacation_time_from == self.vacation_time_to): + raise ValidationError( + _("The start of vacation is exactly the " + "same as the end !")) + date_from_dt = fields.Date.from_string( + self.vacation_date_from) + if date_from_dt.weekday() in (5, 6): + raise ValidationError( + _("The first day of vacation cannot be a " + "saturday or sunday !")) + date_to_dt = fields.Date.from_string( + self.vacation_date_to) + if date_to_dt.weekday() in (5, 6): + raise ValidationError( + _("The last day of Vacation cannot be a " + "saturday or sunday !")) + if hhpo.is_public_holiday(date_from_dt, self.employee_id.id): + raise ValidationError( + _("The first day of vacation cannot be a " + "bank holiday !")) + if hhpo.is_public_holiday(date_to_dt, self.employee_id.id): + raise ValidationError( + _("The last day of vacation cannot be a " + "bank holiday !")) + + @api.onchange('vacation_date_from', 'vacation_time_from') + def vacation_from(self): + hour = 0 # = morning + if self.vacation_time_from and self.vacation_time_from == 'noon': + hour = 12 # noon, LOCAL TIME + datetime_str = False + if self.vacation_date_from: + date_dt = fields.Date.from_string(self.vacation_date_from) + if self._context.get('tz'): + localtz = pytz.timezone(self._context['tz']) + else: + localtz = pytz.utc + datetime_dt = localtz.localize(datetime( + date_dt.year, date_dt.month, date_dt.day, hour, 0, 0)) + # we give to odoo a datetime in UTC + datetime_str = fields.Datetime.to_string( + datetime_dt.astimezone(pytz.utc)) + self.date_from = datetime_str + + @api.onchange('vacation_date_to', 'vacation_time_to') + def vacation_to(self): + hour = 23 # = evening + if self.vacation_time_to and self.vacation_time_to == 'noon': + hour = 14 # Noon, LOCAL TIME + datetime_str = False + if self.vacation_date_to: + date_dt = fields.Date.from_string(self.vacation_date_to) + if self._context.get('tz'): + localtz = pytz.timezone(self._context['tz']) + else: + localtz = pytz.utc + datetime_dt = localtz.localize(datetime( + date_dt.year, date_dt.month, date_dt.day, hour, 0, 0)) + # we give to odoo a datetime in UTC + datetime_str = fields.Datetime.to_string( + datetime_dt.astimezone(pytz.utc)) + self.date_to = datetime_str diff --git a/hr_holidays_usability/hr_holidays_mail.xml b/hr_holidays_usability/hr_holidays_mail.xml new file mode 100644 index 0000000..54f9e26 --- /dev/null +++ b/hr_holidays_usability/hr_holidays_mail.xml @@ -0,0 +1,113 @@ + + + + + + Auto-email confirmed leave + context.update({ + 'wkf_tracker': 'submitted', + 'dbname': cr.dbname, +}) +template_id=self.pool.get('ir.model.data').get_object_reference(cr, uid, 'hr_holidays_usability', 'email_template_hr_holidays')[1] +self.pool.get('email.template').send_mail(cr, uid, template_id, object.id, force_send=True, context=context) + code + ir.actions.server + + True + + + + Auto-email validated leave + context.update({ + 'wkf_tracker': 'validated', + 'dbname': cr.dbname, +}) +template_id=self.pool.get('ir.model.data').get_object_reference(cr, uid, 'hr_holidays_usability', 'email_template_hr_holidays')[1] +self.pool.get('email.template').send_mail(cr, uid, template_id, object.id, force_send=True, context=context) + code + ir.actions.server + + True + + + + Auto-email refused leave + context.update({ + 'wkf_tracker': 'refused', + 'dbname': cr.dbname, +}) +template_id=self.pool.get('ir.model.data').get_object_reference(cr, uid, 'hr_holidays_usability', 'email_template_hr_holidays')[1] +self.pool.get('email.template').send_mail(cr, uid, template_id, object.id, force_send=True, context=context) + code + ir.actions.server + + True + + + + + + + + + + + + + + + + Holidays email template + + ${user.company_id.email} + ${object.employee_id.parent_id.user_id.email or ''} + ${object.employee_id.user_id.email or ''} + ${user.email or ''} + ${ctx.get('dbname') and 'prod' not in ctx.get('dbname') and '[TEST]' or ''}[${object.type == 'remove' and 'Leave' or 'Allocation'} ${ctx.get('wkf_tracker')}] ${object.name or ''} - ${object.employee_id.name or ''} + + ${user.lang} + + +% if ctx.get('dbname') and 'prod' not in ctx.get('dbname'): +

WARNING : THIS IS A TEST E-MAIL sent from a test OpenERP database (${ctx.get('dbname')}). Do not take into account !

+ +% endif +

The following ${object.type == 'remove' and 'leave request' or 'ALLOCATION request (i.e. credit of days, not debit !)'} has been ${ctx.get('wkf_tracker') or 'ERROR'} today in OpenERP by ${user.name or ''} :

+ +
    +
  • Employee : ${object.employee_id.name or ''}
  • +% if object.employee_id.parent_id: +
  • Employee's manager : ${object.employee_id.parent_id.name or ''}
  • +% endif +% if object.type == 'remove': +
  • Start date : ${object.vacation_date_from or ''} ${object.vacation_time_from or ''}
  • +
  • End date : ${object.vacation_date_to or ''} ${object.vacation_time_to or ''}
  • +% endif +
  • Number of days : ${object.number_of_days or '0'}
  • +
  • Leave type : ${object.holiday_status_id.name or ''}
  • +
  • Description : ${object.name or ''}
  • +% if object.notes: +
  • Notes : ${object.notes or ''}
  • +% endif +
+ +% if ctx.get('wkf_tracker') == 'submitted': +% if object.type == 'remove': +

To validate or refuse it, go to the menu Human Resources > Leaves > Leave requests to approve.

+% else: +

To validate or refuse it, go to the menu Human Resources > Leaves > Allocation requests.

+% endif + +% endif +

+--
+Automatic e-mail sent by OpenERP. Do not reply.
+Database : ${ctx.get('dbname')}
+

+ +]]>
+
+ +
+
diff --git a/hr_holidays_usability/hr_holidays_view.xml b/hr_holidays_usability/hr_holidays_view.xml new file mode 100644 index 0000000..731cc02 --- /dev/null +++ b/hr_holidays_usability/hr_holidays_view.xml @@ -0,0 +1,122 @@ + + + + + + + + + hr_holidays_usability.leave_request_form + hr.holidays + + + + {} + + + {} + + + {} + 1 + + + {'invisible': [('type', '=', 'remove')]} + + + + + + + + + + + + + + + hr_holidays_usability.leave_request_tree + hr.holidays + + + + 1 + + + + + + 1 + + + + + + + 1 + + + + + + + 0 + + + + + + hr_holidays_usability.hr.holidays.status.form + hr.holidays.status + + + + + + + + + + hr_holidays_usability.hr.holidays.status.normal.tree + hr.holidays.status + + + + + + + + + + + + + + + Leaves Calendar + resource.calendar.leaves + calendar,tree,form + + + + + + + + + + + diff --git a/hr_holidays_usability/i18n/fr.po b/hr_holidays_usability/i18n/fr.po new file mode 100644 index 0000000..9a2ce29 --- /dev/null +++ b/hr_holidays_usability/i18n/fr.po @@ -0,0 +1,288 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * hr_holidays_usability +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-05-18 21:36+0000\n" +"PO-Revision-Date: 2015-05-18 21:36+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: hr_holidays_usability +#: model:email.template,body_html:hr_holidays_usability.email_template_hr_holidays +msgid "\n" +"
\n" +"\n" +"% if ctx.get('dbname') and 'prod' not in ctx.get('dbname'):\n" +"

WARNING : THIS IS A TEST E-MAIL sent from a test OpenERP database (${ctx.get('dbname')}). Do not take into account !

\n" +"\n" +"% endif\n" +"

La ${object.type == 'remove' and 'demande' or \"demande d'ATTRIBUTION\"} de congé a été ${ctx.get('wkf_tracker') or 'ERROR'} aujourd'hui dans OpenERP par ${user.name or ''} :

\n" +"\n" +"
    \n" +"
  • Employé : ${object.employee_id.name or ''}
  • \n" +"% if object.employee_id.parent_id:\n" +"
  • Manager : ${object.employee_id.parent_id.name or ''}
  • \n" +"% endif\n" +"% if object.type == 'remove':\n" +"
  • Début : ${object.vacation_date_from or ''}\n" +"% if object.vacation_time_from == 'morning':\n" +"au matin\n" +"% elif object.vacation_time_from == 'noon':\n" +"midi\n" +"% endif\n" +"
  • \n" +"
  • Fin : ${object.vacation_date_to or ''}\n" +"% if object.vacation_time_to == 'noon':\n" +"midi\n" +"% elif object.vacation_time_to == 'evening':\n" +"au soir\n" +"% endif\n" +"
  • \n" +"% endif\n" +"
  • Nombre de jours : ${object.number_of_days_temp or '0'}
  • \n" +"
  • Type de congé : ${object.holiday_status_id.name or ''}
  • \n" +"
  • Description : ${object.name or ''}
  • \n" +"% if object.notes:\n" +"
  • Notes : ${object.notes or ''}
  • \n" +"% endif\n" +"
\n" +"\n" +"% if ctx.get('wkf_tracker') == 'soumise':\n" +"% if object.type == 'remove':\n" +"

Pour la valider ou la refuser, allez dans le menu Ressources humaines > Congés > Demandes de congé à valider.

\n" +"% else:\n" +"

Pour la valider ou la refuser, allez dans le menu Ressources humaines > Congés > Demandes d'attribution de congés à valider.

\n" +"% endif\n" +"% endif\n" +"

\n" +"--
\n" +"Mail envoyé automatiquement par OpenERP. Ne pas répondre.
\n" +"Base de donnée : ${ctx.get('dbname')}
\n" +"

\n" +"
\n" +"" +msgstr "\n" +"
\n" +"\n" +"% if ctx.get('dbname') and 'prod' not in ctx.get('dbname'):\n" +"

WARNING : THIS IS A TEST E-MAIL sent from a test OpenERP database (${ctx.get('dbname')}). Do not take into account !

\n" +"\n" +"% endif\n" +"

La ${object.type == 'remove' and 'demande' or \"demande d'ATTRIBUTION\"} de congé a été ${ctx.get('wkf_tracker') or 'ERROR'} aujourd'hui dans OpenERP par ${user.name or ''} :

\n" +"\n" +"
    \n" +"
  • Employé : ${object.employee_id.name or ''}
  • \n" +"% if object.employee_id.parent_id:\n" +"
  • Manager : ${object.employee_id.parent_id.name or ''}
  • \n" +"% endif\n" +"% if object.type == 'remove':\n" +"
  • Début : ${object.vacation_date_from or ''}\n" +"% if object.vacation_time_from == 'morning':\n" +"au matin\n" +"% elif object.vacation_time_from == 'noon':\n" +"midi\n" +"% endif\n" +"
  • \n" +"
  • Fin : ${object.vacation_date_to or ''}\n" +"% if object.vacation_time_to == 'noon':\n" +"midi\n" +"% elif object.vacation_time_to == 'evening':\n" +"au soir\n" +"% endif\n" +"
  • \n" +"% endif\n" +"
  • Nombre de jours : ${object.number_of_days_temp or '0'}
  • \n" +"
  • Type de congé : ${object.holiday_status_id.name or ''}
  • \n" +"
  • Description : ${object.name or ''}
  • \n" +"% if object.notes:\n" +"
  • Notes : ${object.notes or ''}
  • \n" +"% endif\n" +"
\n" +"\n" +"% if ctx.get('wkf_tracker') == 'soumise':\n" +"% if object.type == 'remove':\n" +"

Pour la valider ou la refuser, allez dans le menu Ressources humaines > Congés > Demandes de congé à valider.

\n" +"% else:\n" +"

Pour la valider ou la refuser, allez dans le menu Ressources humaines > Congés > Demandes d'attribution de congés à valider.

\n" +"% endif\n" +"% endif\n" +"

\n" +"--
\n" +"Mail envoyé automatiquement par OpenERP. Ne pas répondre.
\n" +"Base de donnée : ${ctx.get('dbname')}
\n" +"

\n" +"
\n" +"" + +#. module: hr_holidays_usability +#: model:email.template,subject:hr_holidays_usability.email_template_hr_holidays +msgid "${ctx.get('dbname') and 'prod' not in ctx.get('dbname') and '[TEST]' or ''}[${object.type == 'remove' and 'Demande' or 'Attribution'} de congé ${ctx.get('wkf_tracker')}] ${object.name or ''} - ${object.employee_id.name or ''}" +msgstr "${ctx.get('dbname') and 'prod' not in ctx.get('dbname') and '[TEST]' or ''}[${object.type == 'remove' and 'Demande' or 'Attribution'} de congé ${ctx.get('wkf_tracker')}] ${object.name or ''} - ${object.employee_id.name or ''}" + +#. module: hr_holidays_usability +#: model:ir.actions.server,name:hr_holidays_usability.ir_actions_server_hr_holidays_confirm_mail +msgid "Auto-email confirmed leave" +msgstr "Auto-email confirmed leave" + +#. module: hr_holidays_usability +#: model:ir.actions.server,name:hr_holidays_usability.ir_actions_server_hr_holidays_refuse_mail +msgid "Auto-email refused leave" +msgstr "Auto-email refused leave" + +#. module: hr_holidays_usability +#: model:ir.actions.server,name:hr_holidays_usability.ir_actions_server_hr_holidays_validate_mail +msgid "Auto-email validated leave" +msgstr "Auto-email validated leave" + +#. module: hr_holidays_usability +#: field:hr.holidays,vacation_time_to:0 +msgid "End of Vacation" +msgstr "Fin du congé" + +#. module: hr_holidays_usability +#: help:hr.holidays,vacation_date_from:0 +msgid "Enter the first day of vacation. For example, if you leave one full calendar week, the first day of vacation is Monday morning (and not Friday of the week before)" +msgstr "Entrez le premier jour de congé. Par exemple, si vous partez en congé pendant une semaine calendaire, le premier jour de congé est le lundi matin (et non le vendredi de la semaine précédente)" + +#. module: hr_holidays_usability +#: help:hr.holidays,vacation_date_to:0 +msgid "Enter the last day of vacation. For example, if you leave one full calendar week, the last day of vacation is Friday evening (and not Monday of the week after)" +msgstr "Entrez le dernier jour de congé. Par exemple, si vous partez en congé pendant une semaine calendaire, le dernier jour de congé est le vendredi soir (et non le lundi matin de la semaine suivante)" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:196 +#: code:addons/hr_holidays_usability/hr_holidays.py:202 +#: code:addons/hr_holidays_usability/hr_holidays.py:209 +#: code:addons/hr_holidays_usability/hr_holidays.py:216 +#: code:addons/hr_holidays_usability/hr_holidays.py:222 +#: code:addons/hr_holidays_usability/hr_holidays.py:228 +#, python-format +msgid "Error:" +msgstr "Erreur :" + +#. module: hr_holidays_usability +#: selection:hr.holidays,vacation_time_to:0 +msgid "Evening" +msgstr "Soir" + +#. module: hr_holidays_usability +#: field:hr.holidays,vacation_date_from:0 +msgid "First Day of Vacation" +msgstr "Premier jour de congé" + +#. module: hr_holidays_usability +#: help:hr.holidays,vacation_time_to:0 +msgid "For example, if you leave one full calendar week, the end of vacation is Friday Evening" +msgstr "Par exemple, si vous partez en congé pendant une semaine calendaire, le dernier jour de congé est le vendredi soir" + +#. module: hr_holidays_usability +#: help:hr.holidays,vacation_time_from:0 +msgid "For example, if you leave one full calendar week, the first day of vacation is Monday Morning" +msgstr "Par exemple, si vous partez en congé pendant une semaine calendaire, le premier jour de congé est le lundi matin" + +#. module: hr_holidays_usability +#: selection:hr.holidays.status,vacation_compute_method:0 +msgid "Jours ouvrables" +msgstr "Jours ouvrables" + +#. module: hr_holidays_usability +#: selection:hr.holidays.status,vacation_compute_method:0 +msgid "Jours ouvrés" +msgstr "Jours ouvrés" + +#. module: hr_holidays_usability +#: field:hr.holidays,vacation_date_to:0 +msgid "Last Day of Vacation" +msgstr "Dernier jour de congé" + +#. module: hr_holidays_usability +#: model:ir.model,name:hr_holidays_usability.model_hr_holidays +msgid "Leave" +msgstr "Congé" + +#. module: hr_holidays_usability +#: model:ir.model,name:hr_holidays_usability.model_hr_holidays_status +msgid "Leave Type" +msgstr "Type de congé" + +#. module: hr_holidays_usability +#: model:ir.actions.act_window,name:hr_holidays_usability.resource_calendar_leaves_cal_first_action +#: model:ir.ui.menu,name:hr_holidays_usability.resource_calendar_leaves_cal_first_menu +msgid "Leaves Calendar" +msgstr "Calendrier des absences" + +#. module: hr_holidays_usability +#: selection:hr.holidays,vacation_time_from:0 +msgid "Morning" +msgstr "Matin" + +#. module: hr_holidays_usability +#: selection:hr.holidays,vacation_time_from:0 +#: selection:hr.holidays,vacation_time_to:0 +msgid "Noon" +msgstr "Midi" + +#. module: hr_holidays_usability +#: field:hr.holidays,number_of_days_remove:0 +msgid "Number of Days of Vacation" +msgstr "Nombre de jours de congé" + +#. module: hr_holidays_usability +#: field:hr.holidays,vacation_time_from:0 +msgid "Start of Vacation" +msgstr "Début du congé" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:197 +#, python-format +msgid "The first day cannot be after the last day !" +msgstr "Le premier jour de congé ne peut pas être postérieur au dernier jour de congé !" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:223 +#, python-format +msgid "The first day of vacation cannot be a bank holiday !" +msgstr "Le premier jour de congé ne peut pas être un jour férié !" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:210 +#, python-format +msgid "The first day of vacation cannot be a saturday or sunday !" +msgstr "Le premier jour de congé ne peut pas être un Samedi ou un Dimanche !" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:217 +#, python-format +msgid "The last day of Vacation cannot be a saturday or sunday !" +msgstr "Le dernier jour de congé ne peut pas être un Samedi ou un Dimanche !" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:229 +#, python-format +msgid "The last day of vacation cannot be a bank holiday !" +msgstr "Le dernier jour de congé ne peut pas être un jour férié !" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:203 +#, python-format +msgid "The start of vacation is exactly the same as the end !" +msgstr "Le début du congé est égal à la fin du congé !" + +#. module: hr_holidays_usability +#: field:hr.holidays.status,vacation_compute_method:0 +msgid "Vacation Compute Method" +msgstr "Méthode de calcul des jours de congé" + +#. module: hr_holidays_usability +#: constraint:hr.holidays:0 +msgid "error msg in raise" +msgstr "error msg in raise" + diff --git a/hr_holidays_usability/i18n/hr_holidays_usability.pot b/hr_holidays_usability/i18n/hr_holidays_usability.pot new file mode 100644 index 0000000..3bc1937 --- /dev/null +++ b/hr_holidays_usability/i18n/hr_holidays_usability.pot @@ -0,0 +1,237 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * hr_holidays_usability +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-05-18 21:35+0000\n" +"PO-Revision-Date: 2015-05-18 21:35+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: hr_holidays_usability +#: model:email.template,body_html:hr_holidays_usability.email_template_hr_holidays +msgid "\n" +"
\n" +"\n" +"% if ctx.get('dbname') and 'prod' not in ctx.get('dbname'):\n" +"

WARNING : THIS IS A TEST E-MAIL sent from a test OpenERP database (${ctx.get('dbname')}). Do not take into account !

\n" +"\n" +"% endif\n" +"

La ${object.type == 'remove' and 'demande' or \"demande d'ATTRIBUTION\"} de congé a été ${ctx.get('wkf_tracker') or 'ERROR'} aujourd'hui dans OpenERP par ${user.name or ''} :

\n" +"\n" +"
    \n" +"
  • Employé : ${object.employee_id.name or ''}
  • \n" +"% if object.employee_id.parent_id:\n" +"
  • Manager : ${object.employee_id.parent_id.name or ''}
  • \n" +"% endif\n" +"% if object.type == 'remove':\n" +"
  • Début : ${object.vacation_date_from or ''}\n" +"% if object.vacation_time_from == 'morning':\n" +"au matin\n" +"% elif object.vacation_time_from == 'noon':\n" +"midi\n" +"% endif\n" +"
  • \n" +"
  • Fin : ${object.vacation_date_to or ''}\n" +"% if object.vacation_time_to == 'noon':\n" +"midi\n" +"% elif object.vacation_time_to == 'evening':\n" +"au soir\n" +"% endif\n" +"
  • \n" +"% endif\n" +"
  • Nombre de jours : ${object.number_of_days_temp or '0'}
  • \n" +"
  • Type de congé : ${object.holiday_status_id.name or ''}
  • \n" +"
  • Description : ${object.name or ''}
  • \n" +"% if object.notes:\n" +"
  • Notes : ${object.notes or ''}
  • \n" +"% endif\n" +"
\n" +"\n" +"% if ctx.get('wkf_tracker') == 'soumise':\n" +"% if object.type == 'remove':\n" +"

Pour la valider ou la refuser, allez dans le menu Ressources humaines > Congés > Demandes de congé à valider.

\n" +"% else:\n" +"

Pour la valider ou la refuser, allez dans le menu Ressources humaines > Congés > Demandes d'attribution de congés à valider.

\n" +"% endif\n" +"% endif\n" +"

\n" +"--
\n" +"Mail envoyé automatiquement par OpenERP. Ne pas répondre.
\n" +"Base de donnée : ${ctx.get('dbname')}
\n" +"

\n" +"
\n" +"" +msgstr "" + +#. module: hr_holidays_usability +#: model:email.template,subject:hr_holidays_usability.email_template_hr_holidays +msgid "${ctx.get('dbname') and 'prod' not in ctx.get('dbname') and '[TEST]' or ''}[${object.type == 'remove' and 'Demande' or 'Attribution'} de congé ${ctx.get('wkf_tracker')}] ${object.name or ''} - ${object.employee_id.name or ''}" +msgstr "" + +#. module: hr_holidays_usability +#: model:ir.actions.server,name:hr_holidays_usability.ir_actions_server_hr_holidays_confirm_mail +msgid "Auto-email confirmed leave" +msgstr "" + +#. module: hr_holidays_usability +#: model:ir.actions.server,name:hr_holidays_usability.ir_actions_server_hr_holidays_refuse_mail +msgid "Auto-email refused leave" +msgstr "" + +#. module: hr_holidays_usability +#: model:ir.actions.server,name:hr_holidays_usability.ir_actions_server_hr_holidays_validate_mail +msgid "Auto-email validated leave" +msgstr "" + +#. module: hr_holidays_usability +#: field:hr.holidays,vacation_time_to:0 +msgid "End of Vacation" +msgstr "" + +#. module: hr_holidays_usability +#: help:hr.holidays,vacation_date_from:0 +msgid "Enter the first day of vacation. For example, if you leave one full calendar week, the first day of vacation is Monday morning (and not Friday of the week before)" +msgstr "" + +#. module: hr_holidays_usability +#: help:hr.holidays,vacation_date_to:0 +msgid "Enter the last day of vacation. For example, if you leave one full calendar week, the last day of vacation is Friday evening (and not Monday of the week after)" +msgstr "" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:196 +#: code:addons/hr_holidays_usability/hr_holidays.py:202 +#: code:addons/hr_holidays_usability/hr_holidays.py:209 +#: code:addons/hr_holidays_usability/hr_holidays.py:216 +#: code:addons/hr_holidays_usability/hr_holidays.py:222 +#: code:addons/hr_holidays_usability/hr_holidays.py:228 +#, python-format +msgid "Error:" +msgstr "" + +#. module: hr_holidays_usability +#: selection:hr.holidays,vacation_time_to:0 +msgid "Evening" +msgstr "" + +#. module: hr_holidays_usability +#: field:hr.holidays,vacation_date_from:0 +msgid "First Day of Vacation" +msgstr "" + +#. module: hr_holidays_usability +#: help:hr.holidays,vacation_time_to:0 +msgid "For example, if you leave one full calendar week, the end of vacation is Friday Evening" +msgstr "" + +#. module: hr_holidays_usability +#: help:hr.holidays,vacation_time_from:0 +msgid "For example, if you leave one full calendar week, the first day of vacation is Monday Morning" +msgstr "" + +#. module: hr_holidays_usability +#: selection:hr.holidays.status,vacation_compute_method:0 +msgid "Jours ouvrables" +msgstr "" + +#. module: hr_holidays_usability +#: selection:hr.holidays.status,vacation_compute_method:0 +msgid "Jours ouvrés" +msgstr "" + +#. module: hr_holidays_usability +#: field:hr.holidays,vacation_date_to:0 +msgid "Last Day of Vacation" +msgstr "" + +#. module: hr_holidays_usability +#: model:ir.model,name:hr_holidays_usability.model_hr_holidays +msgid "Leave" +msgstr "" + +#. module: hr_holidays_usability +#: model:ir.model,name:hr_holidays_usability.model_hr_holidays_status +msgid "Leave Type" +msgstr "" + +#. module: hr_holidays_usability +#: model:ir.actions.act_window,name:hr_holidays_usability.resource_calendar_leaves_cal_first_action +#: model:ir.ui.menu,name:hr_holidays_usability.resource_calendar_leaves_cal_first_menu +msgid "Leaves Calendar" +msgstr "" + +#. module: hr_holidays_usability +#: selection:hr.holidays,vacation_time_from:0 +msgid "Morning" +msgstr "" + +#. module: hr_holidays_usability +#: selection:hr.holidays,vacation_time_from:0 +#: selection:hr.holidays,vacation_time_to:0 +msgid "Noon" +msgstr "" + +#. module: hr_holidays_usability +#: field:hr.holidays,number_of_days_remove:0 +msgid "Number of Days of Vacation" +msgstr "" + +#. module: hr_holidays_usability +#: field:hr.holidays,vacation_time_from:0 +msgid "Start of Vacation" +msgstr "" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:197 +#, python-format +msgid "The first day cannot be after the last day !" +msgstr "" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:223 +#, python-format +msgid "The first day of vacation cannot be a bank holiday !" +msgstr "" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:210 +#, python-format +msgid "The first day of vacation cannot be a saturday or sunday !" +msgstr "" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:217 +#, python-format +msgid "The last day of Vacation cannot be a saturday or sunday !" +msgstr "" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:229 +#, python-format +msgid "The last day of vacation cannot be a bank holiday !" +msgstr "" + +#. module: hr_holidays_usability +#: code:addons/hr_holidays_usability/hr_holidays.py:203 +#, python-format +msgid "The start of vacation is exactly the same as the end !" +msgstr "" + +#. module: hr_holidays_usability +#: field:hr.holidays.status,vacation_compute_method:0 +msgid "Vacation Compute Method" +msgstr "" + +#. module: hr_holidays_usability +#: constraint:hr.holidays:0 +msgid "error msg in raise" +msgstr "" +