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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# ------------------------------------------------------
# Retourne les lignes de la Fdt avec les totaux par projet
# ------------------------------------------------------
def _to_duration(self, infloat):
return '{0:02.0f}:{1: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