Newer
Older

Benjamin - Le Filament
committed
# © 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

Benjamin - Le Filament
committed
from odoo.exceptions import UserError, ValidationError
class ScopHrTimesheetSheet(models.Model):
_name = "cgscop.timesheet.sheet"
_inherit = ["mail.thread", "mail.activity.mixin"]

Benjamin - Le Filament
committed
_description = "Timesheet Report"
_order = "create_date desc, validation_date desc, id desc"
def _default_ur(self):
return self.env["res.company"]._ur_default_get()

Benjamin - Le Filament
committed
name = fields.Char("Nom", required=True)

Benjamin - Le Filament
committed
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",

Benjamin - Le Filament
committed
index=True,

Benjamin - Le Filament
committed
copy=False,
default="draft",
required=True,
)

Benjamin - Le Filament
committed
employee_id = fields.Many2one(
comodel_name="hr.employee",

Benjamin - Le Filament
committed
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)

Benjamin - Le Filament
committed
company_id = fields.Many2one(
comodel_name="res.company",
string="Company",

Benjamin - Le Filament
committed
readonly=True,
states={"draft": [("readonly", False)]},

Benjamin - Le Filament
committed
validation_date = fields.Date("Date de validation")
submit_date = fields.Date("Soumis le")
ur_id = fields.Many2one(
"union.regionale",
string="Union Régionale",

Benjamin - Le Filament
committed
index=True,
ondelete="restrict",
default=_default_ur,
)
can_edit = fields.Boolean("Can Reset", compute="_compute_can_reset")

Benjamin - Le Filament
committed
# ------------------------------------------------------
# Compute Functions
# ------------------------------------------------------
@api.depends("timesheet_line_ids", "timesheet_line_ids.unit_amount")

Benjamin - Le Filament
committed
def _compute_hour(self):
for sheet in self:
sheet.total_hour = sum(sheet.timesheet_line_ids.mapped("unit_amount"))

Benjamin - Le Filament
committed
def _compute_can_reset(self):
is_timesheet_user = self.user_has_groups("hr_timesheet.group_timesheet_manager")

Benjamin - Le Filament
committed
for sheet in self:
if sheet.state == "draft" or is_timesheet_user:

Benjamin - Le Filament
committed
sheet.can_edit = True
else:
sheet.can_edit = False
# ------------------------------------------------------
# Constain Functions
# ------------------------------------------------------
@api.constrains("timesheet_line_ids", "employee_id")

Benjamin - Le Filament
committed
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
):

Benjamin - Le Filament
committed
raise ValidationError(
_(
"Vous ne pouvez pas ajouter les lignes"
" de temps de plusieurs employés."
)

Benjamin - Le Filament
committed
# ------------------------------------------------------
# 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"
)

Benjamin - Le Filament
committed
super(ScopHrTimesheetSheet, self).unlink()
# ------------------------------------------------------
# Action button
# ------------------------------------------------------
def action_submit_timesheet(self):
self.write({"state": "submit", "submit_date": fields.Date.today()})

Benjamin - Le Filament
committed
def approve_timesheet_sheets(self):
self.write({"state": "valid", "validation_date": fields.Date.today()})

Benjamin - Le Filament
committed
def reset_timesheet_sheets(self):
self.write({"state": "draft", "submit_date": False, "validation_date": False})

Benjamin - Le Filament
committed
def print_timesheet(self):
return self.env.ref(
"cgscop_timesheet.cgscop_timesheet_sheet_report"
).report_action(self)

Hervé Silvant - CGScop
committed
# ------------------------------------------------------
# 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))

Hervé Silvant - CGScop
committed
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)
)

Hervé Silvant - CGScop
committed
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,
}
)

Hervé Silvant - CGScop
committed
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),
}
)

Hervé Silvant - CGScop
committed
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,
}
)

Hervé Silvant - CGScop
committed
return rows