Merge lp:~akretion-team/project-service/add-project-action-item into lp:~project-core-editors/project-service/trunk
- add-project-action-item
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~akretion-team/project-service/add-project-action-item |
Merge into: | lp:~project-core-editors/project-service/trunk |
Diff against target: |
1296 lines (+1230/-0) 11 files modified
project_action_item/__init__.py (+24/-0) project_action_item/__openerp__.py (+54/-0) project_action_item/i18n/fr.po (+277/-0) project_action_item/i18n/project_action_item.pot (+277/-0) project_action_item/project.py (+179/-0) project_action_item/project_demo.xml (+64/-0) project_action_item/project_view.xml (+151/-0) project_action_item/security/ir.model.access.csv (+2/-0) project_action_item/wizard/__init__.py (+23/-0) project_action_item/wizard/update_action_generate_timesheet.py (+137/-0) project_action_item/wizard/update_action_generate_timesheet_view.xml (+42/-0) |
To merge this branch: | bzr merge lp:~akretion-team/project-service/add-project-action-item |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Lorenzo Battistini (community) | Abstain | ||
Raphaël Valyi - http://www.akretion.com | Approve | ||
Daniel Reis | Needs Fixing | ||
Review via email: mp+216224@code.launchpad.net |
Commit message
Description of the change
This merge proposal adds the module "project_
Extract from the module description :
This module adds action items on project tasks. When a user has completed the action item of a task, he can click on a button "Done with Timesheet" that starts a wizard ; this wizard will mark the action item as done and will create a timesheet line.
The idea behind this module is the following : on a task, we have the timesheet lines that give you the history of the actions made for that task... but we don't have anything to store the actions that must be carried out for that action (apart from the text field "description"). So, with this module : on a task, the timesheet lines (object hr.analytic.
Raphaël Valyi - http://www.akretion.com (rvalyi) wrote : | # |
Hello Daniel,
I just want t mention that yesterday I talked with Alexis and I spontaneously made exactly the same remark as you with the concept of children tasks instead of that new actions object.
There are several modules trying to fix the need for a standard Workbench Breakdown Structure (WBS from PMI) in OpenERP.
Ferdinand Gassauer at C2C2 maintained a parent-child task hierarchy module for years (not remembering the link though) and there is also this project_scope_wbs PMI WBS module from Efficient now that would eventually be interesting to bring into OCA:
http://
On our side at Akretion we will also soon push an other module called project_feature that also aim at managing different granularity scales for projects, this time bridging operational tasks with the customer metric expressed with a new object called project.feature.
So there is definitely effort in that direction and we should avoid "leaky abstraction". That is as you said, if with minimum effort would could make it work with a hierarchy instead of introducing that action object, that would be cool.
If that is not possible, we should try to make it at least compatible with the modules trying to bring WBS hierarchy.
All in all, this module seems great, but we should double check if we can make the most of it before blessing it to OCA.
Regards
JB (eficent.com) (jb.eficent) wrote : | # |
Hello Alexis, Daniel and Raphaël,
The module developed by Alexis is a valid option me. Let me expose the two alternatives that I can see as being valid.
First of all, some key definitions of project management terminology as defined by PMI:
- Control Account
A control account is a management control point where scope, budget, actual cost, and schedule are integrated and compared to the earned value for performance measurement (3).
- Planning Package
A planning package is a work breakdown structure component below the control account with known work content but without detailed schedule activities (3).
- Work Package
Same as a planning package, but with detailed activites defined within.
Work package is a more deliverable oriented definition of the work to be completed (identifies work to be done to complete the project scope, but does not provide the low level detail).
- Activty
Activities represent the effort needed to complete a work package. Each work package is decomposed into the activities required to produce the work package deliverables (4). Activities more specifically identify the individual low level actions needed to complete the work package.
- Milestone
Milestones are similar to regular schedule activities, with the same structure and
attributes, but they have zero duration because milestones represent a moment in time (5).
Now let's see how OpenERP seems to be mapping these concepts.
- Control Account --> project.project
- Planning Package --> project.task
- Work Package --> project.task
- Activity --> ?
- Milestone -> ?
From a PMI terminology perspective, OpenERP's project.task is now being used more as a work-package than as an activity (1),(2):
- project.task is now being used to assign work to be done without detailed breakdown (work packages) from other modules such project.issue or sales order lines that are related to internally procured service items.
- project.task is built with the capability to define multiple stages required to complete the work (analysis, design, ..). That is unnecessary in activities, but useful in work packages.
Now let's see how can we completely map in OpenERP the PMI concepts. I can see two options here:
Option 1 -> Use project.project to implement work packages and project.task to implement activities.
Option 2 -> Use project.task to implement work packages and project.action.item to implement activities.
Option 1 adheres to my current project management modules (https:/
1) Project Issue module should create project.project records as workd packages instead of project.task
2) Sale module should create project.project records as work packages instead of project.task.
Option 2 would require a significant redesign of my modules.
Mapping of concepts in Option 1:
Control Account --> project.project
Planning Package --> project.project
Work Package --> project.project
Activity --> project.task
Milestone -> project.task
Mapping of concepts in Option 2:
Control Account --> project.project
Planning Package --> project.task
Work Package --> project.task
Activity --> project.action.item
Milestone -> ...
- 35. By Alexis de Lattre
-
Implement some suggestions of Daniel Reis :
- explain where to find the module hr_timesheet_task in module description
- add state "In Progress" and adapt the wizard and buttons
- add field "to_invoice" on action item, that will be copied to the timesheet
- change "Done with timesheet" to "Done" in the tree view. - 36. By Alexis de Lattre
-
Continue to implement the remarks of Daniel :
- add computed field timesheet_hours on project.action.item
- replace the native field 'planned_hours' on task by a computed field (sum of action items)
Update some strings and field names (Quantity -> Hours)
Flake8 validation
Alexis de Lattre (alexis-via) wrote : | # |
@Daniel Reis
I have implemented all your remarks :
* I would be nice to inform where the lp branch "hr_timesheet_task" can be found, at least until openerpapps.info rules the world.
=> Done
* The "Done with timesheet" is not a real button. It took me some time to realize it's test was clickable.
=> What do you suggest for that ?
* IMO "Done with timesheet" is a confusing label. I would prefer "Log on Timesheet" or the even simpler "Done".
=> We now have 2 buttons : "Done" and "Progress"
* Actions should heave a sequence field, and be manually reordered in the Task Actions tab.
=> They have that since my first commit :) Re-ordering action items works fine.
* If you have the "Manage time estimation on tasks" feature activated, the Task's estimated time should be computed as the total Actions estimated time (in the demo data, the Tasks estimated time is 22h and the Action estimated time is 70h).
=> Done?
* When an Action is Done, you can't see the actual time spent.
=> I added a field "timesheet_hours" on action items
* At the time you are creating the Action list, you should be able to set if you expect it to be billable (or expected Invoicing Ratio).
=> Done.
* You can't log time on an Action without completing it. The demo action "Develop final version" is 42h long, will surely span more than a week, and you will surely won't be able to wait until it's completed to log the time spent.
I suggest the wizard to let you log time on timesheet for an action, but keep it as not done / in progress.
=> Very good idea. Action items now have 3 states instead of 2 : todo, in progress and done.
- 37. By Alexis de Lattre
-
Add icon on button in tree view
Add related field projet_id
Now that we have both "todo" and "progress", the state field should always be visible.
Raphaël Valyi - http://www.akretion.com (rvalyi) wrote : | # |
Considering the suggestion from Jordi that WBS is better implemented using a project hierarchy than a task hierarchy (it's true that OpenERP has some support for a hierarchy of projects), then I approve Alexis' merge.
- 38. By Alexis de Lattre
-
[Usability] Put action items above timesheets, in the same tab
Daniel Reis (dreis-pt) wrote : | # |
Great work Alexis. I hope you don't think it's too nitpicking, but I still have some (mostly UI) comments.
Regarding the "Manage time estimation on tasks" feature, you did a good job, but were tricked but thr ORM limitations: the "Initially planned hours" at the top of the Task form is now correct, but the "Remaining" and "Total Time" at the bottom still calculate as before. (Maybe you need to keep task estimated time a plain float updated when you write on an Action's.)
My UI suggestions are:
1) I find confusing to have both Actions and Work Ids on the same page. Maybe move Actions to a new form Page?
2) Add a read only "Actual Hours" after "Estimated Hours" and remove the "State" field. This gives better information with the same number of columns.
3) Replace the two icon button with a single "Log Time" classic button (I think the icon buttons are no longer used in v7), and instead have two action buttons on the wizard to log time on an Action ("Log and Continue", "Log and Complete"). This also makes the "Action Item Complete" checkbox unnecessary.
4) Remove the menu "Action Items": it's the same as the "My Action Items" menu, except that it has a removable default filter.
- 39. By Alexis de Lattre
-
[Usability] implement some of the remarks of Daniel Reis :
- one menu entry instead of 2
- display "Worked Hours" in Tree view and re-order cols
Alexis de Lattre (alexis-via) wrote : | # |
@Daniel : about your UI suggestions :
1) I have precisely changed the task view so that the Actions and Works Ids are in the same tab, so that a user can see what he has done and what he has left to do in the same screen. I find it very usefull.
2) I added the field "Worked Hours" in the tree view ; I kept the "State" field because I find it usefull and there is enough room to keep it
3) The icon buttons are still used in v7 in the tree views (and only in tree views). For example, on the form view of a delivery order, there are 3 icon buttons : Scrap Products, Put in current pack, Put in new pack. So it's coherent with the rest of OpenERP.
4) I agree with you ; I kept only one menu entry "Action Items", with the filter.
- 40. By Alexis de Lattre
-
[Usability] Larger display for the action description.
Lorenzo Battistini (elbati) wrote : | # |
Thanks Alexis,
some style notes
project_
project_
project_
project_
project_
project_
project_
project_
project_
project_
project_
project_
project_
project_
project_
project_
project_
project_
project_
project_
project_
Alexis de Lattre (alexis-via) wrote : | # |
@Lorenzo :
You have a non-default configuration for flake8 ; as you can see below, flake8 gives me 0 error on the python files (except in __openerp__.py).
% flake8 project_action_item
project_
project_
project_
project_
project_
project_
project_
Lorenzo Battistini (elbati) wrote : | # |
Uh, I'm using this
http://
+
https:/
The command
'flake8 project_action_item --ignore E501'
is the responsible for adding those output lines.
But I don't understand why
Alexis de Lattre (alexis-via) wrote : | # |
@Daniel
I have implemented and/or answered your UI remarks at the end of April. Could you update your review status (currently Needs Fixing) ?
Daniel Reis (dreis-pt) wrote : | # |
This project is now hosted on https:/
This guide may help you https:/
Alexis de Lattre (alexis-via) wrote : | # |
@Daniel :
I won't move this MP in the short term, because I am not familiar with git. By the way, if you had updated your "Needs fixing" review status after I implemented your remarks back in April, this MP would probably have been merged before the move to github !!! So it would have avoided all this additional work to move the MP to github !!!
Daniel Reis (dreis-pt) wrote : | # |
Alexis: I understand it was an avoidable inconvenience.
Since I caused it I'll take the burden for to move.
I'll update the status here.
Alexis de Lattre (alexis-via) wrote : | # |
@Daniel
Thanks a lot for your proposal... it is very much appreciated !
Daniel Reis (dreis-pt) wrote : | # |
This MP has moved to GitHub:
https:/
Unmerged revisions
- 40. By Alexis de Lattre
-
[Usability] Larger display for the action description.
- 39. By Alexis de Lattre
-
[Usability] implement some of the remarks of Daniel Reis :
- one menu entry instead of 2
- display "Worked Hours" in Tree view and re-order cols - 38. By Alexis de Lattre
-
[Usability] Put action items above timesheets, in the same tab
- 37. By Alexis de Lattre
-
Add icon on button in tree view
Add related field projet_id
Now that we have both "todo" and "progress", the state field should always be visible. - 36. By Alexis de Lattre
-
Continue to implement the remarks of Daniel :
- add computed field timesheet_hours on project.action.item
- replace the native field 'planned_hours' on task by a computed field (sum of action items)
Update some strings and field names (Quantity -> Hours)
Flake8 validation - 35. By Alexis de Lattre
-
Implement some suggestions of Daniel Reis :
- explain where to find the module hr_timesheet_task in module description
- add state "In Progress" and adapt the wizard and buttons
- add field "to_invoice" on action item, that will be copied to the timesheet
- change "Done with timesheet" to "Done" in the tree view. - 34. By Alexis de Lattre
-
Add module project_
action_ item.
Preview Diff
1 | === added directory 'project_action_item' |
2 | === added file 'project_action_item/__init__.py' |
3 | --- project_action_item/__init__.py 1970-01-01 00:00:00 +0000 |
4 | +++ project_action_item/__init__.py 2014-05-05 12:05:37 +0000 |
5 | @@ -0,0 +1,24 @@ |
6 | +# -*- encoding: utf-8 -*- |
7 | +############################################################################## |
8 | +# |
9 | +# Project Action Item module for OpenERP |
10 | +# Copyright (C) 2014 Akretion (http://www.akretion.com) |
11 | +# @author Alexis de Lattre <alexis.delattre@akretion.com> |
12 | +# |
13 | +# This program is free software: you can redistribute it and/or modify |
14 | +# it under the terms of the GNU Affero General Public License as |
15 | +# published by the Free Software Foundation, either version 3 of the |
16 | +# License, or (at your option) any later version. |
17 | +# |
18 | +# This program is distributed in the hope that it will be useful, |
19 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 | +# GNU Affero General Public License for more details. |
22 | +# |
23 | +# You should have received a copy of the GNU Affero General Public License |
24 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
25 | +# |
26 | +############################################################################## |
27 | + |
28 | +from . import project |
29 | +from . import wizard |
30 | |
31 | === added file 'project_action_item/__openerp__.py' |
32 | --- project_action_item/__openerp__.py 1970-01-01 00:00:00 +0000 |
33 | +++ project_action_item/__openerp__.py 2014-05-05 12:05:37 +0000 |
34 | @@ -0,0 +1,54 @@ |
35 | +# -*- encoding: utf-8 -*- |
36 | +############################################################################## |
37 | +# |
38 | +# Project Action Item module for OpenERP |
39 | +# Copyright (C) 2014 Akretion (http://www.akretion.com) |
40 | +# @author Alexis de Lattre <alexis.delattre@akretion.com> |
41 | +# |
42 | +# This program is free software: you can redistribute it and/or modify |
43 | +# it under the terms of the GNU Affero General Public License as |
44 | +# published by the Free Software Foundation, either version 3 of the |
45 | +# License, or (at your option) any later version. |
46 | +# |
47 | +# This program is distributed in the hope that it will be useful, |
48 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
49 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
50 | +# GNU Affero General Public License for more details. |
51 | +# |
52 | +# You should have received a copy of the GNU Affero General Public License |
53 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
54 | +# |
55 | +############################################################################## |
56 | + |
57 | + |
58 | +{ |
59 | + 'name': 'Project Action Item', |
60 | + 'version': '0.1', |
61 | + 'category': 'Project Management', |
62 | + 'license': 'AGPL-3', |
63 | + 'summary': 'Adds action items on tasks', |
64 | + 'description': """ |
65 | +Project Action Item |
66 | +=================== |
67 | + |
68 | +This module adds action items on project tasks. When a user has completed the action item of a task, he can click on a button *Done with Timesheet* that starts a wizard ; this wizard will mark the action item as done and will create a timesheet line. |
69 | + |
70 | +This module depends on the module *hr_timesheet_task* which is available on http://code.launchpad.net/hr-timesheet. |
71 | + |
72 | +Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module. |
73 | + """, |
74 | + 'author': 'Akretion', |
75 | + 'website': 'http://www.akretion.com', |
76 | + 'depends': ['project', 'hr_timesheet_task'], |
77 | + 'data': [ |
78 | + 'wizard/update_action_generate_timesheet_view.xml', |
79 | + 'project_view.xml', |
80 | + 'security/ir.model.access.csv', |
81 | + ], |
82 | + 'demo': ['project_demo.xml'], |
83 | + 'images': [ |
84 | + 'static/src/img/screenshots/task_with_action_items.jpg', |
85 | + 'static/src/img/screenshots/create_timesheet_from_action_item_wizard.jpg', |
86 | + ], |
87 | + 'installable': True, |
88 | +} |
89 | |
90 | === added directory 'project_action_item/i18n' |
91 | === added file 'project_action_item/i18n/fr.po' |
92 | --- project_action_item/i18n/fr.po 1970-01-01 00:00:00 +0000 |
93 | +++ project_action_item/i18n/fr.po 2014-05-05 12:05:37 +0000 |
94 | @@ -0,0 +1,277 @@ |
95 | +# Translation of OpenERP Server. |
96 | +# This file contains the translation of the following modules: |
97 | +# * project_action_item |
98 | +# |
99 | +msgid "" |
100 | +msgstr "" |
101 | +"Project-Id-Version: OpenERP Server 7.0\n" |
102 | +"Report-Msgid-Bugs-To: \n" |
103 | +"POT-Creation-Date: 2014-04-24 21:17+0000\n" |
104 | +"PO-Revision-Date: 2014-04-24 21:17+0000\n" |
105 | +"Last-Translator: <>\n" |
106 | +"Language-Team: \n" |
107 | +"MIME-Version: 1.0\n" |
108 | +"Content-Type: text/plain; charset=UTF-8\n" |
109 | +"Content-Transfer-Encoding: \n" |
110 | +"Plural-Forms: \n" |
111 | + |
112 | +#. module: project_action_item |
113 | +#: field:hr.analytic.timesheet,action_item_id:0 |
114 | +#: view:project.action.item:0 |
115 | +msgid "Action Item" |
116 | +msgstr "Point d'action" |
117 | + |
118 | +#. module: project_action_item |
119 | +#: field:project.action.item.timesheet,completed:0 |
120 | +msgid "Action Item Completed" |
121 | +msgstr "Point d'action fini" |
122 | + |
123 | +#. module: project_action_item |
124 | +#: model:ir.actions.act_window,name:project_action_item.project_action_item_action |
125 | +#: model:ir.ui.menu,name:project_action_item.project_action_item_menu |
126 | +#: view:project.action.item:0 |
127 | +#: view:project.task:0 |
128 | +#: field:project.task,action_item_ids:0 |
129 | +msgid "Action Items" |
130 | +msgstr "Points d'action" |
131 | + |
132 | +#. module: project_action_item |
133 | +#: field:project.task,done_action_item_ids:0 |
134 | +msgid "Action Items Done" |
135 | +msgstr "Points d'action faits" |
136 | + |
137 | +#. module: project_action_item |
138 | +#: field:project.task,to_work_action_item_ids:0 |
139 | +msgid "Action Items To Do" |
140 | +msgstr "Points d'action à faire" |
141 | + |
142 | +#. module: project_action_item |
143 | +#: view:project.task:0 |
144 | +msgid "Action Items To Work On" |
145 | +msgstr "Points d'action à travailler" |
146 | + |
147 | +#. module: project_action_item |
148 | +#: field:project.action.item,user_id:0 |
149 | +msgid "Assigned To" |
150 | +msgstr "Assigné à" |
151 | + |
152 | +#. module: project_action_item |
153 | +#: view:project.action.item:0 |
154 | +msgid "Back to To Do" |
155 | +msgstr "Revenir à À faire" |
156 | + |
157 | +#. module: project_action_item |
158 | +#: view:project.action.item.timesheet:0 |
159 | +msgid "Cancel" |
160 | +msgstr "Annuler" |
161 | + |
162 | +#. module: project_action_item |
163 | +#: field:project.action.item,create_uid:0 |
164 | +msgid "Created By" |
165 | +msgstr "Créé par" |
166 | + |
167 | +#. module: project_action_item |
168 | +#: field:project.action.item,create_date:0 |
169 | +msgid "Creation Date" |
170 | +msgstr "Date de création" |
171 | + |
172 | +#. module: project_action_item |
173 | +#: field:project.action.item.timesheet,date:0 |
174 | +msgid "Date" |
175 | +msgstr "Date" |
176 | + |
177 | +#. module: project_action_item |
178 | +#: field:project.action.item,date_done:0 |
179 | +msgid "Date Done" |
180 | +msgstr "Fait le" |
181 | + |
182 | +#. module: project_action_item |
183 | +#: field:project.action.item,date_deadline:0 |
184 | +msgid "Deadline" |
185 | +msgstr "Date limite" |
186 | + |
187 | +#. module: project_action_item |
188 | +#: field:project.action.item,name:0 |
189 | +#: view:project.task:0 |
190 | +msgid "Description" |
191 | +msgstr "Description" |
192 | + |
193 | +#. module: project_action_item |
194 | +#: view:project.action.item:0 |
195 | +#: selection:project.action.item,state:0 |
196 | +msgid "Done" |
197 | +msgstr "Fait" |
198 | + |
199 | +#. module: project_action_item |
200 | +#: code:addons/project_action_item/wizard/update_action_generate_timesheet.py:51 |
201 | +#, python-format |
202 | +msgid "Error:" |
203 | +msgstr "Erreur :" |
204 | + |
205 | +#. module: project_action_item |
206 | +#: field:project.action.item,estimated_hours:0 |
207 | +msgid "Estimated Hours" |
208 | +msgstr "Heures estimées" |
209 | + |
210 | +#. module: project_action_item |
211 | +#: field:project.action.item,to_invoice:0 |
212 | +msgid "Expected Invoicing Ratio" |
213 | +msgstr "Expected Invoicing Ratio" |
214 | + |
215 | +#. module: project_action_item |
216 | +#: view:project.action.item:0 |
217 | +msgid "Group By..." |
218 | +msgstr "Groupé par..." |
219 | + |
220 | +#. module: project_action_item |
221 | +#: selection:project.action.item,state:0 |
222 | +msgid "In Progress" |
223 | +msgstr "En cours" |
224 | + |
225 | +#. module: project_action_item |
226 | +#: view:project.action.item:0 |
227 | +msgid "Mark as Done" |
228 | +msgstr "Marquer comme fait" |
229 | + |
230 | +#. module: project_action_item |
231 | +#: view:project.action.item:0 |
232 | +msgid "Mark as Done with Timesheet" |
233 | +msgstr "Marquer comme fait avec feuille de temps" |
234 | + |
235 | +#. module: project_action_item |
236 | +#: view:project.action.item:0 |
237 | +msgid "Mark as In Progress" |
238 | +msgstr "Marquer comme en cours" |
239 | + |
240 | +#. module: project_action_item |
241 | +#: view:project.action.item:0 |
242 | +msgid "Mark as Progress with Timesheet" |
243 | +msgstr "Marquer comme en cours avec feuille de temps" |
244 | + |
245 | +#. module: project_action_item |
246 | +#: model:ir.actions.act_window,name:project_action_item.my_project_action_item_action |
247 | +#: model:ir.ui.menu,name:project_action_item.my_project_action_item_menu |
248 | +#: view:project.action.item:0 |
249 | +msgid "My Action Items" |
250 | +msgstr "Mes points d'action" |
251 | + |
252 | +#. module: project_action_item |
253 | +#: view:project.action.item:0 |
254 | +msgid "My Action Items To Work On" |
255 | +msgstr "Mes points d'action à travailler" |
256 | + |
257 | +#. module: project_action_item |
258 | +#: view:project.action.item:0 |
259 | +msgid "Progress" |
260 | +msgstr "Avancer" |
261 | + |
262 | +#. module: project_action_item |
263 | +#: model:ir.model,name:project_action_item.model_project_action_item |
264 | +msgid "Project Action Items" |
265 | +msgstr "Points d'action projet" |
266 | + |
267 | +#. module: project_action_item |
268 | +#: field:project.action.item,task_id:0 |
269 | +msgid "Related Task" |
270 | +msgstr "Tâche associée" |
271 | + |
272 | +#. module: project_action_item |
273 | +#: field:project.action.item,timesheet_ids:0 |
274 | +msgid "Related Timesheets" |
275 | +msgstr "Feuilles de temps associées" |
276 | + |
277 | +#. module: project_action_item |
278 | +#: view:project.action.item:0 |
279 | +msgid "Search Action Items" |
280 | +msgstr "Recherche de points d'action" |
281 | + |
282 | +#. module: project_action_item |
283 | +#: field:project.action.item,sequence:0 |
284 | +msgid "Sequence" |
285 | +msgstr "Séquence" |
286 | + |
287 | +#. module: project_action_item |
288 | +#: field:project.action.item,state:0 |
289 | +msgid "State" |
290 | +msgstr "État" |
291 | + |
292 | +#. module: project_action_item |
293 | +#: code:addons/project_action_item/wizard/update_action_generate_timesheet.py:127 |
294 | +#: model:ir.model,name:project_action_item.model_project_task |
295 | +#: view:project.action.item:0 |
296 | +#, python-format |
297 | +msgid "Task" |
298 | +msgstr "Tâche" |
299 | + |
300 | +#. module: project_action_item |
301 | +#: code:addons/project_action_item/wizard/update_action_generate_timesheet.py:52 |
302 | +#, python-format |
303 | +msgid "This action item is not linked to a task, so we cannot generate a timesheet from it." |
304 | +msgstr "Ce point d'action n'est pas lié à une tâche, donc on ne peut pas générer de feuille de temps à partir de celui-ci." |
305 | + |
306 | +#. module: project_action_item |
307 | +#: help:project.action.item,timesheet_hours:0 |
308 | +msgid "This is the sum of the related timesheets." |
309 | +msgstr "Ce champ est la somme des feuilles de temps associées." |
310 | + |
311 | +#. module: project_action_item |
312 | +#: field:project.action.item.timesheet,to_invoice:0 |
313 | +msgid "Timesheet Invoicing Ratio" |
314 | +msgstr "Timesheet Invoicing Ratio" |
315 | + |
316 | +#. module: project_action_item |
317 | +#: model:ir.model,name:project_action_item.model_hr_analytic_timesheet |
318 | +msgid "Timesheet Line" |
319 | +msgstr "Ligne de feuille de temps" |
320 | + |
321 | +#. module: project_action_item |
322 | +#: view:project.action.item:0 |
323 | +msgid "Timesheets" |
324 | +msgstr "Feuilles de temps" |
325 | + |
326 | +#. module: project_action_item |
327 | +#: selection:project.action.item,state:0 |
328 | +msgid "To Do" |
329 | +msgstr "À faire" |
330 | + |
331 | +#. module: project_action_item |
332 | +#: view:project.action.item:0 |
333 | +msgid "To Work On" |
334 | +msgstr "À travailler" |
335 | + |
336 | +#. module: project_action_item |
337 | +#: view:project.action.item:0 |
338 | +msgid "Total Estimated Hours" |
339 | +msgstr "Nb d'heures total estimée" |
340 | + |
341 | +#. module: project_action_item |
342 | +#: code:addons/project_action_item/project.py:121 |
343 | +#: model:ir.actions.act_window,name:project_action_item.project_action_item_timesheet_action |
344 | +#: model:ir.model,name:project_action_item.model_project_action_item_timesheet |
345 | +#: view:project.action.item.timesheet:0 |
346 | +#, python-format |
347 | +msgid "Update Action Item and Create Timesheet Line" |
348 | +msgstr "Mettre à jour le point d'action et créer la ligne de feuille de temps" |
349 | + |
350 | +#. module: project_action_item |
351 | +#: view:project.action.item.timesheet:0 |
352 | +msgid "Update Action and Create Timesheet" |
353 | +msgstr "Mettre à jour le point d'action et créer la feuille de temps" |
354 | + |
355 | +#. module: project_action_item |
356 | +#: view:project.action.item:0 |
357 | +#: field:project.action.item.timesheet,user_id:0 |
358 | +msgid "User" |
359 | +msgstr "Utilisateur" |
360 | + |
361 | +#. module: project_action_item |
362 | +#: field:project.action.item.timesheet,name:0 |
363 | +msgid "Work Description" |
364 | +msgstr "Description du travail réalisé" |
365 | + |
366 | +#. module: project_action_item |
367 | +#: field:project.action.item,timesheet_hours:0 |
368 | +#: field:project.action.item.timesheet,hours:0 |
369 | +msgid "Worked Hours" |
370 | +msgstr "Heures travaillées" |
371 | + |
372 | |
373 | === added file 'project_action_item/i18n/project_action_item.pot' |
374 | --- project_action_item/i18n/project_action_item.pot 1970-01-01 00:00:00 +0000 |
375 | +++ project_action_item/i18n/project_action_item.pot 2014-05-05 12:05:37 +0000 |
376 | @@ -0,0 +1,277 @@ |
377 | +# Translation of OpenERP Server. |
378 | +# This file contains the translation of the following modules: |
379 | +# * project_action_item |
380 | +# |
381 | +msgid "" |
382 | +msgstr "" |
383 | +"Project-Id-Version: OpenERP Server 7.0\n" |
384 | +"Report-Msgid-Bugs-To: \n" |
385 | +"POT-Creation-Date: 2014-04-24 21:17+0000\n" |
386 | +"PO-Revision-Date: 2014-04-24 21:17+0000\n" |
387 | +"Last-Translator: <>\n" |
388 | +"Language-Team: \n" |
389 | +"MIME-Version: 1.0\n" |
390 | +"Content-Type: text/plain; charset=UTF-8\n" |
391 | +"Content-Transfer-Encoding: \n" |
392 | +"Plural-Forms: \n" |
393 | + |
394 | +#. module: project_action_item |
395 | +#: field:hr.analytic.timesheet,action_item_id:0 |
396 | +#: view:project.action.item:0 |
397 | +msgid "Action Item" |
398 | +msgstr "" |
399 | + |
400 | +#. module: project_action_item |
401 | +#: field:project.action.item.timesheet,completed:0 |
402 | +msgid "Action Item Completed" |
403 | +msgstr "" |
404 | + |
405 | +#. module: project_action_item |
406 | +#: model:ir.actions.act_window,name:project_action_item.project_action_item_action |
407 | +#: model:ir.ui.menu,name:project_action_item.project_action_item_menu |
408 | +#: view:project.action.item:0 |
409 | +#: view:project.task:0 |
410 | +#: field:project.task,action_item_ids:0 |
411 | +msgid "Action Items" |
412 | +msgstr "" |
413 | + |
414 | +#. module: project_action_item |
415 | +#: field:project.task,done_action_item_ids:0 |
416 | +msgid "Action Items Done" |
417 | +msgstr "" |
418 | + |
419 | +#. module: project_action_item |
420 | +#: field:project.task,to_work_action_item_ids:0 |
421 | +msgid "Action Items To Do" |
422 | +msgstr "" |
423 | + |
424 | +#. module: project_action_item |
425 | +#: view:project.task:0 |
426 | +msgid "Action Items To Work On" |
427 | +msgstr "" |
428 | + |
429 | +#. module: project_action_item |
430 | +#: field:project.action.item,user_id:0 |
431 | +msgid "Assigned To" |
432 | +msgstr "" |
433 | + |
434 | +#. module: project_action_item |
435 | +#: view:project.action.item:0 |
436 | +msgid "Back to To Do" |
437 | +msgstr "" |
438 | + |
439 | +#. module: project_action_item |
440 | +#: view:project.action.item.timesheet:0 |
441 | +msgid "Cancel" |
442 | +msgstr "" |
443 | + |
444 | +#. module: project_action_item |
445 | +#: field:project.action.item,create_uid:0 |
446 | +msgid "Created By" |
447 | +msgstr "" |
448 | + |
449 | +#. module: project_action_item |
450 | +#: field:project.action.item,create_date:0 |
451 | +msgid "Creation Date" |
452 | +msgstr "" |
453 | + |
454 | +#. module: project_action_item |
455 | +#: field:project.action.item.timesheet,date:0 |
456 | +msgid "Date" |
457 | +msgstr "" |
458 | + |
459 | +#. module: project_action_item |
460 | +#: field:project.action.item,date_done:0 |
461 | +msgid "Date Done" |
462 | +msgstr "" |
463 | + |
464 | +#. module: project_action_item |
465 | +#: field:project.action.item,date_deadline:0 |
466 | +msgid "Deadline" |
467 | +msgstr "" |
468 | + |
469 | +#. module: project_action_item |
470 | +#: field:project.action.item,name:0 |
471 | +#: view:project.task:0 |
472 | +msgid "Description" |
473 | +msgstr "" |
474 | + |
475 | +#. module: project_action_item |
476 | +#: view:project.action.item:0 |
477 | +#: selection:project.action.item,state:0 |
478 | +msgid "Done" |
479 | +msgstr "" |
480 | + |
481 | +#. module: project_action_item |
482 | +#: code:addons/project_action_item/wizard/update_action_generate_timesheet.py:51 |
483 | +#, python-format |
484 | +msgid "Error:" |
485 | +msgstr "" |
486 | + |
487 | +#. module: project_action_item |
488 | +#: field:project.action.item,estimated_hours:0 |
489 | +msgid "Estimated Hours" |
490 | +msgstr "" |
491 | + |
492 | +#. module: project_action_item |
493 | +#: field:project.action.item,to_invoice:0 |
494 | +msgid "Expected Invoicing Ratio" |
495 | +msgstr "" |
496 | + |
497 | +#. module: project_action_item |
498 | +#: view:project.action.item:0 |
499 | +msgid "Group By..." |
500 | +msgstr "" |
501 | + |
502 | +#. module: project_action_item |
503 | +#: selection:project.action.item,state:0 |
504 | +msgid "In Progress" |
505 | +msgstr "" |
506 | + |
507 | +#. module: project_action_item |
508 | +#: view:project.action.item:0 |
509 | +msgid "Mark as Done" |
510 | +msgstr "" |
511 | + |
512 | +#. module: project_action_item |
513 | +#: view:project.action.item:0 |
514 | +msgid "Mark as Done with Timesheet" |
515 | +msgstr "" |
516 | + |
517 | +#. module: project_action_item |
518 | +#: view:project.action.item:0 |
519 | +msgid "Mark as In Progress" |
520 | +msgstr "" |
521 | + |
522 | +#. module: project_action_item |
523 | +#: view:project.action.item:0 |
524 | +msgid "Mark as Progress with Timesheet" |
525 | +msgstr "" |
526 | + |
527 | +#. module: project_action_item |
528 | +#: model:ir.actions.act_window,name:project_action_item.my_project_action_item_action |
529 | +#: model:ir.ui.menu,name:project_action_item.my_project_action_item_menu |
530 | +#: view:project.action.item:0 |
531 | +msgid "My Action Items" |
532 | +msgstr "" |
533 | + |
534 | +#. module: project_action_item |
535 | +#: view:project.action.item:0 |
536 | +msgid "My Action Items To Work On" |
537 | +msgstr "" |
538 | + |
539 | +#. module: project_action_item |
540 | +#: view:project.action.item:0 |
541 | +msgid "Progress" |
542 | +msgstr "" |
543 | + |
544 | +#. module: project_action_item |
545 | +#: model:ir.model,name:project_action_item.model_project_action_item |
546 | +msgid "Project Action Items" |
547 | +msgstr "" |
548 | + |
549 | +#. module: project_action_item |
550 | +#: field:project.action.item,task_id:0 |
551 | +msgid "Related Task" |
552 | +msgstr "" |
553 | + |
554 | +#. module: project_action_item |
555 | +#: field:project.action.item,timesheet_ids:0 |
556 | +msgid "Related Timesheets" |
557 | +msgstr "" |
558 | + |
559 | +#. module: project_action_item |
560 | +#: view:project.action.item:0 |
561 | +msgid "Search Action Items" |
562 | +msgstr "" |
563 | + |
564 | +#. module: project_action_item |
565 | +#: field:project.action.item,sequence:0 |
566 | +msgid "Sequence" |
567 | +msgstr "" |
568 | + |
569 | +#. module: project_action_item |
570 | +#: field:project.action.item,state:0 |
571 | +msgid "State" |
572 | +msgstr "" |
573 | + |
574 | +#. module: project_action_item |
575 | +#: code:addons/project_action_item/wizard/update_action_generate_timesheet.py:127 |
576 | +#: model:ir.model,name:project_action_item.model_project_task |
577 | +#: view:project.action.item:0 |
578 | +#, python-format |
579 | +msgid "Task" |
580 | +msgstr "" |
581 | + |
582 | +#. module: project_action_item |
583 | +#: code:addons/project_action_item/wizard/update_action_generate_timesheet.py:52 |
584 | +#, python-format |
585 | +msgid "This action item is not linked to a task, so we cannot generate a timesheet from it." |
586 | +msgstr "" |
587 | + |
588 | +#. module: project_action_item |
589 | +#: help:project.action.item,timesheet_hours:0 |
590 | +msgid "This is the sum of the related timesheets." |
591 | +msgstr "" |
592 | + |
593 | +#. module: project_action_item |
594 | +#: field:project.action.item.timesheet,to_invoice:0 |
595 | +msgid "Timesheet Invoicing Ratio" |
596 | +msgstr "" |
597 | + |
598 | +#. module: project_action_item |
599 | +#: model:ir.model,name:project_action_item.model_hr_analytic_timesheet |
600 | +msgid "Timesheet Line" |
601 | +msgstr "" |
602 | + |
603 | +#. module: project_action_item |
604 | +#: view:project.action.item:0 |
605 | +msgid "Timesheets" |
606 | +msgstr "" |
607 | + |
608 | +#. module: project_action_item |
609 | +#: selection:project.action.item,state:0 |
610 | +msgid "To Do" |
611 | +msgstr "" |
612 | + |
613 | +#. module: project_action_item |
614 | +#: view:project.action.item:0 |
615 | +msgid "To Work On" |
616 | +msgstr "" |
617 | + |
618 | +#. module: project_action_item |
619 | +#: view:project.action.item:0 |
620 | +msgid "Total Estimated Hours" |
621 | +msgstr "" |
622 | + |
623 | +#. module: project_action_item |
624 | +#: code:addons/project_action_item/project.py:121 |
625 | +#: model:ir.actions.act_window,name:project_action_item.project_action_item_timesheet_action |
626 | +#: model:ir.model,name:project_action_item.model_project_action_item_timesheet |
627 | +#: view:project.action.item.timesheet:0 |
628 | +#, python-format |
629 | +msgid "Update Action Item and Create Timesheet Line" |
630 | +msgstr "" |
631 | + |
632 | +#. module: project_action_item |
633 | +#: view:project.action.item.timesheet:0 |
634 | +msgid "Update Action and Create Timesheet" |
635 | +msgstr "" |
636 | + |
637 | +#. module: project_action_item |
638 | +#: view:project.action.item:0 |
639 | +#: field:project.action.item.timesheet,user_id:0 |
640 | +msgid "User" |
641 | +msgstr "" |
642 | + |
643 | +#. module: project_action_item |
644 | +#: field:project.action.item.timesheet,name:0 |
645 | +msgid "Work Description" |
646 | +msgstr "" |
647 | + |
648 | +#. module: project_action_item |
649 | +#: field:project.action.item,timesheet_hours:0 |
650 | +#: field:project.action.item.timesheet,hours:0 |
651 | +msgid "Worked Hours" |
652 | +msgstr "" |
653 | + |
654 | |
655 | === added file 'project_action_item/project.py' |
656 | --- project_action_item/project.py 1970-01-01 00:00:00 +0000 |
657 | +++ project_action_item/project.py 2014-05-05 12:05:37 +0000 |
658 | @@ -0,0 +1,179 @@ |
659 | +# -*- encoding: utf-8 -*- |
660 | +############################################################################## |
661 | +# |
662 | +# Project Action Item module for OpenERP |
663 | +# Copyright (C) 2014 Akretion (http://www.akretion.com) |
664 | +# @author Alexis de Lattre <alexis.delattre@akretion.com> |
665 | +# |
666 | +# This program is free software: you can redistribute it and/or modify |
667 | +# it under the terms of the GNU Affero General Public License as |
668 | +# published by the Free Software Foundation, either version 3 of the |
669 | +# License, or (at your option) any later version. |
670 | +# |
671 | +# This program is distributed in the hope that it will be useful, |
672 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
673 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
674 | +# GNU Affero General Public License for more details. |
675 | +# |
676 | +# You should have received a copy of the GNU Affero General Public License |
677 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
678 | +# |
679 | +############################################################################## |
680 | + |
681 | +from openerp.osv import orm, fields |
682 | +from openerp.tools.translate import _ |
683 | + |
684 | + |
685 | +class project_action_item(orm.Model): |
686 | + _name = "project.action.item" |
687 | + _description = "Project Action Items" |
688 | + |
689 | + def _compute_timesheet_hours( |
690 | + self, cr, uid, ids, name, arg, context=None): |
691 | + res = {} |
692 | + for action in self.browse(cr, uid, ids, context=context): |
693 | + res[action.id] = 0 |
694 | + for timesheet in action.timesheet_ids: |
695 | + res[action.id] += timesheet.unit_amount |
696 | + return res |
697 | + |
698 | + def _get_action_from_timesheet(self, cr, uid, ids, context=None): |
699 | + return self.pool['project.action.item'].search( |
700 | + cr, uid, [('timesheet_ids', 'in', ids)], context=context) |
701 | + |
702 | + _columns = { |
703 | + 'task_id': fields.many2one('project.task', 'Related Task'), |
704 | + 'project_id': fields.related( |
705 | + 'task_id', 'project_id', type='many2one', |
706 | + relation="project.project", readonly=True, string="Project"), |
707 | + 'name': fields.char('Description', size=256, required=True), |
708 | + 'date_deadline': fields.date('Deadline'), |
709 | + 'date_done': fields.date('Date Done'), |
710 | + 'user_id': fields.many2one('res.users', 'Assigned To'), |
711 | + 'estimated_hours': fields.float('Estimated Hours'), |
712 | + 'to_invoice': fields.many2one( |
713 | + 'hr_timesheet_invoice.factor', 'Expected Invoicing Ratio'), |
714 | + 'timesheet_ids': fields.one2many( |
715 | + 'hr.analytic.timesheet', 'action_item_id', 'Related Timesheets'), |
716 | + 'timesheet_hours': fields.function( |
717 | + _compute_timesheet_hours, type='float', |
718 | + string="Worked Hours", readonly=True, store={ |
719 | + 'hr.analytic.timesheet': ( |
720 | + _get_action_from_timesheet, |
721 | + ['unit_amount', 'action_item_id'], |
722 | + 10), |
723 | + }, help="This is the sum of the related timesheets." |
724 | + ), |
725 | + 'state': fields.selection([ |
726 | + ('todo', 'To Do'), |
727 | + ('progress', 'In Progress'), |
728 | + ('done', 'Done'), |
729 | + ], 'State', readonly=True), |
730 | + 'create_uid': fields.many2one( |
731 | + 'res.users', 'Created By', readonly=True), |
732 | + 'create_date': fields.datetime('Creation Date', readonly=True), |
733 | + 'sequence': fields.integer('Sequence'), |
734 | + } |
735 | + |
736 | + def _get_default_invoice_ratio(self, cr, uid, context=None): |
737 | + if context is None: |
738 | + context = {} |
739 | + active_id = context.get('active_id') |
740 | + active_model = context.get('active_model') |
741 | + if active_model == 'project.task' and active_id: |
742 | + task = self.pool['project.task'].browse( |
743 | + cr, uid, active_id, context=context) |
744 | + return task.project_id and task.project_id.to_invoice.id or False |
745 | + else: |
746 | + return False |
747 | + |
748 | + _defaults = { |
749 | + 'state': 'todo', |
750 | + 'to_invoice': _get_default_invoice_ratio, |
751 | + } |
752 | + |
753 | + def set_to_done(self, cr, uid, ids, context=None): |
754 | + today = fields.date.context_today(self, cr, uid, context=context) |
755 | + self.write(cr, uid, ids, { |
756 | + 'state': 'done', |
757 | + 'date_done': today, |
758 | + }, context=context) |
759 | + return |
760 | + |
761 | + def set_to_progress(self, cr, uid, ids, context=None): |
762 | + self.write(cr, uid, ids, { |
763 | + 'state': 'progress', |
764 | + }, context=context) |
765 | + return |
766 | + |
767 | + def back_to_todo(self, cr, uid, ids, context=None): |
768 | + self.write(cr, uid, ids, { |
769 | + 'state': 'todo', |
770 | + 'date_done': False, |
771 | + }, context=context) |
772 | + return |
773 | + |
774 | + def action_item_done_with_timesheet_wizard( |
775 | + self, cr, uid, ids, context=None): |
776 | + # I cannot pass the context is the button of a tree view, |
777 | + # that's why I wrote a special function for that... |
778 | + if context is None: |
779 | + context = {} |
780 | + context['action_item_completed'] = True |
781 | + return { |
782 | + 'name': _('Update Action Item and Create Timesheet Line'), |
783 | + 'type': 'ir.actions.act_window', |
784 | + 'res_model': 'project.action.item.timesheet', |
785 | + 'view_type': 'form', |
786 | + 'view_mode': 'form', |
787 | + 'nodestroy': True, |
788 | + 'target': 'new', |
789 | + 'context': context, |
790 | + } |
791 | + |
792 | + |
793 | +class hr_analytic_timesheet(orm.Model): |
794 | + _inherit = "hr.analytic.timesheet" |
795 | + |
796 | + _columns = { |
797 | + 'action_item_id': fields.many2one( |
798 | + 'project.action.item', 'Action Item'), |
799 | + } |
800 | + |
801 | + |
802 | +class project_task(orm.Model): |
803 | + _inherit = "project.task" |
804 | + |
805 | + def _compute_planned_hours( |
806 | + self, cr, uid, ids, name, arg, context=None): |
807 | + res = {} |
808 | + for task in self.browse(cr, uid, ids, context=context): |
809 | + res[task.id] = 0 |
810 | + for action in task.action_item_ids: |
811 | + res[task.id] += action.estimated_hours |
812 | + return res |
813 | + |
814 | + def _get_task_from_action(self, cr, uid, ids, context=None): |
815 | + return self.pool['project.task'].search( |
816 | + cr, uid, [('action_item_ids', 'in', ids)], context=context) |
817 | + |
818 | + _columns = { |
819 | + 'to_work_action_item_ids': fields.one2many( |
820 | + 'project.action.item', 'task_id', 'Action Items To Do', |
821 | + domain=[('state', 'in', ('todo', 'progress'))]), |
822 | + 'done_action_item_ids': fields.one2many( |
823 | + 'project.action.item', 'task_id', 'Action Items Done', |
824 | + domain=[('state', '=', 'done')]), |
825 | + 'action_item_ids': fields.one2many( |
826 | + 'project.action.item', 'task_id', 'Action Items'), |
827 | + 'planned_hours': fields.function( |
828 | + _compute_planned_hours, type="float", |
829 | + string="Initially Planned Hours", store={ |
830 | + 'project.action.item': ( |
831 | + _get_task_from_action, |
832 | + ['estimated_hours', 'task_id'], |
833 | + 10), |
834 | + }, |
835 | + help="Estimated time to do the task. It is the sum of the " |
836 | + "estimated time of all the action items of this task."), |
837 | + } |
838 | |
839 | === added file 'project_action_item/project_demo.xml' |
840 | --- project_action_item/project_demo.xml 1970-01-01 00:00:00 +0000 |
841 | +++ project_action_item/project_demo.xml 2014-05-05 12:05:37 +0000 |
842 | @@ -0,0 +1,64 @@ |
843 | +<?xml version="1.0" encoding="utf-8"?> |
844 | +<openerp> |
845 | +<data noupdate="1"> |
846 | + |
847 | +<record id="action_item_1" model="project.action.item"> |
848 | + <field name="name">Write specs</field> |
849 | + <field name="task_id" ref="project.project_task_8"/> |
850 | + <field name="user_id" ref="base.user_demo"/> |
851 | + <field name="estimated_hours">4.5</field> |
852 | + <field name="sequence">1</field> |
853 | +</record> |
854 | + |
855 | +<record id="action_item_2" model="project.action.item"> |
856 | + <field name="name">Develop a proto</field> |
857 | + <field name="task_id" ref="project.project_task_8"/> |
858 | + <field name="user_id" ref="base.user_demo"/> |
859 | + <field name="estimated_hours">16</field> |
860 | + <field name="sequence">2</field> |
861 | +</record> |
862 | + |
863 | +<record id="action_item_3" model="project.action.item"> |
864 | + <field name="name">Show proto to management</field> |
865 | + <field name="task_id" ref="project.project_task_8"/> |
866 | + <field name="user_id" ref="base.user_demo"/> |
867 | + <field name="estimated_hours">1</field> |
868 | + <field name="sequence">3</field> |
869 | +</record> |
870 | + |
871 | +<record id="action_item_4" model="project.action.item"> |
872 | + <field name="name">Update specs after management meeting</field> |
873 | + <field name="task_id" ref="project.project_task_8"/> |
874 | + <field name="user_id" ref="base.user_demo"/> |
875 | + <field name="estimated_hours">1</field> |
876 | + <field name="sequence">4</field> |
877 | +</record> |
878 | + |
879 | +<record id="action_item_5" model="project.action.item"> |
880 | + <field name="name">Develop final version</field> |
881 | + <field name="task_id" ref="project.project_task_8"/> |
882 | + <field name="user_id" ref="base.user_demo"/> |
883 | + <field name="estimated_hours">42</field> |
884 | + <field name="sequence">5</field> |
885 | +</record> |
886 | + |
887 | +<record id="action_item_6" model="project.action.item"> |
888 | + <field name="name">Show final version to usability team</field> |
889 | + <field name="task_id" ref="project.project_task_8"/> |
890 | + <field name="user_id" ref="base.user_demo"/> |
891 | + <field name="estimated_hours">3</field> |
892 | + <field name="sequence">6</field> |
893 | +</record> |
894 | + |
895 | +<record id="action_item_7" model="project.action.item"> |
896 | + <field name="name">Merge proposal and review</field> |
897 | + <field name="task_id" ref="project.project_task_8"/> |
898 | + <field name="user_id" ref="base.user_demo"/> |
899 | + <field name="estimated_hours">3.5</field> |
900 | + <field name="sequence">7</field> |
901 | +</record> |
902 | + |
903 | + |
904 | + |
905 | +</data> |
906 | +</openerp> |
907 | |
908 | === added file 'project_action_item/project_view.xml' |
909 | --- project_action_item/project_view.xml 1970-01-01 00:00:00 +0000 |
910 | +++ project_action_item/project_view.xml 2014-05-05 12:05:37 +0000 |
911 | @@ -0,0 +1,151 @@ |
912 | +<?xml version="1.0" encoding="utf-8"?> |
913 | +<!-- |
914 | + Copyright (C) 2014 Akretion (http://www.akretion.com/) |
915 | + @author: Alexis de Lattre <alexis.delattre@akretion.com> |
916 | + The licence is in the file __openerp__.py |
917 | +--> |
918 | + |
919 | +<openerp> |
920 | +<data> |
921 | + |
922 | +<record id="project_action_item_form" model="ir.ui.view"> |
923 | + <field name="name">project_action_item.form</field> |
924 | + <field name="model">project.action.item</field> |
925 | + <field name="arch" type="xml"> |
926 | + <form string="Action Item" version="7.0"> |
927 | + <header> |
928 | + <button name="%(project_action_item_timesheet_action)d" |
929 | + type="action" string="Mark as Done with Timesheet" |
930 | + class="oe_highlight" states="todo,progress" |
931 | + context="{'action_item_completed': True}"/> |
932 | + <button name="%(project_action_item_timesheet_action)d" |
933 | + type="action" string="Mark as Progress with Timesheet" |
934 | + class="oe_highlight" states="todo,progress" |
935 | + context="{'action_item_completed': False}" /> |
936 | + <button name="set_to_progress" type="object" |
937 | + string="Mark as In Progress" states="todo"/> |
938 | + <button name="set_to_done" type="object" |
939 | + string="Mark as Done" states="todo,progress"/> |
940 | + <button name="back_to_todo" type="object" |
941 | + string="Back to To Do" states="done,progress"/> |
942 | + <field name="state" widget="statusbar"/> |
943 | + </header> |
944 | + <group name="main"> |
945 | + <field name="project_id" |
946 | + invisible="not context.get('project_action_item_main_view')"/> |
947 | + <field name="task_id" |
948 | + invisible="not context.get('project_action_item_main_view')"/> |
949 | + <field name="name" widget="text"/> |
950 | + <field name="date_deadline"/> |
951 | + <field name="date_done" states="done"/> |
952 | + <field name="estimated_hours" widget="float_time"/> |
953 | + <field name="timesheet_hours" widget="float_time"/> |
954 | + <field name="user_id"/> |
955 | + <field name="to_invoice"/> |
956 | + <field name="create_date"/> |
957 | + <field name="create_uid"/> |
958 | + <field name="sequence" invisible="1"/> |
959 | + </group> |
960 | + <group main="timesheet" string="Timesheets"> |
961 | + <field name="timesheet_ids" nolabel="1"/> |
962 | + </group> |
963 | + </form> |
964 | + </field> |
965 | +</record> |
966 | + |
967 | +<record id="project_action_item_tree" model="ir.ui.view"> |
968 | + <field name="name">project_action_item.tree</field> |
969 | + <field name="model">project.action.item</field> |
970 | + <field name="arch" type="xml"> |
971 | + <tree string="Action Items" editable="bottom" colors="blue:state=='todo';grey:state=='progress'"> |
972 | + <field name="name"/> |
973 | + <field name="project_id" |
974 | + invisible="not context.get('project_action_item_main_view')"/> |
975 | + <field name="task_id" |
976 | + invisible="not context.get('project_action_item_main_view')"/> |
977 | + <field name="date_deadline"/> |
978 | + <field name="user_id"/> |
979 | + <field name="estimated_hours" |
980 | + widget="float_time" sum="Total Estimated Hours"/> |
981 | + <field name="timesheet_hours" |
982 | + widget="float_time" sum="Total Estimated Hours"/> |
983 | + <field name="to_invoice"/> |
984 | + <button name="%(project_action_item_timesheet_action)d" |
985 | + type="action" string="Progress" states="todo,progress" |
986 | + icon="gtk-go-forward" |
987 | + context="{'action_item_completed': False}"/> |
988 | + <button name="action_item_done_with_timesheet_wizard" |
989 | + type="object" icon="terp-gtk-jump-to-ltr" string="Done" |
990 | + states="todo,progress"/> |
991 | + <field name="state"/> |
992 | + <field name="sequence" invisible="1"/> |
993 | + </tree> |
994 | + </field> |
995 | +</record> |
996 | + |
997 | +<record id="project_action_item_search" model="ir.ui.view"> |
998 | + <field name="name">project_action_item.search</field> |
999 | + <field name="model">project.action.item</field> |
1000 | + <field name="arch" type="xml"> |
1001 | + <search string="Search Action Items"> |
1002 | + <field name="name" /> |
1003 | + <filter name="my_action_items_to_work" |
1004 | + string="My Action Items To Work On" |
1005 | + domain="[('user_id', '=', uid), ('state', 'in', ('todo', 'progress'))]"/> |
1006 | + <filter name="my_action_items" string="My Action Items" |
1007 | + domain="[('user_id', '=', uid)]"/> |
1008 | + <filter name="to_work" string="To Work On" |
1009 | + domain="[('state', 'in', ('todo', 'progress'))]" /> |
1010 | + <filter name="done" string="Done" |
1011 | + domain="[('state', '=', 'done')]" /> |
1012 | + <group string="Group By..." name="groupby"> |
1013 | + <filter name="user_id_groupby" string="User" |
1014 | + context="{'group_by': 'user_id'}"/> |
1015 | + <filter name="task_groupby" string="Task" |
1016 | + context="{'group_by': 'task_id'}"/> |
1017 | + </group> |
1018 | + </search> |
1019 | + </field> |
1020 | +</record> |
1021 | + |
1022 | +<record id="project_action_item_action" model="ir.actions.act_window"> |
1023 | + <field name="name">Action Items</field> |
1024 | + <field name="res_model">project.action.item</field> |
1025 | + <field name="view_type">form</field> |
1026 | + <field name="view_mode">tree,form</field> |
1027 | + <field name="context">{'project_action_item_main_view': True, 'search_default_my_action_items_to_work': 1}</field> |
1028 | +</record> |
1029 | + |
1030 | + |
1031 | +<menuitem id="project_action_item_menu" action="project_action_item_action" |
1032 | + parent="project.menu_project_management" sequence="11"/> |
1033 | + |
1034 | +<!-- add todo action items on tasks --> |
1035 | +<record id="view_task_form2" model="ir.ui.view"> |
1036 | + <field name="name">add.action.items.on.tasks.form</field> |
1037 | + <field name="model">project.task</field> |
1038 | + <field name="inherit_id" ref="project.view_task_form2"/> |
1039 | + <field name="arch" type="xml"> |
1040 | + <field name="work_ids" position="before"> |
1041 | + <group name="to_work_action_items" string="Action Items To Work On"> |
1042 | + <field name="to_work_action_item_ids" nolabel="1"/> |
1043 | + </group> |
1044 | + <separator string="Timesheets" /> |
1045 | + </field> |
1046 | + </field> |
1047 | +</record> |
1048 | + |
1049 | +<!-- add link to action item on timesheet --> |
1050 | +<record id="hr_timesheet_line_form" model="ir.ui.view"> |
1051 | + <field name="name">add.action.items.on.timesheet.form</field> |
1052 | + <field name="model">hr.analytic.timesheet</field> |
1053 | + <field name="inherit_id" ref="hr_timesheet_task.hr_timesheet_line_form"/> |
1054 | + <field name="arch" type="xml"> |
1055 | + <field name="task_id" position="after"> |
1056 | + <field name="action_item_id"/> |
1057 | + </field> |
1058 | + </field> |
1059 | +</record> |
1060 | + |
1061 | +</data> |
1062 | +</openerp> |
1063 | |
1064 | === added directory 'project_action_item/security' |
1065 | === added file 'project_action_item/security/ir.model.access.csv' |
1066 | --- project_action_item/security/ir.model.access.csv 1970-01-01 00:00:00 +0000 |
1067 | +++ project_action_item/security/ir.model.access.csv 2014-05-05 12:05:37 +0000 |
1068 | @@ -0,0 +1,2 @@ |
1069 | +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
1070 | +access_project_action_item_user,Full access on action items to Project Users,model_project_action_item,project.group_project_user,1,1,1,1 |
1071 | |
1072 | === added directory 'project_action_item/static' |
1073 | === added directory 'project_action_item/static/src' |
1074 | === added directory 'project_action_item/static/src/img' |
1075 | === added directory 'project_action_item/static/src/img/screenshots' |
1076 | === added file 'project_action_item/static/src/img/screenshots/create_timesheet_from_action_item_wizard.jpg' |
1077 | Binary files project_action_item/static/src/img/screenshots/create_timesheet_from_action_item_wizard.jpg 1970-01-01 00:00:00 +0000 and project_action_item/static/src/img/screenshots/create_timesheet_from_action_item_wizard.jpg 2014-05-05 12:05:37 +0000 differ |
1078 | === added file 'project_action_item/static/src/img/screenshots/task_with_action_items.jpg' |
1079 | Binary files project_action_item/static/src/img/screenshots/task_with_action_items.jpg 1970-01-01 00:00:00 +0000 and project_action_item/static/src/img/screenshots/task_with_action_items.jpg 2014-05-05 12:05:37 +0000 differ |
1080 | === added directory 'project_action_item/wizard' |
1081 | === added file 'project_action_item/wizard/__init__.py' |
1082 | --- project_action_item/wizard/__init__.py 1970-01-01 00:00:00 +0000 |
1083 | +++ project_action_item/wizard/__init__.py 2014-05-05 12:05:37 +0000 |
1084 | @@ -0,0 +1,23 @@ |
1085 | +# -*- encoding: utf-8 -*- |
1086 | +############################################################################## |
1087 | +# |
1088 | +# Project Action Item module for OpenERP |
1089 | +# Copyright (C) 2014 Akretion (http://www.akretion.com) |
1090 | +# @author Alexis de Lattre <alexis.delattre@akretion.com> |
1091 | +# |
1092 | +# This program is free software: you can redistribute it and/or modify |
1093 | +# it under the terms of the GNU Affero General Public License as |
1094 | +# published by the Free Software Foundation, either version 3 of the |
1095 | +# License, or (at your option) any later version. |
1096 | +# |
1097 | +# This program is distributed in the hope that it will be useful, |
1098 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1099 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1100 | +# GNU Affero General Public License for more details. |
1101 | +# |
1102 | +# You should have received a copy of the GNU Affero General Public License |
1103 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1104 | +# |
1105 | +############################################################################## |
1106 | + |
1107 | +from . import update_action_generate_timesheet |
1108 | |
1109 | === added file 'project_action_item/wizard/update_action_generate_timesheet.py' |
1110 | --- project_action_item/wizard/update_action_generate_timesheet.py 1970-01-01 00:00:00 +0000 |
1111 | +++ project_action_item/wizard/update_action_generate_timesheet.py 2014-05-05 12:05:37 +0000 |
1112 | @@ -0,0 +1,137 @@ |
1113 | +# -*- encoding: utf-8 -*- |
1114 | +############################################################################## |
1115 | +# |
1116 | +# Project Action Item module for OpenERP |
1117 | +# Copyright (C) 2014 Akretion (http://www.akretion.com) |
1118 | +# @author Alexis de Lattre <alexis.delattre@akretion.com> |
1119 | +# |
1120 | +# This program is free software: you can redistribute it and/or modify |
1121 | +# it under the terms of the GNU Affero General Public License as |
1122 | +# published by the Free Software Foundation, either version 3 of the |
1123 | +# License, or (at your option) any later version. |
1124 | +# |
1125 | +# This program is distributed in the hope that it will be useful, |
1126 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1127 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1128 | +# GNU Affero General Public License for more details. |
1129 | +# |
1130 | +# You should have received a copy of the GNU Affero General Public License |
1131 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1132 | +# |
1133 | +############################################################################## |
1134 | + |
1135 | +from openerp.osv import orm, fields |
1136 | +from openerp.tools.translate import _ |
1137 | + |
1138 | + |
1139 | +class project_action_item_timesheet(orm.TransientModel): |
1140 | + _name = 'project.action.item.timesheet' |
1141 | + _description = 'Update Action Item and Create Timesheet Line' |
1142 | + |
1143 | + _columns = { |
1144 | + 'date': fields.date('Date', required=True), |
1145 | + 'user_id': fields.many2one('res.users', 'User', required=True), |
1146 | + 'hours': fields.float('Worked Hours'), |
1147 | + 'name': fields.char('Work Description', size=256, required=True), |
1148 | + 'to_invoice': fields.many2one( |
1149 | + 'hr_timesheet_invoice.factor', 'Timesheet Invoicing Ratio'), |
1150 | + 'completed': fields.boolean('Action Item Completed'), |
1151 | + } |
1152 | + |
1153 | + def default_get(self, cr, uid, fields_list, context=None): |
1154 | + if context is None: |
1155 | + context = {} |
1156 | + active_id = context.get('active_id') |
1157 | + res = {} |
1158 | + if active_id: |
1159 | + item = self.pool['project.action.item'].browse( |
1160 | + cr, uid, active_id, context=context) |
1161 | + if not item.task_id: |
1162 | + raise orm.except_orm( |
1163 | + _('Error:'), |
1164 | + _("This action item is not linked to a task, " |
1165 | + "so we cannot generate a timesheet from it.")) |
1166 | + remaining = item.estimated_hours - item.timesheet_hours |
1167 | + if remaining < 0: |
1168 | + remaining = 0 |
1169 | + res = { |
1170 | + 'name': item.name, |
1171 | + 'quantity': remaining, |
1172 | + 'to_invoice': item.to_invoice.id or False, |
1173 | + } |
1174 | + res.update({ |
1175 | + 'user_id': uid, |
1176 | + 'date': fields.date.context_today(self, cr, uid, context=context), |
1177 | + 'completed': context.get('action_item_completed'), |
1178 | + }) |
1179 | + return res |
1180 | + |
1181 | + def _prepare_timesheet(self, cr, uid, action_item, wizard, context=None): |
1182 | + task_id = action_item.task_id.id |
1183 | + to_invoice = wizard.to_invoice.id or False |
1184 | + res_user = self.pool['hr.analytic.timesheet'].on_change_user_id( |
1185 | + cr, uid, False, context['user_id']) |
1186 | + journal_id = res_user['value']['journal_id'] |
1187 | + product_id = res_user['value']['product_id'] |
1188 | + res_unit = self.pool['hr.analytic.timesheet'].on_change_unit_amount( |
1189 | + cr, uid, False, product_id, wizard.hours, False, unit=False, |
1190 | + journal_id=journal_id, task_id=task_id, to_invoice=to_invoice, |
1191 | + context=context) |
1192 | + res_unit['value'].update({ |
1193 | + 'name': wizard.name, |
1194 | + 'date': wizard.date, |
1195 | + 'user_id': wizard.user_id.id, |
1196 | + 'unit_amount': wizard.hours, |
1197 | + 'journal_id': journal_id, |
1198 | + 'task_id': task_id, |
1199 | + 'to_invoice': to_invoice, |
1200 | + 'action_item_id': action_item.id, |
1201 | + }) |
1202 | + return res_unit['value'] |
1203 | + |
1204 | + def _prepare_action_item_update( |
1205 | + self, cr, uid, action_item, wizard, context=None): |
1206 | + if wizard.completed: |
1207 | + res = { |
1208 | + 'state': 'done', |
1209 | + 'date_done': wizard.date, |
1210 | + } |
1211 | + else: |
1212 | + res = {'state': 'progress'} |
1213 | + return res |
1214 | + |
1215 | + def update_action_create_timesheet(self, cr, uid, ids, context=None): |
1216 | + assert len(ids) == 1, "Only one ID" |
1217 | + wizard = self.browse(cr, uid, ids[0], context=context) |
1218 | + if context is None: |
1219 | + context = {} |
1220 | + action_item_id = context['active_id'] |
1221 | + ts_ctx = context.copy() |
1222 | + ts_ctx['user_id'] = wizard.user_id.id |
1223 | + action_item_obj = self.pool['project.action.item'] |
1224 | + action_item = action_item_obj.browse( |
1225 | + cr, uid, action_item_id, context=context) |
1226 | + ts_vals = self._prepare_timesheet( |
1227 | + cr, uid, action_item, wizard, context=ts_ctx) |
1228 | + self.pool['hr.analytic.timesheet'].create( |
1229 | + cr, uid, ts_vals, context=ts_ctx) |
1230 | + action_vals = self._prepare_action_item_update( |
1231 | + cr, uid, action_item, wizard, context=context) |
1232 | + self.pool['project.action.item'].write( |
1233 | + cr, uid, action_item_id, action_vals, context=context) |
1234 | + if context.get('project_action_item_main_view'): |
1235 | + res = True |
1236 | + else: |
1237 | + # refresh the view of the task after completion of the wizard |
1238 | + res = { |
1239 | + 'name': _('Task'), |
1240 | + 'type': 'ir.actions.act_window', |
1241 | + 'res_model': 'project.task', |
1242 | + 'view_type': 'form', |
1243 | + 'view_mode': 'form,tree,kanban,calendar,gantt,graph', |
1244 | + 'nodestroy': False, |
1245 | + 'target': 'current', |
1246 | + 'res_id': action_item.task_id.id, |
1247 | + 'context': context, |
1248 | + } |
1249 | + return res |
1250 | |
1251 | === added file 'project_action_item/wizard/update_action_generate_timesheet_view.xml' |
1252 | --- project_action_item/wizard/update_action_generate_timesheet_view.xml 1970-01-01 00:00:00 +0000 |
1253 | +++ project_action_item/wizard/update_action_generate_timesheet_view.xml 2014-05-05 12:05:37 +0000 |
1254 | @@ -0,0 +1,42 @@ |
1255 | +<?xml version="1.0" encoding="utf-8"?> |
1256 | +<!-- |
1257 | + Copyright (C) 2014 Akretion (http://www.akretion.com/) |
1258 | + @author: Alexis de Lattre <alexis.delattre@akretion.com> |
1259 | + The licence is in the file __openerp__.py |
1260 | +--> |
1261 | + |
1262 | +<openerp> |
1263 | +<data> |
1264 | + |
1265 | +<record id="project_action_item_timesheet_form" model="ir.ui.view"> |
1266 | + <field name="name">project_action_item_timesheet.form</field> |
1267 | + <field name="model">project.action.item.timesheet</field> |
1268 | + <field name="arch" type="xml"> |
1269 | + <form string="Update Action Item and Create Timesheet Line" version="7.0"> |
1270 | + <group name="main"> |
1271 | + <field name="name" widget="text"/> |
1272 | + <field name="date"/> |
1273 | + <field name="hours" widget="float_time"/> |
1274 | + <field name="user_id"/> |
1275 | + <field name="to_invoice"/> |
1276 | + <field name="completed"/> |
1277 | + </group> |
1278 | + <footer> |
1279 | + <button name="update_action_create_timesheet" type="object" |
1280 | + string="Update Action and Create Timesheet" class="oe_highlight"/> |
1281 | + <button special="cancel" string="Cancel" class="oe_link"/> |
1282 | + </footer> |
1283 | + </form> |
1284 | + </field> |
1285 | +</record> |
1286 | + |
1287 | +<record id="project_action_item_timesheet_action" model="ir.actions.act_window"> |
1288 | + <field name="name">Update Action Item and Create Timesheet Line</field> |
1289 | + <field name="res_model">project.action.item.timesheet</field> |
1290 | + <field name="view_type">form</field> |
1291 | + <field name="view_mode">form</field> |
1292 | + <field name="target">new</field> |
1293 | +</record> |
1294 | + |
1295 | +</data> |
1296 | +</openerp> |
Very nice feature Alexis.
I tried it out, and I have some comments:
* I would be nice to inform where the lp branch "hr_timesheet_task" can be found, at least until openerpapps.info rules the world.
* The "Done with timesheet" is not a real button. It took me some time to realize it's test was clickable.
* IMO "Done with timesheet" is a confusing label. I would prefer "Log on Timesheet" or the even simpler "Done".
* Actions should heave a sequence field, and be manually reordered in the Task Actions tab.
* If you have the "Manage time estimation on tasks" feature activated, the Task's estimated time should be computed as the total Actions estimated time (in the demo data, the Tasks estimated time is 22h and the Action estimated time is 70h).
* When an Action is Done, you can't see the actual time spent.
* At the time you are creating the Action list, you should be able to set if you expect it to be billable (or expected Invoicing Ratio).
* You can't log time on an Action without completing it. The demo action "Develop final version" is 42h long, will surely span more than a week, and you will surely won't be able to wait until it's completed to log the time spent.
I suggest the wizard to let you log time on timesheet for an action, but keep it as not done / in progress.
Just some food for thought; it may be a bad idea, but:
What if instead of "Actions" we had "Child Tasks"? If that implementation strategy doesn't bring a lot of difficulties, It would open up a lot of interesting use cases ...