[NEW] hr_timesheet_import_from_calendar

This commit is contained in:
clementthomas
2024-12-16 14:05:05 +01:00
parent 091fefc763
commit fd45cf17a2
9 changed files with 207 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
from . import models
from . import wizard

View File

@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': "hr_timesheet_import_from_calendar",
'version': '16.0.1.0.0',
'depends': ['hr_timesheet'],
'author': "Élabore",
'category': 'Human Resources/Employees',
'summary' : "Import HR timesheet from calendar events",
'description': """
In HR timesheet list view, you can import directly from your calendar.
""",
'data': [
'views/hr_timesheet_views.xml',
'wizard/hr_timesheet_import_from_calendar_wizard_views.xml',
'security/ir.model.access.csv'
],
'demo': [
],
'application': False,
'license': 'LGPL-3',
}

View File

@@ -0,0 +1 @@
from . import hr_timesheet

View File

@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
from collections import defaultdict
from lxml import etree
import re
from odoo import api, Command, fields, models, _, _lt
from odoo.exceptions import UserError, AccessError, ValidationError
from odoo.osv import expression
class AccountAnalyticLine(models.Model):
_inherit = 'account.analytic.line'
calendar_event_origin_id = fields.Many2one('calendar.event')

View File

@@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_hr_timesheet_import_from_calendar_wizard,access.hr.timesheet.import.from.calendar.wizard,model_hr_timesheet_import_from_calendar_wizard,hr_timesheet.group_hr_timesheet_user,1,1,1,1
access_hr_timesheet_import_from_calendar_wizard_line,access.hr.timesheet.import.from.calendar.wizard.line,model_hr_timesheet_import_from_calendar_wizard_line,hr_timesheet.group_hr_timesheet_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_hr_timesheet_import_from_calendar_wizard access.hr.timesheet.import.from.calendar.wizard model_hr_timesheet_import_from_calendar_wizard hr_timesheet.group_hr_timesheet_user 1 1 1 1
3 access_hr_timesheet_import_from_calendar_wizard_line access.hr.timesheet.import.from.calendar.wizard.line model_hr_timesheet_import_from_calendar_wizard_line hr_timesheet.group_hr_timesheet_user 1 1 1 1

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
</data>
</odoo>

View File

@@ -0,0 +1 @@
from . import hr_timesheet_import_from_calendar_wizard

View File

@@ -0,0 +1,106 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models
from datetime import date, timedelta
import re
from odoo.exceptions import UserError
class HrTimesheetImportFromCalendarWizard(models.TransientModel):
_name = 'hr.timesheet.import.from.calendar.wizard'
imported = fields.Boolean()
date_from = fields.Date('Du', default=lambda self: self._default_date_from(), required=True)
date_to = fields.Date('Au', default=lambda self: self._default_date_to(), required=True)
lines = fields.One2many('hr.timesheet.import.from.calendar.wizard.line', 'wizard_id', string="Lines")
warning = fields.Boolean()
def _default_date_from(self):
return date.today()-timedelta(days=date.today().weekday())-timedelta(days=7)
def _default_date_to(self):
return date.today()-timedelta(days=date.today().weekday())-timedelta(days=1)
def action_import(self):
self.lines.unlink()
calendar_events = self.env['calendar.event'].search([
('user_id','=',self.env.user.id),
('start','>=',self.date_from),
('start','<=',self.date_to),
]).sorted('start')
for event in calendar_events:
project_id = None
if '[' in event.name and ']' in event.name:
analytic_account_codes = re.findall(r'\[(.*?)\]', event.name)
if analytic_account_codes:
analytic_account_code = analytic_account_codes[0]
analytic_account = self.env['account.analytic.account'].search([('code','=',analytic_account_code)], limit=1)
if analytic_account:
project = self.env['project.project'].search([('analytic_account_id','=',analytic_account.id)], limit=1)
project_id = project.id
# Check if analytic account line already created by this event
existing_lines = self.env['account.analytic.line'].search([('calendar_event_origin_id','=',event.id)])
warning = False
if existing_lines:
warning = True
self.warning = True
self.env['hr.timesheet.import.from.calendar.wizard.line'].create({
'wizard_id':self.id,
'date': event.start,
'name': event.name,
'project_id':project_id,
'unit_amount':event.duration,
'calendar_event_origin_id': event.id,
'warning':warning
})
self.imported = True
return {
'type': 'ir.actions.act_window',
'name': 'Importer depuis le calendrier',
'res_model': 'hr.timesheet.import.from.calendar.wizard',
'res_id': self.id, # Garde le même enregistrement ouvert
'view_mode': 'form',
'target': 'new', # Wizard modal
}
@api.onchange('lines')
def check_warning(self):
for line in self.lines:
if line.warning:
self.warning = True
return
self.warning = False
def action_confirm(self):
if not all([l.project_id for l in self.lines]):
raise UserError("Vous devez indiquer un projet sur chaque ligne. Si une ligne n'est pas concernée, vous devez la supprimer.")
for line in self.lines:
self.env['account.analytic.line'].create({
'date':line.date,
'project_id':line.project_id.id,
'name':line.name,
'unit_amount':line.unit_amount,
'calendar_event_origin_id':line.calendar_event_origin_id.id
})
action = self.env["ir.actions.act_window"]._for_xml_id("hr_timesheet.act_hr_timesheet_line")
action['target'] = 'main' # clear breadcrump
return action
class HrTimesheetImportFromCalendarWizardLine(models.TransientModel):
_name = 'hr.timesheet.import.from.calendar.wizard.line'
wizard_id = fields.Many2one('hr.timesheet.import.from.calendar.wizard')
date = fields.Date()
project_id = fields.Many2one('project.project')
name = fields.Char('Description')
unit_amount = fields.Float('Heures passées')
calendar_event_origin_id = fields.Many2one('calendar.event')
warning = fields.Boolean()

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="hr_timesheet_import_from_calendar_wizard_view" model="ir.ui.view">
<field name="name">hr.timesheet.import.from.calendar.wizard.view</field>
<field name="model">hr.timesheet.import.from.calendar.wizard</field>
<field name="arch" type="xml">
<form>
<field name="imported" invisible="True" />
Du <field name="date_from" />
Au <field name="date_to" />
<button name="action_import" type="object" string="Récupérer la liste" />
<field name="warning" invisible="True" />
<div attrs="{'invisible': [('warning', '=', False)]}">
<p class="oe_field_label" style="color: red;">Attention: Certaines lignes ont déjà été importées !</p>
</div>
<field name="lines" attrs="{'invisible': [('imported', '=', False)]}">
<tree editable="bottom" decoration-warning="warning != False">
<field name="date" />
<field name="project_id" />
<field name="name" />
<field name="unit_amount" />
<field name="warning" invisible="True" />
</tree>
</field>
<footer>
<button class="oe_highlight" name="action_confirm" type="object" string="Créer les feuilles de temps" attrs="{'invisible': [('imported', '=', False)]}" />
<button special="cancel" string="Cancel" class="oe_link" />
</footer>
</form>
</field>
</record>
<record id="action_hr_timesheet_import_from_calendar_wizard" model="ir.actions.act_window">
<field name="name">Importer depuis le calendrier</field>
<field name="res_model">hr.timesheet.import.from.calendar.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<menuitem
id="timesheet_menu_import_from_calendar"
action="action_hr_timesheet_import_from_calendar_wizard"
sequence="11"
parent="hr_timesheet.timesheet_menu_root"
groups="hr_timesheet.group_hr_timesheet_user"
/>
</odoo>