Skip to content
GitLab
Menu
Why GitLab
Pricing
Contact Sales
Explore
Why GitLab
Pricing
Contact Sales
Explore
Sign in
Get free trial
ikus-soft
odoo-addons
Compare revisions
107c0977d82eb5250ee6c95e3af1db9fdf9f9573 to 4e5f99b04235653aa479b854edae377ad139c033
Commits on Source (4)
hr_timesheet_x: Merge the repport with main module.
· 0a1c83a5
Patrik Dufresne
authored
Jan 24, 2018
0a1c83a5
hr_timesheet_x: Rename Employee Categories for "Position". TASK-951
· 0358a36c
Patrik Dufresne
authored
Jan 24, 2018
0358a36c
hr_timesheet_x: Show description field again. TASK-952
· 397a823b
Patrik Dufresne
authored
Jan 24, 2018
397a823b
hr_timsheet_X: split begin - end field in repport. TASK-953
· 4e5f99b0
Patrik Dufresne
authored
Jan 24, 2018
4e5f99b0
Hide whitespace changes
Inline
Side-by-side
hr_timesheet_project_print/__init__.py
deleted
100644 → 0
View file @
107c0977
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Patrik Dufresne
# Copyright 2017 Patrik Dufresne Service Logiciel inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
\ No newline at end of file
hr_timesheet_project_print/__manifest__.py
deleted
100644 → 0
View file @
107c0977
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Patrik Dufresne
# Copyright 2017 Patrik Dufresne Service Logiciel inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"
name
"
:
"
Project Timesheet printing
"
,
"
description
"
:
"""
TODO
This module adds a report on timesheet lines (hr.analytic.timesheet) to print
out the detailed of hours passed.
"""
,
"
version
"
:
"
10.0.1
"
,
'
author
'
:
'
Patrik Dufresne
'
,
'
website
'
:
'
http://www.patrikdufresne.com
'
,
'
company
'
:
'
Patrik Dufresne Service Logiciel inc.
'
,
'
category
'
:
'
Human Resources
'
,
"
license
"
:
'
AGPL-3
'
,
"
depends
"
:
[
"
hr_timesheet_project_sheet
"
,
],
"
data
"
:
[
"
report/report_timesheet_templates.xml
"
,
],
'
installable
'
:
True
}
hr_timesheet_project_print/i18n/fr_CA.po
deleted
100644 → 0
View file @
107c0977
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_timesheet_project_print
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-15 18:34+0000\n"
"PO-Revision-Date: 2018-01-15 18:34+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "<strong>Comment:</strong>"
msgstr "<strong>Commentaire:</strong>"
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "<strong>Location</strong>"
msgstr "<strong>Emplacement</strong>"
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "<strong>Remote Contact</strong>"
msgstr "<strong>Contact sur place</strong>"
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "<strong>Responsible</strong>"
msgstr "<strong>Responsable</strong>"
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "<strong>Timesheet Period</strong>"
msgstr "<strong>Période de la feuille de temps</strong>"
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "<strong>Total</strong>"
msgstr "<strong>Total</strong>"
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "Begin - End"
msgstr "Début - Fin"
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "Break"
msgstr "Pause"
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "Date"
msgstr "Date "
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "Employee"
msgstr "Employé"
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "Employee Category"
msgstr "Catégorie d'employé"
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "Initial"
msgstr "Initial"
#. module: hr_timesheet_project_print
#: model:ir.actions.report.xml,name:hr_timesheet_project_print.timesheet_project_report_sheet
msgid "Project Timesheet"
msgstr "Feuilles de temps projet"
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "Time"
msgstr "Heure"
#. module: hr_timesheet_project_print
#: model:ir.ui.view,arch_db:hr_timesheet_project_print.report_project_timesheet
msgid "to"
msgstr "au"
hr_timesheet_project_print/static/description/icon.png
deleted
100644 → 0
View file @
107c0977
4.37 KiB
hr_timesheet_project_sheet/__manifest__.py
View file @
4e5f99b0
...
...
@@ -35,7 +35,9 @@
'
data
'
:
[
'
security/ir.model.access.csv
'
,
'
security/hr_timesheet_project_sheet_security.xml
'
,
"
report/report_timesheet_templates.xml
"
,
'
data/hr_timesheet_project_sheet_data.xml
'
,
'
data/hr_timesheet_action_data.xml
'
,
'
views/hr_analytic_timesheet.xml
'
,
'
views/hr_timesheet_project_sheet_templates.xml
'
,
'
views/hr_timesheet_project_sheet_views.xml
'
,
...
...
hr_timesheet_project_sheet/data/hr_timesheet_action_data.xml
0 → 100644
View file @
4e5f99b0
<?xml version="1.0" ?>
<odoo>
<!-- Mail template are declared in a NOUPDATE block
so users can freely customize/delete them -->
<data>
<!--Email template -->
<record
id=
"email_template_timesheet"
model=
"mail.template"
>
<field
name=
"name"
>
Timesheet - Send by Email
</field>
<field
name=
"email_from"
>
${(object.user_id.email and '%s
<
%s
>
' % (object.user_id.name, object.user_id.email) or '')|safe}
</field>
<field
name=
"subject"
>
${object.company_id.name} Timesheet (Ref ${object.number or 'n/a'})
</field>
<field
name=
"partner_to"
>
${object.partner_id.id}
</field>
<field
name=
"model_id"
ref=
"hr_timesheet_project_sheet.model_hr_timesheet_project_sheet_sheet"
/>
<field
name=
"auto_delete"
eval=
"True"
/>
<field
name=
"report_template"
ref=
"timesheet_project_report_sheet"
/>
<field
name=
"report_name"
>
Timesheet_${(object.number or '').replace('/','_')}_${object.state == 'draft' and 'draft' or ''}
</field>
<field
name=
"lang"
>
${object.partner_id.lang}
</field>
<field
name=
"body_html"
>
<![CDATA[
<p>
Dear ${object.partner_id.name}
% set access_action = object.get_access_action()
% set access_url = access_action['type'] == 'ir.actions.act_url' and access_action['url'] or '/report/pdf/account.report_invoice/' + str(object.id)
% set is_online = access_action and access_action['type'] == 'ir.actions.act_url'
% if object.partner_id.parent_id:
(
<i>
${object.partner_id.parent_id.name}
</i>
)
% endif
,
</p>
<p>
Here is your invoice
<strong>
${object.number}
</strong>
% if object.origin:
(with reference: ${object.origin} )
% endif
amounting in
<strong>
${object.amount_total} ${object.currency_id.name}
</strong>
from ${object.company_id.name}.
</p>
% if is_online:
<br/><br/>
<center>
<a
href=
"${access_url}"
style=
"background-color: #1abc9c; padding: 20px; text-decoration: none; color: #fff; border-radius: 5px; font-size: 16px;"
class=
"o_default_snippet_text"
>
View Invoice
</a>
</center>
% endif
<br/><br/>
% if object.state=='paid':
<p>
This invoice is already paid.
</p>
% else:
<p>
Please remit payment at your earliest convenience.
</p>
% endif
<p>
Thank you,
</p>
% if object.user_id and object.user_id.signature:
${object.user_id.signature | safe}
% endif
]]>
</field>
</record>
</data>
</odoo>
hr_timesheet_project_sheet/models/account_analytic_line.py
View file @
4e5f99b0
...
...
@@ -125,23 +125,24 @@ class AccountAnalyticLine(models.Model):
float_time_convert
(
hours
))
)
# check if lines overlap
others
=
self
.
search
([
(
'
id
'
,
'
!=
'
,
self
.
id
),
(
'
user_id
'
,
'
=
'
,
self
.
user_id
.
id
),
(
'
date
'
,
'
=
'
,
self
.
date
),
(
'
time_start
'
,
'
<
'
,
self
.
time_stop
),
(
'
time_stop
'
,
'
>
'
,
self
.
time_start
),
])
if
others
:
message
=
_
(
"
Lines can
'
t overlap:
\n
"
)
message
+=
'
\n
'
.
join
([
'
%s - %s
'
%
(
float_time_convert
(
line
.
time_start
),
float_time_convert
(
line
.
time_stop
))
for
line
in
(
self
+
others
).
sorted
(
lambda
l
:
l
.
time_start
)])
raise
exceptions
.
ValidationError
(
message
)
if
self
.
user_id
:
others
=
self
.
search
([
(
'
id
'
,
'
!=
'
,
self
.
id
),
(
'
user_id
'
,
'
=
'
,
self
.
user_id
.
id
),
(
'
date
'
,
'
=
'
,
self
.
date
),
(
'
time_start
'
,
'
<
'
,
self
.
time_stop
),
(
'
time_stop
'
,
'
>
'
,
self
.
time_start
),
])
if
others
:
message
=
_
(
"
Lines can
'
t overlap:
\n
"
)
message
+=
'
\n
'
.
join
([
'
%s - %s
'
%
(
float_time_convert
(
line
.
time_start
),
float_time_convert
(
line
.
time_stop
))
for
line
in
(
self
+
others
).
sorted
(
lambda
l
:
l
.
time_start
)])
raise
exceptions
.
ValidationError
(
message
)
@api.onchange
(
'
time_start
'
,
'
time_stop
'
,
'
time_break
'
)
def
onchange_hours_start_stop
(
self
):
...
...
hr_timesheet_project_sheet/models/hr_timesheet_project_sheet.py
View file @
4e5f99b0
...
...
@@ -19,9 +19,7 @@
#
##############################################################################
import
time
from
datetime
import
datetime
from
dateutil.relativedelta
import
relativedelta
from
odoo
import
api
,
fields
,
models
from
odoo.tools.translate
import
_
...
...
@@ -64,6 +62,7 @@ class HrTimesheetSheet(models.Model):
contact_id
=
fields
.
Many2one
(
'
res.partner
'
,
string
=
'
Remote Contact
'
,
store
=
True
,
readonly
=
False
)
location
=
fields
.
Char
(
string
=
"
Location
"
,
help
=
"
Short description describing the location of the event.
"
,
store
=
True
,
readonly
=
False
)
comment
=
fields
.
Text
(
'
Additional Information
'
,
readonly
=
True
,
states
=
{
'
draft
'
:
[(
'
readonly
'
,
False
)],
'
new
'
:
[(
'
readonly
'
,
False
)]})
sent
=
fields
.
Boolean
(
readonly
=
True
,
default
=
False
,
copy
=
False
,
help
=
"
It indicates that the timesheet has been sent.
"
)
@api.constrains
(
'
date_to
'
,
'
date_from
'
,
'
project_id
'
)
def
_check_sheet_date
(
self
,
forced_project_id
=
False
):
...
...
@@ -109,6 +108,44 @@ class HrTimesheetSheet(models.Model):
raise
UserError
(
_
(
"
Cannot approve a non-submitted timesheet.
"
))
self
.
write
({
'
state
'
:
'
done
'
})
@api.multi
def
timesheet_print
(
self
):
"""
Print the timesheet and mark it as sent, so that we can see more
easily the next step of the workflow
"""
self
.
ensure_one
()
self
.
sent
=
True
return
self
.
env
[
'
report
'
].
get_action
(
self
,
'
hr_timesheet_project_sheet.report_project_timesheet
'
)
@api.multi
def
action_timesheet_sent
(
self
):
"""
Open a window to compose an email, with the edit invoice template
message loaded by default.
"""
self
.
ensure_one
()
template
=
self
.
env
.
ref
(
'
account.email_template_edi_invoice
'
,
False
)
compose_form
=
self
.
env
.
ref
(
'
mail.email_compose_message_wizard_form
'
,
False
)
ctx
=
dict
(
default_model
=
'
account.invoice
'
,
default_res_id
=
self
.
id
,
default_use_template
=
bool
(
template
),
default_template_id
=
template
and
template
.
id
or
False
,
default_composition_mode
=
'
comment
'
,
mark_invoice_as_sent
=
True
,
custom_layout
=
"
account.mail_template_data_notification_email_account_invoice
"
)
return
{
'
name
'
:
_
(
'
Compose Email
'
),
'
type
'
:
'
ir.actions.act_window
'
,
'
view_type
'
:
'
form
'
,
'
view_mode
'
:
'
form
'
,
'
res_model
'
:
'
mail.compose.message
'
,
'
views
'
:
[(
compose_form
.
id
,
'
form
'
)],
'
view_id
'
:
compose_form
.
id
,
'
target
'
:
'
new
'
,
'
context
'
:
ctx
,
}
@api.multi
def
name_get
(
self
):
# week number according to ISO 8601 Calendar
...
...
hr_timesheet_project_
prin
t/report/report_timesheet_templates.xml
→
hr_timesheet_project_
shee
t/report/report_timesheet_templates.xml
View file @
4e5f99b0
...
...
@@ -68,8 +68,10 @@
<tr>
<th>
Date
</th>
<th>
Employee
</th>
<th>
Employee Category
</th>
<th
class=
"text-right"
>
Begin - End
</th>
<th>
Position
</th>
<th>
Comments
</th>
<th
class=
"text-right"
>
Begin
</th>
<th
class=
"text-right"
>
End
</th>
<th
class=
"text-right"
>
Break
</th>
<th
class=
"text-right"
>
Total
</th>
<th
class=
"text-right"
t-if=
"show_draft"
>
Initial
</th>
...
...
@@ -80,7 +82,7 @@
<t
t-foreach=
"o.timesheet_ids.sorted(key=lambda r: (r.date, r.time_start, r.time_stop))"
t-as=
"l"
>
<!-- Group by timerange for display for Draft -->
<t
t-if=
"show_draft and prev_timerange != (l.date, l.time_start, l.time_stop)"
>
<tr><td
colspan=
"
7
"
><strong>
<tr><td
colspan=
"
9
"
><strong>
<span
t-field=
"l.date"
t-field-options=
"{"format": "d MMM y"}"
/>
-
<span
t-esc=
"'%s:%02.0f' % tuple(int(round(x)) for x in divmod(l.time_start*60,60))"
/>
to
...
...
@@ -98,12 +100,14 @@
<td>
<span
t-field=
"l.employee_category"
/>
</td>
<td>
<span
t-if=
"l.name != '/'"
t-field=
"l.name"
/>
</td>
<td
class=
"text-right"
>
<t
t-if=
"not show_draft"
>
<span
t-esc=
"'%s:%02.0f' % tuple(int(round(x)) for x in divmod(l.time_start*60,60))"
/>
to
<span
t-esc=
"'%s:%02.0f' % tuple(int(round(x)) for x in divmod(l.time_stop*60,60))"
/>
</t>
<span
t-if=
"not show_draft"
t-esc=
"'%s:%02.0f' % tuple(int(round(x)) for x in divmod(l.time_start*60,60))"
/>
</td>
<td
class=
"text-right"
>
<span
t-if=
"not show_draft"
t-esc=
"'%s:%02.0f' % tuple(int(round(x)) for x in divmod(l.time_stop*60,60))"
/>
</td>
<td
class=
"text-right"
>
<t
t-if=
"not show_draft"
>
...
...
@@ -123,11 +127,13 @@
<td/>
<td/>
<td/>
<td/>
<td/>
<td
class=
"text-right"
><strong>
Total
</strong></td>
<td
class=
"text-right"
><strong
t-esc=
"'%s:%02.0f' % tuple(int(round(x)) for x in divmod(sum(o.timesheet_ids.mapped('unit_amount'))*60,60))"
/></td>
</tr>
<tr
t-if=
"show_draft"
>
<td
colspan=
"
7
"
/>
<td
colspan=
"
9
"
/>
</tr>
</tbody>
</table>
...
...
@@ -170,7 +176,7 @@
model=
"hr_timesheet_project_sheet.sheet"
string=
"Project Timesheet"
report_type=
"qweb-pdf"
name=
"hr_timesheet_project_
prin
t.report_project_timesheet"
name=
"hr_timesheet_project_
shee
t.report_project_timesheet"
file=
"report_project_timesheet"
/>
...
...
hr_timesheet_project_sheet/views/hr_timesheet_project_sheet_views.xml
View file @
4e5f99b0
...
...
@@ -60,6 +60,10 @@
<button
name=
"action_timesheet_done"
states=
"confirm"
string=
"Approve"
type=
"object"
groups=
"hr_timesheet.group_hr_timesheet_user"
class=
"oe_highlight"
/>
<button
name=
"action_timesheet_draft"
states=
"done"
string=
"Set to Draft"
type=
"object"
groups=
"hr_timesheet.group_hr_timesheet_user"
/>
<button
name=
"action_timesheet_draft"
states=
"confirm"
string=
"Refuse"
type=
"object"
groups=
"hr_timesheet.group_hr_timesheet_user"
/>
<button
name=
"action_timesheet_sent"
type=
"object"
string=
"Send by Email"
attrs=
"{'invisible':['|',('sent','=',True), ('state', '!=', 'draft')]}"
class=
"oe_highlight"
groups=
"base.group_user"
/>
<button
name=
"timesheet_print"
string=
"Print"
type=
"object"
attrs=
"{'invisible':['|',('sent','=',True), ('state', '!=', 'draft')]}"
class=
"oe_highlight"
groups=
"base.group_user"
/>
<button
name=
"action_timesheet_sent"
type=
"object"
string=
"Send by Email"
attrs=
"{'invisible':['|',('sent','=',False), ('state', '!=', 'draft')]}"
groups=
"base.group_user"
/>
<button
name=
"timesheet_print"
string=
"Print Invoice"
type=
"object"
attrs=
"{'invisible':['|',('sent','=',False), ('state', '!=', 'draft')]}"
groups=
"base.group_user"
/>
<field
name=
"state"
widget=
"statusbar"
statusbar_visible=
"new,confirm,done"
/>
</header>
<sheet>
...
...
@@ -79,31 +83,33 @@
<group>
<field
name=
"user_id"
/>
<field
name=
"contact_id"
/>
<field
name=
"sent"
invisible=
"1"
/>
</group>
</group>
<notebook>
<page
string=
"Details"
class=
"o_hr_timesheet_project_sheet_details"
>
<field
context=
"{'default_project_id': project_id, 'default_name': '/', 'default_date': date_from, 'default_user_id': None}"
name=
"timesheet_ids"
nolabel=
"1"
>
<tree
editable=
"bottom"
string=
"Timesheet Activities"
>
<tree
editable=
"bottom"
default_order=
"date"
string=
"Timesheet Activities"
>
<field
name=
"date"
/>
<field
name=
"name"
invisible=
"1"
/>
<field
name=
"time_start"
widget=
"float_time"
/>
<field
name=
"time_stop"
widget=
"float_time"
/>
<field
name=
"time_break"
widget=
"float_time"
/>
<field
name=
"unit_amount"
widget=
"float_time"
string=
"Hours"
sum=
"Hours"
/>
<field
name=
"employee_category"
/>
<field
name=
"employee_category"
string=
"Position"
/>
<field
name=
"name"
/>
<field
name=
"user_id"
domain=
"[('employee_ids.category_ids', 'in', employee_category)]"
string=
"Employee"
/>
<field
name=
"project_id"
invisible=
"1"
/>
<button
name=
"copy"
type=
"object"
icon=
"fa-files-o"
/>
</tree>
<form
string=
"Timesheet Activities"
>
<group>
<field
name=
"date"
/>
<field
name=
"name"
invisible=
"1"
/>
<field
name=
"time_start"
widget=
"float_time"
/>
<field
name=
"time_stop"
widget=
"float_time"
/>
<field
name=
"time_break"
widget=
"float_time"
/>
<field
name=
"unit_amount"
widget=
"float_time"
string=
"Hours"
/>
<field
name=
"employee_category"
/>
<field
name=
"employee_category"
string=
"Position"
/>
<field
name=
"name"
/>
<field
name=
"user_id"
domain=
"[('employee_ids.category_ids', 'in', employee_category)]"
string=
"Employee"
/>
<field
name=
"project_id"
invisible=
"1"
/>
</group>
...
...