Merge lp:~credativ/openobject-addons/elico-6.1-fixes-gap-analysis-template-management into lp:~openerp-community/openobject-addons/elico-6.1
- elico-6.1-fixes-gap-analysis-template-management
- Merge into elico-6.1
Status: | Merged |
---|---|
Merged at revision: | 54 |
Proposed branch: | lp:~credativ/openobject-addons/elico-6.1-fixes-gap-analysis-template-management |
Merge into: | lp:~openerp-community/openobject-addons/elico-6.1 |
Diff against target: |
718 lines (+450/-87) 8 files modified
gap_analysis/__openerp__.py (+2/-1) gap_analysis/gap_analysis.py (+187/-52) gap_analysis/gap_analysis.xml (+99/-29) gap_analysis/wizard/__init__.py (+1/-0) gap_analysis/wizard/import_from_sheet.py (+1/-2) gap_analysis/wizard/import_from_tmpl.py (+12/-3) gap_analysis/wizard/line_create_wizard.py (+75/-0) gap_analysis/wizard/line_create_wizard_view.xml (+73/-0) |
To merge this branch: | bzr merge lp:~credativ/openobject-addons/elico-6.1-fixes-gap-analysis-template-management |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
OpenERP Community (OBSOLETE) | Pending | ||
Review via email: mp+218422@code.launchpad.net |
Commit message
Description of the change
This branch adds several features to the Gap Analysis module which help to facilitate template-orientated workflows. These include:
- The ability to view associated Gap Analysis Lines and Gap Analysis Template Lines from a Functionality's form view.
- The ability to add Functionalities to Gap Analyses and Gap Analysis Templates from the 'All Functionalities' view.
- 'Group By...' options in the All 'Functionalities' view.
- Automatic updates to Gap Analysis Templates when a corresponding Functionality template is modified.
- Avoiding creation of duplicate Gap Analysis lines when importing from a Gap Analysis Template.
- 53. By Tom Pickering
-
[FIX] Fixed traceback when changing the functionality of a non-saved Gap Analysis Line.
- 54. By Tom Pickering
-
[IMP] Duplicate functionality warning can now trigger when creating a new line in an existing Gap Analysis, if any duplicates already exist.
Preview Diff
1 | === modified file 'gap_analysis/__openerp__.py' |
2 | --- gap_analysis/__openerp__.py 2013-06-22 02:18:01 +0000 |
3 | +++ gap_analysis/__openerp__.py 2014-05-09 11:32:13 +0000 |
4 | @@ -63,6 +63,7 @@ |
5 | 'gap_analysis_sequence.xml', |
6 | 'gap_analysis.xml', |
7 | 'wizard/import_from_tmpl.xml', |
8 | + 'wizard/line_create_wizard_view.xml' |
9 | ], |
10 | #'demo_xml': ['gap_analysis_demo.xml'], |
11 | 'test': [], |
12 | @@ -73,4 +74,4 @@ |
13 | 'certificate': '', |
14 | } |
15 | |
16 | -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
17 | \ No newline at end of file |
18 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
19 | |
20 | === modified file 'gap_analysis/gap_analysis.py' |
21 | --- gap_analysis/gap_analysis.py 2013-06-22 02:18:01 +0000 |
22 | +++ gap_analysis/gap_analysis.py 2014-05-09 11:32:13 +0000 |
23 | @@ -86,7 +86,8 @@ |
24 | my_type = self.pool.get('gap_analysis.workload.type').browse(cr, uid, type_id) |
25 | val['duration'] = my_type.duration |
26 | return {'value': val} |
27 | - |
28 | + |
29 | + |
30 | gap_analysis_workload() |
31 | |
32 | |
33 | @@ -150,33 +151,129 @@ |
34 | _name = "gap_analysis.functionality" |
35 | _description = "Gap Analysis Functionalities" |
36 | |
37 | + |
38 | + def _search_ga_lines(self, cr, uid, ids, field_names, arg=None, context=None, tmpl=False): |
39 | + if context is None: |
40 | + context = {} |
41 | + |
42 | + ga_obj = self.pool.get('gap_analysis') |
43 | + ga_line_obj = self.pool.get('gap_analysis.line') |
44 | + func_obj = self.pool.get('gap_analysis.functionality') |
45 | + |
46 | + line_ids = ga_line_obj.search(cr, uid, [('functionality','=', ids[0])], context=context) |
47 | + |
48 | + lids_to_gids = {} |
49 | + tmpl_lids = [] |
50 | + ga_obj = self.pool.get('gap_analysis') |
51 | + gap_ids = ga_line_obj.read(cr, uid, line_ids, ['gap_id'], context=context) |
52 | + |
53 | + for gap_id in gap_ids: |
54 | + lids_to_gids[gap_id['id']] = gap_id['gap_id'][0] |
55 | + |
56 | + tmpl_checks = ga_obj.read(cr, uid, [gid['gap_id'][0] for gid in gap_ids], ['is_tmpl'], context=context) |
57 | + gids_to_checks = dict(zip([c['id'] for c in tmpl_checks], [c['is_tmpl'] == tmpl for c in tmpl_checks])) |
58 | + |
59 | + for lid in lids_to_gids.keys(): |
60 | + if gids_to_checks[lids_to_gids[lid]]: |
61 | + tmpl_lids.append(lid) |
62 | + |
63 | + return {ids[0] : [l for l in line_ids if l in tmpl_lids]} |
64 | + |
65 | + |
66 | + def _search_ga_tmpl_lines(self, cr, uid, ids, field_names, arg=None, context=None): |
67 | + return self._search_ga_lines(cr, uid, ids, field_names, arg=arg, context=context, tmpl=True) |
68 | + |
69 | + |
70 | + def _search_ga_non_tmpl_lines(self, cr, uid, ids, field_names, arg=None, context=None): |
71 | + return self._search_ga_lines(cr, uid, ids, field_names, arg=arg, context=context, tmpl=False) |
72 | + |
73 | + |
74 | _columns = { |
75 | - 'name': fields.char('Functionality', size=256, required=True, translate=True), |
76 | - 'description': fields.text('Description'), |
77 | - 'category': fields.many2one('gap_analysis.functionality.category', 'Category', required=True, select=True), |
78 | - 'is_tmpl': fields.boolean('Template ?', help='This Functionality is a Template ?'), |
79 | - 'proposed': fields.boolean('Propose as template ?'), |
80 | + 'name': fields.char('Functionality', size=256, required=True, translate=True), |
81 | + 'description': fields.text('Description'), |
82 | + 'category': fields.many2one('gap_analysis.functionality.category', 'Category', required=True, select=True), |
83 | + 'is_tmpl': fields.boolean('Template ?', help='This Functionality is a Template ?'), |
84 | + 'proposed': fields.boolean('Propose as template ?'), |
85 | #### Default values (Templating) #### |
86 | - 'workloads': fields.one2many('gap_analysis.workload', 'fct_id', 'Default Workloads'), |
87 | - 'openerp_fct': fields.many2one('gap_analysis.openerp', 'Default OpenERP feature', select=True), |
88 | - 'critical': fields.integer('Default Critical Level', help='Indicator to specify the importance of this functionality in the project.'), |
89 | - 'testing': fields.float('Test (hour)'), |
90 | - 'effort': fields.many2one('gap_analysis.effort', 'Default Effort', help="Development Effort for this functionality."), |
91 | - 'duration_wk': fields.float('Default Duration (hour)', help='Since this effort has no pre-defined duration, you must set one.'), |
92 | - 'unknown_wk': fields.boolean('Must set the duration manually ? (Default)',), |
93 | + 'workloads': fields.one2many('gap_analysis.workload', 'fct_id', 'Default Workloads'), |
94 | + 'openerp_fct': fields.many2one('gap_analysis.openerp', 'Default OpenERP feature', select=True), |
95 | + 'critical': fields.integer('Default Critical Level', help='Indicator to specify the importance of this functionality in the project.'), |
96 | + 'testing': fields.float('Test (hour)'), |
97 | + 'effort': fields.many2one('gap_analysis.effort', 'Default Effort', help="Development Effort for this functionality."), |
98 | + 'duration_wk': fields.float('Default Duration (hour)', help='Since this effort has no pre-defined duration, you must set one.'), |
99 | + 'unknown_wk': fields.boolean('Must set the duration manually ? (Default)',), |
100 | + 'ga_lines': fields.function(_search_ga_non_tmpl_lines, type='one2many', relation='gap_analysis.line', method=True, string='Gap Analysis Lines'), |
101 | + 'ga_tmpl_lines': fields.function(_search_ga_tmpl_lines, type='one2many', relation='gap_analysis.line', method=True, string='Gap Analysis Template Lines'), |
102 | } |
103 | + |
104 | + |
105 | + def open_line_wizard(self, cr, uid, ids, context=None): |
106 | + if context is None: |
107 | + context={} |
108 | + |
109 | + title = context.get('default_tmpl', False) and 'Create New Template Entry' or 'Create New Entry' |
110 | + |
111 | + return { |
112 | + 'type' : 'ir.actions.act_window', |
113 | + 'name' : title, |
114 | + 'res_model': 'gap_analysis.line_create_wizard', |
115 | + 'view_type' : 'form', |
116 | + 'view_mode' : 'form', |
117 | + 'target' : 'new', |
118 | + 'context' : context, |
119 | + } |
120 | |
121 | + |
122 | + def onchange_is_tmpl(self, cr, uid, ids, is_tmpl, context=None): |
123 | + if context is None: |
124 | + context = {} |
125 | + |
126 | + if not is_tmpl or not len(ids): |
127 | + return {} |
128 | + |
129 | + ga_line_pool = self.pool.get('gap_analysis.line') |
130 | + related_lines = ga_line_pool.search(cr, uid, [('functionality','=',ids[0])], context=context) |
131 | + |
132 | + if not related_lines: |
133 | + return {} |
134 | + |
135 | + source_line = max(related_lines) |
136 | + fields_to_read = ['workloads', 'openerp_fct', 'critical', 'testing', 'effort', 'duration_wk', 'unknown_wk'] |
137 | + val = ga_line_pool.read(cr, uid, source_line, fields_to_read, context=context) |
138 | + |
139 | + if val.get('workloads', False): |
140 | + wkld_pool = self.pool.get('gap_analysis.workload') |
141 | + new_wklds = [] |
142 | + for wkld in val['workloads']: |
143 | + wkld_data = wkld_pool.read(cr, uid, wkld, ['type', 'duration']) |
144 | + new_wklds.append({'fct_id' : ids[0], 'gap_line_id' : False, 'type' : wkld_data['type'][0], 'duration' : wkld_data['duration']}) |
145 | + val['workloads'] = new_wklds |
146 | + |
147 | + return {'value' : val} |
148 | + |
149 | + |
150 | def onchange_effort_id(self, cr, uid, ids, effort_id, unknown_wk): |
151 | val = {} |
152 | - my_effort = self.pool.get('gap_analysis.effort').browse(cr, uid, effort_id) |
153 | - val['unknown_wk'] = my_effort.unknown |
154 | + if effort_id: |
155 | + my_effort = self.pool.get('gap_analysis.effort').browse(cr, uid, effort_id) |
156 | + val['unknown_wk'] = my_effort.unknown |
157 | + else: |
158 | + val['unknown_wk'] = False |
159 | return {'value': val} |
160 | |
161 | |
162 | def write(self, cr, uid, ids, vals, context=None): |
163 | if 'is_tmpl' in vals and vals['is_tmpl'] == True: |
164 | vals['proposed'] = False |
165 | - return super(gap_analysis_functionality, self).write(cr, uid, ids, vals, context=context) |
166 | + res = super(gap_analysis_functionality, self).write(cr, uid, ids, vals, context=context) |
167 | + if res: |
168 | + id_list = isinstance(ids, list) and ids[:] or [ids] |
169 | + line_pool = self.pool.get('gap_analysis.line') |
170 | + for fid in id_list: |
171 | + lids = line_pool.search(cr, uid, [('gap_id.is_tmpl','=',True),('functionality','=',fid)], context=context) |
172 | + line_pool.set_values_by_fct(cr, uid, lids, fid, context=context) |
173 | + |
174 | + return res |
175 | |
176 | gap_analysis_functionality() |
177 | |
178 | @@ -351,7 +448,7 @@ |
179 | class gap_analysis_line(osv.osv): |
180 | _name = "gap_analysis.line" |
181 | _description = "Gap-analysis Lines" |
182 | - |
183 | + |
184 | def _estimated_line_time_cost(self, cursor, uid, ids, fields, arg, context=None): |
185 | result = {} |
186 | gap = False |
187 | @@ -404,39 +501,71 @@ |
188 | if w.type.id == arg: |
189 | amount += w.duration |
190 | return amount |
191 | - |
192 | - |
193 | - def onchange_functionality_id(self, cr, uid, ids, functionality_id, gap_line_id): |
194 | - val = {} |
195 | - functionality_tmpl = self.pool.get('gap_analysis.functionality').browse(cr, uid, functionality_id) |
196 | - if functionality_tmpl.effort: |
197 | - val['effort'] = functionality_tmpl.effort.id |
198 | - if functionality_tmpl.category: |
199 | - val['category'] = functionality_tmpl.category.id |
200 | - if functionality_tmpl.testing: |
201 | - val['testing'] = functionality_tmpl.testing |
202 | - if functionality_tmpl.unknown_wk: |
203 | - val['unknown_wk'] = functionality_tmpl.unknown_wk |
204 | - if functionality_tmpl.duration_wk: |
205 | - val['duration_wk'] = functionality_tmpl.duration_wk |
206 | - if functionality_tmpl.critical: |
207 | - val['critical'] = functionality_tmpl.critical |
208 | - if functionality_tmpl.openerp_fct: |
209 | - val['openerp_fct'] = functionality_tmpl.openerp_fct.id |
210 | - if functionality_tmpl.workloads: |
211 | - workload_pool = self.pool.get('gap_analysis.workload') |
212 | - my_workloads = [] |
213 | - for workload in functionality_tmpl.workloads: |
214 | - workload_vals = {'type':workload.type.id,'duration':workload.duration,} |
215 | - if gap_line_id: |
216 | - workload_vals['gap_line_id'] = gap_line_id |
217 | - workload_id = workload_pool.create(cr, uid, workload_vals) |
218 | - if workload_id: |
219 | - my_workloads.append(workload_id) |
220 | - if my_workloads: |
221 | + |
222 | + |
223 | + def set_values_by_fct(self, cr, uid, ids, fct_id, ret_fmt_onchange=False, context=None): |
224 | + vals = [] |
225 | + fct_tmpl = self.pool.get('gap_analysis.functionality').browse(cr, uid, fct_id) |
226 | + id_list = isinstance(ids, list) and ids[:] or [ids] |
227 | + for lid in id_list: |
228 | + val = {} |
229 | + if fct_tmpl.effort: |
230 | + val['effort'] = fct_tmpl.effort.id |
231 | + if fct_tmpl.category: |
232 | + val['category'] = fct_tmpl.category.id |
233 | + if fct_tmpl.testing: |
234 | + val['testing'] = fct_tmpl.testing |
235 | + if fct_tmpl.unknown_wk: |
236 | + val['unknown_wk'] = fct_tmpl.unknown_wk |
237 | + if fct_tmpl.duration_wk: |
238 | + val['duration_wk'] = fct_tmpl.duration_wk |
239 | + if fct_tmpl.critical: |
240 | + val['critical'] = fct_tmpl.critical |
241 | + if fct_tmpl.openerp_fct: |
242 | + val['openerp_fct'] = fct_tmpl.openerp_fct.id |
243 | + if fct_tmpl.workloads: |
244 | + workload_pool = self.pool.get('gap_analysis.workload') |
245 | + my_workloads = [] |
246 | + for workload in fct_tmpl.workloads: |
247 | + workload_vals = {'type':workload.type.id,'duration':workload.duration,} |
248 | + if lid: |
249 | + workload_vals['gap_line_id'] = lid |
250 | + my_workloads.append(workload_vals) |
251 | val['workloads'] = my_workloads |
252 | - |
253 | - return {'value': val} |
254 | + if ret_fmt_onchange: |
255 | + vals.append(val) |
256 | + else: |
257 | + my_workloads = val.get('workloads', False) |
258 | + old_wkld_data = self.read(cr, uid, lid, ['workloads'], context=context) |
259 | + if old_wkld_data: |
260 | + old_wklds = old_wkld_data['workloads'] |
261 | + wkld_unlink_tuples = [(2, wid) for wid in old_wklds] |
262 | + val['workloads'] = wkld_unlink_tuples |
263 | + self.write(cr, uid, lid, val, context=context) |
264 | + if my_workloads: |
265 | + wkld_tuples = [] |
266 | + for wkld in my_workloads: |
267 | + wkld_tuples.append((0, 0, wkld)) |
268 | + self.write(cr, uid, lid, {'workloads':wkld_tuples}, context=context) |
269 | + return ret_fmt_onchange and vals or True |
270 | + |
271 | + |
272 | + def onchange_functionality_id(self, cr, uid, ids, fct_id, gap_id, context=None): |
273 | + ret = {} |
274 | + ids = isinstance(ids, list) and ids or [ids] |
275 | + val = self.set_values_by_fct(cr, uid, ids, fct_id, ret_fmt_onchange=True, context=context) |
276 | + ret.update({'value' : val[0]}) |
277 | + |
278 | + if gap_id: |
279 | + ga_lines = self.search(cr, uid, [('gap_id','=',gap_id),('id','!=',ids[0])], context=context) |
280 | + if ga_lines: |
281 | + ga_fcts = self.read(cr, uid, ga_lines, ['functionality'], context=context) |
282 | + if fct_id in [fct['functionality'][0] for fct in ga_fcts]: |
283 | + ret.update({'warning' : { |
284 | + 'title' : 'Warning: Functionality Duplication.', |
285 | + 'message' : 'This functionality already exists within this Gap Analysis.', |
286 | + }}) |
287 | + return ret |
288 | |
289 | |
290 | def onchange_effort_id(self, cr, uid, ids, effort_id, unknown_wk): |
291 | @@ -444,8 +573,13 @@ |
292 | my_effort = self.pool.get('gap_analysis.effort').browse(cr, uid, effort_id) |
293 | val['unknown_wk'] = my_effort.unknown |
294 | return {'value': val} |
295 | - |
296 | - |
297 | + |
298 | + |
299 | + def _get_dummy_gap_is_tmpl(self, cr, uid, ids, fields, arg, context=None): |
300 | + gid = self.read(cr, uid, ids[0], ['gap_id'], context=context)['gap_id'][0] |
301 | + return {ids[0] : self.pool.get('gap_analysis').read(cr, uid, gid, ['is_tmpl'], context=context)['is_tmpl']} |
302 | + |
303 | + |
304 | _columns = { |
305 | 'gap_id': fields.many2one('gap_analysis', 'Gap-analysis', required=True, ondelete='cascade', select=True, readonly=True), |
306 | 'seq': fields.char('Sequence', size=48), |
307 | @@ -463,6 +597,7 @@ |
308 | 'effort': fields.many2one('gap_analysis.effort', 'Effort', help="Development Effort for this functionality."), |
309 | 'duration_wk': fields.float('Duration (hour)', help='Since this effort has no pre-defined duration, you must set one.'), |
310 | 'unknown_wk': fields.boolean('Must set the duration manually ?',), |
311 | + 'dummy_gap_is_tmpl': fields.function(_get_dummy_gap_is_tmpl, type='boolean', name='dummy_gap_is_tmpl', method=True), |
312 | } |
313 | _defaults = { |
314 | 'unknown_wk': lambda *a: False, |
315 | @@ -475,4 +610,4 @@ |
316 | |
317 | gap_analysis_line() |
318 | |
319 | -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
320 | \ No newline at end of file |
321 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
322 | |
323 | === modified file 'gap_analysis/gap_analysis.xml' |
324 | --- gap_analysis/gap_analysis.xml 2013-06-22 02:18:01 +0000 |
325 | +++ gap_analysis/gap_analysis.xml 2014-05-09 11:32:13 +0000 |
326 | @@ -24,36 +24,104 @@ |
327 | <form string="Gap Analysis Functionalities"> |
328 | <field name="category"/> |
329 | <field name="name"/> |
330 | - <field name="is_tmpl" groups="gap_analysis.res_group_gap1"/> |
331 | + <field name="is_tmpl" groups="gap_analysis.res_group_gap1" on_change="onchange_is_tmpl(is_tmpl)"/> |
332 | <field name="proposed" attrs="{'invisible':[('is_tmpl','=',True)]}"/> |
333 | <newline/> |
334 | - <separator string="Description" colspan="4"/> |
335 | - <field name="description" colspan="4" nolabel="1"/> |
336 | - <newline/> |
337 | - <group groups="gap_analysis.res_group_gap1" attrs="{'invisible':[('is_tmpl','=',False)]}" colspan="4" col="4"> |
338 | - <separator colspan="4" string="Template Default Values"/> |
339 | + |
340 | + <notebook colspan="4"> |
341 | + <page string="Details"> |
342 | + <separator string="Description" colspan="4"/> |
343 | + <field name="description" colspan="4" nolabel="1"/> |
344 | + <newline/> |
345 | + <group groups="gap_analysis.res_group_gap1" attrs="{'invisible':[('is_tmpl','=',False)]}" colspan="4" col="4"> |
346 | + <separator colspan="4" string="Default Values"/> |
347 | <field name="critical"/> |
348 | <field name="openerp_fct"/> |
349 | <field name="effort" on_change="onchange_effort_id(effort,unknown_wk)"/> |
350 | <field name="unknown_wk" invisible="1"/> |
351 | - <field name="duration_wk" attrs="{'invisible':[('unknown_wk','=',False)]}"/> |
352 | - <field name="testing"/> |
353 | + <field name="duration_wk" attrs="{'invisible':[('unknown_wk','=',False)]}"/> |
354 | + <field name="testing"/> |
355 | <newline/> |
356 | + |
357 | <separator colspan="4" string="Workloads"/> |
358 | - <field colspan="4" name="workloads" nolabel="1" widget="one2many_list"> |
359 | - <form string="Workloads"> |
360 | - <field name="type" on_change="onchange_type_id(type)" colspan="4"/> |
361 | - <field name="duration"/> |
362 | - </form> |
363 | - <tree string="Workloads"> |
364 | - <field name="type"/> |
365 | - <field name="duration"/> |
366 | - </tree> |
367 | - </field> |
368 | - </group> |
369 | + <field colspan="4" name="workloads" nolabel="1" widget="one2many_list"> |
370 | + <form string="Workloads"> |
371 | + <field name="type" on_change="onchange_type_id(type)" colspan="4"/> |
372 | + <field name="duration"/> |
373 | + </form> |
374 | + <tree> |
375 | + <field name="type"/> |
376 | + <field name="duration"/> |
377 | + </tree> |
378 | + </field> |
379 | + <newline/> |
380 | + </group> |
381 | + </page> |
382 | + |
383 | + <page string="Analyses"> |
384 | + <group colspan="4" col="4"> |
385 | + <separator colspan="4" string="Instances"/> |
386 | + <field colspan="4" name="ga_lines" nolabel="1"> |
387 | + <tree colors="grey:keep==False;"> |
388 | + <field name="gap_id" string="Gap Analysis"/> |
389 | + <field name="code"/> |
390 | + <field name="keep" invisible="1"/> |
391 | + <field name="phase"/> |
392 | + <field name="critical"/> |
393 | + <field name="effort"/> |
394 | + <field name="testing"/> |
395 | + <field name="duration_wk"/> |
396 | + <field name="total_time"/> |
397 | + <field name="total_cost"/> |
398 | + </tree> |
399 | + </field> |
400 | + <button name="open_line_wizard" string="Add to Analysis" type="object" icon="gtk-add" context="{'default_tmpl':False}"/> |
401 | + </group> |
402 | + <group attrs="{'invisible':[('is_tmpl','=',False)]}" colspan="4" col="4"> |
403 | + <separator colspan="4" string="Gap Templates"/> |
404 | + <field colspan="4" name="ga_tmpl_lines" nolabel="1" options="{'deletable': false}"> |
405 | + <tree colors="grey:keep==False;"> |
406 | + <field name="gap_id" string="Template"/> |
407 | + <field name="code"/> |
408 | + <field name="keep" invisible="1"/> |
409 | + <field name="phase"/> |
410 | + <field name="critical"/> |
411 | + <field name="effort"/> |
412 | + <field name="testing"/> |
413 | + <field name="duration_wk"/> |
414 | + </tree> |
415 | + </field> |
416 | + <button name="open_line_wizard" string="Add to Template" type="object" icon="gtk-add" context="{'default_tmpl':True}"/> |
417 | + </group> |
418 | + </page> |
419 | + </notebook> |
420 | </form> |
421 | </field> |
422 | </record> |
423 | + |
424 | + <record id="view_gap_analysis_functionality_filter" model="ir.ui.view"> |
425 | + <field name="name">gap_analysis.functionality.search</field> |
426 | + <field name="model">gap_analysis.functionality</field> |
427 | + <field name="type">search</field> |
428 | + <field name="arch" type="xml"> |
429 | + <search string="Search Functionality"> |
430 | + <filter string="Template" icon="star-on" domain="[('is_tmpl','=',True)]"/> |
431 | + <filter string="Regular" icon="star-off" domain="[('is_tmpl','=',False)]"/> |
432 | + <separator orientation="vertical"/> |
433 | + <filter string="Proposed" icon="terp-idea" domain="[('proposed','=',True)]"/> |
434 | + <field name="category"/> |
435 | + <field name="name" string="Name"/> |
436 | + <field name="description"/> |
437 | + <field name="openerp_fct" string="OpenERP Feature"/> |
438 | + <newline/> |
439 | + <group expand="0" string="Group By..." colspan="4"> |
440 | + <filter string="Category" icon="terp-stage" context="{'group_by':'category'}"/> |
441 | + <filter string="Critical Level" icon="terp-gnome-cpu-frequency-applet+" context="{'group_by':'critical'}"/> |
442 | + <filter string="Effort" icon="terp-project" context="{'group_by':'effort'}"/> |
443 | + </group> |
444 | + </search> |
445 | + </field> |
446 | + </record> |
447 | |
448 | <!-- Functionality Categories --> |
449 | <record id="view_gap_analysis_functionality_category_tree" model="ir.ui.view"> |
450 | @@ -202,19 +270,20 @@ |
451 | <form string="Functionalities"> |
452 | <group colspan="4" col="4"> |
453 | <field name="id" invisible="1"/> |
454 | - <field name="functionality" on_change="onchange_functionality_id(functionality,id)" colspan="4" domain="[('is_tmpl','=',True)]"/> |
455 | - <field name="category"/> |
456 | + <field name="dummy_gap_is_tmpl" invisible="1"/> |
457 | + <field name="functionality" on_change="onchange_functionality_id(functionality,parent.id)" colspan="4" domain="[('is_tmpl','=',True)]"/> |
458 | + <field name="category" attrs="{'readonly':[('dummy_gap_is_tmpl','=',True)]}"/> |
459 | <field name="keep"/> |
460 | - <field name="critical"/> |
461 | - <field name="openerp_fct"/> |
462 | + <field name="critical" attrs="{'readonly':[('dummy_gap_is_tmpl','=',True)]}"/> |
463 | + <field name="openerp_fct" attrs="{'readonly':[('dummy_gap_is_tmpl','=',True)]}"/> |
464 | <field name="contributors"/> |
465 | - <field name="testing"/> |
466 | - <field name="effort" on_change="onchange_effort_id(effort,unknown_wk)"/> |
467 | - <field name="unknown_wk" invisible="1"/> |
468 | - <field name="duration_wk" attrs="{'invisible':[('unknown_wk','=',False)]}"/> |
469 | + <field name="testing" attrs="{'readonly':[('dummy_gap_is_tmpl','=',True)]}"/> |
470 | + <field name="effort" on_change="onchange_effort_id(effort,unknown_wk)" attrs="{'readonly':[('dummy_gap_is_tmpl','=',True)]}"/> |
471 | + <field name="unknown_wk" invisible="1" attrs="{'readonly':[('dummy_gap_is_tmpl','=',True)]}"/> |
472 | + <field name="duration_wk" attrs="{'invisible':[('unknown_wk','=',False)],'readonly':[('dummy_gap_is_tmpl','=',True)]}"/> |
473 | <newline/> |
474 | <separator colspan="4" string="Workloads"/> |
475 | - <field colspan="4" name="workloads" nolabel="1" widget="one2many_list"> |
476 | + <field colspan="4" name="workloads" nolabel="1" widget="one2many_list" attrs="{'readonly':[('dummy_gap_is_tmpl','=',True)]}"> |
477 | <form string="Workloads"> |
478 | <field name="type" on_change="onchange_type_id(type)"/> |
479 | <field name="duration"/> |
480 | @@ -295,6 +364,7 @@ |
481 | <field name="res_model">gap_analysis.functionality</field> |
482 | <field name="view_type">form</field> |
483 | <field name="view_mode">tree,form</field> |
484 | + <field name="search_view">gap_analysis.view_gap_analysis_functionality_filter</field> |
485 | </record> |
486 | <record id="act_gap_analysis_fct_tmpl" model="ir.actions.act_window"> |
487 | <field name="name">Functionality Templates</field> |
488 | @@ -376,4 +446,4 @@ |
489 | <menuitem id="menu_gap_022" name="Efforts" parent="menu_gap_02" sequence="6" action="act_gap_analysis_effort" /> |
490 | <menuitem id="menu_gap_023" name="OpenERP Features" parent="menu_gap_02" sequence="9" action="act_gap_analysis_openerp" /> |
491 | </data> |
492 | -</openerp> |
493 | \ No newline at end of file |
494 | +</openerp> |
495 | |
496 | === modified file 'gap_analysis/wizard/__init__.py' |
497 | --- gap_analysis/wizard/__init__.py 2013-06-22 02:18:01 +0000 |
498 | +++ gap_analysis/wizard/__init__.py 2014-05-09 11:32:13 +0000 |
499 | @@ -22,5 +22,6 @@ |
500 | |
501 | import import_from_tmpl |
502 | import import_from_sheet |
503 | +import line_create_wizard |
504 | |
505 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
506 | |
507 | === modified file 'gap_analysis/wizard/import_from_sheet.py' |
508 | --- gap_analysis/wizard/import_from_sheet.py 2013-06-22 02:18:01 +0000 |
509 | +++ gap_analysis/wizard/import_from_sheet.py 2014-05-09 11:32:13 +0000 |
510 | @@ -222,8 +222,7 @@ |
511 | |
512 | # Check Functionality |
513 | fct_ids = g_fct_pool.search(cr, uid, [('name','ilike',gap_line.functionality)]) |
514 | - if True: |
515 | -# if not fct_ids: |
516 | + if not fct_ids: |
517 | # Create Functionality |
518 | fct_id = g_fct_pool.create(cr, uid, {'name':gap_line.functionality,'description': gap_line.function_desc,'category':gap_line.category,}) |
519 | print('Gap Import: Fct %s created (%s)'%(gap_line.functionality,fct_id)) |
520 | |
521 | === modified file 'gap_analysis/wizard/import_from_tmpl.py' |
522 | --- gap_analysis/wizard/import_from_tmpl.py 2013-06-22 02:18:01 +0000 |
523 | +++ gap_analysis/wizard/import_from_tmpl.py 2014-05-09 11:32:13 +0000 |
524 | @@ -38,10 +38,19 @@ |
525 | this = self.browse(cr, uid, ids[0], context=context) |
526 | gap_line_pool = self.pool.get('gap_analysis.line') |
527 | workload_pool = self.pool.get('gap_analysis.workload') |
528 | - |
529 | + |
530 | for id in context.get('active_ids', []): #for each gap in which we want to import stuff |
531 | + current_line_ids = gap_line_pool.search(cr, uid, [('gap_id','=',id)], context=context) |
532 | + current_fcts = gap_line_pool.read(cr, uid, current_line_ids, ['functionality']) |
533 | + current_fct_ids = [f['functionality'][0] for f in current_fcts] |
534 | + |
535 | #copy gap_line with functionalities and workloads |
536 | for gap_line in this.template.gap_lines: |
537 | + |
538 | + if gap_line.functionality.id in current_fct_ids: |
539 | + # Functionality already exists in the Gap. |
540 | + continue |
541 | + |
542 | line_vals = { |
543 | 'gap_id': id, |
544 | 'functionality': gap_line.functionality.id, |
545 | @@ -54,7 +63,7 @@ |
546 | 'duration_wk': gap_line.duration_wk, |
547 | 'unknown_wk': gap_line.unknown_wk, |
548 | 'testing': gap_line.testing, |
549 | - 'category': gap_line.category, |
550 | + 'category': gap_line.category.id, |
551 | } |
552 | gap_line_id = gap_line_pool.create(cr, uid, line_vals, context=context) |
553 | |
554 | @@ -70,4 +79,4 @@ |
555 | |
556 | gap_analysis_import_from_tmpl() |
557 | |
558 | -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
559 | \ No newline at end of file |
560 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
561 | |
562 | === added file 'gap_analysis/wizard/line_create_wizard.py' |
563 | --- gap_analysis/wizard/line_create_wizard.py 1970-01-01 00:00:00 +0000 |
564 | +++ gap_analysis/wizard/line_create_wizard.py 2014-05-09 11:32:13 +0000 |
565 | @@ -0,0 +1,75 @@ |
566 | + |
567 | + |
568 | +from osv import osv, fields |
569 | +from osv.osv import except_osv |
570 | +from tools.translate import _ |
571 | + |
572 | +class line_create_wizard(osv.TransientModel): |
573 | + _name = 'gap_analysis.line_create_wizard' |
574 | + |
575 | + _columns = { |
576 | + 'gap_id' : fields.many2one('gap_analysis', 'Gap Analysis', required=True), |
577 | + 'tmpl' : fields.boolean('', help='This is used to control the gap_id domain presented in the wizard'), |
578 | + } |
579 | + |
580 | + |
581 | + def create_line(self, cr, uid, ids, context=None): |
582 | + if context is None: |
583 | + context = {} |
584 | + |
585 | + fct_fields = [ |
586 | + 'workloads', |
587 | + 'critical', |
588 | + 'testing', |
589 | + 'duration_wk', |
590 | + 'unknown_wk', |
591 | + ] |
592 | + |
593 | + fct_rel_fields = [ |
594 | + 'category', |
595 | + 'openerp_fct', |
596 | + 'effort', |
597 | + ] |
598 | + |
599 | + line_pool = self.pool.get('gap_analysis.line') |
600 | + fct_pool = self.pool.get('gap_analysis.functionality') |
601 | + self_browse = self.browse(cr, uid, ids[0], context=context) |
602 | + |
603 | + # If adding to a template, make sure all the functionalities are also templates. |
604 | + if self_browse.gap_id.is_tmpl: |
605 | + tmpl_stats = fct_pool.read(cr, uid, context['active_ids'], ['is_tmpl','name'], context=context) |
606 | + if not all([tmpl_stat['is_tmpl'] for tmpl_stat in tmpl_stats]): |
607 | + non_tmpls = [tmpl_stat['name'] for tmpl_stat in tmpl_stats if not tmpl_stat['is_tmpl']] |
608 | + raise except_osv( |
609 | + _('Error: Non-template functionalities may not be added to a Gap Analysis Template.'), |
610 | + _('Please configure these functionalities accordingly and retry:\n\n%s') % ('\n\n'.join(non_tmpls)) |
611 | + ) |
612 | + |
613 | + fct_defs = fct_pool.read(cr, uid, context['active_ids'], fct_fields + fct_rel_fields, context=context) |
614 | + gap_id = self_browse.gap_id.id |
615 | + new_params = {'gap_id' : gap_id} |
616 | + |
617 | + for fct_def in fct_defs: |
618 | + for rel_field in fct_rel_fields: |
619 | + fct_def[rel_field] = fct_def[rel_field] and fct_def[rel_field][0] |
620 | + |
621 | + if fct_def['workloads']: |
622 | + wkld_pool = self.pool.get('gap_analysis.workload') |
623 | + wkld_cps = [] |
624 | + for wkld in fct_def['workloads']: |
625 | + wkld_cp = wkld_pool.copy(cr, uid, wkld, {'fct_id' : False}, context=context) |
626 | + wkld_cps.append(wkld_cp) |
627 | + fct_def['workloads'] = [(6, 0, wkld_cps)] |
628 | + |
629 | + new_params.update(functionality=fct_def['id']) |
630 | + |
631 | + fct_def.update(new_params) |
632 | + del fct_def['id'] |
633 | + line_pool.create(cr, uid, fct_def, context=context) |
634 | + |
635 | + return {'type' : 'ir.actions.act_window_close'} |
636 | + |
637 | + |
638 | +line_create_wizard() |
639 | + |
640 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
641 | |
642 | === added file 'gap_analysis/wizard/line_create_wizard_view.xml' |
643 | --- gap_analysis/wizard/line_create_wizard_view.xml 1970-01-01 00:00:00 +0000 |
644 | +++ gap_analysis/wizard/line_create_wizard_view.xml 2014-05-09 11:32:13 +0000 |
645 | @@ -0,0 +1,73 @@ |
646 | +<?xml version="1.0" encoding="utf-8"?> |
647 | + |
648 | +<openerp> |
649 | + <data> |
650 | + <record id="line_create_wizard_view" model="ir.ui.view"> |
651 | + <field name="name">gap.analysis.line.create.wizard</field> |
652 | + <field name="model">gap_analysis.line_create_wizard</field> |
653 | + <field name="type">form</field> |
654 | + <field name="arch" type="xml"> |
655 | + <form string="Create Gap Analysis Lines"> |
656 | + <group col="2" colspan="2"> |
657 | + <field name="tmpl" invisible="1"/> |
658 | + <field name="gap_id" domain="[('is_tmpl','=',tmpl),'|',('is_tmpl','=',True),('state','=','draft')]"/> |
659 | + </group> |
660 | + <group colspan="2"/> |
661 | + <separator colspan="4"/> |
662 | + <group colspan="2"/> |
663 | + <group col="2" colspan="2"> |
664 | + <button icon="gtk-cancel" special="cancel" string="Cancel" colspan="1"/> |
665 | + <button icon="gtk-apply" name="create_line" string="Create" type="object" colspan="1" default_focus="1"/> |
666 | + </group> |
667 | + </form> |
668 | + </field> |
669 | + </record> |
670 | + |
671 | + <record model="ir.actions.act_window" id="action_gap_analysis_mass_add_to_analysis"> |
672 | + <field name="name">Add to Analysis</field> |
673 | + <field name="type">ir.actions.act_window</field> |
674 | + <field name="view_id" ref="line_create_wizard_view"/> |
675 | + <field name="domain">[]</field> |
676 | + <field name="context">{'default_tmpl' : False}</field> |
677 | + <field name="res_model">gap_analysis.line_create_wizard</field> |
678 | + <field name="view_type">form</field> |
679 | + <field name="view_mode">form</field> |
680 | + <field name="usage">menu</field> |
681 | + <field name="target">new</field> |
682 | + </record> |
683 | + |
684 | + <record model="ir.values" id="values_gap_analysis_mass_add_to_analysis"> |
685 | + <field name="model_id" ref="gap_analysis.model_gap_analysis_functionality" /> |
686 | + <field name="object" eval="1" /> |
687 | + <field name="name">Add to Analysis</field> |
688 | + <field name="key2">client_action_multi</field> |
689 | + <field name="value" eval="'ir.actions.act_window,' + str(ref('action_gap_analysis_mass_add_to_analysis'))" /> |
690 | + <field name="key">action</field> |
691 | + <field name="model">gap_analysis.functionality</field> |
692 | + </record> |
693 | + |
694 | + <record model="ir.actions.act_window" id="action_gap_analysis_mass_add_to_template"> |
695 | + <field name="name">Add to Template</field> |
696 | + <field name="type">ir.actions.act_window</field> |
697 | + <field name="view_id" ref="line_create_wizard_view"/> |
698 | + <field name="domain">[]</field> |
699 | + <field name="context">{'default_tmpl' : True}</field> |
700 | + <field name="res_model">gap_analysis.line_create_wizard</field> |
701 | + <field name="view_type">form</field> |
702 | + <field name="view_mode">form</field> |
703 | + <field name="usage">menu</field> |
704 | + <field name="target">new</field> |
705 | + </record> |
706 | + |
707 | + <record model="ir.values" id="values_gap_analysis_mass_add_to_template"> |
708 | + <field name="model_id" ref="gap_analysis.model_gap_analysis_functionality" /> |
709 | + <field name="object" eval="1" /> |
710 | + <field name="name">Add to Template</field> |
711 | + <field name="key2">client_action_multi</field> |
712 | + <field name="value" eval="'ir.actions.act_window,' + str(ref('action_gap_analysis_mass_add_to_template'))" /> |
713 | + <field name="key">action</field> |
714 | + <field name="model">gap_analysis.functionality</field> |
715 | + </record> |
716 | + |
717 | + </data> |
718 | +</openerp> |