Merge lp:~credativ/openobject-addons/elico-6.1-fixes-gap-analysis-template-management into lp:~openerp-community/openobject-addons/elico-6.1

Proposed by Tom Pickering
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
Reviewer Review Type Date Requested Status
OpenERP Community (OBSOLETE) Pending
Review via email: mp+218422@code.launchpad.net

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.

To post a comment you must log in.
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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>

Subscribers

People subscribed via source and target branches