Merge lp:~camptocamp/hr-timesheet/7.0-hr_timesheet_reminder-migr into lp:~hr-core-editors/hr-timesheet/7.0
- 7.0-hr_timesheet_reminder-migr
- Merge into 7.0
Status: | Merged |
---|---|
Merged at revision: | 40 |
Proposed branch: | lp:~camptocamp/hr-timesheet/7.0-hr_timesheet_reminder-migr |
Merge into: | lp:~hr-core-editors/hr-timesheet/7.0 |
Diff against target: |
1734 lines (+626/-669) 14 files modified
hr_timesheet_reminder/__init__.py (+15/-26) hr_timesheet_reminder/__openerp__.py (+41/-43) hr_timesheet_reminder/company.py (+50/-57) hr_timesheet_reminder/hr_employee.py (+42/-53) hr_timesheet_reminder/hr_employee_view.xml (+0/-1) hr_timesheet_reminder/reminder.py (+100/-88) hr_timesheet_reminder/report/__init__.py (+16/-25) hr_timesheet_reminder/report/timesheet_status.py (+63/-65) hr_timesheet_reminder/report/timesheet_status.rml (+157/-163) hr_timesheet_reminder/timesheet_report.xml (+10/-10) hr_timesheet_reminder/wizard/reminder_config.py (+37/-45) hr_timesheet_reminder/wizard/reminder_config_view.xml (+38/-28) hr_timesheet_reminder/wizard/reminder_status.py (+35/-44) hr_timesheet_reminder/wizard/reminder_status_view.xml (+22/-21) |
To merge this branch: | bzr merge lp:~camptocamp/hr-timesheet/7.0-hr_timesheet_reminder-migr |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alexandre Fayolle - camptocamp | code review, no test | Approve | |
Review via email: mp+139655@code.launchpad.net |
Commit message
[MIGR] migration of hr_timesheet_
Description of the change
Migration to OpenERP version 7 of the addon hr_timesheet_
* change of license from GPLv2 to AGPLv3
* replace openerp.
* the dates were not displayed on the report
* migrate the views using the new layout
* formatting and styling
* fix bug: lp:1089390
* fix a small issue on the nextcall of the cron which was initialized not 'tomorrow' but approximately the next day of the server date
- 47. By Guewen Baconnier @ Camptocamp <email address hidden>
-
[MRG] from lp:hr-timesheet/7.0
- 48. By Guewen Baconnier @ Camptocamp <email address hidden>
-
[MIGR] set installable to True
- 49. By Guewen Baconnier @ Camptocamp <email address hidden>
-
[FIX] license in timesheet_
status. rml, formatting
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote : | # |
- 50. By Guewen Baconnier @ Camptocamp <email address hidden>
-
[FIX] use a correct name for a local variable, use tomorrow.strftime instead of time.strftime, so get rid of 'import time'
- 51. By Guewen Baconnier @ Camptocamp <email address hidden>
-
[FIX] use fields.date.today() instead of time.strftime() for a default date
- 52. By Guewen Baconnier @ Camptocamp <email address hidden>
-
[IMP] use a html field instead of a text field for the message
- 53. By Guewen Baconnier @ Camptocamp <email address hidden>
-
[FIX] skip earlier the employees who do not receive the timesheet alerts, avoid unecessary computations/
queries - 54. By Guewen Baconnier @ Camptocamp <email address hidden>
-
[FIX] remove unused import
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
You are right on all the points. I fixed them in my proposal.
Some comments:
* There is now a fields.html. I use it now for the message. As a bonus, we gain a rich editing of the reminder message (yippee, 'Please take time to complete and confirm your timesheet' in *bold*).
* Learned the word Mojibake today :-)
* there is a constant for '%Y-%m-%d' but there is even better for the default values of date and datetime:
fields.
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote : | # |
Yay !
<off-topic>
Mojibake (pronounce modjibaké in fr_FR) is one of these useful words I enjoy sharing :-)
For other illustrated funny / rare french words, you may want to check out http://
</off-topic>
Preview Diff
1 | === modified file 'hr_timesheet_reminder/__init__.py' |
2 | --- hr_timesheet_reminder/__init__.py 2011-08-12 12:53:16 +0000 |
3 | +++ hr_timesheet_reminder/__init__.py 2012-12-13 17:06:20 +0000 |
4 | @@ -1,32 +1,21 @@ |
5 | # -*- coding: utf-8 -*- |
6 | ############################################################################## |
7 | # |
8 | -# Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com) |
9 | -# All Right Reserved |
10 | -# |
11 | -# Author : Arnaud Wüst (Camptocamp) |
12 | -# Author : Guewen Baconnier (Camptocamp) |
13 | -# |
14 | -# WARNING: This program as such is intended to be used by professional |
15 | -# programmers who take the whole responsability of assessing all potential |
16 | -# consequences resulting from its eventual inadequacies and bugs |
17 | -# End users who are looking for a ready-to-use solution with commercial |
18 | -# garantees and support are strongly adviced to contract a Free Software |
19 | -# Service Company |
20 | -# |
21 | -# This program is Free Software; you can redistribute it and/or |
22 | -# modify it under the terms of the GNU General Public License |
23 | -# as published by the Free Software Foundation; either version 2 |
24 | -# of the License, or (at your option) any later version. |
25 | -# |
26 | -# This program is distributed in the hope that it will be useful, |
27 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
28 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
29 | -# GNU General Public License for more details. |
30 | -# |
31 | -# You should have received a copy of the GNU General Public License |
32 | -# along with this program; if not, write to the Free Software |
33 | -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
34 | +# Author: Arnaud Wüst (Camptocamp) |
35 | +# Copyright 2011-2012 Camptocamp SA |
36 | +# |
37 | +# This program is free software: you can redistribute it and/or modify |
38 | +# it under the terms of the GNU Affero General Public License as |
39 | +# published by the Free Software Foundation, either version 3 of the |
40 | +# License, or (at your option) any later version. |
41 | +# |
42 | +# This program is distributed in the hope that it will be useful, |
43 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
44 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
45 | +# GNU Affero General Public License for more details. |
46 | +# |
47 | +# You should have received a copy of the GNU Affero General Public License |
48 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
49 | # |
50 | ############################################################################## |
51 | |
52 | |
53 | === modified file 'hr_timesheet_reminder/__openerp__.py' |
54 | --- hr_timesheet_reminder/__openerp__.py 2012-12-13 12:20:12 +0000 |
55 | +++ hr_timesheet_reminder/__openerp__.py 2012-12-13 17:06:20 +0000 |
56 | @@ -1,54 +1,52 @@ |
57 | # -*- coding: utf-8 -*- |
58 | ############################################################################## |
59 | # |
60 | -# Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com) |
61 | -# All Right Reserved |
62 | -# |
63 | -# Author : Arnaud Wüst (Camptocamp) |
64 | -# Author : Nicolas Bessi (Camptocamp) |
65 | -# Author : Guewen Baconnier (Camptocamp) |
66 | -# |
67 | -# WARNING: This program as such is intended to be used by professional |
68 | -# programmers who take the whole responsability of assessing all potential |
69 | -# consequences resulting from its eventual inadequacies and bugs |
70 | -# End users who are looking for a ready-to-use solution with commercial |
71 | -# garantees and support are strongly adviced to contract a Free Software |
72 | -# Service Company |
73 | -# |
74 | -# This program is Free Software; you can redistribute it and/or |
75 | -# modify it under the terms of the GNU General Public License |
76 | -# as published by the Free Software Foundation; either version 2 |
77 | -# of the License, or (at your option) any later version. |
78 | -# |
79 | -# This program is distributed in the hope that it will be useful, |
80 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
81 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
82 | -# GNU General Public License for more details. |
83 | -# |
84 | -# You should have received a copy of the GNU General Public License |
85 | -# along with this program; if not, write to the Free Software |
86 | -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
87 | +# Author: Arnaud Wüst (Camptocamp) |
88 | +# Author: Nicolas Bessi (Camptocamp) |
89 | +# Author: Guewen Baconnier (Camptocamp) (port to v7) |
90 | +# Copyright 2011-2012 Camptocamp SA |
91 | +# |
92 | +# This program is free software: you can redistribute it and/or modify |
93 | +# it under the terms of the GNU Affero General Public License as |
94 | +# published by the Free Software Foundation, either version 3 of the |
95 | +# License, or (at your option) any later version. |
96 | +# |
97 | +# This program is distributed in the hope that it will be useful, |
98 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
99 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
100 | +# GNU Affero General Public License for more details. |
101 | +# |
102 | +# You should have received a copy of the GNU Affero General Public License |
103 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
104 | # |
105 | ############################################################################## |
106 | |
107 | - |
108 | { |
109 | - "name" : "Timesheet Reminder", |
110 | - "version" : "2.0", |
111 | - "author" : "Camptocamp", |
112 | - "category" : "", |
113 | - "website" : "http://www.camptocamp.com", |
114 | + "name": "Timesheet Reminder", |
115 | + "version": "2.0", |
116 | + "author": "Camptocamp", |
117 | + "license": 'AGPL-3', |
118 | + "category": "", |
119 | + "website": "http://www.camptocamp.com", |
120 | "description": """ |
121 | -Timesheet Reports Module: |
122 | - * Add a menu in Human Resources / Configuration / Timesheet Reminder. It allows to send automatic emails to those who did not complete their timesheet in the last 5 weeks. |
123 | - * Per employee, you can choose to send the reminder or not. |
124 | - * Add a report in Human Resources / Reporting / Timesheet / Timesheet Status which displays the state of the last 5 timesheets for all users per company. |
125 | - |
126 | -This module replaces the modules c2c_timesheet_reports in TinyERP 4 and OpenERP 5. |
127 | +Timesheet Reports Module |
128 | +======================== |
129 | + |
130 | + * Add a menu in `Human Resources / Configuration |
131 | + / Timesheet Reminder`. |
132 | + It allows to send automatic emails to those who did |
133 | + not complete their timesheet in the last 5 weeks. |
134 | + * Per employee, you can choose to send the reminder or not. |
135 | + * Add a report in `Human Resources / Reporting / Timesheet |
136 | + / Timesheet Status` which displays the state of the last |
137 | + 5 timesheets for all users per company. |
138 | + |
139 | +This module replaces the modules c2c_timesheet_reports |
140 | +of TinyERP 4 and OpenERP 5. |
141 | """, |
142 | - "depends" : ["hr_timesheet_sheet"], |
143 | - "init_xml" : [], |
144 | - "update_xml" : [ |
145 | + "depends": ["hr_timesheet_sheet"], |
146 | + "init_xml": [], |
147 | + "update_xml": [ |
148 | 'security/ir.model.access.csv', |
149 | 'wizard/reminder_config_view.xml', |
150 | 'wizard/reminder_status_view.xml', |
151 | @@ -56,5 +54,5 @@ |
152 | 'timesheet_report.xml', |
153 | ], |
154 | "active": False, |
155 | - 'installable': False |
156 | + 'installable': True |
157 | } |
158 | |
159 | === modified file 'hr_timesheet_reminder/company.py' |
160 | --- hr_timesheet_reminder/company.py 2011-09-01 13:44:19 +0000 |
161 | +++ hr_timesheet_reminder/company.py 2012-12-13 17:06:20 +0000 |
162 | @@ -1,57 +1,50 @@ |
163 | # -*- coding: utf-8 -*- |
164 | ############################################################################## |
165 | # |
166 | -# Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com) |
167 | -# All Right Reserved |
168 | -# |
169 | -# Author : Arnaud Wüst (Camptocamp) |
170 | -# Author : Guewen Baconnier (Camptocamp) |
171 | -# |
172 | -# WARNING: This program as such is intended to be used by professional |
173 | -# programmers who take the whole responsability of assessing all potential |
174 | -# consequences resulting from its eventual inadequacies and bugs |
175 | -# End users who are looking for a ready-to-use solution with commercial |
176 | -# garantees and support are strongly adviced to contract a Free Software |
177 | -# Service Company |
178 | -# |
179 | -# This program is Free Software; you can redistribute it and/or |
180 | -# modify it under the terms of the GNU General Public License |
181 | -# as published by the Free Software Foundation; either version 2 |
182 | -# of the License, or (at your option) any later version. |
183 | -# |
184 | -# This program is distributed in the hope that it will be useful, |
185 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
186 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
187 | -# GNU General Public License for more details. |
188 | -# |
189 | -# You should have received a copy of the GNU General Public License |
190 | -# along with this program; if not, write to the Free Software |
191 | -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
192 | +# Author: Arnaud Wüst (Camptocamp) |
193 | +# Author: Guewen Baconnier (Camptocamp) |
194 | +# Copyright 2011-2012 Camptocamp SA |
195 | +# |
196 | +# This program is free software: you can redistribute it and/or modify |
197 | +# it under the terms of the GNU Affero General Public License as |
198 | +# published by the Free Software Foundation, either version 3 of the |
199 | +# License, or (at your option) any later version. |
200 | +# |
201 | +# This program is distributed in the hope that it will be useful, |
202 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
203 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
204 | +# GNU Affero General Public License for more details. |
205 | +# |
206 | +# You should have received a copy of the GNU Affero General Public License |
207 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
208 | # |
209 | ############################################################################## |
210 | |
211 | - |
212 | -from datetime import date, datetime |
213 | -from dateutil.relativedelta import * |
214 | -from osv import fields, osv |
215 | -from tools.translate import _ |
216 | - |
217 | - |
218 | -class res_company(osv.osv): |
219 | +from datetime import datetime |
220 | +from dateutil.relativedelta import relativedelta, MO, SU |
221 | +from openerp.osv import osv, orm |
222 | +from openerp.tools.translate import _ |
223 | + |
224 | + |
225 | +class res_company(orm.Model): |
226 | _inherit = 'res.company' |
227 | |
228 | def get_reminder_recipients(self, cr, uid, ids, context=None): |
229 | """Return the list of users that must receive the email""" |
230 | - res = {}.fromkeys(ids, []) |
231 | + res = dict((company_id, []) for company_id in ids) |
232 | + |
233 | employee_obj = self.pool.get('hr.employee') |
234 | |
235 | - companies = self.browse(cr, uid, ids, context=context) |
236 | - |
237 | - for company in companies: |
238 | - employee_ids = employee_obj.search(cr, uid, |
239 | - [('company_id', '=', company.id), |
240 | - ('active', '=', True)], |
241 | - context=context) |
242 | + for company in self.browse(cr, uid, ids, context=context): |
243 | + employee_ids = employee_obj.search( |
244 | + cr, uid, |
245 | + [('company_id', '=', company.id), |
246 | + ('receive_timesheet_alerts', '=', True)], |
247 | + context=context) |
248 | + |
249 | + if not employee_ids: |
250 | + continue |
251 | + |
252 | employees = employee_obj.browse(cr, uid, employee_ids, context=context) |
253 | |
254 | #periods |
255 | @@ -62,24 +55,26 @@ |
256 | # for each employee |
257 | for employee in employees: |
258 | # is timesheet for a period not confirmed ? |
259 | - for p_index in range(len(periods)): |
260 | - period = periods[p_index] |
261 | + for period in periods: |
262 | status = employee_obj.compute_timesheet_status(cr, uid, employee.id, period, context) |
263 | |
264 | # if there is a missing sheet or a draft sheet |
265 | # and the user can receive alerts |
266 | # then we must alert the user |
267 | - if status in ['Missing', 'Draft'] and employee.receive_timesheet_alerts: |
268 | + if status in ['Missing', 'Draft']: |
269 | res[company.id].append(employee) |
270 | - break # no need to go further for this user, he is now added in the list, go to the next one |
271 | + # no need to go further for this user, |
272 | + # he is now added in the list, go to the next one |
273 | + break |
274 | return res |
275 | |
276 | def compute_timesheet_periods(self, cr, uid, company, date, periods_number=5, context=None): |
277 | """ return the timeranges to display. This is the 5 last timesheets""" |
278 | periods = [] |
279 | - last_start_date, last_end_date = self.get_last_period_dates(cr, uid, company, date, context=context) |
280 | + last_start_date, last_end_date = self.get_last_period_dates( |
281 | + cr, uid, company, date, context=context) |
282 | for cpt in range(periods_number): |
283 | - #find the delta between last_XXX_date to XXX_date |
284 | + # find the delta between last_XXX_date to XXX_date |
285 | if company.timesheet_range == 'month': |
286 | delta = relativedelta(months=-cpt) |
287 | elif company.timesheet_range == 'week': |
288 | @@ -87,7 +82,9 @@ |
289 | elif company.timesheet_range == 'year': |
290 | delta = relativedelta(years=-cpt) |
291 | else: |
292 | - raise osv.except_osv(_('Error'), _('Unknow timesheet range: %s') % (company.timesheet_range,)) |
293 | + raise osv.except_osv( |
294 | + _('Error'), |
295 | + _('Unknow timesheet range: %s') % company.timesheet_range) |
296 | |
297 | start_date = last_start_date + delta |
298 | end_date = last_end_date + delta |
299 | @@ -97,26 +94,22 @@ |
300 | |
301 | def get_last_period_dates(self, cr, uid, company, date, context=None): |
302 | """ return the start date and end date of the last period to display """ |
303 | - |
304 | + |
305 | # return the first day and last day of the month |
306 | if company.timesheet_range == 'month': |
307 | start_date = date |
308 | - end_date = start_date + relativedelta(months = +1) |
309 | + end_date = start_date + relativedelta(months=+1) |
310 | |
311 | #return the first and last days of the week |
312 | elif company.timesheet_range == 'week': |
313 | # get monday of current week |
314 | start_date = date + relativedelta(weekday=MO(-1)) |
315 | - # get sunday of current week |
316 | + # get sunday of current week |
317 | end_date = date + relativedelta(weekday=SU(+1)) |
318 | |
319 | # return the first and last days of the year |
320 | else: |
321 | - start_date = datetime(date.year, 1, 1) |
322 | + start_date = datetime(date.year, 1, 1) |
323 | end_date = datetime(date.year, 12, 31) |
324 | |
325 | - |
326 | return start_date, end_date |
327 | - |
328 | - |
329 | -res_company() |
330 | |
331 | === modified file 'hr_timesheet_reminder/hr_employee.py' |
332 | --- hr_timesheet_reminder/hr_employee.py 2011-09-01 13:44:19 +0000 |
333 | +++ hr_timesheet_reminder/hr_employee.py 2012-12-13 17:06:20 +0000 |
334 | @@ -1,47 +1,38 @@ |
335 | # -*- coding: utf-8 -*- |
336 | ############################################################################## |
337 | # |
338 | -# Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com) |
339 | -# All Right Reserved |
340 | -# |
341 | -# Author : Arnaud Wüst (Camptocamp) |
342 | -# Author : Guewen Baconnier (Camptocamp) |
343 | -# |
344 | -# WARNING: This program as such is intended to be used by professional |
345 | -# programmers who take the whole responsability of assessing all potential |
346 | -# consequences resulting from its eventual inadequacies and bugs |
347 | -# End users who are looking for a ready-to-use solution with commercial |
348 | -# garantees and support are strongly adviced to contract a Free Software |
349 | -# Service Company |
350 | -# |
351 | -# This program is Free Software; you can redistribute it and/or |
352 | -# modify it under the terms of the GNU General Public License |
353 | -# as published by the Free Software Foundation; either version 2 |
354 | -# of the License, or (at your option) any later version. |
355 | -# |
356 | -# This program is distributed in the hope that it will be useful, |
357 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
358 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
359 | -# GNU General Public License for more details. |
360 | -# |
361 | -# You should have received a copy of the GNU General Public License |
362 | -# along with this program; if not, write to the Free Software |
363 | -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
364 | +# Author: Arnaud Wüst (Camptocamp) |
365 | +# Author: Guewen Baconnier (Camptocamp) (port to v7) |
366 | +# Copyright 2011-2012 Camptocamp SA |
367 | +# |
368 | +# This program is free software: you can redistribute it and/or modify |
369 | +# it under the terms of the GNU Affero General Public License as |
370 | +# published by the Free Software Foundation, either version 3 of the |
371 | +# License, or (at your option) any later version. |
372 | +# |
373 | +# This program is distributed in the hope that it will be useful, |
374 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
375 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
376 | +# GNU Affero General Public License for more details. |
377 | +# |
378 | +# You should have received a copy of the GNU Affero General Public License |
379 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
380 | # |
381 | ############################################################################## |
382 | -from datetime import * |
383 | - |
384 | -from osv import fields, osv |
385 | - |
386 | - |
387 | -class hr_employee(osv.osv): |
388 | + |
389 | +from openerp.osv import fields, orm |
390 | +from openerp.tools import DEFAULT_SERVER_DATE_FORMAT |
391 | + |
392 | + |
393 | +class hr_employee(orm.Model): |
394 | _inherit = 'hr.employee' |
395 | + |
396 | _columns = { |
397 | - 'receive_timesheet_alerts': fields.boolean('Receive Timesheet Alerts'), |
398 | + 'receive_timesheet_alerts': fields.boolean('Receive Timesheet Alerts'), |
399 | } |
400 | |
401 | _defaults = { |
402 | - 'receive_timesheet_alerts': lambda *a: True, |
403 | + 'receive_timesheet_alerts': True, |
404 | } |
405 | |
406 | def compute_timesheet_status(self, cr, uid, ids, period, context): |
407 | @@ -50,35 +41,33 @@ |
408 | status = 'Error' |
409 | |
410 | if isinstance(ids, list): |
411 | + assert len(ids) == 1, "Only 1 ID expected" |
412 | ids = ids[0] |
413 | |
414 | employee = self.browse(cr, uid, ids, context=context) |
415 | |
416 | - time_from = period[0] |
417 | - time_to = period[1] |
418 | - |
419 | - # does the timesheet exsists in db and what is its status? |
420 | - timeformat = "%Y-%m-%d" |
421 | - str_date_from = time_from.strftime(timeformat) |
422 | - str_date_to = time_to.strftime(timeformat) |
423 | - |
424 | - cr.execute("""SELECT state, date_from, date_to |
425 | - FROM hr_timesheet_sheet_sheet |
426 | - WHERE employee_id = %s |
427 | - AND date_from >= %s |
428 | - AND date_to <= %s""", |
429 | + time_from, time_to = period |
430 | + |
431 | + # does the timesheet exists in db and what is its status? |
432 | + str_date_from = time_from.strftime(DEFAULT_SERVER_DATE_FORMAT) |
433 | + str_date_to = time_to.strftime(DEFAULT_SERVER_DATE_FORMAT) |
434 | + |
435 | + cr.execute( |
436 | + """SELECT state, date_from, date_to |
437 | + FROM hr_timesheet_sheet_sheet |
438 | + WHERE employee_id = %s |
439 | + AND date_from >= %s |
440 | + AND date_to <= %s""", |
441 | (employee.id, str_date_from, str_date_to)) |
442 | sheets = cr.dictfetchall() |
443 | |
444 | - #the timesheet does not exists in db |
445 | + # the timesheet does not exists in db |
446 | if not sheets: |
447 | status = 'Missing' |
448 | |
449 | - if len(sheets) > 0: |
450 | + else: |
451 | status = 'Confirmed' |
452 | - for s in sheets: |
453 | - if s['state'] == 'draft': |
454 | + for sheet in sheets: |
455 | + if sheet['state'] == 'draft': |
456 | status = 'Draft' |
457 | return status |
458 | - |
459 | -hr_employee() |
460 | |
461 | === modified file 'hr_timesheet_reminder/hr_employee_view.xml' |
462 | --- hr_timesheet_reminder/hr_employee_view.xml 2011-08-12 12:53:16 +0000 |
463 | +++ hr_timesheet_reminder/hr_employee_view.xml 2012-12-13 17:06:20 +0000 |
464 | @@ -5,7 +5,6 @@ |
465 | <field name="name">hr.timesheet.employee.rmnd_form</field> |
466 | <field name="inherit_id" ref="hr_timesheet.hr_timesheet_employee_extd_form"/> |
467 | <field name="model">hr.employee</field> |
468 | - <field name="type">form</field> |
469 | <field name="arch" type="xml"> |
470 | <field name="journal_id" widget="selection" position="after"> |
471 | <field name="receive_timesheet_alerts"/> |
472 | |
473 | === modified file 'hr_timesheet_reminder/reminder.py' |
474 | --- hr_timesheet_reminder/reminder.py 2011-09-01 13:44:19 +0000 |
475 | +++ hr_timesheet_reminder/reminder.py 2012-12-13 17:06:20 +0000 |
476 | @@ -1,157 +1,170 @@ |
477 | # -*- coding: utf-8 -*- |
478 | ############################################################################## |
479 | # |
480 | -# Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com) |
481 | -# All Right Reserved |
482 | -# |
483 | -# Author : Arnaud Wüst (Camptocamp) |
484 | -# Author : Guewen Baconnier (Camptocamp) |
485 | -# |
486 | -# WARNING: This program as such is intended to be used by professional |
487 | -# programmers who take the whole responsability of assessing all potential |
488 | -# consequences resulting from its eventual inadequacies and bugs |
489 | -# End users who are looking for a ready-to-use solution with commercial |
490 | -# garantees and support are strongly adviced to contract a Free Software |
491 | -# Service Company |
492 | -# |
493 | -# This program is Free Software; you can redistribute it and/or |
494 | -# modify it under the terms of the GNU General Public License |
495 | -# as published by the Free Software Foundation; either version 2 |
496 | -# of the License, or (at your option) any later version. |
497 | -# |
498 | -# This program is distributed in the hope that it will be useful, |
499 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
500 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
501 | -# GNU General Public License for more details. |
502 | -# |
503 | -# You should have received a copy of the GNU General Public License |
504 | -# along with this program; if not, write to the Free Software |
505 | -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
506 | +# Author: Arnaud Wüst (Camptocamp) |
507 | +# Author: Guewen Baconnier (Camptocamp) (port to v7) |
508 | +# Copyright 2011-2012 Camptocamp SA |
509 | +# |
510 | +# This program is free software: you can redistribute it and/or modify |
511 | +# it under the terms of the GNU Affero General Public License as |
512 | +# published by the Free Software Foundation, either version 3 of the |
513 | +# License, or (at your option) any later version. |
514 | +# |
515 | +# This program is distributed in the hope that it will be useful, |
516 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
517 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
518 | +# GNU Affero General Public License for more details. |
519 | +# |
520 | +# You should have received a copy of the GNU Affero General Public License |
521 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
522 | # |
523 | ############################################################################## |
524 | |
525 | -import tools |
526 | -import time |
527 | - |
528 | from datetime import datetime, timedelta |
529 | -from osv import fields, osv |
530 | -from tools.translate import _ |
531 | - |
532 | -class reminder(osv.osv): |
533 | +from openerp.osv import fields, orm |
534 | +from openerp.tools.translate import _ |
535 | +from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT |
536 | + |
537 | + |
538 | +class reminder(orm.Model): |
539 | _name = "hr.timesheet.reminder" |
540 | _description = "Handle the scheduling of timesheet reminders" |
541 | |
542 | _columns = { |
543 | - 'reply_to': fields.char('Reply To', size=100), |
544 | - 'message': fields.text('Message'), |
545 | - 'subject': fields.char('Subject', size=200), |
546 | + 'reply_to': fields.char('Reply To'), |
547 | + 'message': fields.html('Message'), |
548 | + 'subject': fields.char('Subject'), |
549 | } |
550 | |
551 | - #default cron (the one created if missing) |
552 | + # default cron (the one created if missing) |
553 | cron = {'active': False, |
554 | 'priority': 1, |
555 | 'interval_number': 1, |
556 | 'interval_type': 'weeks', |
557 | - 'nextcall': time.strftime("%Y-%m-%d %H:%M:%S", |
558 | - (datetime.today() |
559 | - + timedelta(days=1)).timetuple()), # tomorrow same time |
560 | + 'nextcall': False, # to set on the creation of the cron |
561 | 'numbercall': -1, |
562 | - 'doall': True, |
563 | + 'doall': False, |
564 | 'model': 'hr.timesheet.reminder', |
565 | 'function': 'run', |
566 | 'args': '()', |
567 | } |
568 | |
569 | - #default message (the one created if missing) |
570 | + # default message (the one created if missing) |
571 | message = {'reply_to': 'spam@camptocamp.com'} |
572 | |
573 | def run(self, cr, uid, context=None): |
574 | """ find the reminder recipients and send them an email """ |
575 | - context = context or {} |
576 | - |
577 | company_obj = self.pool.get('res.company') |
578 | - #get all companies |
579 | + # get all companies |
580 | company_ids = company_obj.search(cr, uid, [], context=context) |
581 | |
582 | - #for each company, get all recipients |
583 | + # for each company, get all recipients |
584 | recipients = [] |
585 | - company_recipients = company_obj.get_reminder_recipients(cr, uid, company_ids, context=context) |
586 | - for company_id, rec in company_recipients.iteritems(): |
587 | + company_recipients = company_obj.get_reminder_recipients( |
588 | + cr, uid, company_ids, context=context) |
589 | + for rec in company_recipients.itervalues(): |
590 | recipients += rec |
591 | |
592 | - #get the message to send |
593 | + # get the message to send |
594 | message_id = self.get_message_id(cr, uid, context) |
595 | message_data = self.browse(cr, uid, message_id, context=context) |
596 | |
597 | - #send them email if they have an email defined |
598 | - emails = [] |
599 | + # send them email if they have an email defined |
600 | for employee in recipients: |
601 | - if employee.work_email: |
602 | - emails.append(employee.work_email) |
603 | - |
604 | - if emails: |
605 | - tools.email_send(message_data.reply_to, [], message_data.subject, message_data.message, email_bcc=emails) |
606 | - |
607 | - def get_cron_id(self, cr, uid, context): |
608 | + if not employee.work_email: |
609 | + continue |
610 | + vals = { |
611 | + 'state': 'outgoing', |
612 | + 'subject': message_data.subject, |
613 | + 'body_html': message_data.message, |
614 | + 'email_to': employee.work_email, |
615 | + 'email_from': message_data.reply_to, |
616 | + } |
617 | + self.pool.get('mail.mail').create(cr, uid, vals, context=context) |
618 | + |
619 | + return True |
620 | + |
621 | + def get_cron_id(self, cr, uid, context=None): |
622 | """return the reminder cron's id. Create one if the cron does not exists """ |
623 | + if context is None: |
624 | + context = {} |
625 | cron_obj = self.pool.get('ir.cron') |
626 | # find the cron that send messages |
627 | - cron_id = cron_obj.search(cr, uid, [('function', 'ilike', self.cron['function']), |
628 | - ('model', 'ilike', self.cron['model'])], |
629 | - context={'active_test': False}) |
630 | - if cron_id: |
631 | - cron_id = cron_id[0] |
632 | + ctx = dict(context, active_test=False) |
633 | + cron_ids = cron_obj.search( |
634 | + cr, uid, |
635 | + [('function', 'ilike', self.cron['function']), |
636 | + ('model', 'ilike', self.cron['model'])], |
637 | + context=ctx) |
638 | + |
639 | + cron_id = None |
640 | + if cron_ids: |
641 | + cron_id = cron_ids[0] |
642 | |
643 | # the cron does not exists |
644 | - if not cron_id: |
645 | - self.cron['name'] = _('timesheet status reminder') |
646 | - cron_id = cron_obj.create(cr, uid, self.cron, context) |
647 | + if cron_id is None: |
648 | + vals = dict(self.cron, |
649 | + name=_('timesheet status reminder'), |
650 | + nextcall=self._cron_nextcall()) |
651 | + |
652 | + cron_id = cron_obj.create(cr, uid, vals, context=context) |
653 | |
654 | return cron_id |
655 | |
656 | - def get_message_id(self, cr, uid, context): |
657 | - """ return the message'id. create one if the message does not exists """ |
658 | + @staticmethod |
659 | + def _cron_nextcall(): |
660 | + tomorrow = datetime.today() + timedelta(days=1) |
661 | + return tomorrow.strftime(DEFAULT_SERVER_DATETIME_FORMAT) |
662 | + |
663 | + def get_message_id(self, cr, uid, context=None): |
664 | + """ return the message's id. create one if the message does not exists """ |
665 | #there is only one line in db, let's get it |
666 | - message_id = self.search(cr, uid, [], limit=1, context=context) |
667 | + message_ids = self.search(cr, uid, [], limit=1, context=context) |
668 | |
669 | - if message_id: |
670 | - message_id = message_id[0] |
671 | + message_id = None |
672 | + if message_ids: |
673 | + message_id = message_ids[0] |
674 | |
675 | #the message does not exists |
676 | - if not message_id: |
677 | - #translate |
678 | - self.message['subject'] = _('Timesheet Reminder') |
679 | - self.message['message'] = _('At least one of your last timesheets is still in draft or is missing. Please take time to complete and confirm it.') |
680 | + if message_id is None: |
681 | + vals = dict(self.message, |
682 | + subject=_('Timesheet Reminder'), |
683 | + message=_( |
684 | + 'At least one of your last timesheets is still ' |
685 | + 'in draft or is missing. Please take time to ' |
686 | + 'complete and confirm it.')) |
687 | |
688 | - message_id = self.create(cr, uid, self.message, context) |
689 | + message_id = self.create(cr, uid, vals, context) |
690 | |
691 | return message_id |
692 | |
693 | - def get_config(self, cr, uid, context): |
694 | + def get_config(self, cr, uid, context=None): |
695 | """return the reminder config from the db """ |
696 | |
697 | cron_id = self.get_cron_id(cr, uid, context) |
698 | |
699 | - cron_data = self.pool.get('ir.cron').browse(cr, uid, cron_id) |
700 | + cron_data = self.pool.get('ir.cron').browse( |
701 | + cr, uid, cron_id, context=context) |
702 | |
703 | - #there is only one line in db, let's get it |
704 | - message_id = self.get_message_id(cr, uid, context) |
705 | - message_data = self.browse(cr, uid, message_id) |
706 | + # there is only one line in db, let's get it |
707 | + message_id = self.get_message_id(cr, uid, context=context) |
708 | + message_data = self.browse(cr, uid, message_id, context=context) |
709 | return {'reminder_active': cron_data.active, |
710 | 'interval_type': cron_data.interval_type, |
711 | 'interval_number': cron_data.interval_number, |
712 | 'reply_to': message_data.reply_to, |
713 | 'message': message_data.message, |
714 | 'subject': message_data.subject, |
715 | - 'nextcall': cron_data.nextcall, |
716 | + 'nextcall': self._cron_nextcall(), |
717 | } |
718 | |
719 | - def save_config(self, cr, uid, ids, datas, context): |
720 | + def save_config(self, cr, uid, ids, datas, context=None): |
721 | """save the reminder config """ |
722 | |
723 | #modify the cron |
724 | - cron_id = self.get_cron_id(cr, uid, context) |
725 | - self.pool.get('ir.cron').write(cr, uid, [cron_id], |
726 | + cron_id = self.get_cron_id(cr, uid, context=context) |
727 | + self.pool.get('ir.cron').write( |
728 | + cr, uid, [cron_id], |
729 | {'active': datas['reminder_active'], |
730 | 'interval_number': datas['interval_number'], |
731 | 'interval_type': datas['interval_type'], |
732 | @@ -159,11 +172,10 @@ |
733 | context=context) |
734 | #modify the message |
735 | message_id = ids or self.get_message_id(cr, uid, context) |
736 | - self.write(cr, uid, [message_id], |
737 | + self.write( |
738 | + cr, uid, [message_id], |
739 | {'reply_to': datas['reply_to'], |
740 | 'message': datas['message'], |
741 | 'subject': datas['subject'], |
742 | }, context=context) |
743 | return True |
744 | - |
745 | -reminder() |
746 | |
747 | === modified file 'hr_timesheet_reminder/report/__init__.py' |
748 | --- hr_timesheet_reminder/report/__init__.py 2011-08-12 12:53:16 +0000 |
749 | +++ hr_timesheet_reminder/report/__init__.py 2012-12-13 17:06:20 +0000 |
750 | @@ -1,31 +1,22 @@ |
751 | # -*- coding: utf-8 -*- |
752 | ############################################################################## |
753 | # |
754 | -# Copyright (c) Camptocamp SA |
755 | -# Author: Arnaud WÃŒst |
756 | -# |
757 | -# |
758 | -# |
759 | -# WARNING: This program as such is intended to be used by professional |
760 | -# programmers who take the whole responsability of assessing all potential |
761 | -# consequences resulting from its eventual inadequacies and bugs |
762 | -# End users who are looking for a ready-to-use solution with commercial |
763 | -# garantees and support are strongly adviced to contract a Free Software |
764 | -# Service Company |
765 | -# |
766 | -# This program is Free Software; you can redistribute it and/or |
767 | -# modify it under the terms of the GNU General Public License |
768 | -# as published by the Free Software Foundation; either version 2 |
769 | -# of the License, or (at your option) any later version. |
770 | -# |
771 | -# This program is distributed in the hope that it will be useful, |
772 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
773 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
774 | -# GNU General Public License for more details. |
775 | -# |
776 | -# You should have received a copy of the GNU General Public License |
777 | -# along with this program; if not, write to the Free Software |
778 | -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
779 | +# Author: Arnaud Wüst (Camptocamp) |
780 | +# Copyright 2011-2012 Camptocamp SA |
781 | +# |
782 | +# This program is free software: you can redistribute it and/or modify |
783 | +# it under the terms of the GNU Affero General Public License as |
784 | +# published by the Free Software Foundation, either version 3 of the |
785 | +# License, or (at your option) any later version. |
786 | +# |
787 | +# This program is distributed in the hope that it will be useful, |
788 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
789 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
790 | +# GNU Affero General Public License for more details. |
791 | +# |
792 | +# You should have received a copy of the GNU Affero General Public License |
793 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
794 | # |
795 | ############################################################################## |
796 | + |
797 | import timesheet_status |
798 | |
799 | === modified file 'hr_timesheet_reminder/report/timesheet_status.py' |
800 | --- hr_timesheet_reminder/report/timesheet_status.py 2011-09-01 13:44:19 +0000 |
801 | +++ hr_timesheet_reminder/report/timesheet_status.py 2012-12-13 17:06:20 +0000 |
802 | @@ -1,47 +1,40 @@ |
803 | # -*- coding: utf-8 -*- |
804 | ############################################################################## |
805 | # |
806 | -# Copyright (c) Camptocamp SA |
807 | -# Author: Arnaud WÃŒst |
808 | -# Author: Guewen Baconnier |
809 | -# |
810 | -# |
811 | -# |
812 | -# WARNING: This program as such is intended to be used by professional |
813 | -# programmers who take the whole responsability of assessing all potential |
814 | -# consequences resulting from its eventual inadequacies and bugs |
815 | -# End users who are looking for a ready-to-use solution with commercial |
816 | -# garantees and support are strongly adviced to contract a Free Software |
817 | -# Service Company |
818 | -# |
819 | -# This program is Free Software; you can redistribute it and/or |
820 | -# modify it under the terms of the GNU General Public License |
821 | -# as published by the Free Software Foundation; either version 2 |
822 | -# of the License, or (at your option) any later version. |
823 | -# |
824 | -# This program is distributed in the hope that it will be useful, |
825 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
826 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
827 | -# GNU General Public License for more details. |
828 | -# |
829 | -# You should have received a copy of the GNU General Public License |
830 | -# along with this program; if not, write to the Free Software |
831 | -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
832 | +# Author: Arnaud Wüst (Camptocamp) |
833 | +# Author: Guewen Baconnier (Camptocamp) (port to v7) |
834 | +# Copyright 2011-2012 Camptocamp SA |
835 | +# |
836 | +# This program is free software: you can redistribute it and/or modify |
837 | +# it under the terms of the GNU Affero General Public License as |
838 | +# published by the Free Software Foundation, either version 3 of the |
839 | +# License, or (at your option) any later version. |
840 | +# |
841 | +# This program is distributed in the hope that it will be useful, |
842 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
843 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
844 | +# GNU Affero General Public License for more details. |
845 | +# |
846 | +# You should have received a copy of the GNU Affero General Public License |
847 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
848 | # |
849 | ############################################################################## |
850 | |
851 | import time |
852 | |
853 | from datetime import datetime |
854 | -from report import report_sxw |
855 | +from openerp.report import report_sxw |
856 | +from openerp.tools import DEFAULT_SERVER_DATE_FORMAT |
857 | +from openerp.tools.translate import _ |
858 | |
859 | |
860 | class timesheet_status(report_sxw.rml_parse): |
861 | _name = 'report.timesheet.reminder.status' |
862 | |
863 | - def __init__(self, cr, uid, name, context): |
864 | - super(timesheet_status, self).__init__(cr, uid, name, context) |
865 | + def __init__(self, cr, uid, name, context=None): |
866 | + super(timesheet_status, self).__init__(cr, uid, name, context=context) |
867 | self.data = {} |
868 | + self.end_date = None |
869 | self.localcontext.update({ |
870 | 'compute': self.compute, |
871 | 'time': time, |
872 | @@ -60,64 +53,65 @@ |
873 | """compute all datas and do all the calculations before to start the rml rendering |
874 | - objects are companies |
875 | """ |
876 | - #init the data array |
877 | + # init the data array |
878 | self.data = {} |
879 | for o in objects: |
880 | self.data[o.id] = {} |
881 | - #get the list of employees ids to treat |
882 | + # get the list of employees ids to treat |
883 | for o in objects: |
884 | self.data[o.id]['employees'] = self._compute_employees_list(o) |
885 | |
886 | - #get the time range for each company |
887 | + # get the time range for each company |
888 | + end_date = datetime.strptime(self.end_date, DEFAULT_SERVER_DATE_FORMAT) |
889 | for o in objects: |
890 | - self.data[o.id]['time_ranges'] = \ |
891 | - self._compute_periods(o, datetime.strptime(self.end_date, "%Y-%m-%d")) |
892 | + self.data[o.id]['time_ranges'] = self._compute_periods(o, end_date) |
893 | |
894 | - #get the status of each timesheet for each employee |
895 | + # get the status of each timesheet for each employee |
896 | for o in objects: |
897 | self.data[o.id]['sheet_status'] = self._compute_all_status(o) |
898 | |
899 | def _compute_employees_list(self, company): |
900 | - """ return a dictionnary of lists of employees ids linked to the companies (param company) """ |
901 | + """ return a dictionnary of lists of employees ids linked |
902 | + to the companies (param company) """ |
903 | employee_obj = self.pool.get('hr.employee') |
904 | employee_ids = employee_obj.search(self.cr, self.uid, |
905 | [('company_id', '=', company.id), |
906 | ('active', '=', True)], |
907 | context=self.localcontext) |
908 | - return employee_obj.browse(self.cr, self.uid, employee_ids, context=self.localcontext) |
909 | + return employee_obj.browse( |
910 | + self.cr, self.uid, employee_ids, context=self.localcontext) |
911 | |
912 | def _get_last_period_dates(self, company, date): |
913 | """ return the start date of the last period to display """ |
914 | - return self.pool.get('res.company').\ |
915 | - get_last_period_dates(self.cr, self.uid, company, date, context=self.localcontext) |
916 | + return self.pool.get('res.company').get_last_period_dates( |
917 | + self.cr, |
918 | + self.uid, |
919 | + company, |
920 | + date, |
921 | + context=self.localcontext) |
922 | |
923 | def _compute_periods(self, company, date): |
924 | """ return the timeranges to display. This is the 5 last timesheets """ |
925 | - return self.pool.get('res.company').\ |
926 | - compute_timesheet_periods(self.cr, self.uid, company, date, context=self.localcontext) |
927 | + return self.pool.get('res.company').compute_timesheet_periods( |
928 | + self.cr, |
929 | + self.uid, |
930 | + company, |
931 | + date, |
932 | + context=self.localcontext) |
933 | |
934 | def get_title(self, obj): |
935 | """ return the title of the main table """ |
936 | - last_id = len(self.data[obj.id]['time_ranges']) - 1 |
937 | - start_date = time.strptime(str(self.data[obj.id]['time_ranges'][last_id][0]), |
938 | - "%Y-%m-%d %H:%M:%S") |
939 | - start_date = time.strftime("%d.%m.%Y", start_date) |
940 | - |
941 | - end_date = time.strptime(str(self.data[obj.id]['time_ranges'][0][1]), |
942 | - "%Y-%m-%d %H:%M:%S") |
943 | - end_date = time.strftime("%d.%m.%Y", end_date) |
944 | - |
945 | - return obj.name + ", " + start_date + " to " + end_date |
946 | + timerange = self.data[obj.id]['time_ranges'] |
947 | + start_date = self.formatLang(timerange[-1][0], date=True) |
948 | + end_date = self.formatLang(timerange[0][1], date=True) |
949 | + |
950 | + return obj.name + ", " + start_date + _(" to ") + end_date |
951 | |
952 | def get_timerange_title(self, obj, cpt): |
953 | """ return a header text for a periods column """ |
954 | - start_date = self.data[obj.id]['time_ranges'][cpt][0] |
955 | - start_date = time.strptime(str(start_date), "%Y-%m-%d %H:%M:%S") |
956 | - start_date = time.strftime("%d.%m.%Y", start_date) |
957 | - |
958 | - end_date = self.data[obj.id]['time_ranges'][cpt][1] |
959 | - end_date = time.strptime(str(end_date), "%Y-%m-%d %H:%M:%S") |
960 | - end_date = time.strftime("%d.%m.%Y", end_date) |
961 | + timerange = self.data[obj.id]['time_ranges'][cpt] |
962 | + start_date = self.formatLang(timerange[0], date=True) |
963 | + end_date = self.formatLang(timerange[1], date=True) |
964 | |
965 | return start_date + "\n " + end_date |
966 | |
967 | @@ -131,21 +125,25 @@ |
968 | |
969 | def _compute_timesheet_status(self, employee_id, period): |
970 | """ return the timesheet status for a user and a period """ |
971 | - return self.pool.get('hr.employee').\ |
972 | - compute_timesheet_status(self.cr, self.uid, employee_id, period, context=self.localcontext) |
973 | + return self.pool.get('hr.employee').compute_timesheet_status( |
974 | + self.cr, |
975 | + self.uid, |
976 | + employee_id, |
977 | + period, |
978 | + context=self.localcontext) |
979 | |
980 | - def _compute_all_status(self, o): |
981 | + def _compute_all_status(self, obj): |
982 | """ compute all status for all employees for all periods """ |
983 | result = {} |
984 | |
985 | #for each periods |
986 | - for p_index in range(len(self.data[o.id]['time_ranges'])): |
987 | + for p_index, period in enumerate(self.data[obj.id]['time_ranges']): |
988 | result[p_index] = {} |
989 | - period = self.data[o.id]['time_ranges'][p_index] |
990 | #for each employees |
991 | - for employee in self.data[o.id]['employees']: |
992 | + for employee in self.data[obj.id]['employees']: |
993 | #compute the status |
994 | - result[p_index][employee.id] = self._compute_timesheet_status(employee.id, period) |
995 | + result[p_index][employee.id] = self._compute_timesheet_status( |
996 | + employee.id, period) |
997 | |
998 | return result |
999 | |
1000 | |
1001 | === modified file 'hr_timesheet_reminder/report/timesheet_status.rml' |
1002 | --- hr_timesheet_reminder/report/timesheet_status.rml 2011-08-12 12:53:16 +0000 |
1003 | +++ hr_timesheet_reminder/report/timesheet_status.rml 2012-12-13 17:06:20 +0000 |
1004 | @@ -1,165 +1,159 @@ |
1005 | <?xml version="1.0"?> |
1006 | <document filename="timesheet_status.pdf"> |
1007 | -############################################################################## |
1008 | -# |
1009 | -# Copyright (c) Camptocamp SA |
1010 | -# Author: Arnaud Wüst |
1011 | -# |
1012 | -# |
1013 | -# WARNING: This program as such is intended to be used by professional |
1014 | -# programmers who take the whole responsability of assessing all potential |
1015 | -# consequences resulting from its eventual inadequacies and bugs |
1016 | -# End users who are looking for a ready-to-use solution with commercial |
1017 | -# garantees and support are strongly adviced to contract a Free Software |
1018 | -# Service Company |
1019 | -# |
1020 | -# This program is Free Software; you can redistribute it and/or |
1021 | -# modify it under the terms of the GNU General Public License |
1022 | -# as published by the Free Software Foundation; either version 2 |
1023 | -# of the License, or (at your option) any later version. |
1024 | -# |
1025 | -# This program is distributed in the hope that it will be useful, |
1026 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1027 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1028 | -# GNU General Public License for more details. |
1029 | -# |
1030 | -# You should have received a copy of the GNU General Public License |
1031 | -# along with this program; if not, write to the Free Software |
1032 | -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
1033 | -# |
1034 | -############################################################################## |
1035 | - |
1036 | - <!-- Process all datas --> |
1037 | - <template pageSize="(21cm,29.7cm)" title="Timesheet Status" author="Camptocamp" allowSplitting="20"> |
1038 | - |
1039 | - |
1040 | - <!-- PAGE: template of all pages (= all pages except first and last if defined)--> |
1041 | - <pageTemplate id="all"> |
1042 | - <pageGraphics> |
1043 | - <setFont name="Helvetica-Bold" size="9"/> |
1044 | - |
1045 | - <!--Header--> |
1046 | - <drawString x="1.2cm" y="28.1cm">[[ company.name ]]</drawString> |
1047 | - <drawString x="17.0cm" y="28.1cm">Timesheet Status</drawString> |
1048 | - |
1049 | - <lineMode width="0.7"/> |
1050 | - <lines>1.2cm 28.0cm 19.8cm 28.0cm</lines> |
1051 | - |
1052 | - <!-- Footer --> |
1053 | - <setFont name="Helvetica" size="9"/> |
1054 | - <drawString x="1.2cm" y="1.3cm"> [[ time.strftime("%m-%d-%y %H:%M", time.localtime()) ]]</drawString> |
1055 | - <drawString x="18.8cm" y="1.3cm">Page <pageNumber/></drawString> |
1056 | - |
1057 | - </pageGraphics> |
1058 | - <frame id="all" x1="1.2cm" y1="1.7cm" width="18.6cm" height="25.8cm"/> |
1059 | - </pageTemplate> |
1060 | - |
1061 | - </template> |
1062 | - <stylesheet> |
1063 | - |
1064 | - <!--TABLE: standard table type "columns" (which means there is a title, a header of fields names and then lines of values) --> |
1065 | - <blockTableStyle id="std"> |
1066 | - <blockAlignment value="LEFT"/> |
1067 | - <blockValign value="TOP"/> |
1068 | - <blockBottomPadding length="4"/> |
1069 | - <blockFont name="Helvetica" size="9" start="0,0" stop="-1,-1"/> |
1070 | - |
1071 | - <!-- first line: table name, fake as it was only one cell. grey bg --> |
1072 | - <lineStyle kind="BOX" colorName="black" start="0,0" stop="-1,0"/> |
1073 | - <blockBackground colorName="#cccccc" start="0,0" stop="-1,0"/> |
1074 | - <blockFont name="Helvetica" size="9" start="0,0" stop="-1,0"/> |
1075 | - <!-- second line: header of columns --> |
1076 | - <lineStyle kind="GRID" colorName="black" start="0,1" stop="-1,1"/> |
1077 | - <blockFont name="Helvetica-Oblique" start="0,1" stop="-1,1"/> |
1078 | - <!-- next lines: light grey lines, strong black columns separator, reduce padding to write more data in cells --> |
1079 | - <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,2" stop="-1,-1"/> |
1080 | - <lineStyle kind="LINEAFTER" colorName="black" start="0,2" stop="-1,-1"/> |
1081 | - <!-- last line: line below --> |
1082 | - <lineStyle kind="OUTLINE" colorName="black" start="0,0" stop="-1,-1"/> |
1083 | - <!-- all columns centered except the first two (1 system columns + employee) --> |
1084 | - <blockAlignment value="CENTER" start="2,1" stop="-1,-1" /> |
1085 | - |
1086 | - </blockTableStyle> |
1087 | - |
1088 | - <!-- default para in tables --> |
1089 | - <paraStyle name="std" |
1090 | - fontName="Helvetica" |
1091 | - fontSize="9" |
1092 | - alignment="LEFT" |
1093 | - /> |
1094 | - |
1095 | - <paraStyle name="Confirmed" |
1096 | - fontName="Helvetica" |
1097 | - fontSize="9" |
1098 | - alignment="CENTER" |
1099 | - backColor="green" |
1100 | - textColor="white" |
1101 | - /> |
1102 | - |
1103 | - <paraStyle name="Missing" |
1104 | - fontName="Helvetica" |
1105 | - fontSize="9" |
1106 | - alignment="CENTER" |
1107 | - backColor="red" |
1108 | - textColor="white" |
1109 | - /> |
1110 | - |
1111 | - <paraStyle name="Draft" |
1112 | - fontName="Helvetica" |
1113 | - fontSize="9" |
1114 | - alignment="CENTER" |
1115 | - backColor="orange" |
1116 | - textColor="black" |
1117 | - /> |
1118 | - |
1119 | - <paraStyle name="Error" |
1120 | - fontName="Helvetica" |
1121 | - fontSize="9" |
1122 | - alignment="CENTER" |
1123 | - textColor="red" |
1124 | - /> |
1125 | - |
1126 | - <paraStyle name="Not in Company" |
1127 | - fontName="Helvetica" |
1128 | - fontSize="9" |
1129 | - alignment="CENTER" |
1130 | - textColor="lightgrey" |
1131 | - /> |
1132 | - |
1133 | - |
1134 | - </stylesheet> |
1135 | - |
1136 | - <story> |
1137 | - |
1138 | - [[repeatIn(objects, 'o')]] |
1139 | - <blockTable style="std" repeatRows="2" colWidths="0,5cm,2.7cm,2.7cm,2.7cm,2.7cm,2.7cm" > |
1140 | - |
1141 | - <tr> |
1142 | - <td/> |
1143 | - <td>[[get_title(o)]]</td> |
1144 | - </tr> |
1145 | - |
1146 | - <tr> |
1147 | - <td/> |
1148 | - <td>Employees</td> |
1149 | - <td>[[ get_timerange_title(o, 4) ]]</td> |
1150 | - <td>[[ get_timerange_title(o, 3) ]]</td> |
1151 | - <td>[[ get_timerange_title(o, 2) ]]</td> |
1152 | - <td>[[ get_timerange_title(o, 1) ]]</td> |
1153 | - <td>[[ get_timerange_title(o, 0) ]]</td> |
1154 | - </tr> |
1155 | - |
1156 | - <tr> |
1157 | - <td>[[repeatIn(get_user_list(o),'u')]]</td> |
1158 | - <td><para style="std">[[ u.name ]]</para></td> |
1159 | - <td><para>[[ setTag('para','para',{'style':get_timesheet_status(o, u, 4)}) ]][[ get_timesheet_status(o, u, 4) ]]</para></td> |
1160 | - <td><para>[[ setTag('para','para',{'style':get_timesheet_status(o, u, 3)}) ]][[ get_timesheet_status(o, u, 3) ]]</para></td> |
1161 | - <td><para>[[ setTag('para','para',{'style':get_timesheet_status(o, u, 2)}) ]][[ get_timesheet_status(o, u, 2) ]]</para></td> |
1162 | - <td><para>[[ setTag('para','para',{'style':get_timesheet_status(o, u, 1)}) ]][[ get_timesheet_status(o, u, 1) ]]</para></td> |
1163 | - <td><para>[[ setTag('para','para',{'style':get_timesheet_status(o, u, 0)}) ]][[ get_timesheet_status(o, u, 0) ]]</para></td> |
1164 | - </tr> |
1165 | - |
1166 | - </blockTable> |
1167 | - |
1168 | - </story> |
1169 | - </document> |
1170 | + <!-- |
1171 | + ############################################################################## |
1172 | + # |
1173 | + # Author: Arnaud Wüst (Camptocamp) |
1174 | + # Copyright 2011-2012 Camptocamp SA |
1175 | + # |
1176 | + # This program is free software: you can redistribute it and/or modify |
1177 | + # it under the terms of the GNU Affero General Public License as |
1178 | + # published by the Free Software Foundation, either version 3 of the |
1179 | + # License, or (at your option) any later version. |
1180 | + # |
1181 | + # This program is distributed in the hope that it will be useful, |
1182 | + # but WITHOUT ANY WARRANTY; without even the implied warranty of |
1183 | + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1184 | + # GNU Affero General Public License for more details. |
1185 | + # |
1186 | + # You should have received a copy of the GNU Affero General Public License |
1187 | + # along with this program. If not, see <http://www.gnu.org/licenses/>. |
1188 | + # |
1189 | + ############################################################################## |
1190 | + --> |
1191 | + |
1192 | + |
1193 | + <!-- Process all datas --> |
1194 | + <template pageSize="(21cm,29.7cm)" title="Timesheet Status" author="Camptocamp" allowSplitting="20"> |
1195 | + |
1196 | + |
1197 | + <!-- PAGE: template of all pages (= all pages except first and last if defined)--> |
1198 | + <pageTemplate id="all"> |
1199 | + <pageGraphics> |
1200 | + <setFont name="Helvetica-Bold" size="9"/> |
1201 | + |
1202 | + <!--Header--> |
1203 | + <drawString x="1.2cm" y="28.1cm">[[ company.name ]]</drawString> |
1204 | + <drawString x="17.0cm" y="28.1cm">Timesheet Status</drawString> |
1205 | + |
1206 | + <lineMode width="0.7"/> |
1207 | + <lines>1.2cm 28.0cm 19.8cm 28.0cm</lines> |
1208 | + |
1209 | + <!-- Footer --> |
1210 | + <setFont name="Helvetica" size="9"/> |
1211 | + <drawString x="1.2cm" y="1.3cm"> [[ time.strftime("%m-%d-%y %H:%M", time.localtime()) ]]</drawString> |
1212 | + <drawString x="18.8cm" y="1.3cm">Page <pageNumber/></drawString> |
1213 | + |
1214 | + </pageGraphics> |
1215 | + <frame id="all" x1="1.2cm" y1="1.7cm" width="18.6cm" height="25.8cm"/> |
1216 | + </pageTemplate> |
1217 | + |
1218 | + </template> |
1219 | + <stylesheet> |
1220 | + |
1221 | + <!--TABLE: standard table type "columns" (which means there is a title, a header of fields names and then lines of values) --> |
1222 | + <blockTableStyle id="std"> |
1223 | + <blockAlignment value="LEFT"/> |
1224 | + <blockValign value="TOP"/> |
1225 | + <blockBottomPadding length="4"/> |
1226 | + <blockFont name="Helvetica" size="9" start="0,0" stop="-1,-1"/> |
1227 | + |
1228 | + <!-- first line: table name, fake as it was only one cell. grey bg --> |
1229 | + <lineStyle kind="BOX" colorName="black" start="0,0" stop="-1,0"/> |
1230 | + <blockBackground colorName="#cccccc" start="0,0" stop="-1,0"/> |
1231 | + <blockFont name="Helvetica" size="9" start="0,0" stop="-1,0"/> |
1232 | + <!-- second line: header of columns --> |
1233 | + <lineStyle kind="GRID" colorName="black" start="0,1" stop="-1,1"/> |
1234 | + <blockFont name="Helvetica-Oblique" start="0,1" stop="-1,1"/> |
1235 | + <!-- next lines: light grey lines, strong black columns separator, reduce padding to write more data in cells --> |
1236 | + <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,2" stop="-1,-1"/> |
1237 | + <lineStyle kind="LINEAFTER" colorName="black" start="0,2" stop="-1,-1"/> |
1238 | + <!-- last line: line below --> |
1239 | + <lineStyle kind="OUTLINE" colorName="black" start="0,0" stop="-1,-1"/> |
1240 | + <!-- all columns centered except the first two (1 system columns + employee) --> |
1241 | + <blockAlignment value="CENTER" start="2,1" stop="-1,-1" /> |
1242 | + |
1243 | + </blockTableStyle> |
1244 | + |
1245 | + <!-- default para in tables --> |
1246 | + <paraStyle name="std" |
1247 | + fontName="Helvetica" |
1248 | + fontSize="9" |
1249 | + alignment="LEFT" |
1250 | + /> |
1251 | + |
1252 | + <paraStyle name="Confirmed" |
1253 | + fontName="Helvetica" |
1254 | + fontSize="9" |
1255 | + alignment="CENTER" |
1256 | + backColor="green" |
1257 | + textColor="white" |
1258 | + /> |
1259 | + |
1260 | + <paraStyle name="Missing" |
1261 | + fontName="Helvetica" |
1262 | + fontSize="9" |
1263 | + alignment="CENTER" |
1264 | + backColor="red" |
1265 | + textColor="white" |
1266 | + /> |
1267 | + |
1268 | + <paraStyle name="Draft" |
1269 | + fontName="Helvetica" |
1270 | + fontSize="9" |
1271 | + alignment="CENTER" |
1272 | + backColor="orange" |
1273 | + textColor="black" |
1274 | + /> |
1275 | + |
1276 | + <paraStyle name="Error" |
1277 | + fontName="Helvetica" |
1278 | + fontSize="9" |
1279 | + alignment="CENTER" |
1280 | + textColor="red" |
1281 | + /> |
1282 | + |
1283 | + <paraStyle name="Not in Company" |
1284 | + fontName="Helvetica" |
1285 | + fontSize="9" |
1286 | + alignment="CENTER" |
1287 | + textColor="lightgrey" |
1288 | + /> |
1289 | + |
1290 | + |
1291 | + </stylesheet> |
1292 | + |
1293 | + <story> |
1294 | + |
1295 | + [[repeatIn(objects, 'o')]] |
1296 | + <blockTable style="std" repeatRows="2" colWidths="0,5cm,2.7cm,2.7cm,2.7cm,2.7cm,2.7cm" > |
1297 | + |
1298 | + <tr> |
1299 | + <td/> |
1300 | + <td>[[get_title(o)]]</td> |
1301 | + </tr> |
1302 | + |
1303 | + <tr> |
1304 | + <td/> |
1305 | + <td>Employees</td> |
1306 | + <td>[[ get_timerange_title(o, 4) ]]</td> |
1307 | + <td>[[ get_timerange_title(o, 3) ]]</td> |
1308 | + <td>[[ get_timerange_title(o, 2) ]]</td> |
1309 | + <td>[[ get_timerange_title(o, 1) ]]</td> |
1310 | + <td>[[ get_timerange_title(o, 0) ]]</td> |
1311 | + </tr> |
1312 | + |
1313 | + <tr> |
1314 | + <td>[[repeatIn(get_user_list(o),'u')]]</td> |
1315 | + <td><para style="std">[[ u.name ]]</para></td> |
1316 | + <td><para>[[ setTag('para', 'para', {'style': get_timesheet_status(o, u, 4)}) ]][[ get_timesheet_status(o, u, 4) ]]</para></td> |
1317 | + <td><para>[[ setTag('para', 'para', {'style': get_timesheet_status(o, u, 3)}) ]][[ get_timesheet_status(o, u, 3) ]]</para></td> |
1318 | + <td><para>[[ setTag('para', 'para', {'style': get_timesheet_status(o, u, 2)}) ]][[ get_timesheet_status(o, u, 2) ]]</para></td> |
1319 | + <td><para>[[ setTag('para', 'para', {'style': get_timesheet_status(o, u, 1)}) ]][[ get_timesheet_status(o, u, 1) ]]</para></td> |
1320 | + <td><para>[[ setTag('para', 'para', {'style': get_timesheet_status(o, u, 0)}) ]][[ get_timesheet_status(o, u, 0) ]]</para></td> |
1321 | + </tr> |
1322 | + |
1323 | + </blockTable> |
1324 | + |
1325 | + </story> |
1326 | +</document> |
1327 | |
1328 | === modified file 'hr_timesheet_reminder/timesheet_report.xml' |
1329 | --- hr_timesheet_reminder/timesheet_report.xml 2011-08-12 12:53:16 +0000 |
1330 | +++ hr_timesheet_reminder/timesheet_report.xml 2012-12-13 17:06:20 +0000 |
1331 | @@ -1,15 +1,15 @@ |
1332 | <?xml version="1.0"?> |
1333 | <openerp> |
1334 | - <data> |
1335 | - <report |
1336 | - id="timesheet_status" |
1337 | - string="Timesheet Status" |
1338 | - model="res.company" |
1339 | - name="timesheet.reminder.status" |
1340 | - rml="hr_timesheet_reminder/report/timesheet_status.rml" |
1341 | - auto="False" |
1342 | + <data> |
1343 | + <report |
1344 | + id="timesheet_status" |
1345 | + string="Timesheet Status" |
1346 | + model="res.company" |
1347 | + name="timesheet.reminder.status" |
1348 | + rml="hr_timesheet_reminder/report/timesheet_status.rml" |
1349 | + auto="False" |
1350 | header="True" |
1351 | menu="False"/> |
1352 | - |
1353 | - </data> |
1354 | + |
1355 | + </data> |
1356 | </openerp> |
1357 | |
1358 | === modified file 'hr_timesheet_reminder/wizard/reminder_config.py' |
1359 | --- hr_timesheet_reminder/wizard/reminder_config.py 2011-08-12 12:53:16 +0000 |
1360 | +++ hr_timesheet_reminder/wizard/reminder_config.py 2012-12-13 17:06:20 +0000 |
1361 | @@ -1,53 +1,48 @@ |
1362 | # -*- coding: utf-8 -*- |
1363 | ############################################################################## |
1364 | # |
1365 | -# Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com) |
1366 | -# All Right Reserved |
1367 | -# |
1368 | -# Author : Guewen Baconnier (Camptocamp) |
1369 | -# Author : Arnaud Wüst (Camptocamp) |
1370 | -# |
1371 | -# WARNING: This program as such is intended to be used by professional |
1372 | -# programmers who take the whole responsability of assessing all potential |
1373 | -# consequences resulting from its eventual inadequacies and bugs |
1374 | -# End users who are looking for a ready-to-use solution with commercial |
1375 | -# garantees and support are strongly adviced to contract a Free Software |
1376 | -# Service Company |
1377 | -# |
1378 | -# This program is Free Software; you can redistribute it and/or |
1379 | -# modify it under the terms of the GNU General Public License |
1380 | -# as published by the Free Software Foundation; either version 2 |
1381 | -# of the License, or (at your option) any later version. |
1382 | -# |
1383 | -# This program is distributed in the hope that it will be useful, |
1384 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1385 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1386 | -# GNU General Public License for more details. |
1387 | -# |
1388 | -# You should have received a copy of the GNU General Public License |
1389 | -# along with this program; if not, write to the Free Software |
1390 | -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
1391 | +# Author: Arnaud Wüst (Camptocamp) |
1392 | +# Author: Guewen Baconnier (Camptocamp) (port to v7) |
1393 | +# Copyright 2011-2012 Camptocamp SA |
1394 | +# |
1395 | +# This program is free software: you can redistribute it and/or modify |
1396 | +# it under the terms of the GNU Affero General Public License as |
1397 | +# published by the Free Software Foundation, either version 3 of the |
1398 | +# License, or (at your option) any later version. |
1399 | +# |
1400 | +# This program is distributed in the hope that it will be useful, |
1401 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1402 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1403 | +# GNU Affero General Public License for more details. |
1404 | +# |
1405 | +# You should have received a copy of the GNU Affero General Public License |
1406 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1407 | # |
1408 | ############################################################################## |
1409 | |
1410 | -from osv import osv, fields |
1411 | - |
1412 | - |
1413 | -class reminder_config(osv.osv_memory): |
1414 | +from openerp.osv import orm, fields |
1415 | + |
1416 | + |
1417 | +class reminder_config(orm.TransientModel): |
1418 | _name = 'hr.timesheet.reminder.config' |
1419 | |
1420 | _columns = { |
1421 | 'reminder_active': fields.boolean('Reminder Active'), |
1422 | - 'interval_type': fields.selection([('days','Day(s)'), ('weeks', 'Week(s)'), ('months', 'Month(s)')], |
1423 | - 'Periodicity Unit',), |
1424 | - 'interval_number': fields.integer('Periodicity Quantity',), |
1425 | - 'nextcall': fields.datetime('Next Run',), |
1426 | - 'message': fields.text('Message', required=True), |
1427 | - 'subject': fields.char('Subject', size=200, required=True), |
1428 | - 'reply_to': fields.char('Reply To', size=100, required=True), |
1429 | + 'interval_type': fields.selection( |
1430 | + [('days', 'Day(s)'), |
1431 | + ('weeks', 'Week(s)'), |
1432 | + ('months', 'Month(s)')], |
1433 | + 'Periodicity Unit'), |
1434 | + 'interval_number': fields.integer('Periodicity Quantity'), |
1435 | + 'nextcall': fields.datetime('Next Run'), |
1436 | + 'message': fields.html('Message', required=True), |
1437 | + 'subject': fields.char('Subject', required=True), |
1438 | + 'reply_to': fields.char('Reply To', required=True), |
1439 | } |
1440 | |
1441 | def _check_interval_number(self, cr, uid, ids, context=None): |
1442 | + """This constraint should always have 1 id, we are in a TransientModel""" |
1443 | + assert len(ids) == 1, "Only 1 ID expected" |
1444 | obj = self.browse(cr, uid, ids[0], context=context) |
1445 | if obj.interval_number < 1: |
1446 | return False |
1447 | @@ -60,23 +55,22 @@ |
1448 | def default_get(self, cr, uid, fields, context=None): |
1449 | res = super(reminder_config, self).default_get(cr, uid, fields, context=context) |
1450 | data = self.pool.get('hr.timesheet.reminder').\ |
1451 | - get_config(cr, uid, context) |
1452 | + get_config(cr, uid, context=context) |
1453 | res.update(data) |
1454 | return res |
1455 | |
1456 | - def run(self, cr, uid, ids, context): |
1457 | + def run(self, cr, uid, ids, context=None): |
1458 | """ execute the timesheets check and send emails """ |
1459 | reminder_obj = self.pool.get('hr.timesheet.reminder') |
1460 | reminder_obj.run(cr, uid, context=context) |
1461 | return {'type': 'ir.actions.act_window_close'} |
1462 | |
1463 | - def save(self, cr, uid, ids, context): |
1464 | + def save(self, cr, uid, ids, context=None): |
1465 | """ save defined settings in db """ |
1466 | - |
1467 | # get the wizard datas |
1468 | - wizard = self.browse(cr, uid, ids, context=context)[0] |
1469 | + wizard = self.browse(cr, uid, ids[0], context=context) |
1470 | |
1471 | - #retrieve the default cron values |
1472 | + # retrieve the default cron values |
1473 | reminder_obj = self.pool.get('hr.timesheet.reminder') |
1474 | |
1475 | values = {}.fromkeys(wizard._columns.keys(), False) |
1476 | @@ -85,5 +79,3 @@ |
1477 | |
1478 | reminder_obj.save_config(cr, uid, False, values, context=context) |
1479 | return {'type': 'ir.actions.act_window_close'} |
1480 | - |
1481 | -reminder_config() |
1482 | |
1483 | === modified file 'hr_timesheet_reminder/wizard/reminder_config_view.xml' |
1484 | --- hr_timesheet_reminder/wizard/reminder_config_view.xml 2011-08-12 12:53:16 +0000 |
1485 | +++ hr_timesheet_reminder/wizard/reminder_config_view.xml 2012-12-13 17:06:20 +0000 |
1486 | @@ -5,29 +5,39 @@ |
1487 | <record id="view_hr_timesheet_reminder_config_form" model="ir.ui.view"> |
1488 | <field name="name">hr.timesheet.reminder.config.form</field> |
1489 | <field name="model">hr.timesheet.reminder.config</field> |
1490 | - <field name="type">form</field> |
1491 | <field name="arch" type="xml"> |
1492 | - <form string="Timesheet Reminder"> |
1493 | - <group colspan="4" col="4" string="Periodicity" > |
1494 | - <field name="reminder_active" /> |
1495 | - <newline/> |
1496 | - <field name="nextcall" attrs="{'required':[('reminder_active','==',True)]}"/> |
1497 | - <newline/> |
1498 | - <field name="interval_number" string="Then send message every" attrs="{'required':[('reminder_active','==',True)]}"/> |
1499 | - <field name="interval_type" nolabel="1" attrs="{'required':[('reminder_active','==',True)]}"/> |
1500 | - </group> |
1501 | - |
1502 | - <group colspan="4" col="2" string="Message"> |
1503 | - <field name="reply_to"/> |
1504 | - <field name="subject"/> |
1505 | - <field name="message" height="200"/> |
1506 | - </group> |
1507 | - |
1508 | - <group colspan="4" col="6"> |
1509 | - <button icon="gtk-cancel" special="cancel" string="Cancel"/> |
1510 | - <button icon="gtk-ok" string="Save configuration" name="save" type="object"/> |
1511 | - <button icon="gtk-ok" string="Run now" name="run" type="object"/> |
1512 | - </group> |
1513 | + <form string="Timesheet Reminder" version="7.0"> |
1514 | + <sheet> |
1515 | + <group> |
1516 | + <separator string="Periodicity" colspan="4"/> |
1517 | + <field name="reminder_active" /> |
1518 | + <newline/> |
1519 | + <field name="nextcall" attrs="{'required':[('reminder_active','==',True)]}"/> |
1520 | + <newline/> |
1521 | + <label for="interval_number" string="Then send message every"/> |
1522 | + <div> |
1523 | + <field name="interval_number" class="oe_inline" |
1524 | + attrs="{'required':[('reminder_active','==',True)]}"/> |
1525 | + <field name="interval_type" nolabel="1" class="oe_inline" |
1526 | + attrs="{'required':[('reminder_active','==',True)]}"/> |
1527 | + </div> |
1528 | + </group> |
1529 | + |
1530 | + <group col="2"> |
1531 | + <separator string="Message" colspan="4"/> |
1532 | + <field name="reply_to"/> |
1533 | + <field name="subject"/> |
1534 | + <field name="message" height="200"/> |
1535 | + </group> |
1536 | + </sheet> |
1537 | + |
1538 | + <footer> |
1539 | + <button name="save" string="Save configuration" colspan="1" |
1540 | + type="object" class="oe_highlight"/> or |
1541 | + <button name="run" string="Run now" colspan="1" |
1542 | + type="object" class="oe_highlight"/> or |
1543 | + <button special="cancel" string="Cancel" class="oe_link"/> |
1544 | + </footer> |
1545 | </form> |
1546 | </field> |
1547 | </record> |
1548 | @@ -42,11 +52,11 @@ |
1549 | </record> |
1550 | |
1551 | <menuitem id="menu_hr_timesheet_reminder_config" |
1552 | - icon="STOCK_PRINT" |
1553 | - action="action_hr_timesheet_reminder_config" |
1554 | - parent="hr.menu_hr_configuration" |
1555 | - name="Timesheet Reminder" |
1556 | - groups="base.group_hr_manager"/> |
1557 | + icon="STOCK_PRINT" |
1558 | + action="action_hr_timesheet_reminder_config" |
1559 | + parent="hr.menu_hr_configuration" |
1560 | + name="Timesheet Reminder" |
1561 | + groups="base.group_hr_manager"/> |
1562 | |
1563 | -</data> |
1564 | + </data> |
1565 | </openerp> |
1566 | |
1567 | === modified file 'hr_timesheet_reminder/wizard/reminder_status.py' |
1568 | --- hr_timesheet_reminder/wizard/reminder_status.py 2011-11-07 13:58:29 +0000 |
1569 | +++ hr_timesheet_reminder/wizard/reminder_status.py 2012-12-13 17:06:20 +0000 |
1570 | @@ -1,67 +1,58 @@ |
1571 | # -*- coding: utf-8 -*- |
1572 | ############################################################################## |
1573 | # |
1574 | -# Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com) |
1575 | -# All Right Reserved |
1576 | -# |
1577 | -# Author : Guewen Baconnier (Camptocamp) |
1578 | -# |
1579 | -# WARNING: This program as such is intended to be used by professional |
1580 | -# programmers who take the whole responsability of assessing all potential |
1581 | -# consequences resulting from its eventual inadequacies and bugs |
1582 | -# End users who are looking for a ready-to-use solution with commercial |
1583 | -# garantees and support are strongly adviced to contract a Free Software |
1584 | -# Service Company |
1585 | -# |
1586 | -# This program is Free Software; you can redistribute it and/or |
1587 | -# modify it under the terms of the GNU General Public License |
1588 | -# as published by the Free Software Foundation; either version 2 |
1589 | -# of the License, or (at your option) any later version. |
1590 | -# |
1591 | -# This program is distributed in the hope that it will be useful, |
1592 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1593 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1594 | -# GNU General Public License for more details. |
1595 | -# |
1596 | -# You should have received a copy of the GNU General Public License |
1597 | -# along with this program; if not, write to the Free Software |
1598 | -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
1599 | +# Author: Arnaud Wüst (Camptocamp) |
1600 | +# Author: Guewen Baconnier (Camptocamp) (port to v7) |
1601 | +# Copyright 2011-2012 Camptocamp SA |
1602 | +# |
1603 | +# This program is free software: you can redistribute it and/or modify |
1604 | +# it under the terms of the GNU Affero General Public License as |
1605 | +# published by the Free Software Foundation, either version 3 of the |
1606 | +# License, or (at your option) any later version. |
1607 | +# |
1608 | +# This program is distributed in the hope that it will be useful, |
1609 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1610 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1611 | +# GNU Affero General Public License for more details. |
1612 | +# |
1613 | +# You should have received a copy of the GNU Affero General Public License |
1614 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1615 | # |
1616 | ############################################################################## |
1617 | |
1618 | -import time |
1619 | - |
1620 | -from osv import osv, fields |
1621 | - |
1622 | - |
1623 | -class reminder_status(osv.osv_memory): |
1624 | +from openerp.osv import orm, fields |
1625 | + |
1626 | + |
1627 | +class reminder_status(orm.TransientModel): |
1628 | _name = 'hr.timesheet.reminder.status' |
1629 | |
1630 | _columns = { |
1631 | - 'company_ids': fields.many2many('res.company', 'reminder_company_rel', 'wid', 'rid', 'Company'), |
1632 | + 'company_ids': fields.many2many( |
1633 | + 'res.company', |
1634 | + 'reminder_company_rel', |
1635 | + 'wid', |
1636 | + 'rid', |
1637 | + string='Company'), |
1638 | 'date': fields.date('End Date', required=True), |
1639 | } |
1640 | |
1641 | _defaults = { |
1642 | - 'date': lambda *a: time.strftime('%Y-%m-%d'), |
1643 | + 'date': lambda *a: fields.date.today(), |
1644 | } |
1645 | |
1646 | - def print_report(self, cr, uid, ids, context): |
1647 | - if context is None: |
1648 | - context = {} |
1649 | - |
1650 | - form_values = self.read(cr, uid, ids, ['company_ids', 'date'])[0] |
1651 | - |
1652 | + def print_report(self, cr, uid, ids, context=None): |
1653 | + form_values = self.read( |
1654 | + cr, uid, ids[0], ['company_ids', 'date'], context=context) |
1655 | + |
1656 | + # when no company is selected, select them all |
1657 | if not form_values['company_ids']: |
1658 | form_values['company_ids'] = self.pool.get('res.company').\ |
1659 | - search(cr, uid, [], context=context) |
1660 | + search(cr, uid, [], context=context) |
1661 | + |
1662 | data = {'ids': form_values['company_ids'], |
1663 | 'model': 'res.company', |
1664 | - 'form': {}} |
1665 | - data['form'].update(form_values) |
1666 | + 'form': form_values} |
1667 | |
1668 | return {'type': 'ir.actions.report.xml', |
1669 | 'report_name': 'timesheet.reminder.status', |
1670 | 'datas': data} |
1671 | - |
1672 | -reminder_status() |
1673 | |
1674 | === modified file 'hr_timesheet_reminder/wizard/reminder_status_view.xml' |
1675 | --- hr_timesheet_reminder/wizard/reminder_status_view.xml 2011-08-12 12:53:16 +0000 |
1676 | +++ hr_timesheet_reminder/wizard/reminder_status_view.xml 2012-12-13 17:06:20 +0000 |
1677 | @@ -5,23 +5,24 @@ |
1678 | <record id="view_hr_timesheet_reminder_status_form" model="ir.ui.view"> |
1679 | <field name="name">hr.timesheet.reminder.status.form</field> |
1680 | <field name="model">hr.timesheet.reminder.status</field> |
1681 | - <field name="type">form</field> |
1682 | <field name="arch" type="xml"> |
1683 | - <form string="Reminder Status"> |
1684 | - <group colspan="4" col="4" string="Parameter"> |
1685 | - <separator string="End Date (display the 5 timesheets previous to this date)" colspan="4"/> |
1686 | - <field name="date" colspan="4" nolabel="1" width="400" /> |
1687 | - </group> |
1688 | + <form string="Reminder Status" version="7.0"> |
1689 | + <sheet> |
1690 | + <group> |
1691 | + <label for="date" string="End Date (display the 5 timesheets previous to this date)"/> |
1692 | + <field name="date" colspan="4" nolabel="1" width="400" /> |
1693 | + </group> |
1694 | |
1695 | - <group colspan="4" col="4" string="Filter"> |
1696 | - <separator string="Filter by a Company (leave empty to select all companies)" colspan="4"/> |
1697 | - <field name="company_ids" colspan="4" nolabel="1"/> |
1698 | - <newline/> |
1699 | - </group> |
1700 | - <group colspan="4" col="6"> |
1701 | - <button icon="gtk-cancel" special="cancel" string="Cancel"/> |
1702 | - <button icon="gtk-print" string="Print" name="print_report" type="object" colspan="2" default_focus="1" /> |
1703 | - </group> |
1704 | + <group> |
1705 | + <separator string="Companies" colspan="4"/> |
1706 | + <label for="company_ids" colspan="4" string="Filter by a Company (leave empty to select all companies)"/> |
1707 | + <field name="company_ids" colspan="4" nolabel="1"/> |
1708 | + </group> |
1709 | + </sheet> |
1710 | + <footer> |
1711 | + <button name="print_report" string="Print" colspan="1" type="object" class="oe_highlight"/> or |
1712 | + <button special="cancel" string="Cancel" class="oe_link"/> |
1713 | + </footer> |
1714 | </form> |
1715 | </field> |
1716 | </record> |
1717 | @@ -36,11 +37,11 @@ |
1718 | </record> |
1719 | |
1720 | <menuitem id="menu_hr_timesheet_reminder_status" |
1721 | - icon="STOCK_PRINT" |
1722 | - action="action_hr_timesheet_reminder_status" |
1723 | - parent="hr_timesheet.menu_hr_reporting_timesheet" |
1724 | - name="Timesheet Status" |
1725 | - groups="base.group_hr_manager"/> |
1726 | + icon="STOCK_PRINT" |
1727 | + action="action_hr_timesheet_reminder_status" |
1728 | + parent="hr.menu_hr_reporting_timesheet" |
1729 | + name="Timesheet Status" |
1730 | + groups="base.group_hr_manager"/> |
1731 | |
1732 | -</data> |
1733 | + </data> |
1734 | </openerp> |
line 263: if status in ['Missing', 'Draft'] and employee. receive_ timesheet_ alerts
The second part of the test should be moved out to the outer loop (just after line 253) or even better to the search domain (line 243) : that way we don't make further queries for employees who don't recevie timesheet alerts (or am I missing something?)
653 + def _cron_nextcall(): SERVER_ DATETIME_ FORMAT,
654 + now = datetime.today() + timedelta(days=1)
655 + return time.strftime(
656 + DEFAULT_
657 + now.timetuple())
1 -> I'd rename 'now' to 'tomorrow' or 'when' DEFAULT_ SERVER_ DATETIME_ FORMAT) (or tomorrow. strftime. ..) instead of time.strftime(...) ?
2. why not use now.strftime(
There are probably a number of 'import time' which can be removed (pylint will tell you about unused imports)
607 + 'body_html': '<pre>%s</pre>' % message_ data.message,
I expect mail clients to be fairly tolerant in what they accept, but this makes me uncomfortable.
Have you tested what happens if the user has typed in:
* html (e.g. "fill your timesheet <b>now!</b>")
* a raw text message with HTML special chars inside (e.g: "I'm very disapointed you did not fill your timesheet <:-( I'll make sure your manager is notified & takes proper action.
Best chance would be to allow the edition of the body of the message with a rich text editor. Is there such widget available in the oerp7 client ?
803 -# Author: Arnaud WÃŒst
-> Mojibake! (but you fixed it)
1638 + 'date': time.strftime( '%Y-%m- %d'),
Is there not a constant defining this format?