openerp-community team mailing list archive
-
openerp-community team
-
Mailing list archive
-
Message #03561
[Merge] lp:~mmakonnen/openobject-addons/elico-7.0-gap_analysis_ver7.0 into lp:~openerp-community/openobject-addons/elico-7.0
Michael Telahun Makonnen has proposed merging lp:~mmakonnen/openobject-addons/elico-7.0-gap_analysis_ver7.0 into lp:~openerp-community/openobject-addons/elico-7.0.
Requested reviews:
LIN Yu (lin-yu)
For more details, see:
https://code.launchpad.net/~mmakonnen/openobject-addons/elico-7.0-gap_analysis_ver7.0/+merge/192168
This is a port of the following modules from the elico-6.1 branch:
gap_analysis
gap_analysis_project
gap_analsys_project_long_term
gap_analysis_aeroo_report
There are no functional changes. The porting changes include:
- correcting references to fields in res.partner.address that are now folded into res.partner itself
- s/osv.osv/osv.Model/ and s/osv.osv_memory/osv.TransientModel/
- removing lambda in _defaults dict for non-mutable objects
- updating form views to display properly in ver. 7.0
- updating module description formats for 7.0
- remove type fields from 'ir.ui.view' xml declarations
- update xpaths in inherited views where the original paths have changed in ver. 7.0
- clean up and enable demo xml data
--
https://code.launchpad.net/~mmakonnen/openobject-addons/elico-7.0-gap_analysis_ver7.0/+merge/192168
Your team OpenERP Community is subscribed to branch lp:~openerp-community/openobject-addons/elico-7.0.
=== added directory 'gap_analysis'
=== added file 'gap_analysis/__init__.py'
--- gap_analysis/__init__.py 1970-01-01 00:00:00 +0000
+++ gap_analysis/__init__.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import gap_analysis
+import wizard
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'gap_analysis/__openerp__.py'
--- gap_analysis/__openerp__.py 1970-01-01 00:00:00 +0000
+++ gap_analysis/__openerp__.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+
+{
+ 'name': 'Gap Analysis',
+ 'version': '1.0',
+ 'category': 'Tools',
+ 'complexity': "easy",
+ 'description': """
+This module provides the necessary tools to create and manage your gap-analysis.
+Once the Gap Analysis set as Done, you can generate a new project with all the task from the Gap Analysis.
+
+
+You can manage
+--------------
+* functionalities, eg: "Ability to provide quantity discount"
+* categories, eg: "SEO, Website, ..."
+* workload, eg: "1 day for 500$"
+* workload type, eg: "Training, Advanced Development, ..."
+
+
+Report
+------
+* Generate a full gap-analysis, with the total planned workload and cost estimation.
+
+
+Security
+--------
+* Everybody can read
+* Gap Analysis Users can create, read and update their own gap-analysis
+* Gap Analysis Managers can create, read, update and delete any gap-analysis
+""",
+ 'author': 'Elico Corp',
+ 'website': 'http://www.elico-corp.com',
+ 'images': ['images/report.jpg','images/gap_analysis.jpg','images/gap_analysis2.jpg'],
+ 'depends': ['report_webkit','project'],
+ 'init_xml': [],
+ 'update_xml': [
+ 'security/gap_analysis_rules.xml',
+ 'security/ir.model.access.csv',
+ 'report/gap_analysis_report_view.xml',
+ #'gap_analysis_workflow.xml',
+ 'gap_analysis_sequence.xml',
+ 'gap_analysis.xml',
+ 'wizard/import_from_tmpl.xml',
+ ],
+ 'demo_xml': ['gap_analysis_demo.xml'],
+ 'test': [],
+ 'installable': True,
+ 'auto_install': False,
+ 'application': True,
+ 'active': True,
+ 'certificate': '',
+}
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'gap_analysis/gap_analysis.py'
--- gap_analysis/gap_analysis.py 1970-01-01 00:00:00 +0000
+++ gap_analysis/gap_analysis.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,467 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from datetime import datetime
+import time
+from osv import fields, osv
+from tools.translate import _
+from tools import ustr
+#import tools
+
+
+class gap_analysis_effort(osv.Model):
+ _name = "gap_analysis.effort"
+ _description = "Gap Analysis Efforts"
+
+ _columns = {
+ 'name': fields.char('Effort', size=4, required=True,),
+ 'unknown': fields.boolean('Undefined duration ?', help='If checked, when this effort is used, the user would have to specify the duration manually.'),
+ 'duration': fields.float('Duration (hour)', help='Duration in hour for this effort.', required=True,),
+ }
+
+ def onchange_unknown(self, cr, uid, ids, unknown):
+ val = {}
+ val['unknown'] = unknown
+ if not unknown:
+ val['duration'] = 0.0
+ return {'value': val}
+
+ _order = 'name'
+
+
+class gap_analysis_workload_type(osv.Model):
+ _name = "gap_analysis.workload.type"
+ _description = "Gap Analysis Workload Type"
+
+ _columns = {
+ 'name': fields.char('Name', size=64, required=True, translate=True),
+ 'category': fields.selection([('Functional Analysis','Functional'), ('Technical Analysis','Technical')], 'Analysis', required=True,),
+ 'code': fields.char('Code for Report', size=8, required=True, translate=True, help="Set the code if name is too long (eg: in reports)."),
+ 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of workload type."),
+ 'duration': fields.float('Duration (hour)', help='Default duration in hour for this type of workload.', required=True,),
+ }
+ _defaults = {
+ 'sequence': 10,
+ 'category': 'Functional Analysis',
+ 'duration': 4,
+ }
+ _order = 'sequence'
+
+
+
+class gap_analysis_workload(osv.Model):
+ _name = "gap_analysis.workload"
+ _description = "Gap Analysis Workload"
+
+ _columns = {
+ 'gap_line_id': fields.many2one('gap_analysis.line', 'Gap-analysis Line', ondelete='cascade', select=True, readonly=True),
+ 'fct_id': fields.many2one('gap_analysis.functionality', 'Gap-analysis Functionality Template', ondelete='cascade', select=True, readonly=True),
+ 'type': fields.many2one('gap_analysis.workload.type', 'Type', required=True, select=True),
+ 'duration': fields.float('Duration (hour)', help='Duration in hour for this task.', required=True,),
+ }
+
+ def onchange_type_id(self, cr, uid, ids, type_id):
+ val = {}
+ my_type = self.pool.get('gap_analysis.workload.type').browse(cr, uid, type_id)
+ val['duration'] = my_type.duration
+ return {'value': val}
+
+
+
+
+class gap_analysis_functionality_category(osv.Model):
+ _inherit = "product.category"
+ _name = "gap_analysis.functionality.category"
+ _description = "Gap Analysis Functionality Categories"
+
+
+ def _category_to_update(self, cr, uid, ids, fields=None, arg=None, context=None):
+ if type(ids) != type([]):
+ ids = [ids]
+ return self.pool.get('gap_analysis.functionality.category').search(cr, uid, [], order='parent_left') or []
+
+ def _name_get_full_path(self, cursor, uid, ids, fields, arg, context=None):
+ result = {}
+ for category in self.browse(cursor, uid, ids):
+ full_path = ''
+ current_category = category
+ while current_category:
+ if full_path=='':
+ full_path = ustr(current_category.name)
+ else:
+ full_path = ustr(current_category.name) + ' / ' + full_path
+ current_category = current_category.parent_id or False
+ result[category.id] = full_path
+ return result
+
+
+ _columns = {
+ 'parent_id': fields.many2one('gap_analysis.functionality.category','Parent Category', select=True, ondelete='cascade'),
+ 'child_id': fields.one2many('gap_analysis.functionality.category', 'parent_id', string='Child Categories'),
+ 'code': fields.char('Code', size=8, required=True, help="Use for functionality sequencing."),
+ 'full_path': fields.function(_name_get_full_path, type="char", method=True, size=2048, store={'gap_analysis.functionality.category': (_category_to_update, ['name','parent_id'], 10)}, string='Name'),
+ }
+
+ def _check_recursion(self, cr, uid, ids, context=None):
+ level = 100
+ while len(ids):
+ cr.execute('select distinct parent_id from gap_analysis_functionality_category where id IN %s',(tuple(ids),))
+ ids = filter(None, map(lambda x:x[0], cr.fetchall()))
+ if not level:
+ return False
+ level -= 1
+ return True
+
+ _constraints = [
+ (_check_recursion, 'Error ! You cannot create recursive categories.', ['parent_id'])
+ ]
+
+ _parent_name = "parent_id"
+ _parent_store = True
+ _parent_order = 'sequence, name'
+ _order = 'parent_left'
+
+
+
+class gap_analysis_functionality(osv.Model):
+ _name = "gap_analysis.functionality"
+ _description = "Gap Analysis Functionalities"
+
+ _columns = {
+ 'name': fields.char('Functionality', size=256, required=True, translate=True),
+ 'description': fields.text('Description'),
+ 'category': fields.many2one('gap_analysis.functionality.category', 'Category', required=True, select=True),
+ 'is_tmpl': fields.boolean('Template ?', help='This Functionality is a Template ?'),
+ 'proposed': fields.boolean('Propose as template ?'),
+ #### Default values (Templating) ####
+ 'workloads': fields.one2many('gap_analysis.workload', 'fct_id', 'Default Workloads'),
+ 'openerp_fct': fields.many2one('gap_analysis.openerp', 'Default OpenERP feature', select=True),
+ 'critical': fields.integer('Default Critical Level', help='Indicator to specify the importance of this functionality in the project.'),
+ 'testing': fields.float('Test (hour)'),
+ 'effort': fields.many2one('gap_analysis.effort', 'Default Effort', help="Development Effort for this functionality."),
+ 'duration_wk': fields.float('Default Duration (hour)', help='Since this effort has no pre-defined duration, you must set one.'),
+ 'unknown_wk': fields.boolean('Must set the duration manually ? (Default)',),
+ }
+
+ def onchange_effort_id(self, cr, uid, ids, effort_id, unknown_wk):
+ val = {}
+ my_effort = self.pool.get('gap_analysis.effort').browse(cr, uid, effort_id)
+ val['unknown_wk'] = my_effort.unknown
+ return {'value': val}
+
+
+ def write(self, cr, uid, ids, vals, context=None):
+ if 'is_tmpl' in vals and vals['is_tmpl'] == True:
+ vals['proposed'] = False
+ return super(gap_analysis_functionality, self).write(cr, uid, ids, vals, context=context)
+
+
+class gap_analysis_openerp(osv.Model):
+ _name = "gap_analysis.openerp"
+ _description = "Gap Analysis OpenERP features"
+
+ _columns = {
+ 'name': fields.char('OpenERP feature', size=256, required=True, translate=True),
+ }
+
+
+class gap_analysis(osv.Model):
+ _name = "gap_analysis"
+ _description = "Gap Analysis"
+
+ def _estimated_time_cost(self, cursor, uid, ids, fields, arg, context=None):
+ result = {}
+ for gap in self.browse(cursor, uid, ids):
+ res = {}
+ res['estimated_time'] = 0.0
+ res['estimated_cost'] = 0.0
+
+ for gap_line in gap.gap_lines:
+ if gap_line.keep:
+ res['estimated_time'] += gap_line.total_time
+ res['estimated_cost'] += gap_line.total_cost
+
+ result[gap.id] = res
+ return result
+
+
+ def _sorted_distinct_workloads(self, cursor, uid, ids, arg, context=None):
+ result = {}
+ for gap in self.browse(cursor, uid, ids):
+ types = []
+ line_ids = [l.id for l in gap.gap_lines]
+ if line_ids:
+ cursor.execute("SELECT id, code FROM gap_analysis_workload_type T WHERE id in (SELECT DISTINCT(W.type) FROM gap_analysis_workload W WHERE W.gap_line_id IN %s) ORDER BY T.sequence ASC",(tuple(line_ids),))
+ types = cursor.fetchall()
+ return types
+
+
+ def button_dummy(self, cr, uid, ids, context=None):
+ gapline_pool = self.pool.get('gap_analysis.line')
+ gap_cat_pool = self.pool.get('gap_analysis.functionality.category')
+ if type(ids) != type([]):
+ ids = [ids]
+
+ for gap_id in ids:
+ cr.execute("SELECT DISTINCT c.code FROM gap_analysis_line l, gap_analysis_functionality_category c WHERE l.category=c.id AND l.gap_id = %s",(gap_id,))
+ categ_codes = map(lambda x: x[0], cr.fetchall()) or []
+
+ for code in categ_codes:
+ idx = 1
+ seq = 999
+
+ cr.execute("SELECT id FROM gap_analysis_functionality_category WHERE id IN (SELECT DISTINCT c.id FROM gap_analysis_line l, gap_analysis_functionality_category c WHERE l.category=c.id AND c.code = %s AND l.gap_id = %s) ORDER BY parent_left",(code, gap_id,))
+ categ_ids = map(lambda x: x[0], cr.fetchall()) or []
+
+ for categ in gap_cat_pool.browse(cr, uid, categ_ids):
+ current_categ = categ
+ seq = ''
+ while current_categ:
+ seq = str(current_categ.sequence) + seq
+ current_categ = current_categ.parent_id or False
+
+ line_ids = gapline_pool.search(cr, uid, [('category','=',categ.id),('gap_id','=',gap_id)], order='critical desc, effort asc') or []
+ for line_id in line_ids:
+ code_line = code
+ code_line += str(idx).rjust(3, '0')
+ gapline_pool.write(cr, uid, [line_id], {'code':code_line,'seq':seq})
+ idx += 1
+ return True
+
+
+ def import_from_tmpl(self, cr, uid, ids, context=None):
+ return {
+ 'name': _('Import from Template'),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'view_id': False,
+ 'res_model': 'gap_analysis.import_from_tmpl',
+ 'context': context,
+ 'type': 'ir.actions.act_window',
+ 'target': 'new',
+ 'res_id': False,
+ }
+
+
+ def _get_lines(self, cr, uid, ids, context=None):
+ result = {}
+ for line in self.pool.get('gap_analysis.line').browse(cr, uid, ids, context=context):
+ result[line.gap_id.id] = True
+ return result.keys()
+
+
+ def action_change(self, cr, uid, ids, context=None):
+ for o in self.browse(cr, uid, ids):
+ self.write(cr, uid, [o.id], {'state':'draft', 'date_confirm': False})
+ return True
+
+ def action_done(self, cr, uid, ids, context=None):
+ for o in self.browse(cr, uid, ids):
+ self.write(cr, uid, [o.id], {'state': 'done', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
+ return True
+
+ def action_cancel(self, cr, uid, ids, context=None):
+ for o in self.browse(cr, uid, ids):
+ self.write(cr, uid, [o.id], {'state': 'cancel'})
+ return True
+
+
+ def copy(self, cr, uid, id, default=None, context=None):
+ raise osv.except_osv(_('Warning'), _("Copying a Gap Analysis is currently not allowed."))
+ return False
+
+
+ def onchange_project_id(self, cr, uid, ids, project_id):
+ val = {}
+ my_project = self.pool.get('project.project').browse(cr, uid, project_id)
+ if my_project.partner_id:
+ val['partner_id'] = my_project.partner_id.id
+ return {'value': val}
+
+
+ _columns = {
+ 'reference': fields.char('Reference', size=64, required=True, readonly=True, states={'draft': [('readonly', False)]}, select=True),
+ 'name': fields.char('Name', size=256, required=True, readonly=True, states={'draft': [('readonly', False)]}),
+ 'state': fields.selection([('draft', 'Draft'), ('done', 'Done'), ('cancel', 'Cancelled')], 'State', readonly=True, help="Gives the state of the gap-analysis.", select=True),
+ 'note': fields.text('Note'),
+ 'date_create': fields.datetime('Creation Date', readonly=True, select=True, help="Date on which the gap-analysis is created."),
+ 'date_confirm': fields.date('Confirmation Date', readonly=True, select=True, help="Date on which the gap-analysis is confirmed."),
+ 'user_id': fields.many2one('res.users', 'Analyst', readonly=True, states={'draft': [('readonly', False)]}, select=True),
+ 'partner_id': fields.many2one('res.partner', 'Customer', select=True, readonly=True, states={'draft': [('readonly', False)]}, ),
+ 'gap_lines': fields.one2many('gap_analysis.line', 'gap_id', 'Functionalities', readonly=True, states={'draft': [('readonly', False)]}),
+ 'estimated_time': fields.function(_estimated_time_cost, type='float', multi="gapsums", string='Estimated Time', store = False),
+ 'estimated_cost': fields.function(_estimated_time_cost, type='float', multi="gapsums", string='Estimated Selling Price', store = False),
+ 'project_id': fields.many2one('project.project', 'Project'),
+ 'partner_id': fields.many2one('res.partner', 'Partner'),
+ 'is_tmpl': fields.boolean('Template ?', help='This Gap Analysis is a Template ?'),
+ 'tech_cost': fields.float('Technical Analysis Price', help='Default Price per hour for Technical Analysis.'),
+ 'func_cost': fields.float('Functional Analysis Price', help='Default Price per hour for Functional Analysis.'),
+ 'dev_cost': fields.float('Effort Price', help='Price per hour for Effort.'),
+
+ 'user_functional': fields.many2one('res.users', 'Default Functional Analyst'),
+ 'user_technical': fields.many2one('res.users', 'Default Technical Analyst'),
+ 'user_dev': fields.many2one('res.users', 'Default Developer'),
+ 'user_test': fields.many2one('res.users', 'Default Tester'),
+ }
+ _defaults = {
+ 'state': 'draft',
+ 'user_id': lambda obj, cr, uid, context: uid,
+ 'user_functional': lambda obj, cr, uid, context: uid,
+ 'reference': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'gap_analysis'),
+ 'date_create': fields.date.context_today,
+ 'tech_cost': 500.0,
+ 'func_cost': 500.0,
+ 'dev_cost': 250.0,
+ }
+ _sql_constraints = [
+ ('reference_uniq', 'unique(reference)', 'Reference must be unique !'),
+ ]
+ _order = 'name desc'
+
+
+
+class gap_analysis_line(osv.Model):
+ _name = "gap_analysis.line"
+ _description = "Gap-analysis Lines"
+
+ def _estimated_line_time_cost(self, cursor, uid, ids, fields, arg, context=None):
+ result = {}
+ gap = False
+ for gap_line in self.browse(cursor, uid, ids):
+ res = {}
+ res['total_time'] = 0
+ res['total_cost'] = 0
+
+ if not gap:
+ gap = self.pool.get("gap_analysis").browse(cursor, uid, gap_line.gap_id.id)
+
+ if gap_line.effort:
+ if gap_line.effort.unknown:
+ thistime = gap_line.duration_wk
+ else:
+ thistime = gap_line.effort.duration
+
+ res['total_time'] = thistime
+ res['total_cost'] = (gap.dev_cost * thistime)
+
+ for workload in gap_line.workloads:
+ if workload.type.category == "Technical Analysis":
+ workload_cost = gap.tech_cost
+ else:
+ workload_cost = gap.func_cost
+
+ res['total_time'] += workload.duration
+ res['total_cost'] += (workload.duration * workload_cost)
+
+ if gap_line.testing:
+ res['total_time'] += gap_line.testing
+ res['total_cost'] += (gap_line.testing * gap.tech_cost)
+
+ result[gap_line.id] = res
+ return result
+
+
+ def _get_lines_from_workload(self, cr, uid, ids, context=None):
+ result = {}
+ for workload in self.pool.get('gap_analysis.workload').browse(cr, uid, ids, context=context):
+ result[workload.gap_line_id.id] = True
+ return result.keys()
+
+
+ def _total_workloads(self, cursor, uid, ids, arg, context=None):
+ result = {}
+ for line in self.browse(cursor, uid, ids):
+ amount = 0
+ for w in line.workloads:
+ if w.type.id == arg:
+ amount += w.duration
+ return amount
+
+
+ def onchange_functionality_id(self, cr, uid, ids, functionality_id, gap_line_id):
+ val = {}
+ functionality_tmpl = self.pool.get('gap_analysis.functionality').browse(cr, uid, functionality_id)
+ if functionality_tmpl.effort:
+ val['effort'] = functionality_tmpl.effort.id
+ if functionality_tmpl.category:
+ val['category'] = functionality_tmpl.category.id
+ if functionality_tmpl.testing:
+ val['testing'] = functionality_tmpl.testing
+ if functionality_tmpl.unknown_wk:
+ val['unknown_wk'] = functionality_tmpl.unknown_wk
+ if functionality_tmpl.duration_wk:
+ val['duration_wk'] = functionality_tmpl.duration_wk
+ if functionality_tmpl.critical:
+ val['critical'] = functionality_tmpl.critical
+ if functionality_tmpl.openerp_fct:
+ val['openerp_fct'] = functionality_tmpl.openerp_fct.id
+ if functionality_tmpl.workloads:
+ workload_pool = self.pool.get('gap_analysis.workload')
+ my_workloads = []
+ for workload in functionality_tmpl.workloads:
+ workload_vals = {'type':workload.type.id,'duration':workload.duration,}
+ if gap_line_id:
+ workload_vals['gap_line_id'] = gap_line_id
+ workload_id = workload_pool.create(cr, uid, workload_vals)
+ if workload_id:
+ my_workloads.append(workload_id)
+ if my_workloads:
+ val['workloads'] = my_workloads
+
+ return {'value': val}
+
+
+ def onchange_effort_id(self, cr, uid, ids, effort_id, unknown_wk):
+ val = {}
+ my_effort = self.pool.get('gap_analysis.effort').browse(cr, uid, effort_id)
+ val['unknown_wk'] = my_effort.unknown
+ return {'value': val}
+
+
+ _columns = {
+ 'gap_id': fields.many2one('gap_analysis', 'Gap-analysis', required=True, ondelete='cascade', select=True, readonly=True),
+ 'seq': fields.char('Sequence', size=48),
+ 'code': fields.char('Code', size=6),
+ 'functionality': fields.many2one('gap_analysis.functionality', 'Functionality', required=True, select=True),
+ 'category': fields.many2one('gap_analysis.functionality.category', 'Category', required=True, select=True),
+ 'workloads': fields.one2many('gap_analysis.workload', 'gap_line_id', 'Workloads'),
+ 'total_time': fields.function(_estimated_line_time_cost, method=True, type='float', multi=True, string='Estimated Time', store = {'gap_analysis.line': (lambda self, cr, uid, ids, c={}: ids, ['testing','workloads','duration_wk','effort','unknown_wk'], 10),'gap_analysis.workload': (_get_lines_from_workload, ['workload', 'duration'], 10),}),
+ 'total_cost': fields.function(_estimated_line_time_cost, method=True, type='float', multi=True, string='Estimated Selling Price', store = {'gap_analysis.line': (lambda self, cr, uid, ids, c={}: ids, ['testing','workloads','duration_wk','effort','unknown_wk'], 10),'gap_analysis.workload': (_get_lines_from_workload, ['workload', 'duration'], 10),}),
+ 'openerp_fct': fields.many2one('gap_analysis.openerp', 'OpenERP feature', select=True),
+ 'contributors': fields.char('Contributor', size=256, help='Who is/are your main contact(s) to define this functionality.'),
+ 'keep': fields.boolean('Keep ?', help='Keep the functionality in the Gap Analysis. If unchecked, the functionality will be print in the report but not used for the price calculation.'),
+ 'critical': fields.integer('Critical Level', help='Indicator to specify the importance of this functionality in the project.'),
+ 'testing': fields.float('Test (hour)'),
+ 'effort': fields.many2one('gap_analysis.effort', 'Effort', help="Development Effort for this functionality."),
+ 'duration_wk': fields.float('Duration (hour)', help='Since this effort has no pre-defined duration, you must set one.'),
+ 'unknown_wk': fields.boolean('Must set the duration manually ?',),
+ }
+ _defaults = {
+ 'unknown_wk': False,
+ 'keep': True,
+ 'critical': 1,
+ }
+
+ _order = 'seq asc, code asc'
+ _rec_name = 'code'
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis/gap_analysis.xml'
--- gap_analysis/gap_analysis.xml 1970-01-01 00:00:00 +0000
+++ gap_analysis/gap_analysis.xml 2013-10-22 14:58:07 +0000
@@ -0,0 +1,429 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <!-- Functionalities -->
+ <record id="view_gap_analysis_functionality_tree" model="ir.ui.view">
+ <field name="name">gap_analysis.functionality.tree</field>
+ <field name="model">gap_analysis.functionality</field>
+ <field name="arch" type="xml">
+ <tree string="Gap Analysis Functionalities">
+ <field name="category"/>
+ <field name="name"/>
+ <field name="effort" groups="gap_analysis.res_group_gap1"/>
+ <field name="critical" groups="gap_analysis.res_group_gap1"/>
+ <field name="openerp_fct" groups="gap_analysis.res_group_gap1"/>
+ </tree>
+ </field>
+ </record>
+ <record id="view_gap_analysis_functionality_form" model="ir.ui.view">
+ <field name="name">gap_analysis.functionality.form</field>
+ <field name="model">gap_analysis.functionality</field>
+ <field name="arch" type="xml">
+ <form string="Gap Analysis Functionalities" version="7.0">
+ <sheet>
+ <group>
+ <group>
+ <field name="category"/>
+ <field name="name"/>
+ <field name="is_tmpl" groups="gap_analysis.res_group_gap1"/>
+ <field name="proposed" attrs="{'invisible':[('is_tmpl','=',True)]}"/>
+ </group>
+ </group>
+ <group string="Description">
+ <field name="description" nolabel="1"/>
+ </group>
+ <group groups="gap_analysis.res_group_gap1" attrs="{'invisible':[('is_tmpl','=',False)]}">
+ <group string="Template Default Values">
+ <field name="critical"/>
+ <field name="openerp_fct"/>
+ <field name="effort" on_change="onchange_effort_id(effort,unknown_wk)"/>
+ <field name="unknown_wk" invisible="1"/>
+ <field name="duration_wk" attrs="{'invisible':[('unknown_wk','=',False)]}"/>
+ <field name="testing"/>
+ </group>
+ <group string="Workloads">
+ <field name="workloads" nolabel="1" widget="one2many_list">
+ <form string="Workloads">
+ <field name="type" on_change="onchange_type_id(type)"/>
+ <field name="duration"/>
+ </form>
+ <tree string="Workloads">
+ <field name="type"/>
+ <field name="duration"/>
+ </tree>
+ </field>
+ </group>
+ </group>
+ </sheet>
+ </form>
+ </field>
+ </record>
+
+ <!-- Functionality Categories -->
+ <record id="view_gap_analysis_functionality_category_tree" model="ir.ui.view">
+ <field name="name">gap_analysis.functionality.category.tree</field>
+ <field name="model">gap_analysis.functionality.category</field>
+ <field name="arch" type="xml">
+ <tree string="Gap Analysis Functionality categories">
+ <field name="sequence"/>
+ <field name="code"/>
+ <field name="full_path"/>
+ </tree>
+ </field>
+ </record>
+ <record id="view_gap_analysis_functionality_category_search" model="ir.ui.view">
+ <field name="name">gap_analysis.functionality.category.search</field>
+ <field name="model">gap_analysis.functionality.category</field>
+ <field name="arch" type="xml">
+ <search string="Gap Analysis Functionality categories">
+ <field name="parent_id" select="1" widget="selection"/>
+ <field name="child_id" select="1" widget="selection"/>
+ <field name="sequence"/>
+ <field name="full_path"/>
+ <field name="code"/>
+ </search>
+ </field>
+ </record>
+ <record id="view_gap_analysis_functionality_category_form" model="ir.ui.view">
+ <field name="name">gap_analysis.functionality.category.form</field>
+ <field name="model">gap_analysis.functionality.category</field>
+ <field name="arch" type="xml">
+ <form string="Gap Analysis Functionality categories" version="7.0">
+ <sheet>
+ <group>
+ <group>
+ <field name="name"/>
+ <field name="code"/>
+ <field name="parent_id"/>
+ <field name="sequence"/>
+ <field name="type" invisible="1"/>
+ </group>
+ </group>
+ </sheet>
+ </form>
+ </field>
+ </record>
+
+ <!-- Effort -->
+ <record id="view_gap_analysis_effort_tree" model="ir.ui.view">
+ <field name="name">gap_analysis.effort.tree</field>
+ <field name="model">gap_analysis.effort</field>
+ <field name="arch" type="xml">
+ <tree string="Gap Analysis Efforts">
+ <field name="name"/>
+ <field name="unknown"/>
+ <field name="duration"/>
+ </tree>
+ </field>
+ </record>
+ <record id="view_gap_analysis_effort_form" model="ir.ui.view">
+ <field name="name">gap_analysis.effort.form</field>
+ <field name="model">gap_analysis.effort</field>
+ <field name="arch" type="xml">
+ <form string="Gap Analysis Efforts" version="7.0">
+ <sheet>
+ <group>
+ <group>
+ <field name="name"/>
+ <field name="unknown" on_change="onchange_unknown(unknown)"/>
+ <field name="duration" attrs="{'invisible':[('unknown','=',True)]}"/>
+ </group>
+ </group>
+ </sheet>
+ </form>
+ </field>
+ </record>
+
+ <!-- Workload Type -->
+ <record id="view_gap_analysis_workload_type_tree" model="ir.ui.view">
+ <field name="name">gap_analysis.workload.type.tree</field>
+ <field name="model">gap_analysis.workload.type</field>
+ <field name="arch" type="xml">
+ <tree string="Gap Analysis workload type">
+ <field name="sequence"/>
+ <field name="category"/>
+ <field name="code"/>
+ <field name="name"/>
+ <field name="duration"/>
+ </tree>
+ </field>
+ </record>
+ <record id="view_gap_analysis_workload_type_form" model="ir.ui.view">
+ <field name="name">gap_analysis.workload.type.form</field>
+ <field name="model">gap_analysis.workload.type</field>
+ <field name="arch" type="xml">
+ <form string="Gap Analysis workload type" version="7.0">
+ <sheet>
+ <group>
+ <group>
+ <field name="sequence"/>
+ <field name="code"/>
+ <field name="duration"/>
+ </group>
+ <group>
+ <field name="category"/>
+ <field name="name"/>
+ </group>
+ </group>
+ </sheet>
+ </form>
+ </field>
+ </record>
+
+ <!-- Gap Analysis -->
+ <record model="ir.ui.view" id="view_gap_analysis_graph">
+ <field name="name">gap_analysis.graph</field>
+ <field name="model">gap_analysis</field>
+ <field name="arch" type="xml">
+ <graph string="Gap Analysis" type="bar">
+ <field name="partner_id"/>
+ <field name="estimated_cost" operator="+"/>
+ </graph>
+ </field>
+ </record>
+ <record id="view_gap_analysis_tree" model="ir.ui.view">
+ <field name="name">gap_analysis.tree</field>
+ <field name="model">gap_analysis</field>
+ <field name="arch" type="xml">
+ <tree string="Gap Analysis" colors="grey:state=='cancel';blue:state in ('draft');">
+ <field name="reference"/>
+ <field name="name"/>
+ <field name="partner_id"/>
+ <field name="user_id"/>
+ <field name="estimated_cost"/>
+ <field name="state"/>
+ </tree>
+ </field>
+ </record>
+ <record id="view_gap_analysis_form" model="ir.ui.view">
+ <field name="name">gap_analysis.form</field>
+ <field name="model">gap_analysis</field>
+ <field name="arch" type="xml">
+ <form string="Gap Analysis" version="7.0">
+ <header>
+ <group attrs="{'invisible':[('is_tmpl','=',True)]}">
+ <div class="oe_button_box oe_left">
+ <button name="action_done" states="draft" string="Confirm" type="object" icon="gtk-apply" class="oe_highlight"/>
+ <button name="action_change" states="done,cancel" string="Reactivate" type="object" icon="gtk-convert" class="oe_highlight"/>
+ <button name="action_cancel" states="draft" string="Cancel" type="object" icon="gtk-cancel"/>
+ </div>
+ <field name="state" widget="statusbar" statusbar_visible="draft,done,cancel" statusbar_colors='{"cancel":"red"}' nolabel="1"/>
+ </group>
+ </header>
+ <sheet>
+ <group>
+ <group>
+ <field name="reference"/>
+ <field name="date_create"/>
+ <field name="is_tmpl" groups="gap_analysis.res_group_gap1"/>
+ <field name="project_id" on_change="onchange_project_id(project_id)"/>
+ </group>
+ <group>
+ <field name="name"/>
+ <field name="date_confirm"/>
+ <field name="user_id"/>
+ <field name="partner_id"/>
+ </group>
+ </group>
+ <notebook>
+ <page string="Functionalities">
+ <button name="import_from_tmpl" attrs="{'invisible':['|',('state','!=','draft'),('is_tmpl','=',True)]}" icon="gtk-execute" type="object" string="Import from Template" />
+ <field name="gap_lines" nolabel="1" widget="one2many_list">
+ <form string="Functionalities" version="7.0">
+ <group>
+ <group>
+ <field name="id" invisible="1"/>
+ <field name="functionality" on_change="onchange_functionality_id(functionality,id)" colspan="4" domain="[('is_tmpl','=',True)]"/>
+ <field name="keep"/>
+ <field name="openerp_fct"/>
+ <field name="testing"/>
+ <field name="unknown_wk" invisible="1"/>
+ </group>
+ <group>
+ <field name="category"/>
+ <field name="critical"/>
+ <field name="contributors"/>
+ <field name="effort" on_change="onchange_effort_id(effort,unknown_wk)"/>
+ <field name="duration_wk" attrs="{'invisible':[('unknown_wk','=',False)]}"/>
+ </group>
+ </group>
+ <group string="Workloads">
+ <field name="workloads" nolabel="1" widget="one2many_list">
+ <form string="Workloads" version="7.0">
+ <group>
+ <group>
+ <field name="type" on_change="onchange_type_id(type)"/>
+ <field name="duration"/>
+ </group>
+ </group>
+ </form>
+ <tree string="Workloads">
+ <field name="type"/>
+ <field name="duration"/>
+ </tree>
+ </field>
+ </group>
+ <group>
+ <group>
+ <field name="total_cost"/>
+ </group>
+ </group>
+ </form>
+ <tree string="Functionalities" colors="grey:keep==False;">
+ <field name="code"/>
+ <field name="keep"/>
+ <field name="category"/>
+ <field name="functionality"/>
+ <field name="total_cost"/>
+ </tree>
+ </field>
+ </page>
+ <page string="Pricing" groups="gap_analysis.res_group_gap1">
+ <group>
+ <group>
+ <field name="func_cost"/>
+ <field name="tech_cost"/>
+ <field name="dev_cost"/>
+ </group>
+ </group>
+ </page>
+ <page string="Resources" groups="gap_analysis.res_group_gap1">
+ <group>
+ <group>
+ <field colspan="2" name="user_functional"/>
+ <field colspan="2" name="user_dev"/>
+ </group>
+ <group>
+ <field colspan="2" name="user_technical"/>
+ <field colspan="2" name="user_test"/>
+ </group>
+ </group>
+ </page>
+ <page string="Notes">
+ <field name="note" nolabel="1"/>
+ </page>
+ </notebook>
+ <group col="5" colspan="4">
+ <group>
+ <group>
+ <field name="estimated_cost"/>
+ </group>
+ <group>
+ <button name="button_dummy" type="object" string="Compute Price / Code" groups="gap_analysis.res_group_gap0,gap_analysis.res_group_gap1"/>
+ </group>
+ </group>
+ </group>
+ </sheet>
+ </form>
+ </field>
+ </record>
+
+ <!-- Actions -->
+ <record id="act_gap_analysis" model="ir.actions.act_window">
+ <field name="name">Gap Analysis</field>
+ <field name="res_model">gap_analysis</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form,graph</field>
+ <field name="domain">[('is_tmpl','=',False)]</field>
+ </record>
+ <record id="act_my_gap" model="ir.actions.act_window">
+ <field name="name">My Gap Analysis</field>
+ <field name="res_model">gap_analysis</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form,graph</field>
+ <field name="domain">[('user_id','=',uid),('state','!=','cancel'),('is_tmpl','=',False)]</field>
+ </record>
+ <record id="act_gap_analysis_tmpl" model="ir.actions.act_window">
+ <field name="name">Gap Analysis Template</field>
+ <field name="res_model">gap_analysis</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form,graph</field>
+ <field name="domain">[('is_tmpl','=',True)]</field>
+ </record>
+ <record id="act_gap_analysis_fct" model="ir.actions.act_window">
+ <field name="name">Functionalities</field>
+ <field name="res_model">gap_analysis.functionality</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+ <record id="act_gap_analysis_fct_tmpl" model="ir.actions.act_window">
+ <field name="name">Functionality Templates</field>
+ <field name="res_model">gap_analysis.functionality</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="domain">[('is_tmpl','=',True)]</field>
+ </record>
+ <record id="act_gap_analysis_fct_proposed" model="ir.actions.act_window">
+ <field name="name">Proposed Functionalities</field>
+ <field name="res_model">gap_analysis.functionality</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="domain">[('proposed','=',True)]</field>
+ </record>
+ <record id="act_gap_analysis_fct_cat" model="ir.actions.act_window">
+ <field name="name">Functionality Categories</field>
+ <field name="res_model">gap_analysis.functionality.category</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="search_view_id" ref="view_gap_analysis_functionality_category_search"/>
+ </record>
+ <record id="act_gap_analysis_openerp" model="ir.actions.act_window">
+ <field name="name">OpenERP Features</field>
+ <field name="res_model">gap_analysis.openerp</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+ <record id="act_gap_analysis_workload_type" model="ir.actions.act_window">
+ <field name="name">Workload Type</field>
+ <field name="res_model">gap_analysis.workload.type</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+ <record id="act_gap_analysis_effort" model="ir.actions.act_window">
+ <field name="name">Effort</field>
+ <field name="res_model">gap_analysis.effort</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+
+ <!-- Board -->
+ <record id="board_gap_form" model="ir.ui.view">
+ <field name="name">board.gap.form</field>
+ <field name="model">board.board</field>
+ <field name="arch" type="xml">
+ <form string="My Board">
+ <hpaned>
+ <child1>
+ <action colspan="4" height="100" name="%(act_my_gap)d" string="My Gap Analysis"/>
+ </child1>
+ </hpaned>
+ </form>
+ </field>
+ </record>
+ <record id="act_board_gap" model="ir.actions.act_window">
+ <field name="name">Gap Analysis Dashboard</field>
+ <field name="res_model">board.board</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="usage">menu</field>
+ <field name="view_id" ref="board_gap_form"/>
+ </record>
+
+ <!-- Menus -->
+ <menuitem web_icon="images/gap.png" web_icon_hover="images/gap-hover.png" id="menu_gap" name="Gap Analysis" groups="gap_analysis.res_group_gap0,gap_analysis.res_group_gap1" action="act_board_gap"/>
+ <menuitem id="menu_gap_00" name="Gap Analysis" parent="menu_gap" sequence="1"/>
+ <menuitem id="menu_gap_000" name="Gap Analysis" parent="menu_gap_00" sequence="1" action="act_gap_analysis"/>
+
+ <menuitem id="menu_gap_01" name="Templates" parent="menu_gap" sequence="50" groups="gap_analysis.res_group_gap1"/>
+ <menuitem id="menu_gap_010" name="Gap Analysis Templates" parent="menu_gap_01" sequence="1" action="act_gap_analysis_tmpl"/>
+ <menuitem id="menu_gap_011" name="Functionality Templates" parent="menu_gap_01" sequence="10" action="act_gap_analysis_fct_tmpl"/>
+ <menuitem id="menu_gap_012" name="Proposed Functionalities" parent="menu_gap_01" sequence="20" action="act_gap_analysis_fct_proposed"/>
+
+ <menuitem id="menu_gap_02" name="Configuration" parent="menu_gap" sequence="99" groups="gap_analysis.res_group_gap1"/>
+ <menuitem id="menu_gap_020" name="Functionality Categories" parent="menu_gap_02" sequence="1" action="act_gap_analysis_fct_cat" />
+ <menuitem id="menu_gap020b" name="All Functionalities" parent="menu_gap_02" sequence="2" action="act_gap_analysis_fct"/>
+ <menuitem id="menu_gap_021" name="Workload Types" parent="menu_gap_02" sequence="3" action="act_gap_analysis_workload_type" />
+ <menuitem id="menu_gap_022" name="Efforts" parent="menu_gap_02" sequence="6" action="act_gap_analysis_effort" />
+ <menuitem id="menu_gap_023" name="OpenERP Features" parent="menu_gap_02" sequence="9" action="act_gap_analysis_openerp" />
+ </data>
+</openerp>
\ No newline at end of file
=== added file 'gap_analysis/gap_analysis_demo.xml'
--- gap_analysis/gap_analysis_demo.xml 1970-01-01 00:00:00 +0000
+++ gap_analysis/gap_analysis_demo.xml 2013-10-22 14:58:07 +0000
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data noupdate="1">
+ <!--Resource: gap_analysis.functionality.category-->
+ <record id="gap_analysis_fct_cat1" model="gap_analysis.functionality.category">
+ <field name="name">Customer Relationship Management</field>
+ <field name="code">CRM</field>
+ <field name="sequence">5</field>
+ </record>
+ <record id="gap_analysis_fct_cat2" model="gap_analysis.functionality.category">
+ <field name="name">Sales</field>
+ <field name="code">SAJ</field>
+ <field name="sequence">6</field>
+ </record>
+
+ <!--Resource: gap_analysis.effort-->
+ <record id="gap_analysis_effort1" model="gap_analysis.effort">
+ <field name="name">1</field>
+ <field name="duration">4</field>
+ <field name="cost">250</field>
+ </record>
+ <record id="gap_analysis_effort2" model="gap_analysis.effort">
+ <field name="name">2</field>
+ <field name="duration">8</field>
+ <field name="cost">250</field>
+ </record>
+
+ <!--Resource: gap_analysis.functionality-->
+ <record id="gap_analysis_fct1" model="gap_analysis.functionality">
+ <field name="name">Ability to synchronize OpenERP with Current System</field>
+ <field name="category" ref="gap_analysis_fct_cat1"/>
+ </record>
+ <record id="gap_analysis_fct2" model="gap_analysis.functionality">
+ <field name="name">Ability to translate Lead</field>
+ <field name="category" ref="gap_analysis_fct_cat1"/>
+ </record>
+ <record id="gap_analysis_fct3" model="gap_analysis.functionality">
+ <field name="name">Ability to manage pricelist</field>
+ <field name="category" ref="gap_analysis_fct_cat2"/>
+ </record>
+
+ <!--Resource: gap_analysis.workload.type-->
+ <record id="gap_analysis_type1" model="gap_analysis.workload.type">
+ <field name="name">Report (Basic)</field>
+ <field name="code">RPTBA</field>
+ <field name="sequence">5</field>
+ <field name="cost">350</field>
+ <field name="category">Functional Analysis</field>
+ </record>
+ <record id="gap_analysis_type2" model="gap_analysis.workload.type">
+ <field name="name">Report (Advanced)</field>
+ <field name="code">RPTAD</field>
+ <field name="sequence">6</field>
+ <field name="cost">550</field>
+ <field name="category">Functional Analysis</field>
+ </record>
+ <record id="gap_analysis_type3" model="gap_analysis.workload.type">
+ <field name="name">Workflow</field>
+ <field name="code">RPTWKF</field>
+ <field name="sequence">7</field>
+ <field name="cost">500</field>
+ <field name="category">Technical Analysis</field>
+ </record>
+
+ <!--Resource: gap_analysis-->
+ <record id="gap_analysis1" model="gap_analysis">
+ <field name="name">Gap Analysis DEMO Data</field>
+ <field name="note">DEMO Data</field>
+ <field name="user_id" ref="base.user_root"/>
+ </record>
+
+ <!--Resource: gap_analysis.line-->
+ <record id="gap_analysis_line1" model="gap_analysis.line">
+ <field name="gap_id" ref="gap_analysis1"/>
+ <field name="functionality" ref="gap_analysis_fct1"/>
+ <field name="effort" ref="gap_analysis_effort1"/>
+ <field name="category" ref="gap_analysis_fct_cat1"/>
+ </record>
+ <record id="gap_analysis_line2" model="gap_analysis.line">
+ <field name="gap_id" ref="gap_analysis1"/>
+ <field name="functionality" ref="gap_analysis_fct2"/>
+ <field name="effort" ref="gap_analysis_effort1"/>
+ <field name="category" ref="gap_analysis_fct_cat1"/>
+ </record>
+ <record id="gap_analysis_line3" model="gap_analysis.line">
+ <field name="gap_id" ref="gap_analysis1"/>
+ <field name="functionality" ref="gap_analysis_fct3"/>
+ <field name="effort" ref="gap_analysis_effort2"/>
+ <field name="category" ref="gap_analysis_fct_cat2"/>
+ </record>
+
+ <!--Resource: gap_analysis.workload-->
+ <record id="gap_analysis_workload1" model="gap_analysis.workload">
+ <field name="gap_line_id" ref="gap_analysis_line1"/>
+ <field name="type" ref="gap_analysis_type2"/>
+ <field name="duration">1</field>
+ <field name="cost">600</field>
+ </record>
+ <record id="gap_analysis_workload2" model="gap_analysis.workload">
+ <field name="gap_line_id" ref="gap_analysis_line1"/>
+ <field name="type" ref="gap_analysis_type3"/>
+ <field name="duration">1</field>
+ <field name="cost">500</field>
+ </record>
+ <record id="gap_analysis_workload3" model="gap_analysis.workload">
+ <field name="gap_line_id" ref="gap_analysis_line2"/>
+ <field name="type" ref="gap_analysis_type1"/>
+ <field name="duration">2</field>
+ <field name="cost">350</field>
+ </record>
+ <record id="gap_analysis_workload3" model="gap_analysis.workload">
+ <field name="gap_line_id" ref="gap_analysis_line3"/>
+ <field name="type" ref="gap_analysis_type3"/>
+ <field name="duration">1</field>
+ <field name="cost">500</field>
+ </record>
+ </data>
+</openerp>
=== added file 'gap_analysis/gap_analysis_how_to.pdf'
Binary files gap_analysis/gap_analysis_how_to.pdf 1970-01-01 00:00:00 +0000 and gap_analysis/gap_analysis_how_to.pdf 2013-10-22 14:58:07 +0000 differ
=== added file 'gap_analysis/gap_analysis_sequence.xml'
--- gap_analysis/gap_analysis_sequence.xml 1970-01-01 00:00:00 +0000
+++ gap_analysis/gap_analysis_sequence.xml 2013-10-22 14:58:07 +0000
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data noupdate="1">
+ <record id="seq_type_gap_analysis" model="ir.sequence.type">
+ <field name="name">Gap Analysis</field>
+ <field name="code">gap_analysis</field>
+ </record>
+
+ <record id="seq_gap_analysis" model="ir.sequence">
+ <field name="name">Gap Analysis</field>
+ <field name="code">gap_analysis</field>
+ <field name="prefix">GAP</field>
+ <field name="padding">3</field>
+ </record>
+ </data>
+</openerp>
=== added file 'gap_analysis/gap_analysis_workflow.xml'
--- gap_analysis/gap_analysis_workflow.xml 1970-01-01 00:00:00 +0000
+++ gap_analysis/gap_analysis_workflow.xml 2013-10-22 14:58:07 +0000
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="wkf_gap_analysis" model="workflow">
+ <field name="name">gap_analysis.basic</field>
+ <field name="osv">gap_analysis</field>
+ <field name="on_create">True</field>
+ </record>
+
+ <!-- Activity -->
+ <record id="act_gap_analysis_draft" model="workflow.activity">
+ <field name="wkf_id" ref="wkf_gap_analysis"/>
+ <field name="flow_start">True</field>
+ <field name="name">draft</field>
+ <field name="action">write({'state':'draft', 'date_confirm': False})</field>
+ </record>
+ <record id="act_gap_analysis_done" model="workflow.activity">
+ <field name="wkf_id" ref="wkf_gap_analysis"/>
+ <field name="name">done</field>
+ <field name="flow_stop">True</field>
+ <field name="kind">function</field>
+ <field name="action">action_done()</field>
+ </record>
+ <record id="act_gap_analysis_cancel" model="workflow.activity">
+ <field name="wkf_id" ref="wkf_gap_analysis"/>
+ <field name="name">cancel</field>
+ <field name="flow_stop">True</field>
+ <field name="kind">function</field>
+ <field name="action">write({'state':'cancel'})</field>
+ </record>
+
+ <!-- Transition -->
+ <record id="trans_gap_draft_done" model="workflow.transition">
+ <field name="act_from" ref="act_gap_analysis_draft"/>
+ <field name="act_to" ref="act_gap_analysis_done"/>
+ <field name="signal">confirm</field>
+ </record>
+
+ <record id="trans_gap_draft_cancel" model="workflow.transition">
+ <field name="act_from" ref="act_gap_analysis_done"/>
+ <field name="act_to" ref="act_gap_analysis_cancel"/>
+ <field name="signal">cancel</field>
+ </record>
+
+ <record id="trans_gap_cancel_draft" model="workflow.transition">
+ <field name="act_from" ref="act_gap_analysis_cancel"/>
+ <field name="act_to" ref="act_gap_analysis_draft"/>
+ <field name="signal">change</field>
+ </record>
+
+ <record id="trans_gap_done_draft" model="workflow.transition">
+ <field name="act_from" ref="act_gap_analysis_done"/>
+ <field name="act_to" ref="act_gap_analysis_draft"/>
+ <field name="signal">reopen</field>
+ </record>
+ </data>
+</openerp>
\ No newline at end of file
=== added directory 'gap_analysis/images'
=== added file 'gap_analysis/images/gap-hover.png'
Binary files gap_analysis/images/gap-hover.png 1970-01-01 00:00:00 +0000 and gap_analysis/images/gap-hover.png 2013-10-22 14:58:07 +0000 differ
=== added file 'gap_analysis/images/gap.png'
Binary files gap_analysis/images/gap.png 1970-01-01 00:00:00 +0000 and gap_analysis/images/gap.png 2013-10-22 14:58:07 +0000 differ
=== added file 'gap_analysis/images/gap_analysis.jpg'
Binary files gap_analysis/images/gap_analysis.jpg 1970-01-01 00:00:00 +0000 and gap_analysis/images/gap_analysis.jpg 2013-10-22 14:58:07 +0000 differ
=== added file 'gap_analysis/images/gap_analysis2.jpg'
Binary files gap_analysis/images/gap_analysis2.jpg 1970-01-01 00:00:00 +0000 and gap_analysis/images/gap_analysis2.jpg 2013-10-22 14:58:07 +0000 differ
=== added file 'gap_analysis/images/report.jpg'
Binary files gap_analysis/images/report.jpg 1970-01-01 00:00:00 +0000 and gap_analysis/images/report.jpg 2013-10-22 14:58:07 +0000 differ
=== added directory 'gap_analysis/report'
=== added file 'gap_analysis/report/__init__.py'
--- gap_analysis/report/__init__.py 1970-01-01 00:00:00 +0000
+++ gap_analysis/report/__init__.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,26 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import gap_analysis
+import gap_analysis_report
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis/report/gap_analysis_report.py'
--- gap_analysis/report/gap_analysis_report.py 1970-01-01 00:00:00 +0000
+++ gap_analysis/report/gap_analysis_report.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,41 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import time
+from report import report_sxw
+from osv import osv
+
+class gap_analysis_report(report_sxw.rml_parse):
+ def __init__(self, cr, uid, name, context):
+ super(gap_analysis_report, self).__init__(cr, uid, name, context=context)
+ self.localcontext.update({
+ 'time': time,
+ 'cr':cr,
+ 'uid': uid,
+ })
+
+report_sxw.report_sxw('report.webkit_gap_analysis',
+ 'gap_analysis',
+ 'gap_analysis/report/report_webkit_gap_analysis.mako',
+ parser=report_webkit_html)
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis/report/gap_analysis_report_view.xml'
--- gap_analysis/report/gap_analysis_report_view.xml 1970-01-01 00:00:00 +0000
+++ gap_analysis/report/gap_analysis_report_view.xml 2013-10-22 14:58:07 +0000
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+<data>
+ <report auto="False"
+ id="report_webkit_gap_analysis"
+ model="gap_analysis"
+ name="Gap_Analysis"
+ file="gap_analysis/report/report_webkit_gap_analysis.mako"
+ string="Gap Analysis"
+ report_type="webkit"
+ webkit_header="report_webkit.ir_header_webkit_basesample0"/>
+</data>
+</openerp>
\ No newline at end of file
=== added file 'gap_analysis/report/report_webkit_gap_analysis.mako'
--- gap_analysis/report/report_webkit_gap_analysis.mako 1970-01-01 00:00:00 +0000
+++ gap_analysis/report/report_webkit_gap_analysis.mako 2013-10-22 14:58:07 +0000
@@ -0,0 +1,90 @@
+<html>
+<head>
+ <style type="text/css">
+ body {font-family:helvetica;font-size:12px;line-height:14px;}
+ .basic_table {text-align:center;border:1px solid lightGrey;border-collapse: collapse;}
+ .basic_table td {border:1px solid lightGrey;font-size:12px;line-height:14px;padding:3px;vertical-align:middle;}
+ .list_table {border-color:black;text-align:center;border-collapse: collapse;}
+ .list_table td {border-color:gray;border-top:1px solid gray;text-align:left;font-size:12px;padding:3px;line-height:14px;}
+ .list_table th {border-bottom:2px solid black;text-align:left;font-size:12px;font-weight:bold;padding:0 3px;line-height:14px;}
+ .list_table thead { display:table-header-group;}
+ table.gap_list_table tr th, table.gap_list_table tr td {vertical-align:middle;border-left:1px solid gray;}
+ table.gap_list_table tr th.firsttd, table.gap_list_table tr td.firsttd {border-left:none;}
+ #report_company_header {border:none;font-size:14px;line-height:16px;vertical-align:top;}
+ </style>
+</head>
+<body>
+ <table id="report_company_header" width="100%">
+ <tr>
+ <td width="50%">${helper.embed_logo_by_name('logo')|n}</td>
+ <td>${company.partner_id.name |entity}<br />
+ ${company.partner_id.street |entity}<br />
+ Phone: ${company.partner_id.phone |entity}<br />
+ Mail: ${company.partner_id.email |entity}</td>
+ </tr>
+ </table>
+ <br /><br />
+
+ %for gap in objects :
+ %if gap.partner_id:
+ <% setLang(gap.partner_id.lang) %>
+ %endif
+
+ <table class="basic_table" width="100%">
+ <tr><td>${_("Reference")}</td><td>${_("Document")}</td><td>${_("Date")}</td></tr>
+ <tr><td>${gap.reference}</td><td>${gap.name}</td><td>${formatLang(gap.date_confirm, date=True)|entity}</td></tr>
+ </table>
+ <br /><br />
+
+ <table class="list_table gap_list_table" width="100%">
+ <%
+ types_id = []
+ types = gap._sorted_distinct_workloads(gap.id)
+ colspan = len(types)
+ %>
+ <thead>
+ <tr>
+ <th class="firsttd" rowspan="2"> </th>
+ <th rowspan="2">${_("Category")}</th>
+ <th rowspan="2">${_("Functionality")}</th>
+ <th rowspan="2" style="text-align:center;">${_("Effort")}</th>
+ <th colspan="${colspan}" style="text-align:center;border-bottom:1px solid gray;">${_("Duration (hours)")}</th>
+ <th rowspan="2" style="text-align:center;">${_("Estimate")}</th>
+ </tr>
+ <tr>
+ %for type in types:
+ <th style="text-align:center;">${type[1]}</th>
+ <% types_id.append(type[0]) %>
+ %endfor
+ </tr>
+ </thead>
+ <tbody>
+ %for line in gap.gap_lines :
+ %if line.keep:
+ <% effort = '' %>
+ %if line.effort:
+ <% effort = line.effort.name %>
+ %endif
+ <tr>
+ <td class="firsttd">${line.code|entity}</td>
+ <td>${line.category and line.category.full_path|entity}</td>
+ <td>${line.functionality.name}</td>
+ <td style="text-align:center;">${effort}</td>
+ %for type_id in types_id:
+ <td style="text-align:center;">${line._total_workloads(type_id) or 0}</td>
+ %endfor
+ <td style="text-align:right;">${formatLang(line.total_cost)}</td>
+ </tr>
+ %endif
+ %endfor
+ <% colspan = len(types_id) + 3 %>
+ <tr>
+ <td class="firsttd" colspan="${colspan}" style="text-align:right;padding-right:5px;font-weight:bold;">${_("TOTAL:")}</td>
+ <td style="text-align:right;">${formatLang(gap.estimated_cost)}</td>
+ </tr>
+ </tbody>
+ </table>
+ <p style="page-break-after:always"></p>
+ %endfor
+</body>
+</html>
\ No newline at end of file
=== added directory 'gap_analysis/security'
=== added file 'gap_analysis/security/gap_analysis_rules.xml'
--- gap_analysis/security/gap_analysis_rules.xml 1970-01-01 00:00:00 +0000
+++ gap_analysis/security/gap_analysis_rules.xml 2013-10-22 14:58:07 +0000
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data noupdate="1">
+ <record id="res_group_gap0" model="res.groups">
+ <field name="name">Gap Analysis / User</field>
+ </record>
+ <record id="res_group_gap1" model="res.groups">
+ <field name="name">Gap Analysis / Manager</field>
+ </record>
+ </data>
+
+ <data noupdate="1">
+ <record id="ir_rule_write_gap_user" model="ir.rule">
+ <field name="model_id" ref="gap_analysis.model_gap_analysis"/>
+ <field name="domain_force">[('user_id','=',user.id)]</field>
+ <field name="name">Write own Gap Analysis</field>
+ <field eval="0" name="global"/>
+ <field eval="[(6,0,[ref('gap_analysis.res_group_gap0')])]" name="groups"/>
+ <field eval="0" name="perm_unlink"/>
+ <field eval="1" name="perm_write"/>
+ <field eval="0" name="perm_read"/>
+ <field eval="0" name="perm_create"/>
+ </record>
+ <record id="ir_rule_delete_gap_manager" model="ir.rule">
+ <field name="model_id" ref="gap_analysis.model_gap_analysis"/>
+ <field name="domain_force">[('state','in',['draft','cancel'])]</field>
+ <field name="name">Delete Draft Gap Analysis</field>
+ <field eval="0" name="global"/>
+ <field eval="[(6,0,[ref('gap_analysis.res_group_gap1')])]" name="groups"/>
+ <field eval="1" name="perm_unlink"/>
+ <field eval="0" name="perm_write"/>
+ <field eval="0" name="perm_read"/>
+ <field eval="0" name="perm_create"/>
+ </record>
+ </data>
+</openerp>
\ No newline at end of file
=== added file 'gap_analysis/security/ir.model.access.csv'
--- gap_analysis/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
+++ gap_analysis/security/ir.model.access.csv 2013-10-22 14:58:07 +0000
@@ -0,0 +1,25 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_gap_analysis_user,gap_analysis base user,gap_analysis.model_gap_analysis,base.group_user,1,0,0,0
+access_gap_analysis_Guser,gap_analysis user,gap_analysis.model_gap_analysis,gap_analysis.res_group_gap0,1,1,1,0
+access_gap_analysis_manager,gap_analysis manager,gap_analysis.model_gap_analysis,gap_analysis.res_group_gap1,1,1,1,1
+access_gap_analysis_line_user,gap_analysis_line base user,gap_analysis.model_gap_analysis_line,base.group_user,1,0,0,0
+access_gap_analysis_line_Guser,gap_analysis_line user,gap_analysis.model_gap_analysis_line,gap_analysis.res_group_gap0,1,1,1,1
+access_gap_analysis_line_manager,gap_analysis_line manager,gap_analysis.model_gap_analysis_line,gap_analysis.res_group_gap1,1,1,1,1
+access_gap_analysis_functionality_user,gap_analysis_functionality base user,gap_analysis.model_gap_analysis_functionality,base.group_user,1,0,0,0
+access_gap_analysis_functionality_Guser,gap_analysis_functionality user,gap_analysis.model_gap_analysis_functionality,gap_analysis.res_group_gap0,1,0,1,0
+access_gap_analysis_functionality_manager,gap_analysis_functionality manager,gap_analysis.model_gap_analysis_functionality,gap_analysis.res_group_gap1,1,1,1,1
+access_gap_analysis_functionality_category_user,gap_analysis_functionality_category base user,gap_analysis.model_gap_analysis_functionality_category,base.group_user,1,0,0,0
+access_gap_analysis_functionality_category_Guser,gap_analysis_functionality_category user,gap_analysis.model_gap_analysis_functionality_category,gap_analysis.res_group_gap0,1,0,1,0
+access_gap_analysis_functionality_category_manager,gap_analysis_functionality_category manager,gap_analysis.model_gap_analysis_functionality_category,gap_analysis.res_group_gap1,1,1,1,1
+access_gap_analysis_workload_user,gap_analysis_workload base user,gap_analysis.model_gap_analysis_workload,base.group_user,1,0,0,0
+access_gap_analysis_workload_Guser,gap_analysis_workload user,gap_analysis.model_gap_analysis_workload,gap_analysis.res_group_gap0,1,1,1,1
+access_gap_analysis_workload_manager,gap_analysis_workload manager,gap_analysis.model_gap_analysis_workload,gap_analysis.res_group_gap1,1,1,1,1
+access_gap_analysis_workload_type_user,gap_analysis_workload_type base user,gap_analysis.model_gap_analysis_workload_type,base.group_user,1,0,0,0
+access_gap_analysis_workload_type_Guser,gap_analysis_workload_type user,gap_analysis.model_gap_analysis_workload_type,gap_analysis.res_group_gap0,1,0,1,0
+access_gap_analysis_workload_type_manager,gap_analysis_workload_type manager,gap_analysis.model_gap_analysis_workload_type,gap_analysis.res_group_gap1,1,1,1,1
+access_gap_analysis_openerp_user,gap_analysis_openerp base user,gap_analysis.model_gap_analysis_openerp,base.group_user,1,0,0,0
+access_gap_analysis_openerp_Guser,gap_analysis_openerp user,gap_analysis.model_gap_analysis_openerp,gap_analysis.res_group_gap0,1,1,1,0
+access_gap_analysis_openerp_manager,gap_analysis_openerp manager,gap_analysis.model_gap_analysis_openerp,gap_analysis.res_group_gap1,1,1,1,1
+access_gap_analysis_effort_user,gap_analysis_effort base user,gap_analysis.model_gap_analysis_effort,base.group_user,1,0,0,0
+access_gap_analysis_effort_Guser,gap_analysis_effort user,gap_analysis.model_gap_analysis_effort,gap_analysis.res_group_gap0,1,0,0,0
+access_gap_analysis_effort_manager,gap_analysis_effort manager,gap_analysis.model_gap_analysis_effort,gap_analysis.res_group_gap1,1,1,1,1
\ No newline at end of file
=== added directory 'gap_analysis/wizard'
=== added file 'gap_analysis/wizard/__init__.py'
--- gap_analysis/wizard/__init__.py 1970-01-01 00:00:00 +0000
+++ gap_analysis/wizard/__init__.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,26 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import import_from_tmpl
+import import_from_sheet
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'gap_analysis/wizard/gap_analysis_import_template.xls'
Binary files gap_analysis/wizard/gap_analysis_import_template.xls 1970-01-01 00:00:00 +0000 and gap_analysis/wizard/gap_analysis_import_template.xls 2013-10-22 14:58:07 +0000 differ
=== added file 'gap_analysis/wizard/import_from_sheet.py'
--- gap_analysis/wizard/import_from_sheet.py 1970-01-01 00:00:00 +0000
+++ gap_analysis/wizard/import_from_sheet.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,517 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import time
+import netsvc
+from osv import fields, osv
+import pooler
+from osv.orm import browse_record, browse_null
+from tools.translate import _
+import base64
+
+import xlrd
+from xlrd import open_workbook
+import xlutils.copy
+
+
+def getcell(rs, line, col, forceText=False):
+ if not rs.cell(line, col).ctype in [0, 6]:
+ if forceText and rs.cell(line, col).ctype in (2,3):
+ return str(int(rs.cell_value(line, col)))
+ else:
+ return rs.cell_value(line, col)
+ return None
+
+
+def getfloat(str_float):
+ try:
+ if str_float:
+ return float(str_float)
+ except ValueError:
+ pass
+ return 0.0
+
+
+def getint(str_int):
+ try:
+ if str_int:
+ return int(str_int)
+ except ValueError:
+ pass
+ return 0
+
+
+
+class GapLineTemp(object):
+ def __init__(self, gap_analysis, keep, functionality, function_desc, category, critical_level, phase, contributors, openerp_fct, basic_report, advan_report, basic_process, advan_process, basic_screen, advan_screen, basic_workflow, advan_workflow, acl, obj, calcul_field, basic_wizard, advan_wizard, effort, duration_wk, total_cost, total_analysis, total_dev, testing, training, project_mgmt):
+ self.gap_analysis = gap_analysis
+ self.keep = keep
+ self.functionality = functionality
+ self.function_desc = function_desc
+ self.category = category
+ self.critical_level = critical_level or 0
+ self.phase = phase or '1'
+ self.contributors = contributors or ''
+ self.openerp_fct = openerp_fct or ''
+ self.basic_report = (basic_report * 1)
+ self.advan_report = (advan_report * 1)
+ self.basic_process = (basic_process * 1)
+ self.advan_process = (advan_process * 1)
+ self.basic_screen = (basic_screen * 1)
+ self.advan_screen = (advan_screen * 1)
+ self.basic_workflow = (basic_workflow * 1)
+ self.advan_workflow = (advan_workflow * 1)
+ self.acl = (acl * 1)
+ self.obj = (obj * 1)
+ self.calcul_field = (calcul_field * 1)
+ self.basic_wizard = (basic_wizard * 1)
+ self.advan_wizard = (advan_wizard * 1)
+ self.effort = effort
+ self.testing = testing
+ self.training = training
+ self.project_mgmt = project_mgmt
+ self.duration_wk = (duration_wk * 1)
+ self.total_cost = total_cost
+ self.total_analysis = total_analysis
+ self.total_dev = total_dev
+
+
+
+class gap_analysis_import_xls(osv.osv_memory):
+ _name='gap_analysis.import_xls'
+
+ _columns = {
+ 'import_file': fields.binary('.XLS file', required=True),
+ }
+
+
+ def import_xls(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+
+ (data,) = self.browse(cr, uid, ids, context=context)
+ import_file = base64.b64decode(data.import_file)
+
+
+ def create_workload(cr, uid, g_wkld_pool, wkld_type, gap_line_id, duration):
+ wkld_vals = {
+ 'gap_line_id': gap_line_id,
+ 'fct_id': False,
+ 'type': wkld_type,
+ 'duration': duration,
+ }
+ return g_wkld_pool.create(cr, uid, wkld_vals)
+
+
+ def retrieve_gap_analysis(filecontents):
+ warning = ''
+ g_cat_pool = self.pool.get('gap_analysis.functionality.category')
+ gap_lines_entries = {}
+ rb = open_workbook(file_contents=filecontents,formatting_info=True, encoding_override="utf-8")
+
+ for rs in rb.sheets():
+ for line in range(3, rs.nrows):
+ try:
+ keep = getcell(rs, line, 1)
+ if keep in [1, 'keep', 'Keep']:
+ keep = True
+ else:
+ keep = False
+
+ gap_analysis = rs.name.strip()
+ category = getcell(rs, line, 2, forceText=True)
+ functionality = getcell(rs, line, 3, forceText=True)
+ function_desc = getcell(rs, line, 4, forceText=True)
+ critical_level = getint(getcell(rs, line, 5))
+ phase = getcell(rs, line, 6)
+ contributors = getcell(rs, line, 7, forceText=True)
+ openerp_fct = getcell(rs, line, 8, forceText=True)
+ basic_report = getfloat(getcell(rs, line, 9))
+ advan_report = getfloat(getcell(rs, line, 10))
+ basic_process = getfloat(getcell(rs, line,11))
+ advan_process = getfloat(getcell(rs, line,12))
+ basic_screen = getfloat(getcell(rs, line,13))
+ advan_screen = getfloat(getcell(rs, line,14))
+ basic_workflow = getfloat(getcell(rs, line,15))
+ advan_workflow = getfloat(getcell(rs, line,16))
+ acl = getfloat(getcell(rs, line,17))
+ obj = getfloat(getcell(rs, line,18))
+ calcul_field = getfloat(getcell(rs, line,19))
+ basic_wizard = getfloat(getcell(rs, line,20))
+ advan_wizard = getfloat(getcell(rs, line,21))
+ training = getfloat(getcell(rs, line,22))
+ project_mgmt = getfloat(getcell(rs, line,23))
+ effort = getint(getcell( rs, line,24))
+ duration_wk = getfloat(getcell(rs, line,25))
+ testing = getfloat(getcell(rs, line,26))
+ total_cost = getfloat(getcell(rs, line,27))
+ total_analysis = getfloat(getcell(rs, line,28))
+ total_dev = getfloat(getcell(rs, line,29))
+
+ if functionality:
+ if category:
+ categ_ids = g_cat_pool.search(cr, uid, ['|',('name','ilike',category),('full_path','ilike',category)])
+ if categ_ids:
+ category = categ_ids[0]
+
+ gap_line = GapLineTemp(gap_analysis, keep, functionality.strip(), function_desc, category, critical_level, phase, contributors, openerp_fct, basic_report, advan_report, basic_process, advan_process, basic_screen, advan_screen, basic_workflow, advan_workflow, acl, obj, calcul_field, basic_wizard, advan_wizard, effort, duration_wk, total_cost, total_analysis, total_dev, testing, training, project_mgmt)
+ if gap_line:
+ gap_lines_entries[rs.name.lower().strip() + str(line)] = gap_line
+ else:
+ warning += 'The category ' + str(category) + ' does not exist in OpenERP. Please create it first, then upload you Gap analysis again.\n'
+ else:
+ warning += 'The category ' + str(category) + ' does not exist in OpenERP. Please create it first, then upload you Gap analysis again.\n'
+ else:
+ print(" ("+ str(line) +"), No functionality... ######################## .......")
+ except RuntimeError as error:
+ print(" ("+ str(line) +", "+ str(col) +"), didn't make it ######################## ......."+ str(error))
+
+ if warning != '':
+ raise osv.except_osv(_('Error'), warning)
+ return []
+ return gap_lines_entries
+
+ gap_pool = self.pool.get('gap_analysis')
+ g_line_pool = self.pool.get('gap_analysis.line')
+ g_fct_pool = self.pool.get('gap_analysis.functionality')
+ g_open_pool = self.pool.get('gap_analysis.openerp')
+ effort_pool = self.pool.get('gap_analysis.effort')
+ g_wkld_pool = self.pool.get('gap_analysis.workload')
+ g_type_pool = self.pool.get('gap_analysis.workload.type')
+
+ gap_lines = retrieve_gap_analysis(import_file)
+ gap_dic = {}
+ wkld_dic = {}
+
+ # Get list of possible workload
+ all_wkld = g_type_pool.search(cr, uid, [])
+ for wkld in g_type_pool.browse(cr, uid, all_wkld):
+ wkld_dic[wkld.code] = wkld.id
+
+ for linenb, gap_line in gap_lines.items():
+ # Check Gap Analysis
+ if gap_line.gap_analysis not in gap_dic:
+ gap_ids = gap_pool.search(cr, uid, [('name','=',gap_line.gap_analysis)])
+ if not gap_ids:
+ gap_id = gap_pool.create(cr, uid, {'name':gap_line.gap_analysis,})
+ print('Gap Import: Gap %s created (%s)'%(gap_line.gap_analysis,gap_id))
+ else:
+ gap_id = gap_ids[0]
+ print('Gap Import: Gap %s found (%s)'%(gap_line.gap_analysis,gap_id))
+ gap_dic[gap_line.gap_analysis] = gap_id
+
+
+ # Check Functionality
+ fct_ids = g_fct_pool.search(cr, uid, [('name','ilike',gap_line.functionality)])
+ if True:
+# if not fct_ids:
+ # Create Functionality
+ fct_id = g_fct_pool.create(cr, uid, {'name':gap_line.functionality,'description': gap_line.function_desc,'category':gap_line.category,})
+ print('Gap Import: Fct %s created (%s)'%(gap_line.functionality,fct_id))
+ else:
+ fct_id = fct_ids[0]
+ print('Gap Import: Fct %s found (%s)'%(gap_line.functionality,fct_id))
+
+
+ # Check OpenERP Features
+ open_id = False
+ if gap_line.openerp_fct:
+ open_ids = g_open_pool.search(cr, uid, [('name','=',gap_line.openerp_fct)])
+ if not open_ids:
+ open_id = g_open_pool.create(cr, uid, {'name':gap_line.openerp_fct,})
+ print('Gap Import: OpenERP %s created (%s)'%(gap_line.openerp_fct,open_id))
+ else:
+ open_id = open_ids[0]
+ print('Gap Import: OpenERP %s found (%s)'%(gap_line.openerp_fct,open_id))
+
+ # Check Effort
+ effort_id = False
+ effort_ids = effort_pool.search(cr, uid, [('name','=',gap_line.effort)])
+ if effort_ids:
+ effort_id = effort_ids[0]
+
+ # Create Gap Analysis Line
+ if gap_line.duration_wk:
+ unknown_wk = True
+ else:
+ unknown_wk = False
+
+ g_line_vals = {
+ 'gap_id': gap_dic[gap_line.gap_analysis],
+ 'functionality': fct_id,
+ 'workloads': [],
+ 'openerp_fct': open_id,
+ 'contributors': gap_line.contributors,
+ 'keep': gap_line.keep,
+ 'phase': gap_line.phase,
+ 'critical': gap_line.critical_level,
+ 'effort': effort_id,
+ 'duration_wk': gap_line.duration_wk,
+ 'unknown_wk': unknown_wk,
+ 'testing': gap_line.testing,
+ 'category': gap_line.category,
+ }
+ g_line_id = g_line_pool.create(cr, uid, g_line_vals)
+
+ # Create Workloads
+ if gap_line.basic_report > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['BasRep'], g_line_id, gap_line.basic_report)
+ if gap_line.advan_report > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['AdvRep'], g_line_id, gap_line.advan_report)
+ if gap_line.basic_process > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['BasPro'], g_line_id, gap_line.basic_process)
+ if gap_line.advan_process > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['AdvPro'], g_line_id, gap_line.advan_process)
+ if gap_line.basic_screen > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['BasScr'], g_line_id, gap_line.basic_screen)
+ if gap_line.advan_screen > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['AdvScr'], g_line_id, gap_line.advan_screen)
+ if gap_line.basic_workflow > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['BasWkf'], g_line_id, gap_line.basic_workflow)
+ if gap_line.advan_workflow > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['AdvWkf'], g_line_id, gap_line.advan_workflow)
+ if gap_line.acl > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['Acl'], g_line_id, gap_line.acl)
+ if gap_line.obj > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['Obj'], g_line_id, gap_line.obj)
+ if gap_line.calcul_field > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['Cal'], g_line_id, gap_line.calcul_field)
+ if gap_line.basic_wizard > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['BasWiz'], g_line_id, gap_line.basic_wizard)
+ if gap_line.advan_wizard > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['AdvWiz'], g_line_id, gap_line.advan_wizard)
+ if gap_line.project_mgmt > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['PrjMan'], g_line_id, gap_line.project_mgmt)
+ if gap_line.training > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['Train'], g_line_id, gap_line.training)
+
+ return {'type': 'ir.actions.act_window_close'}
+
+gap_analysis_import_xls()
+
+
+
+
+class gap_analysis_import_fct_xls(osv.osv_memory):
+ _name='gap_analysis.import_fct_xls'
+
+ _columns = {
+ 'import_file': fields.binary('.XLS file', required=True),
+ }
+
+
+ def import_xls(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+
+ (data,) = self.browse(cr, uid, ids, context=context)
+ import_file = base64.b64decode(data.import_file)
+
+
+ def create_workload(cr, uid, g_wkld_pool, wkld_type, fct_id, duration):
+ wkld_vals = {
+ 'gap_line_id': False,
+ 'fct_id': fct_id,
+ 'type': wkld_type,
+ 'duration': duration,
+ }
+ return g_wkld_pool.create(cr, uid, wkld_vals)
+
+
+ def retrieve_gap_analysis_fct(filecontents):
+ fct_entries = {}
+ g_cat_pool = self.pool.get('gap_analysis.functionality.category')
+ warning = ''
+ rb = open_workbook(file_contents=filecontents,formatting_info=True, encoding_override="utf-8")
+
+ for rs in rb.sheets():
+ for line in range(3, rs.nrows):
+ try:
+ keep = False
+ gap_analysis = rs.name.strip()
+ functionality = getcell(rs, line, 0, forceText=True)
+ function_desc = getcell(rs, line, 1, forceText=True)
+ critical_level = getint(getcell(rs, line, 2))
+ phase = False
+ contributors = ''
+ openerp_fct = getcell(rs, line, 3, forceText=True)
+ basic_report = getfloat(getcell(rs, line, 4))
+ advan_report = getfloat(getcell(rs, line, 5))
+ basic_process = getfloat(getcell(rs, line, 6))
+ advan_process = getfloat(getcell(rs, line, 7))
+ basic_screen = getfloat(getcell(rs, line, 8))
+ advan_screen = getfloat(getcell(rs, line, 9))
+ basic_workflow = getfloat(getcell(rs, line,10))
+ advan_workflow = getfloat(getcell(rs, line,11))
+ acl = getfloat(getcell(rs, line,12))
+ obj = getfloat(getcell(rs, line,13))
+ calcul_field = getfloat(getcell(rs, line,14))
+ basic_wizard = getfloat(getcell(rs, line,15))
+ advan_wizard = getfloat(getcell(rs, line,16))
+ training = getfloat(getcell(rs, line,17))
+ project_mgmt = getfloat(getcell(rs, line,18))
+ effort = getint(getcell( rs, line,19))
+ duration_wk = getfloat(getcell(rs, line,20))
+ testing = getfloat(getcell(rs, line,21))
+ total_cost = getfloat(getcell(rs, line,22))
+ total_analysis = getfloat(getcell(rs, line,23))
+ total_dev = getfloat(getcell(rs, line,24))
+ category = getcell(rs, line, 25, forceText=True)
+
+ if functionality:
+ if category:
+ categ_ids = g_cat_pool.search(cr, uid, ['|',('name','ilike',category),('full_path','ilike',category)])
+ if categ_ids:
+ category = categ_ids[0]
+ one_fct = GapLineTemp(gap_analysis, keep, functionality.strip(), function_desc, category, critical_level, phase, contributors, openerp_fct, basic_report, advan_report, basic_process, advan_process, basic_screen, advan_screen, basic_workflow, advan_workflow, acl, obj, calcul_field, basic_wizard, advan_wizard, effort, duration_wk, total_cost, total_analysis, total_dev, testing, training, project_mgmt)
+ if one_fct:
+ fct_entries[rs.name.lower().strip() + str(line)] = one_fct
+ else:
+ warning += 'The category ' + str(category) + ' dont exist in OpenERP. Please create it first, then upload you Gap analysis.\n'
+ else:
+ warning += 'The category ' + str(category) + ' dont exist in OpenERP. Please create it first, then upload you Gap analysis.\n'
+ else:
+ print(" ("+ str(line) +"), No functionality... ######################## .......")
+ except RuntimeError as error:
+ print(" ("+ str(line) +", "+ str(col) +"), didn't make it ######################## ......."+ str(error))
+
+ if warning != '':
+ raise osv.except_osv(_('Error'), warning)
+ return []
+ return fct_entries
+
+
+ g_fct_pool = self.pool.get('gap_analysis.functionality')
+ g_open_pool = self.pool.get('gap_analysis.openerp')
+ effort_pool = self.pool.get('gap_analysis.effort')
+ g_wkld_pool = self.pool.get('gap_analysis.workload')
+ g_type_pool = self.pool.get('gap_analysis.workload.type')
+
+ fct_entries = retrieve_gap_analysis_fct(import_file)
+ gap_dic = {}
+ wkld_dic = {}
+
+ # Get list of possible workload
+ all_wkld = g_type_pool.search(cr, uid, [])
+ for wkld in g_type_pool.browse(cr, uid, all_wkld):
+ wkld_dic[wkld.code] = wkld.id
+
+ for linenb, one_fct in fct_entries.items():
+ # Check OpenERP Features
+ open_id = False
+ if one_fct.openerp_fct:
+ open_ids = g_open_pool.search(cr, uid, [('name','=',one_fct.openerp_fct)])
+ if not open_ids:
+ open_id = g_open_pool.create(cr, uid, {'name':one_fct.openerp_fct,})
+ print('Gap Import: OpenERP %s created (%s)'%(one_fct.openerp_fct,open_id))
+ else:
+ open_id = open_ids[0]
+ print('Gap Import: OpenERP %s found (%s)'%(one_fct.openerp_fct,open_id))
+
+ # Check Effort
+ effort_id = False
+ effort_ids = effort_pool.search(cr, uid, [('name','=',one_fct.effort)])
+ if effort_ids:
+ effort_id = effort_ids[0]
+
+ if one_fct.duration_wk:
+ unknown_wk = True
+ else:
+ unknown_wk = False
+
+
+ # Check Functionality
+ fct_ids = g_fct_pool.search(cr, uid, [('name','ilike',one_fct.functionality)])
+ if not fct_ids:
+ # Create Functionality
+ fct_vals = {
+ 'name': one_fct.functionality,
+ 'description': one_fct.function_desc,
+ 'category': one_fct.category,
+ 'workloads': [],
+ 'openerp_fct': open_id,
+ 'critical': one_fct.critical_level,
+ 'effort': effort_id,
+ 'duration_wk': one_fct.duration_wk,
+ 'unknown_wk': unknown_wk,
+ 'is_tmpl': True,
+ 'proposed': False,
+ 'testing': gap_line.testing,
+ }
+ fct_id = g_fct_pool.create(cr, uid, fct_vals)
+ print('Gap Import: Fct %s created (%s)'%(one_fct.functionality,fct_id))
+
+ else:
+ fct_id = fct_ids[0]
+ # Update Functionality
+ fct_vals = {
+ 'description': one_fct.function_desc,
+ 'workloads': [],
+ 'openerp_fct': open_id,
+ 'critical': one_fct.critical_level,
+ 'effort': effort_id,
+ 'duration_wk': one_fct.duration_wk,
+ 'unknown_wk': unknown_wk,
+ 'is_tmpl': True,
+ 'proposed': False,
+ 'testing': gap_line.testing,
+ }
+ g_fct_pool.write(cr, uid, [fct_id], fct_vals)
+ print('Gap Import: Fct %s found (%s) (%s)'%(one_fct.functionality,fct_id,fct_vals))
+
+ # Create Workloads
+ if one_fct.basic_report > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['BasRep'], fct_id, one_fct.basic_report)
+ if one_fct.advan_report > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['AdvRep'], fct_id, one_fct.advan_report)
+ if one_fct.basic_process > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['BasPro'], fct_id, one_fct.basic_process)
+ if one_fct.advan_process > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['AdvPro'], fct_id, one_fct.advan_process)
+ if one_fct.basic_screen > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['BasScr'], fct_id, one_fct.basic_screen)
+ if one_fct.advan_screen > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['AdvScr'], fct_id, one_fct.advan_screen)
+ if one_fct.basic_workflow > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['BasWkf'], fct_id, one_fct.basic_workflow)
+ if one_fct.advan_workflow > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['AdvWkf'], fct_id, one_fct.advan_workflow)
+ if one_fct.acl > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['Acl'], fct_id, one_fct.acl)
+ if one_fct.obj > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['Obj'], fct_id, one_fct.obj)
+ if one_fct.calcul_field > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['Cal'], fct_id, one_fct.calcul_field)
+ if one_fct.basic_wizard > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['BasWiz'], fct_id, one_fct.basic_wizard)
+ if one_fct.advan_wizard > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['AdvWiz'], fct_id, one_fct.advan_wizard)
+ if one_fct.project_mgmt > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['PrjMan'], fct_id, one_fct.project_mgmt)
+ if one_fct.training > 0:
+ g_wkld_id = create_workload(cr, uid, g_wkld_pool, wkld_dic['Train'], fct_id, one_fct.training)
+
+ return {'type': 'ir.actions.act_window_close'}
+
+gap_analysis_import_fct_xls()
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'gap_analysis/wizard/import_from_tmpl.py'
--- gap_analysis/wizard/import_from_tmpl.py 1970-01-01 00:00:00 +0000
+++ gap_analysis/wizard/import_from_tmpl.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,71 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from osv import osv, fields
+from tools.translate import _
+
+class gap_analysis_import_from_tmpl(osv.TransientModel):
+ _name='gap_analysis.import_from_tmpl'
+
+ _columns = {
+ 'template': fields.many2one('gap_analysis', 'Template', required=True, select=True),
+ }
+
+
+ def go_import(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+
+ this = self.browse(cr, uid, ids[0], context=context)
+ gap_line_pool = self.pool.get('gap_analysis.line')
+ workload_pool = self.pool.get('gap_analysis.workload')
+
+ for id in context.get('active_ids', []): #for each gap in which we want to import stuff
+ #copy gap_line with functionalities and workloads
+ for gap_line in this.template.gap_lines:
+ line_vals = {
+ 'gap_id': id,
+ 'functionality': gap_line.functionality.id,
+ 'workloads': [],
+ 'openerp_fct': gap_line.openerp_fct and gap_line.openerp_fct.id or False,
+ 'contributors': gap_line.contributors,
+ 'keep': gap_line.keep,
+ 'critical': gap_line.critical,
+ 'effort': gap_line.effort and gap_line.effort.id or False,
+ 'duration_wk': gap_line.duration_wk,
+ 'unknown_wk': gap_line.unknown_wk,
+ 'testing': gap_line.testing,
+ 'category': gap_line.category,
+ }
+ gap_line_id = gap_line_pool.create(cr, uid, line_vals, context=context)
+
+ for workload in gap_line.workloads:
+ workload_vals = {
+ 'gap_line_id': gap_line_id,
+ 'type': workload.type.id,
+ 'duration': workload.duration,
+ }
+ workload_id = workload_pool.create(cr, uid, workload_vals, context=context)
+
+ return {'type': 'ir.actions.act_window_close'}
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis/wizard/import_from_tmpl.xml'
--- gap_analysis/wizard/import_from_tmpl.xml 1970-01-01 00:00:00 +0000
+++ gap_analysis/wizard/import_from_tmpl.xml 2013-10-22 14:58:07 +0000
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="wizard_import_from_tmpl" model="ir.ui.view">
+ <field name="name">Import Gap from Template</field>
+ <field name="model">gap_analysis.import_from_tmpl</field>
+ <field name="arch" type="xml">
+ <form string="Import from Template" version="7.0">
+ <group>
+ <button icon="gtk-print" name="go_import" string="Import from Template" type="object" class="oe_highlight" attrs="{'invisible':[('template','=',False)]}"/>
+ </group>
+ <group>
+ <field name="template" domain="[('is_tmpl','=',True)]"/>
+ </group>
+ </form>
+ </field>
+ </record>
+ </data>
+
+ <data>
+ <record id="gap_analysis_imp_xls_view" model="ir.ui.view">
+ <field name="name">Gap Analysis: Import from Excel</field>
+ <field name="model">gap_analysis.import_xls</field>
+ <field name="arch" type="xml">
+ <form string="Gap Analysis: Import from Excel" version="7.0">
+ <group>
+ <button name="import_xls" string="Import" type="object" class="oe_highlight" icon="gtk-convert"/>
+ </group>
+ <group>
+ <field name="import_file"/>
+ </group>
+ </form>
+ </field>
+ </record>
+ <record id="gap_analysis_imp_fct_view" model="ir.ui.view">
+ <field name="name">Gap Analysis: Import Functionalities from Excel</field>
+ <field name="model">gap_analysis.import_fct_xls</field>
+ <field name="arch" type="xml">
+ <form string="Functionalities: Import from Excel" version="7.0">
+ <group>
+ <button name="import_xls" string="Import" type="object" class="oe_highlight" icon="gtk-convert"/>
+ </group>
+ <group>
+ <field name="import_file"/>
+ </group>
+ </form>
+ </field>
+ </record>
+
+ <record id="act_gap_analysis_imp_xls" model="ir.actions.act_window">
+ <field name="name">Gap Analysis: Import from Excel</field>
+ <field name="res_model">gap_analysis.import_xls</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="view_id" ref="gap_analysis_imp_xls_view"/>
+ <field name="target">new</field>
+ </record>
+ <record id="act_gap_analysis_imp_fct" model="ir.actions.act_window">
+ <field name="name">Gap Analysis: Import Functionalities from Excel</field>
+ <field name="res_model">gap_analysis.import_fct_xls</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="view_id" ref="gap_analysis_imp_fct_view"/>
+ <field name="target">new</field>
+ </record>
+
+ <menuitem id="menu_gap_002" name="Import Gap from Excel" parent="menu_gap_00" sequence="10" action="act_gap_analysis_imp_xls" groups="gap_analysis.res_group_gap1"/>
+ <menuitem id="menu_gap_026" name="Import Functionalities from Excel" parent="menu_gap_00" sequence="11" action="act_gap_analysis_imp_fct" groups="gap_analysis.res_group_gap1"/>
+ </data>
+</openerp>
\ No newline at end of file
=== added directory 'gap_analysis_aeroo_report'
=== added file 'gap_analysis_aeroo_report/__init__.py'
--- gap_analysis_aeroo_report/__init__.py 1970-01-01 00:00:00 +0000
+++ gap_analysis_aeroo_report/__init__.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import report
+import wizard
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis_aeroo_report/__openerp__.py'
--- gap_analysis_aeroo_report/__openerp__.py 1970-01-01 00:00:00 +0000
+++ gap_analysis_aeroo_report/__openerp__.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,69 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Gap Analysis Aeroo Report',
+ 'version': '1.0',
+ 'category': 'Tools',
+ 'complexity': "easy",
+ 'description': """
+Generate a gap-analysis with cost estimation
+--------------------------------------------
+
+To generate .xls instead of .ods
+---------------------------------
+ 1. download and install report_aeroo_ooo
+ 2. download
+ 3. download
+ 4. download
+
+
+Current addon Limit
+-------------------
+The columns are not managed dynamically, so the you can make a report with <= 6 workload type.
+You can have more workload type used in your gap analysis, but they won't be shown.
+
+Need to show more columns ?
+
+ 1. download
+ 2. download
+ 3. download
+ 4. download
+""",
+ 'author': 'Elico Corp',
+ 'website': 'http://www.elico-corp.com',
+ 'images': ['images/report.jpg'],
+ 'depends': ['gap_analysis_project_long_term','report_aeroo'],
+ 'init_xml': [],
+ 'update_xml': [
+ 'wizard/wizard_view.xml',
+ ],
+ 'demo_xml': [],
+ 'test': [],
+ 'installable': True,
+ 'auto_install': False,
+ 'application': False,
+ 'active': True,
+ 'certificate': '',
+}
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis_aeroo_report/gap_analysis_how_to.pdf'
Binary files gap_analysis_aeroo_report/gap_analysis_how_to.pdf 1970-01-01 00:00:00 +0000 and gap_analysis_aeroo_report/gap_analysis_how_to.pdf 2013-10-22 14:58:07 +0000 differ
=== added directory 'gap_analysis_aeroo_report/images'
=== added file 'gap_analysis_aeroo_report/images/report.jpg'
Binary files gap_analysis_aeroo_report/images/report.jpg 1970-01-01 00:00:00 +0000 and gap_analysis_aeroo_report/images/report.jpg 2013-10-22 14:58:07 +0000 differ
=== added directory 'gap_analysis_aeroo_report/report'
=== added file 'gap_analysis_aeroo_report/report/__init__.py'
--- gap_analysis_aeroo_report/report/__init__.py 1970-01-01 00:00:00 +0000
+++ gap_analysis_aeroo_report/report/__init__.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import gap_analysis_report
+import tasks_list_report
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis_aeroo_report/report/gap_analysis_report.ods'
Binary files gap_analysis_aeroo_report/report/gap_analysis_report.ods 1970-01-01 00:00:00 +0000 and gap_analysis_aeroo_report/report/gap_analysis_report.ods 2013-10-22 14:58:07 +0000 differ
=== added file 'gap_analysis_aeroo_report/report/gap_analysis_report.py'
--- gap_analysis_aeroo_report/report/gap_analysis_report.py 1970-01-01 00:00:00 +0000
+++ gap_analysis_aeroo_report/report/gap_analysis_report.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,180 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import time
+import datetime
+from report import report_sxw
+from report.report_sxw import rml_parse
+import netsvc
+from osv import osv
+from tools import ustr
+import pooler
+
+class Parser(report_sxw.rml_parse):
+ def __init__(self, cr, uid, name, context):
+ super(Parser, self).__init__(cr, uid, name, context=context)
+ datenow = datetime.datetime.now()
+ self.localcontext.update({
+ 'time': datenow.strftime("%Y-%m-%d %H:%M:%S"),
+ 'myheaders': self.get_cols(context=context),
+ 'mylines': self.get_lines(context=context),
+ })
+
+
+ def get_cols(self, context=None):
+ if not context:
+ context = {}
+
+ res = {}
+ result = []
+ ranges_list = []
+ active_ids = context.get('active_ids', [])
+
+ # Report Currency
+ res['currency'] = "USD"
+ company_pool = self.pool.get('res.company')
+ company_id = company_pool._company_default_get(self.cr, self.uid, 'gap_analysis', context=context)
+ if company_id:
+ company = company_pool.browse(self.cr, self.uid, company_id)
+ res['currency'] = company.currency_id.name
+ context.update({'currency_symbol':company.currency_id.symbol})
+
+ # List of Columns
+ for cpt in range(1, 18):# Set default value
+ range_name = "range" + str(cpt)
+ res[range_name] = ""
+
+ cpt = 1
+ self.cr.execute("SELECT id, name FROM gap_analysis_workload_type ORDER BY sequence ASC")
+ ranges = self.cr.fetchall()
+ for idx, one_range in enumerate(ranges):
+ range_name = "range" + str(cpt)
+ ranges_list.append(one_range[0])
+ res[range_name] = str(one_range[1])
+ cpt += 1
+
+ result.append(res)
+ context.update({'workload_type_list':ranges_list})
+ return result
+
+
+ def get_lines(self, context=None):
+ if not context:
+ context = {}
+
+ result = []
+ all_categ_ids = []
+ gap_categ_ids = []
+ cpt = {}
+ active_id = context.get('active_id', False)
+ currency = context.get('currency_symbol', '$')
+ gap_pool = self.pool.get('gap_analysis')
+
+ total_cost = 0
+ total_analysis = 0
+ total_dev = 0
+ total_cost_keep = 0
+ total_analysis_keep = 0
+ total_dev_keep = 0
+
+ if active_id:
+ # First we get all the used category for this Gap Analysis
+ active_gap = gap_pool.browse(self.cr, self.uid, active_id)
+ for one_line in active_gap.gap_lines:
+ res = {}
+
+ res['functionality'] = one_line.functionality.name
+ res['description'] = one_line.functionality.description or one_line.functionality.name
+ res['fct_category'] = one_line.category.full_path or one_line.category.name
+ res['phase'] = one_line.phase
+ res['critical'] = one_line.critical
+ res['keep'] = "Keep"
+ res['openerp_fct'] = one_line.openerp_fct and one_line.openerp_fct.name or ''
+ res['contributor'] = one_line.contributors or ''
+ res['effort'] = one_line.effort and one_line.effort.name or ''
+ res['effort2day'] = ''
+ res['cpt'] = one_line.code
+ res['testing'] = one_line.testing
+
+ res['total_cost'] = one_line.total_cost or 0
+
+ if one_line.effort and one_line.effort.unknown:
+ res['effort2day'] = one_line.duration_wk
+
+ if one_line.effort:
+ if one_line.effort.unknown:
+ res['total_dev'] = one_line.duration_wk
+ else:
+ res['total_dev'] = one_line.effort.duration
+ res['total_analysis'] = one_line.total_time - res['total_dev']
+ else:
+ res['total_dev'] = 0
+ res['total_analysis'] = one_line.total_time
+
+ if res['total_analysis'] <= 0:
+ res['total_analysis'] = 0
+
+
+ if res['total_cost'] == '':
+ tmp_cost = 0
+ else:
+ tmp_cost = res['total_cost']
+ if res['total_analysis'] == '':
+ tmp_analysis = 0
+ else:
+ tmp_analysis = res['total_analysis']
+ if res['total_dev'] == '':
+ tmp_dev = 0
+ else:
+ tmp_dev = res['total_dev']
+
+
+ if not one_line.keep:
+ res['keep'] = "DROP"
+ total_cost += tmp_cost
+ total_analysis += tmp_analysis
+ total_dev += tmp_dev
+ else:
+ total_cost += tmp_cost
+ total_analysis += tmp_analysis
+ total_dev += tmp_dev
+ total_cost_keep += tmp_cost
+ total_analysis_keep += tmp_analysis
+ total_dev_keep += tmp_dev
+
+
+ for ii in range(1, 18):# Set default value
+ cost_name = "cost" + str(ii)
+ res[cost_name] = ''
+
+ ii = 1
+ for one_type in context['workload_type_list']:
+ for one_workload in one_line.workloads:#for each possible Workload Type
+ if one_workload.type.id == one_type:
+ cost_name = "cost" + str(ii)
+ res[cost_name] = str(one_workload.duration)
+ ii += 1
+ result.append(res)
+
+ return result
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'gap_analysis_aeroo_report/report/tasks_list_report.ods'
Binary files gap_analysis_aeroo_report/report/tasks_list_report.ods 1970-01-01 00:00:00 +0000 and gap_analysis_aeroo_report/report/tasks_list_report.ods 2013-10-22 14:58:07 +0000 differ
=== added file 'gap_analysis_aeroo_report/report/tasks_list_report.py'
--- gap_analysis_aeroo_report/report/tasks_list_report.py 1970-01-01 00:00:00 +0000
+++ gap_analysis_aeroo_report/report/tasks_list_report.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,108 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import time
+import datetime
+from report import report_sxw
+from report.report_sxw import rml_parse
+import netsvc
+from osv import osv
+from tools import ustr
+import pooler
+
+TASK_PRIORITY = {
+ '4':'Very Low',
+ '3':'Low',
+ '2':'Medium',
+ '1':'Important',
+ '0':'Very important',
+}
+
+class Parser(report_sxw.rml_parse):
+ def __init__(self, cr, uid, name, context):
+ super(Parser, self).__init__(cr, uid, name, context=context)
+ self.localcontext.update({
+ 'myheaders': self.get_cols(context=context),
+ 'mylines': self.get_lines(context=context),
+ })
+
+
+ def get_cols(self, context=None):
+ context = context or {}
+ res = {}
+ result = []
+ ranges_list = []
+ active_id = context.get('active_id', False)
+
+ if active_id:
+ project = self.pool.get('project.project').browse(self.cr, self.uid, active_id)
+ res["project"] = 'Project "' + project.name + '"'
+ res["customer"] = project.partner_id and project.partner_id.name or 'Customer Undefined'
+ else:
+ res["project"] = 'Project Undefined'
+ res["customer"] = 'Customer Undefined'
+
+ res["time"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
+ result.append(res)
+ return result
+
+
+ def get_lines(self, context=None):
+ context = context or {}
+ result = []
+ active_id = context.get('active_id', False)
+ task_pool = self.pool.get('project.task')
+
+ if active_id:
+ cpt = 0
+ task_ids = task_pool.search(self.cr, self.uid, [('project_id','=',active_id),('to_report','=',True)], order='id') or []
+ for one_line in task_pool.browse(self.cr, self.uid, task_ids):
+ res = {}
+ cpt += 1
+ duration = one_line.planned_hours or one_line.child_planned_hours or 0
+ duration = duration / 8.00#Hours => Days
+
+ original_duration = one_line.org_planned_hours or one_line.org_child_planned_hours or 0
+ original_duration = original_duration / 8.00#Hours => Days
+
+ resolution = 'n/a'
+ if one_line.date_start and one_line.date_end:
+ resolution = datetime.datetime.strptime(one_line.date_end, "%Y-%m-%d %H:%M:%S") - datetime.datetime.strptime(one_line.date_start, "%Y-%m-%d %H:%M:%S")
+ resolution = abs(resolution.days)
+
+ res['code'] = one_line.gap_line_id and one_line.gap_line_id.code or cpt
+ res['category'] = one_line.gap_category_id and one_line.gap_category_id.name or ''
+ res['module'] = one_line.module_id and one_line.module_id.name or ''
+ res['name'] = one_line.name
+ res['assigned'] = one_line.user_id and one_line.user_id.name or ''
+ res['start'] = one_line.date_start and one_line.date_start.split()[0] or ''
+ res['end'] = one_line.date_end and one_line.date_end.split()[0] or ''
+ res['priority'] = one_line.priority in TASK_PRIORITY and TASK_PRIORITY[one_line.priority] or 'n/a'
+ res['status'] = one_line.state
+ res['org_duration'] = original_duration
+ res['duration'] = duration
+ res['resolution'] = resolution
+ result.append(res)
+
+ return result
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added directory 'gap_analysis_aeroo_report/wizard'
=== added file 'gap_analysis_aeroo_report/wizard/__init__.py'
--- gap_analysis_aeroo_report/wizard/__init__.py 1970-01-01 00:00:00 +0000
+++ gap_analysis_aeroo_report/wizard/__init__.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import wizard_view
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis_aeroo_report/wizard/wizard_view.py'
--- gap_analysis_aeroo_report/wizard/wizard_view.py 1970-01-01 00:00:00 +0000
+++ gap_analysis_aeroo_report/wizard/wizard_view.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from osv import osv, fields
+from tools.translate import _
+
+class gap_analysis_wizard(osv.TransientModel):
+ _name='gap_analysis.gap_analysis_wizard'
+
+ def print_xls(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+
+ data = {'model':'gap_analysis', 'ids':context.get('active_ids', []), 'id':ids[0], 'report_type': 'aeroo'}
+
+ return {
+ 'type': 'ir.actions.report.xml',
+ 'report_name': 'gap_analysis',
+ 'datas': data,
+ 'context':context
+ }
+
+
+class gap_analysis_tasks_list(osv.TransientModel):
+ _name='gap_analysis.tasks_list'
+
+ def print_xls(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+
+ data = {'model':'project.task', 'ids':context.get('active_ids', []), 'id': context.get('active_id', ids[0]), 'report_type': 'aeroo'}
+
+ return {
+ 'type': 'ir.actions.report.xml',
+ 'report_name': 'tasks_list',
+ 'datas': data,
+ 'context':context
+ }
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis_aeroo_report/wizard/wizard_view.xml'
--- gap_analysis_aeroo_report/wizard/wizard_view.xml 1970-01-01 00:00:00 +0000
+++ gap_analysis_aeroo_report/wizard/wizard_view.xml 2013-10-22 14:58:07 +0000
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="gap_analysis_aeroo_wizard_view" model="ir.ui.view">
+ <field name="name">Gap Analysis Report Wizard</field>
+ <field name="model">gap_analysis.gap_analysis_wizard</field>
+ <field name="arch" type="xml">
+ <form string="Gap Analysis Report Wizard">
+ <newline/>
+ <group col="4" colspan="4">
+ <button icon="gtk-cancel" special="cancel" string="Cancel" colspan="1"/>
+ <button icon="gtk-print" name="print_xls" string="Generate XLS" type="object" colspan="1" default_focus="1" />
+ </group>
+ </form>
+ </field>
+ </record>
+ <record id="tasks_list_aeroo_wizard_view" model="ir.ui.view">
+ <field name="name">Tasks List</field>
+ <field name="model">gap_analysis.tasks_list</field>
+ <field name="arch" type="xml">
+ <form string="Tasks List">
+ <newline/>
+ <group col="4" colspan="4">
+ <button icon="gtk-cancel" special="cancel" string="Cancel" colspan="1"/>
+ <button icon="gtk-print" name="print_xls" string="Generate XLS" type="object" colspan="1" default_focus="1" />
+ </group>
+ </form>
+ </field>
+ </record>
+
+ <!-- Aeroo Report -->
+ <record id="report_aeroo_gap_analysis" model="ir.actions.report.xml">
+ <field name="name">Export Full Gap Analysis</field>
+ <field name="type">ir.actions.report.xml</field>
+ <field name="model">gap_analysis</field>
+ <field name="report_name">gap_analysis</field>
+ <field name="report_type">aeroo</field>
+ <field name="in_format">oo-ods</field>
+ <field name="out_format">2</field>
+ <field name="parser_loc">gap_analysis_aeroo_report/report/gap_analysis_report.py</field>
+ <field name="report_rml">gap_analysis_aeroo_report/report/gap_analysis_report.ods</field>
+ <field name="parser_state">loc</field>
+ <field name="tml_source">file</field>
+ </record>
+ <record id="report_aeroo_tasks_list" model="ir.actions.report.xml">
+ <field name="name">Export Tasks List</field>
+ <field name="type">ir.actions.report.xml</field>
+ <field name="model">project.task</field>
+ <field name="report_name">tasks_list</field>
+ <field name="report_type">aeroo</field>
+ <field name="in_format">oo-ods</field>
+ <field name="out_format">2</field>
+ <field name="parser_loc">gap_analysis_aeroo_report/report/tasks_list_report.py</field>
+ <field name="report_rml">gap_analysis_aeroo_report/report/tasks_list_report.ods</field>
+ <field name="parser_state">loc</field>
+ <field name="tml_source">file</field>
+ </record>
+
+ <act_window id="action_report_aeroo_gap_analysis"
+ name="Export Full Gap Analysis"
+ src_model="gap_analysis"
+ res_model="gap_analysis.gap_analysis_wizard"
+ view_mode="form"
+ target="new"
+ key2="client_action_multi" />
+
+ <act_window id="action_report_aeroo_tasks_list"
+ name="Export Tasks List"
+ src_model="project.project"
+ res_model="gap_analysis.tasks_list"
+ view_mode="form"
+ target="new"
+ key2="client_action_multi" />
+ </data>
+</openerp>
\ No newline at end of file
=== added directory 'gap_analysis_project'
=== added file 'gap_analysis_project/__init__.py'
--- gap_analysis_project/__init__.py 1970-01-01 00:00:00 +0000
+++ gap_analysis_project/__init__.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import gap_analysis_project
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis_project/__openerp__.py'
--- gap_analysis_project/__openerp__.py 1970-01-01 00:00:00 +0000
+++ gap_analysis_project/__openerp__.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+
+{
+ 'name': 'Gap Analysis Project',
+ 'version': '1.0',
+ 'category': 'Tools',
+ 'complexity': "easy",
+ 'description': """
+This module provides the necessary tools to generate a new project with all the task from the Gap Analysis.
+""",
+ 'author': 'Elico Corp',
+ 'website': 'http://www.elico-corp.com',
+ 'images': [],
+ 'depends': ['gap_analysis'],
+ 'init_xml': [],
+ 'update_xml': [
+ 'gap_analysis_project.xml',
+ 'security/ir.model.access.csv',
+ ],
+ 'demo_xml': [],
+ 'test': [],
+ 'installable': True,
+ 'auto_install': False,
+ 'application': False,
+ 'active': True,
+ 'certificate': '',
+}
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis_project/gap_analysis_how_to.pdf'
Binary files gap_analysis_project/gap_analysis_how_to.pdf 1970-01-01 00:00:00 +0000 and gap_analysis_project/gap_analysis_how_to.pdf 2013-10-22 14:58:07 +0000 differ
=== added file 'gap_analysis_project/gap_analysis_project.py'
--- gap_analysis_project/gap_analysis_project.py 1970-01-01 00:00:00 +0000
+++ gap_analysis_project/gap_analysis_project.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,274 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from datetime import datetime
+import time
+from osv import fields, osv
+from tools.translate import _
+import tools
+from tools import ustr
+
+
+class gap_analysis(osv.Model):
+ _inherit = "gap_analysis"
+ _name = "gap_analysis"
+
+ def generate_project(self, cr, uid, ids, context=None):
+ project_pool = self.pool.get('project.project')
+ task_pool = self.pool.get('project.task')
+
+ for gap in self.browse(cr, uid, ids, context=context):
+ partner_id = gap.partner_id and gap.partner_id.id or False
+ notes = gap.note or ''
+
+ project_vals = {
+ 'name': gap.name,
+ 'description': notes,
+ 'user_id': gap.user_id.id,
+ 'partner_id': partner_id,
+ 'gap_analysis_id': gap.id,
+ }
+ project_id = project_pool.create(cr, uid, project_vals, context=context)
+
+ for gap_line in gap.gap_lines:
+ if gap_line.to_project and gap_line.keep:
+ time4dev = 0
+ time4tech = 0
+ time4fct = 0
+ time4test = gap_line.testing or 0
+
+ if gap_line.effort:
+ if gap_line.effort.unknown:
+ time4dev = gap_line.duration_wk
+ else:
+ time4dev = gap_line.effort.duration
+
+ for workload in gap_line.workloads:
+ if workload.type.category == "Technical Analysis":
+ time4tech += workload.duration
+ else:
+ time4fct += workload.duration
+
+ # Create Tasks
+ if time4dev > 0 or time4tech > 0 or time4fct > 0 or time4test > 0:
+ maintask_vals = {
+ 'name': gap_line.functionality.name[0:100],
+ 'code_gap': gap_line.code or "",
+ 'project_id': project_id,
+ 'notes': ustr(gap_line.functionality.description or gap_line.functionality.name),
+ 'partner_id': partner_id,
+ 'gap_category_id': gap_line.category and gap_line.category.id or False,
+ 'user_id': gap.user_functional and gap.user_functional.id or False,
+ 'gap_line_id': gap_line.id,
+ 'to_report': True,
+ 'org_planned_hours': 0,
+ 'planned_hours': 0,
+ 'remaining_hours': 0,
+ }
+ maintask_id = task_pool.create(cr, uid, maintask_vals, context=context)
+ maintask_id = [int(maintask_id)]
+
+ if time4test > 0:
+ task_vals4test = {
+ 'name': gap_line.functionality.name[0:100] + " [TEST]",
+ 'code_gap': gap_line.code or "",
+ 'project_id': project_id,
+ 'notes': ustr(gap_line.functionality.description or gap_line.functionality.name),
+ 'partner_id': partner_id,
+ 'org_planned_hours': time4test,
+ 'planned_hours': time4test,
+ 'remaining_hours': time4test,
+ 'parent_ids': [(6,0,maintask_id)],
+ 'gap_category_id': gap_line.category and gap_line.category.id or False,
+ 'user_id': gap.user_test and gap.user_test.id or False,
+ 'gap_line_id': gap_line.id,
+ }
+ task_pool.create(cr, uid, task_vals4test, context=context)
+
+ if time4dev > 0:
+ task_vals4dev = {
+ 'name': gap_line.functionality.name[0:100] + " [DEV]",
+ 'code_gap': gap_line.code or "",
+ 'project_id': project_id,
+ 'notes': ustr(gap_line.functionality.description or gap_line.functionality.name),
+ 'partner_id': partner_id,
+ 'org_planned_hours': time4dev,
+ 'planned_hours': time4dev,
+ 'remaining_hours': time4dev,
+ 'parent_ids': [(6,0,maintask_id)],
+ 'gap_category_id': gap_line.category and gap_line.category.id or False,
+ 'user_id': gap.user_dev and gap.user_dev.id or False,
+ 'gap_line_id': gap_line.id,
+ }
+ task_pool.create(cr, uid, task_vals4dev, context=context)
+
+ if time4tech > 0:
+ task_vals4tech = {
+ 'name': gap_line.functionality.name[0:100] + " [TECH]",
+ 'code_gap': gap_line.code or "",
+ 'project_id': project_id,
+ 'notes': ustr(gap_line.functionality.description or gap_line.functionality.name),
+ 'partner_id': partner_id,
+ 'org_planned_hours': time4tech,
+ 'planned_hours': time4tech,
+ 'remaining_hours': time4tech,
+ 'parent_ids': [(6,0,maintask_id)],
+ 'gap_category_id': gap_line.category and gap_line.category.id or False,
+ 'user_id': gap.user_technical and gap.user_technical.id or False,
+ 'gap_line_id': gap_line.id,
+ }
+ task_pool.create(cr, uid, task_vals4tech, context=context)
+
+ if time4fct > 0:
+ task_vals4fct = {
+ 'name': gap_line.functionality.name[0:100] + " [FUNC]",
+ 'code_gap': gap_line.code or "",
+ 'project_id': project_id,
+ 'notes': ustr(gap_line.functionality.description or gap_line.functionality.name),
+ 'partner_id': partner_id,
+ 'org_planned_hours': time4fct,
+ 'planned_hours': time4fct,
+ 'remaining_hours': time4fct,
+ 'parent_ids': [(6,0,maintask_id)],
+ 'gap_category_id': gap_line.functionality.category and gap_line.functionality.category.id or False,
+ 'user_id': gap.user_functional and gap.user_functional.id or False,
+ 'gap_line_id': gap_line.id,
+ }
+ task_pool.create(cr, uid, task_vals4fct, context=context)
+
+ if project_id:
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name':"Generated Project",
+ 'view_mode': 'form',
+ 'view_id': False,
+ 'view_type': 'form',
+ 'res_model': 'project.project',
+ 'res_id': project_id,
+ 'context': context
+ }
+ return True
+
+
+
+class gap_analysis_line(osv.Model):
+ _name = "gap_analysis.line"
+ _inherit = "gap_analysis.line"
+
+ _columns = {
+ 'to_project': fields.boolean('Add to project ?', help='Specify whether this functionality must create a task or not when you generate a project.'),
+ }
+ _defaults = {
+ 'to_project': True,
+ }
+
+
+
+class openerp_module(osv.Model):
+ _name = "openerp_module"
+
+ _columns = {
+ 'name': fields.char('Name', size=128, required=True),
+ 'version': fields.char('Version', size=128),
+ 'note': fields.text('Note'),
+ }
+
+
+
+class project(osv.Model):
+ _inherit = "project.project"
+ _name = "project.project"
+
+ _columns = {
+ 'gap_analysis_id': fields.many2one('gap_analysis', 'Gap Analysis'),
+ }
+
+
+class project_task(osv.Model):
+ _inherit = "project.task"
+ _name = "project.task"
+
+ def _get_parent_category(self, cr, uid, ids, fields, args, context=None):
+ context = context or {}
+ res = {}
+ for task in self.browse(cr, uid, ids):
+ res[task.id] = task.gap_category_id and task.gap_category_id.parent_id.id or False
+ return res
+
+ def _task_to_update_after_category_change(self, cr, uid, ids, fields=None, arg=None, context=None):
+ if type(ids) != type([]):
+ ids = [ids]
+ return self.pool.get('project.task').search(cr, uid, [('gap_category_id', 'in', ids)]) or []
+
+ def _get_child_tasks(self, cr, uid, ids, context=None):
+ if type(ids) != type([]):
+ ids = [ids]
+ cr.execute("SELECT DISTINCT parent_id FROM project_task_parent_rel WHERE task_id in %s", (tuple(ids),))
+ task_ids = filter(None, map(lambda x:x[0], cr.fetchall())) or []
+ return task_ids
+
+ def _get_child_hours(self, cr, uid, ids, field_names, args, context=None):
+ result = {}
+ for task in self.browse(cr, uid, ids, context=context):
+ res = {}
+ child_org_planned_hours = 0.0
+ child_planned_hours = 0.0
+ child_remaining_hours = 0.0
+
+ for child in task.child_ids:
+ child_org_planned_hours += child.org_planned_hours
+ child_planned_hours += child.planned_hours
+ child_remaining_hours += child.remaining_hours
+
+ res['child_org_planned_hours'] = child_org_planned_hours
+ res['child_planned_hours'] = child_planned_hours
+ res['child_remaining_hours'] = child_remaining_hours
+ result[task.id] = res
+ return result
+
+# def onchange_planned(self, cr, uid, ids, planned = 0.0, effective = 0.0):
+# return {'value':{'remaining_hours': planned - effective, 'org_planned_hours':planned}}
+
+ _columns = {
+ 'child_org_planned_hours': fields.function(_get_child_hours, string='Child Original Planned Hours', multi='child_hours', help="Computed using the sum of the child tasks Original planned hours.",
+ store = {
+ 'project.task': (_get_child_tasks, ['org_planned_hours','planned_hours'], 10),
+ }),
+ 'child_planned_hours': fields.function(_get_child_hours, string='Child Planned Hours', multi='child_hours', help="Computed using the sum of the child tasks planned hours.",
+ store = {
+ 'project.task': (_get_child_tasks, ['planned_hours','remaining_hours'], 10),
+ }),
+ 'child_remaining_hours': fields.function(_get_child_hours, string='Child Remaining Hours', multi='child_hours', help="Computed using the sum of the child tasks work done.",
+ store = {
+ 'project.task': (_get_child_tasks, ['planned_hours','remaining_hours'], 10),
+ }),
+
+ 'module_id': fields.many2one('openerp_module', 'Module', select=True),
+ 'gap_category_id': fields.many2one('gap_analysis.functionality.category','Category', select=True),
+ 'parent_category': fields.function(_get_parent_category, method=True, type='many2one', obj='gap_analysis.functionality.category', string='Parent Category', store={'project.task': (lambda self, cr, uid, ids, context: ids, ['gap_category_id'], 10), 'gap_analysis.functionality.category': (_task_to_update_after_category_change, ['parent_id'], 10),}),
+ 'gap_line_id': fields.many2one('gap_analysis.line', 'Gap Analysis Line', select=True),
+ 'code_gap': fields.char('Code in Gap', size=6),
+ 'to_report': fields.boolean('Report to customer'),
+ 'org_planned_hours': fields.float('Original Planned Hours', help='Original estimated time to do the task, usually set by the project manager when the task is in draft state.'),
+ }
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis_project/gap_analysis_project.xml'
--- gap_analysis_project/gap_analysis_project.xml 1970-01-01 00:00:00 +0000
+++ gap_analysis_project/gap_analysis_project.xml 2013-10-22 14:58:07 +0000
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="view_gap_analysis_form_project_inherit" model="ir.ui.view">
+ <field name="name">gap_analysis.project.form</field>
+ <field name="model">gap_analysis</field>
+ <field name="inherit_id" ref="gap_analysis.view_gap_analysis_form"/>
+ <field name="priority" eval="9"/>
+ <field name="arch" type="xml">
+ <xpath expr="//field[@name='functionality']" position="after">
+ <field name="to_project"/>
+ </xpath>
+ <xpath expr="//button[@name='action_cancel']" position="after">
+ <button string="Generate New Project" icon="gtk-go-forward" name="generate_project" type="object" groups="gap_analysis.res_group_gap0,gap_analysis.res_group_gap1" attrs="{'invisible': [('state','!=','done')]}"/>
+ </xpath>
+ </field>
+ </record>
+
+ <record id="edit_project_gap_inherit" model="ir.ui.view">
+ <field name="name">project.project.form</field>
+ <field name="model">project.project</field>
+ <field name="inherit_id" ref="project.edit_project"/>
+ <field name="priority" eval="2"/>
+ <field name="arch" type="xml">
+ <xpath expr="//field[@name='date']" position='after'>
+ <field name="gap_analysis_id" />
+ </xpath>
+ </field>
+ </record>
+ <record id="view_task_form_gap_inherit" model="ir.ui.view">
+ <field name="name">project.task.form</field>
+ <field name="model">project.task</field>
+ <field name="inherit_id" ref="project.view_task_form2"/>
+ <field name="priority" eval="2"/>
+ <field name="arch" type="xml">
+ <xpath expr="//field[@name='planned_hours']" position="before">
+ <field name="org_planned_hours" widget="float_time" attrs="{'readonly':[('state','!=','draft')]}"/>
+ <field name="child_org_planned_hours" readonly="1" attrs="{'invisible':[('child_org_planned_hours','=',0)]}"/>
+ </xpath>
+ <xpath expr="//field[@name='planned_hours']" position="after">
+ <field name="child_planned_hours" readonly="1" attrs="{'invisible':[('child_planned_hours','=',0)]}"/>
+ </xpath>
+ <xpath expr="//field[@name='remaining_hours']" position="after">
+ <field name="child_remaining_hours" readonly="1" attrs="{'invisible':[('child_planned_hours','=',0)]}"/>
+ </xpath>
+ <xpath expr="/form/sheet/notebook/page[@string='Extra Info']/group/group[@string='Gantt View']" position="after">
+ <group string="Gap Analysis">
+ <field name="gap_category_id" readonly="1"/>
+ <field name="parent_category" readonly="1"/>
+ <field name="gap_line_id" readonly="1"/>
+ <field name="code_gap" groups="gap_analysis.res_group_gap1"/>
+ <field name="module_id" groups="gap_analysis.res_group_gap1"/>
+ <field name="to_report" groups="gap_analysis.res_group_gap1"/>
+ </group>
+ </xpath>
+ </field>
+ </record>
+ <record id="view_task_search_form_gap" model="ir.ui.view">
+ <field name="name">project.task.search.form.gap</field>
+ <field name="model">project.task</field>
+ <field name="inherit_id" ref="project.view_task_search_form"/>
+ <field name="arch" type="xml">
+ <xpath expr="//filter[@name='group_user_id']" position="after">
+ <separator orientation="vertical"/>
+ <filter string="Gap Category" name="group_gap_category_id" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'gap_category_id'}"/>
+ <filter string="Gap Parent Category" name="group_parent_category" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'parent_category'}"/>
+ <filter string="Module" name="group_module_id" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'module_id'}"/>
+ </xpath>
+ </field>
+ </record>
+ <record id="view_task_tree_gap_inherit" model="ir.ui.view">
+ <field name="name">project.task.tree.gap</field>
+ <field name="model">project.task</field>
+ <field name="inherit_id" ref="project.view_task_tree2" />
+ <field name="arch" type="xml">
+ <field name="remaining_hours" position="before">
+ <field name="gap_category_id"/>
+ <field name="parent_category" invisible="1"/>
+ </field>
+ </field>
+ </record>
+
+
+ <record id="openerp_module_form" model="ir.ui.view">
+ <field name="name">openerp_module.form</field>
+ <field name="model">openerp_module</field>
+ <field name="arch" type="xml">
+ <form string="Modules" version="7.0">
+ <sheet>
+ <group>
+ <group>
+ <field name="name" colspan="2"/>
+ </group>
+ <group>
+ <field name="version" colspan="2"/>
+ </group>
+ </group>
+ <group string="Notes">
+ <field name="note" nolabel="1"/>
+ </group>
+ </sheet>
+ </form>
+ </field>
+ </record>
+ <record id="openerp_module_tree" model="ir.ui.view">
+ <field name="name">openerp_module.tree</field>
+ <field name="model">openerp_module</field>
+ <field name="arch" type="xml">
+ <tree string="Modules">
+ <field name="name" />
+ <field name="version" />
+ </tree>
+ </field>
+ </record>
+
+ <record id="act_gap_analysis_modules" model="ir.actions.act_window">
+ <field name="name">Modules</field>
+ <field name="res_model">openerp_module</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+ <menuitem id="menu_gap_024" name="Modules" parent="gap_analysis.menu_gap_02" sequence="12" action="act_gap_analysis_modules" />
+ </data>
+</openerp>
\ No newline at end of file
=== added directory 'gap_analysis_project/security'
=== added file 'gap_analysis_project/security/ir.model.access.csv'
--- gap_analysis_project/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
+++ gap_analysis_project/security/ir.model.access.csv 2013-10-22 14:58:07 +0000
@@ -0,0 +1,4 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_openerp_module_user,openerp_module base user,gap_analysis_project.model_openerp_module,base.group_user,1,0,0,0
+access_openerp_module_Guser,openerp_module user,gap_analysis_project.model_openerp_module,gap_analysis.res_group_gap0,1,1,1,0
+access_openerp_module_manager,openerp_module manager,gap_analysis_project.model_openerp_module,gap_analysis.res_group_gap1,1,1,1,1
\ No newline at end of file
=== added directory 'gap_analysis_project_long_term'
=== added file 'gap_analysis_project_long_term/__init__.py'
--- gap_analysis_project_long_term/__init__.py 1970-01-01 00:00:00 +0000
+++ gap_analysis_project_long_term/__init__.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import gap_analysis_project_long_term
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis_project_long_term/__openerp__.py'
--- gap_analysis_project_long_term/__openerp__.py 1970-01-01 00:00:00 +0000
+++ gap_analysis_project_long_term/__openerp__.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+
+{
+ 'name': 'Gap Analysis Project Long Term',
+ 'version': '1.0',
+ 'category': 'Tools',
+ 'complexity': "easy",
+ 'description': """
+This module provides the necessary tools to manage Phases in your Gap Analysis and generated project.
+""",
+ 'author': 'Elico Corp',
+ 'website': 'http://www.elico-corp.com',
+ 'images': [],
+ 'depends': ['gap_analysis_project','project_long_term'],
+ 'init_xml': [],
+ 'update_xml': [
+ 'gap_analysis_project_long_term.xml',
+ ],
+ 'demo_xml': [],
+ 'test': [],
+ 'installable': True,
+ 'auto_install': False,
+ 'application': False,
+ 'active': True,
+ 'certificate': '',
+}
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis_project_long_term/gap_analysis_how_to.pdf'
Binary files gap_analysis_project_long_term/gap_analysis_how_to.pdf 1970-01-01 00:00:00 +0000 and gap_analysis_project_long_term/gap_analysis_how_to.pdf 2013-10-22 14:58:07 +0000 differ
=== added file 'gap_analysis_project_long_term/gap_analysis_project_long_term.py'
--- gap_analysis_project_long_term/gap_analysis_project_long_term.py 1970-01-01 00:00:00 +0000
+++ gap_analysis_project_long_term/gap_analysis_project_long_term.py 2013-10-22 14:58:07 +0000
@@ -0,0 +1,217 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (c) 2010-2013 Elico Corp. All Rights Reserved.
+# Author: Yannick Gouin <yannick.gouin@xxxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from datetime import datetime
+import time
+from osv import fields, osv
+from tools.translate import _
+from tools import ustr
+#import tools
+
+
+class gap_analysis(osv.Model):
+ _inherit = "gap_analysis"
+ _name = "gap_analysis"
+
+ def generate_project(self, cr, uid, ids, context=None):
+ project_pool = self.pool.get('project.project')
+ phase_pool = self.pool.get('project.phase')
+ gapline_pool = self.pool.get('gap_analysis.line')
+ task_pool = self.pool.get('project.task')
+ uom_hour = self.pool.get('product.uom').search(cr, uid, [('name', '=', _('Hour'))], context=context)[0]
+
+ for gap in self.browse(cr, uid, ids, context=context):
+ partner_id = gap.partner_id and gap.partner_id.id or False
+ notes = gap.note or ''
+
+ notes = gap.note or ''
+
+ project_vals = {
+ 'name': gap.name,
+ 'description': notes,
+ 'user_id': gap.user_id.id,
+ 'partner_id': partner_id,
+ 'gap_analysis_id': gap.id,
+ }
+ project_id = project_pool.create(cr, uid, project_vals, context=context)
+
+ phases = {}
+ for gap_line in gap.gap_lines:
+ if gap_line.to_project and gap_line.keep:
+ time4dev = 0
+ time4tech = 0
+ time4fct = 0
+ time4test = gap_line.testing or 0
+
+ if gap_line.effort:
+ if gap_line.effort.unknown:
+ time4dev = gap_line.duration_wk
+ else:
+ time4dev = gap_line.effort.duration
+
+ for workload in gap_line.workloads:
+ if workload.type.category == "Technical Analysis":
+ time4tech += workload.duration
+ else:
+ time4fct += workload.duration
+
+ #CREATE PROJECT PHASES
+ phase = gap_line.phase or '0'
+ phase = phase.upper()
+
+ if phase not in phases:
+ gapline_ids = gapline_pool.search(cr, uid, [('gap_id', '=', gap.id),('phase', 'ilike', phase),('keep', '=', True),('to_project', '=', True)])
+ duration_hour = 0
+ if gapline_ids:
+ for l in gapline_pool.browse(cr, uid, gapline_ids):
+ duration_hour += l.total_time
+
+ phase_vals = {
+ 'name': gap.name + " - " + phase,
+ 'project_id': project_id,
+ 'duration': duration_hour,
+ 'product_uom': uom_hour,
+ 'previous_phase_ids': [],#TODO
+ 'next_phase_ids': [],#TODO
+ }
+ phases[phase] = phase_pool.create(cr, uid, phase_vals, context=context)
+
+ # Create Tasks
+ if time4dev > 0 or time4tech > 0 or time4fct > 0 or time4test > 0:
+ maintask_vals = {
+ 'name': gap_line.functionality.name[0:100],
+ 'code_gap': gap_line.code or "",
+ 'project_id': project_id,
+ 'notes': ustr(gap_line.functionality.description or gap_line.functionality.name),
+ 'partner_id': partner_id,
+ 'phase_id': phases[phase],
+ 'gap_category_id': gap_line.category and gap_line.category.id or False,
+ 'user_id': gap.user_functional and gap.user_functional.id or False,
+ 'gap_line_id': gap_line.id,
+ 'to_report': True,
+ 'org_planned_hours': 0,
+ 'planned_hours': 0,
+ 'remaining_hours': 0,
+ }
+ maintask_id = task_pool.create(cr, uid, maintask_vals, context=context)
+ maintask_id = [int(maintask_id)]
+
+ if time4test > 0:
+ task_vals4test = {
+ 'name': gap_line.functionality.name[0:100] + " [TEST]",
+ 'code_gap': gap_line.code or "",
+ 'project_id': project_id,
+ 'notes': ustr(gap_line.functionality.description or gap_line.functionality.name),
+ 'partner_id': partner_id,
+ 'org_planned_hours': time4test,
+ 'planned_hours': time4test,
+ 'remaining_hours': time4test,
+ 'phase_id': phases[phase],
+ 'parent_ids': [(6,0,maintask_id)],
+ 'gap_category_id': gap_line.category and gap_line.category.id or False,
+ 'user_id': gap.user_test and gap.user_test.id or False,
+ 'gap_line_id': gap_line.id,
+ }
+ task_pool.create(cr, uid, task_vals4test, context=context)
+
+ if time4dev > 0:
+ task_vals4dev = {
+ 'name': gap_line.functionality.name[0:100] + " [DEV]",
+ 'code_gap': gap_line.code or "",
+ 'project_id': project_id,
+ 'notes': ustr(gap_line.functionality.description or gap_line.functionality.name),
+ 'partner_id': partner_id,
+ 'org_planned_hours': time4dev,
+ 'planned_hours': time4dev,
+ 'remaining_hours': time4dev,
+ 'phase_id': phases[phase],
+ 'parent_ids': [(6,0,maintask_id)],
+ 'gap_category_id': gap_line.category and gap_line.category.id or False,
+ 'user_id': gap.user_dev and gap.user_dev.id or False,
+ 'gap_line_id': gap_line.id,
+ }
+ task_pool.create(cr, uid, task_vals4dev, context=context)
+
+ if time4tech > 0:
+ task_vals4tech = {
+ 'name': gap_line.functionality.name[0:100] + " [TECH]",
+ 'code_gap': gap_line.code or "",
+ 'project_id': project_id,
+ 'notes': ustr(gap_line.functionality.description or gap_line.functionality.name),
+ 'partner_id': partner_id,
+ 'org_planned_hours': time4tech,
+ 'planned_hours': time4tech,
+ 'remaining_hours': time4tech,
+ 'phase_id': phases[phase],
+ 'parent_ids': [(6,0,maintask_id)],
+ 'gap_category_id': gap_line.category and gap_line.category.id or False,
+ 'user_id': gap.user_technical and gap.user_technical.id or False,
+ 'gap_line_id': gap_line.id,
+ }
+ task_pool.create(cr, uid, task_vals4tech, context=context)
+
+ if time4fct > 0:
+ task_vals4fct = {
+ 'name': gap_line.functionality.name[0:100] + " [FUNC]",
+ 'code_gap': gap_line.code or "",
+ 'project_id': project_id,
+ 'notes': ustr(gap_line.functionality.description or gap_line.functionality.name),
+ 'partner_id': partner_id,
+ 'org_planned_hours': time4fct,
+ 'planned_hours': time4fct,
+ 'remaining_hours': time4fct,
+ 'phase_id': phases[phase],
+ 'parent_ids': [(6,0,maintask_id)],
+ 'gap_category_id': gap_line.category and gap_line.category.id or False,
+ 'user_id': gap.user_functional and gap.user_functional.id or False,
+ 'gap_line_id': gap_line.id,
+ }
+ task_pool.create(cr, uid, task_vals4fct, context=context)
+
+ if project_id:
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name':"Generated Project",
+ 'view_mode': 'form',
+ 'view_id': False,
+ 'view_type': 'form',
+ 'res_model': 'project.project',
+ 'res_id': project_id,
+ 'context': context
+ }
+ return True
+
+
+class gap_analysis_line(osv.Model):
+ _inherit = "gap_analysis.line"
+ _name = "gap_analysis.line"
+
+ _columns = {
+ 'phase': fields.char('Phase', size=4, help='Specify the Phase where the functionality will be done.', required=True),
+ }
+ _defaults = {
+ 'phase': 1,
+ }
+
+ _order = 'phase asc, critical desc, effort asc'
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'gap_analysis_project_long_term/gap_analysis_project_long_term.xml'
--- gap_analysis_project_long_term/gap_analysis_project_long_term.xml 1970-01-01 00:00:00 +0000
+++ gap_analysis_project_long_term/gap_analysis_project_long_term.xml 2013-10-22 14:58:07 +0000
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="view_gap_analysis_form_project_long_term_inherit" model="ir.ui.view">
+ <field name="name">gap_analysis.project_long_term.form</field>
+ <field name="model">gap_analysis</field>
+ <field name="inherit_id" ref="gap_analysis_project.view_gap_analysis_form_project_inherit"/>
+ <field name="priority" eval="5"/>
+ <field name="arch" type="xml">
+ <xpath expr="//field[@name='to_project']" position="before">
+ <field name="phase"/>
+ </xpath>
+ </field>
+ </record>
+ </data>
+</openerp>
\ No newline at end of file
Follow ups