Adds 2 new modules: l10n_fr_hr_holidays l10n_fr_hr_work_entry_holidays This commit adds modules allowing to compute accurately the number of days off taken by a french part-timer. Both modules will automatically install when hr_holidays is installed and at least one of the companies is located in France In France, when taking a time off using a different calendar from the company's calendar you have to count the days as if you were taking time off in the company calendar. For example let's say you have an employee working only monday through wednesday, if that employee were to take a time off ending with wednesday afternoon, the time off would count up until friday (if the company calendar if monday->friday), so that a whole week is always 5 days regardless of the employee calendar. This is also the case for 'holes' in the employee calendar, for example a calendar where one would work monday, wednesday and friday only. l10n_fr_work_entry_holidays: By default time off only generate work entries for intersections between time off and attendance period, so that when taking a time off for a whole month you wouldn't get work entries on the weekend if you normally don't work that day. But since l10n_fr_hr_holidays computes the number of days it would normally cost with french rules. We also have to make sure that the work entries are generated appropriately. Essentially this modules adds the logic required to fill the holes needed using the company calendar instead of the employee one. OTHER: Fixes a redundant call to super function in hr.leave._get_number_of_days, improving its performance a bit task-2602897 closes odoo/odoo#82637 Related: odoo/enterprise#25805 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com> Co-authored-by: Bertrand Dossogne <bedo@odoo.com>
122 lines
6.2 KiB
Python
122 lines
6.2 KiB
Python
# -*- 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 UserError
|
|
|
|
|
|
class ResConfigSettings(models.TransientModel):
|
|
|
|
_inherit = 'res.config.settings'
|
|
|
|
company_id = fields.Many2one('res.company', string='Company', required=True,
|
|
default=lambda self: self.env.company)
|
|
user_default_rights = fields.Boolean(
|
|
"Default Access Rights",
|
|
config_parameter='base_setup.default_user_rights')
|
|
external_email_server_default = fields.Boolean(
|
|
"Use Custom Email Servers",
|
|
config_parameter='base_setup.default_external_email_server')
|
|
module_base_import = fields.Boolean("Allow users to import data from CSV/XLS/XLSX/ODS files")
|
|
module_google_calendar = fields.Boolean(
|
|
string='Allow the users to synchronize their calendar with Google Calendar')
|
|
module_microsoft_calendar = fields.Boolean(
|
|
string='Allow the users to synchronize their calendar with Outlook Calendar')
|
|
module_mail_plugin = fields.Boolean(
|
|
string='Allow integration with the mail plugins'
|
|
)
|
|
module_auth_oauth = fields.Boolean("Use external authentication providers (OAuth)")
|
|
module_auth_ldap = fields.Boolean("LDAP Authentication")
|
|
module_account_inter_company_rules = fields.Boolean("Manage Inter Company")
|
|
module_voip = fields.Boolean("Asterisk (VoIP)")
|
|
module_web_unsplash = fields.Boolean("Unsplash Image Library")
|
|
module_partner_autocomplete = fields.Boolean("Partner Autocomplete")
|
|
module_base_geolocalize = fields.Boolean("GeoLocalize")
|
|
module_google_recaptcha = fields.Boolean("reCAPTCHA")
|
|
module_website_cf_turnstile = fields.Boolean("Cloudflare Turnstile")
|
|
report_footer = fields.Html(related="company_id.report_footer", string='Custom Report Footer', help="Footer text displayed at the bottom of all reports.", readonly=False)
|
|
group_multi_currency = fields.Boolean(string='Multi-Currencies',
|
|
implied_group='base.group_multi_currency',
|
|
help="Allows to work in a multi currency environment")
|
|
external_report_layout_id = fields.Many2one(related="company_id.external_report_layout_id", readonly=False)
|
|
show_effect = fields.Boolean(string="Show Effect", config_parameter='base_setup.show_effect')
|
|
company_count = fields.Integer('Number of Companies', compute="_compute_company_count")
|
|
active_user_count = fields.Integer('Number of Active Users', compute="_compute_active_user_count")
|
|
language_count = fields.Integer('Number of Languages', compute="_compute_language_count")
|
|
company_name = fields.Char(related="company_id.display_name", string="Company Name")
|
|
company_informations = fields.Text(compute="_compute_company_informations")
|
|
company_country_code = fields.Char(related="company_id.country_id.code", string="Company Country Code", readonly=True)
|
|
profiling_enabled_until = fields.Datetime("Profiling enabled until", config_parameter='base.profiling_enabled_until')
|
|
module_product_images = fields.Boolean("Get product pictures using barcode")
|
|
|
|
def open_company(self):
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': 'My Company',
|
|
'view_mode': 'form',
|
|
'res_model': 'res.company',
|
|
'res_id': self.env.company.id,
|
|
'target': 'current',
|
|
}
|
|
|
|
def open_default_user(self):
|
|
action = self.env["ir.actions.actions"]._for_xml_id("base.action_res_users")
|
|
if self.env.ref('base.default_user', raise_if_not_found=False):
|
|
action['res_id'] = self.env.ref('base.default_user').id
|
|
else:
|
|
raise UserError(_("Default User Template not found."))
|
|
action['views'] = [[self.env.ref('base.view_users_form').id, 'form']]
|
|
return action
|
|
|
|
@api.model
|
|
def _prepare_report_view_action(self, template):
|
|
template_id = self.env.ref(template)
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'ir.ui.view',
|
|
'view_mode': 'form',
|
|
'res_id': template_id.id,
|
|
}
|
|
|
|
def edit_external_header(self):
|
|
if not self.external_report_layout_id:
|
|
return False
|
|
return self._prepare_report_view_action(self.external_report_layout_id.key)
|
|
|
|
# NOTE: These fields depend on the context, if we want them to be computed
|
|
# we have to make them depend on a field. This is because we are on a TransientModel.
|
|
@api.depends('company_id')
|
|
def _compute_company_count(self):
|
|
company_count = self.env['res.company'].sudo().search_count([])
|
|
for record in self:
|
|
record.company_count = company_count
|
|
|
|
@api.depends('company_id')
|
|
def _compute_active_user_count(self):
|
|
active_user_count = self.env['res.users'].sudo().search_count([('share', '=', False)])
|
|
for record in self:
|
|
record.active_user_count = active_user_count
|
|
|
|
@api.depends('company_id')
|
|
def _compute_language_count(self):
|
|
language_count = len(self.env['res.lang'].get_installed())
|
|
for record in self:
|
|
record.language_count = language_count
|
|
|
|
@api.depends('company_id')
|
|
def _compute_company_informations(self):
|
|
informations = '%s\n' % self.company_id.street if self.company_id.street else ''
|
|
informations += '%s\n' % self.company_id.street2 if self.company_id.street2 else ''
|
|
informations += '%s' % self.company_id.zip if self.company_id.zip else ''
|
|
informations += '\n' if self.company_id.zip and not self.company_id.city else ''
|
|
informations += ' - ' if self.company_id.zip and self.company_id.city else ''
|
|
informations += '%s\n' % self.company_id.city if self.company_id.city else ''
|
|
informations += '%s\n' % self.company_id.state_id.display_name if self.company_id.state_id else ''
|
|
informations += '%s' % self.company_id.country_id.display_name if self.company_id.country_id else ''
|
|
vat_display = self.company_id.country_id.vat_label or _('VAT')
|
|
vat_display = '\n' + vat_display + ': '
|
|
informations += '%s %s' % (vat_display, self.company_id.vat) if self.company_id.vat else ''
|
|
|
|
for record in self:
|
|
record.company_informations = informations
|