# © 2019 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from datetime import datetime, time from odoo import models, fields, api from odoo.exceptions import UserError, ValidationError class ScopHrTimesheet(models.Model): _inherit = "account.analytic.line" def _default_ur(self): return self.env['res.company']._ur_default_get() # Inherited fields name = fields.Char(required=False) partner_id = fields.Many2one(required=True) # New fields cgscop_timesheet_code_id = fields.Many2one( related='project_id.cgscop_timesheet_code_id', string='Code Activité National', store=True) ur_financial_system_id = fields.Many2one( comodel_name='ur.financial.system', string='Dispositif Financier') ur_regional_convention_id = fields.Many2one( comodel_name='ur.regional.convention', string='Convention Régionale') ur_id = fields.Many2one( 'union.regionale', string='Union Régionale', index=True, ondelete='restrict', default=_default_ur) sheet_id = fields.Many2one( comodel_name='cgscop.timesheet.sheet', string="Feuille de temps", readonly=True, copy=False) state = fields.Selection([ ('to_report', 'A rapporter'), ('draft', 'Brouillon'), ('submit', 'Soumis'), ('valid', 'Validé')], compute='_compute_state', string='Statut', copy=False, index=True, readonly=True, store=True,) ur_financial_system_nb = fields.Integer( string="Nb Dispositifs Financiers", compute="_compute_ur_system_nb") ur_regional_convention_nb = fields.Integer( string="Nb conventions régionales", compute="_compute_ur_system_nb") is_present = fields.Boolean("Présentiel") justificatifs = fields.Char( string="Justificatifs", required=False) calendar_l1 = fields.Char( string='Ligne 1 calendrier', compute='_compute_calendar_l1', store=False) calendar_l2 = fields.Char( string='Ligne 2 calendrier', compute='_compute_calendar_l2', store=False) # ------------------------------------------------------ # Compute Functions # ------------------------------------------------------ @api.depends('ur_id') def _compute_ur_system_nb(self): for timesheet in self: # Calcul nombre de dispositifs financiers financial_system = timesheet.env['ur.financial.system'].search([ ('ur_id', '=', timesheet.ur_id.id)]) timesheet.ur_financial_system_nb = len( financial_system) # Calcul nombre de conventions regional_convention = timesheet.env['ur.regional.convention'].search([ ('ur_id', '=', timesheet.ur_id.id)]) timesheet.ur_regional_convention_nb = len( regional_convention) @api.depends('sheet_id', 'sheet_id.state') def _compute_state(self): for timesheet in self: if not timesheet.sheet_id: timesheet.state = "to_report" else: timesheet.state = timesheet.sheet_id.state @api.depends('project_id', 'partner_id') def _compute_calendar_l1(self): for ts in self: ts.calendar_l1 = "" if ts.project_id: ts.calendar_l1 += ts.project_id.name + ', ' if ts.partner_id: ts.calendar_l1 += ts.partner_id.name @api.depends('unit_amount') def _compute_calendar_l2(self): for ts in self: ts.calendar_l2 = "Durée : " + str(ts.unit_amount) + " heure(s)" # ------------------------------------------------------ # Override le _rec_name # ------------------------------------------------------ @api.multi @api.depends('project_id', 'partner_id') def name_get(self): result = [] for ts in self: name = ts.calendar_l1 result.append((ts.id, name)) return result # ------------------------------------------------------ # OnChange Functions # ------------------------------------------------------ @api.onchange('project_id') def onchange_project_id(self): self.partner_id = self.project_id.partner_id @api.onchange('partner_id') def onchange_partner_id(self): # affiche le Dispositif Financier par défaut sur la LdT # si il n'y a pas de date limite du dispositif # ou si la date de la Ldt est inférieure à la date limite du dispositif if not self.partner_id.ur_financial_system_date or \ self.date <= self.partner_id.ur_financial_system_date: self.ur_financial_system_id = self.partner_id.ur_financial_system_id # affiche la Convention par défaut sur la LdT # si il n'y a pas de date limite de la convention # ou si la date de la LdT est inférieure à la date limite de la convention if not self.partner_id.ur_regional_convention_date or \ self.date <= self.partner_id.ur_regional_convention_date: self.ur_regional_convention_id = self.partner_id.\ ur_regional_convention_id # ------------------------------------------------------ # Contrains # ------------------------------------------------------ @api.constrains('unit_amount') def _check_hours(self): for record in self: lines = self.search([ ('date', '=', record.date), ('employee_id', '=', record.employee_id.id)]) total = sum(lines.mapped('unit_amount')) if (not self.env.user.company_id.day_working and total > self.env.user.company_id.day_duration): raise ValidationError( "Vous ne pouvez imputer plus de %sh sur la même journée.\n" "Journée du %s" % ( self.env.user.company_id.day_duration, record.date.strftime("%d/%m/%Y"))) @api.constrains('date') def _check_weekday(self): for line in self: dt = datetime.combine(line.date, time(12, 00)) holiday = self.env['resource.calendar.leaves'].search([ '|', ('company_id', '=', False), ('company_id', '=', self.env.user.company_id.id), ('date_from', '<=', dt), ('date_to', '>=', dt), ]) if line.date.weekday() in (5, 6) or holiday: raise ValidationError( "Vous ne pouvez imputer du temps sur un weekend " "ou un jour férié.") # ------------------------------------------------------ # Override ORM # ------------------------------------------------------ @api.multi def unlink(self): for timesheet in self: if timesheet.state in ['submit', 'valid']: raise UserError('Vous ne pouvez pas supprimer une ' 'ligne de temps soumise ou validée') super(ScopHrTimesheet, self).unlink() # ------------------------------------------------------ # Actions # ------------------------------------------------------ @api.multi def action_submit_timesheet_lines(self): """ Crée une feuille de temps avec les lignes sélectionnées """ if any(time.state != 'to_report' or time.sheet_id for time in self): raise UserError( "Vous ne pouvez pas insérer 2 fois la même ligne !") if len(self.mapped('employee_id')) != 1: raise UserError( "Il ne peut y avoir plusieurs employés dans une " "même feuille de temps.") return { 'name': 'New Expense Report', 'type': 'ir.actions.act_window', 'view_mode': 'form', 'res_model': 'cgscop.timesheet.sheet', 'target': 'current', 'context': { 'default_timesheet_line_ids': self.ids, 'default_employee_id': self[0].employee_id.id, 'default_name': self[0].name if len(self) == 1 else '' } }