# © 2020 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import _, api, fields, models from odoo.exceptions import UserError, ValidationError class ScopHrTimesheetSheet(models.Model): _name = "cgscop.timesheet.sheet" _inherit = ["mail.thread", "mail.activity.mixin"] _description = "Timesheet Report" _order = "create_date desc, validation_date desc, id desc" def _default_ur(self): return self.env["res.company"]._ur_default_get() name = fields.Char("Nom", required=True) timesheet_line_ids = fields.One2many( comodel_name="account.analytic.line", inverse_name="sheet_id", string="Lignes de temps", states={"valid": [("readonly", True)]}, copy=False, ) state = fields.Selection( [("draft", "Brouillon"), ("submit", "Soumis"), ("valid", "Validé")], string="Statut", index=True, tracking=True, copy=False, default="draft", required=True, ) employee_id = fields.Many2one( comodel_name="hr.employee", string="Employé", required=True, readonly=True, states={"draft": [("readonly", False)]}, default=lambda self: self.env["hr.employee"].search( [("user_id", "=", self.env.uid)], limit=1 ), ) total_hour = fields.Float(string="Total", compute="_compute_hour", store=True) company_id = fields.Many2one( comodel_name="res.company", string="Company", readonly=True, states={"draft": [("readonly", False)]}, default=lambda self: self.env.company, ) validation_date = fields.Date("Date de validation") submit_date = fields.Date("Soumis le") ur_id = fields.Many2one( "union.regionale", string="Union Régionale", index=True, ondelete="restrict", default=_default_ur, ) can_edit = fields.Boolean("Can Reset", compute="_compute_can_reset") # ------------------------------------------------------ # Compute Functions # ------------------------------------------------------ @api.depends("timesheet_line_ids", "timesheet_line_ids.unit_amount") def _compute_hour(self): for sheet in self: sheet.total_hour = sum(sheet.timesheet_line_ids.mapped("unit_amount")) def _compute_can_reset(self): is_timesheet_user = self.user_has_groups("hr_timesheet.group_timesheet_manager") for sheet in self: if sheet.state == "draft" or is_timesheet_user: sheet.can_edit = True else: sheet.can_edit = False # ------------------------------------------------------ # Constain Functions # ------------------------------------------------------ @api.constrains("timesheet_line_ids", "employee_id") def _check_employee(self): for sheet in self: employee_ids = sheet.timesheet_line_ids.mapped("employee_id") if len(employee_ids) > 1 or ( len(employee_ids) == 1 and employee_ids != sheet.employee_id ): raise ValidationError( _( "Vous ne pouvez pas ajouter les lignes" " de temps de plusieurs employés." ) ) # ------------------------------------------------------ # Override ORM # ------------------------------------------------------ def unlink(self): for timesheet in self: if timesheet.state in ["submit", "valid"]: raise UserError( _( "Vous ne pouvez pas supprimer une " "feuille de temps soumise ou validée" ) ) super(ScopHrTimesheetSheet, self).unlink() # ------------------------------------------------------ # Action button # ------------------------------------------------------ def action_submit_timesheet(self): self.write({"state": "submit", "submit_date": fields.Date.today()}) def approve_timesheet_sheets(self): self.write({"state": "valid", "validation_date": fields.Date.today()}) def reset_timesheet_sheets(self): self.write({"state": "draft", "submit_date": False, "validation_date": False}) def print_timesheet(self): return self.env.ref( "cgscop_timesheet.cgscop_timesheet_sheet_report" ).report_action(self) # ------------------------------------------------------ # Retourne les lignes de la Fdt avec les totaux par projet # ------------------------------------------------------ def _to_duration(self, infloat): return "{:02.0f}:{:02.0f}".format(*divmod(infloat * 60, 60)) def _get_timesheet_line_act(self): for sheet in self: lines = sheet.timesheet_line_ids.sorted( key=lambda b: (b.project_id.name, b.date) ) rows = [] last_project = False tot_project = 0 for line in lines: # On insère un total intermédiaire if last_project != line.project_id.name and tot_project != 0: rows.append( { "total": 1, "name": False, "partner": False, "project": False, "date": False, "ur_financial_system": "Total " + last_project + " : " + self._to_duration(tot_project), "unit_amount": False, } ) tot_project = 0 # On insère la ligne lue rows.append( { "total": 0, "name": line.name, "partner": line.partner_id.name, "project": line.project_id.name, "date": line.date, "ur_financial_system": line.ur_financial_system_id.name, "unit_amount": self._to_duration(line.unit_amount), } ) last_project = line.project_id.name tot_project = tot_project + line.unit_amount # On insère le dernier total rows.append( { "total": 1, "name": False, "partner": False, "project": False, "date": False, "ur_financial_system": "Total " + last_project + " : " + self._to_duration(tot_project), "unit_amount": False, } ) return rows