[NEW] hr_timesheet_import_from_calendar
This commit is contained in:
2
hr_timesheet_import_from_calendar/__init__.py
Normal file
2
hr_timesheet_import_from_calendar/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from . import models
|
||||
from . import wizard
|
23
hr_timesheet_import_from_calendar/__manifest__.py
Normal file
23
hr_timesheet_import_from_calendar/__manifest__.py
Normal 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',
|
||||
}
|
1
hr_timesheet_import_from_calendar/models/__init__.py
Normal file
1
hr_timesheet_import_from_calendar/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import hr_timesheet
|
14
hr_timesheet_import_from_calendar/models/hr_timesheet.py
Normal file
14
hr_timesheet_import_from_calendar/models/hr_timesheet.py
Normal 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')
|
@@ -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
|
|
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
</data>
|
||||
</odoo>
|
1
hr_timesheet_import_from_calendar/wizard/__init__.py
Normal file
1
hr_timesheet_import_from_calendar/wizard/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import hr_timesheet_import_from_calendar_wizard
|
@@ -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()
|
@@ -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>
|
Reference in New Issue
Block a user