From 070458069b22bebf726f42559bfe973cbc1ef5e7 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Wed, 30 May 2007 20:22:11 +0000 Subject: [PATCH] New module: account_analytic_analysis: stats on analytic accounts Dashboards for projects: Project member Project manager bzr revid: fp@tinyerp.com-d809ba846377547fc784c8b3a3e99b7549249a3c --- addons/account/project/project_view.xml | 11 +- addons/account_analytic_analysis/__init__.py | 29 ++ addons/account_analytic_analysis/__terp__.py | 20 + .../account_analytic_analysis.py | 389 ++++++++++++++++++ .../account_analytic_analysis_menu.xml | 124 ++++++ .../account_analytic_analysis_view.xml | 113 +++++ addons/base_setup/wizard/wizard_base_setup.py | 8 +- addons/board_project/__terp__.py | 2 +- .../board_project_manager_view.xml | 112 ++--- addons/board_project/board_project_view.xml | 10 +- .../report_analytic_planning.py | 6 +- .../report_analytic_planning_view.xml | 12 + 12 files changed, 750 insertions(+), 86 deletions(-) create mode 100644 addons/account_analytic_analysis/__init__.py create mode 100644 addons/account_analytic_analysis/__terp__.py create mode 100644 addons/account_analytic_analysis/account_analytic_analysis.py create mode 100644 addons/account_analytic_analysis/account_analytic_analysis_menu.xml create mode 100644 addons/account_analytic_analysis/account_analytic_analysis_view.xml diff --git a/addons/account/project/project_view.xml b/addons/account/project/project_view.xml index 92514cb3262..2f7305cdc4c 100644 --- a/addons/account/project/project_view.xml +++ b/addons/account/project/project_view.xml @@ -9,10 +9,8 @@ - - @@ -29,7 +27,6 @@ - @@ -53,7 +50,7 @@ - + @@ -105,7 +102,7 @@ - + @@ -206,8 +203,8 @@
- - + + diff --git a/addons/account_analytic_analysis/__init__.py b/addons/account_analytic_analysis/__init__.py new file mode 100644 index 00000000000..e32a3d4ab84 --- /dev/null +++ b/addons/account_analytic_analysis/__init__.py @@ -0,0 +1,29 @@ +############################################################################## +# +# Copyright (c) 2004 TINY SPRL. (http://tiny.be) All Rights Reserved. +# Fabien Pinckaers +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import account_analytic_analysis diff --git a/addons/account_analytic_analysis/__terp__.py b/addons/account_analytic_analysis/__terp__.py new file mode 100644 index 00000000000..a776b126cd1 --- /dev/null +++ b/addons/account_analytic_analysis/__terp__.py @@ -0,0 +1,20 @@ +{ + "name" : "report_account_analytic", + "description": """Modifiy the account analytic view to show +important data for project manager for services companies. +Add menu to show relevant information for each manager.""", + "version" : "1.0", + "author" : "Camptocamp", + "category" : "Generic Modules/Account", + "module": "", + "website": "http://www.camptocamp.com/", + "depends" : ["account","hr_timesheet","hr_timesheet_invoice"], + "init_xml" : [], + "update_xml" : [ + "account_analytic_analysis_view.xml", + "account_analytic_analysis_menu.xml", + ], + "demo_xml" : [], + "active": False, + "installable": True +} diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py new file mode 100644 index 00000000000..9a2441dd999 --- /dev/null +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -0,0 +1,389 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2004 TINY SPRL. (http://tiny.be) All Rights Reserved. +# Fabien Pinckaers +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## +import operator +from osv import osv, fields + +class account_analytic_account(osv.osv): + _name = "account.analytic.account" + _inherit = "account.analytic.account" + # OK !!! + def _ca_invoiced_calc(self, cr, uid, ids, name, arg, context={}): + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + acc_set = ",".join(map(str, ids2)) + cr.execute("select account_analytic_line.account_id, sum(amount) from account_analytic_line join account_analytic_journal on account_analytic_line.journal_id = account_analytic_journal.id where account_analytic_line.account_id IN (%s) and account_analytic_journal.type = 'sale' group by account_analytic_line.account_id" % acc_set) + res = {} + for account_id, sum in cr.fetchall(): + res[account_id] = round(sum,2) + for id in ids: + res[id] = round(res.get(id, 0.0),2) + return res + # OK !!! + def _ca_to_invoice_calc(self, cr, uid, ids, name, arg, context={}): + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + # Montant des heures non-facturées à facturer au prix de vente : + acc_set = ",".join(map(str, ids2)) + cr.execute("""SELECT account_analytic_account.id,(sum (product_template.list_price * account_analytic_line.unit_amount) + - sum(product_template.list_price * account_analytic_line.unit_amount * (hr_timesheet_invoice_factor.factor/100))) + AS ca_to_invoice + FROM product_template join product_product on product_template.id = product_product.product_tmpl_id + JOIN account_analytic_line on account_analytic_line.product_id = product_product.id + JOIN account_analytic_journal on account_analytic_line.journal_id = account_analytic_journal.id + JOIN account_analytic_account on account_analytic_account.id = account_analytic_line.account_id + JOIN hr_timesheet_invoice_factor on hr_timesheet_invoice_factor.id = account_analytic_account.to_invoice + WHERE account_analytic_account.id IN (%s) + AND account_analytic_journal.type='general' + AND account_analytic_line.invoice_id is null + GROUP BY account_analytic_account.id;"""%acc_set) + res = {} + for account_id, sum in cr.fetchall(): + res[account_id] = round(sum,2) + + # Montant des expense et facture d'achat : + acc_set = ",".join(map(str, ids2)) + cr.execute ("select account_analytic_line.account_id,sum(amount) from account_analytic_line join account_analytic_journal on account_analytic_line.journal_id = account_analytic_journal.id where account_analytic_line.account_id IN (%s) and (account_analytic_journal.type = 'purchase' OR lower(account_analytic_journal.name) like 'expense%%') GROUP BY account_analytic_line.account_id;"%acc_set) + res2 = {} + for account_id, sum in cr.fetchall(): + res2[account_id] = round(sum,2) + # sum both result on account_id + for id in ids: + res[id] = round(res.get(id, 0.0),2) + round(res2.get(id, 0.0),2) + return res + # OK !!!! + def _hours_qtt_non_invoiced_calc (self, cr, uid, ids, name, arg, context={}): + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + acc_set = ",".join(map(str, ids2)) + cr.execute("select account_analytic_line.account_id,sum(unit_amount) from account_analytic_line join account_analytic_journal on account_analytic_line.journal_id = account_analytic_journal.id where account_analytic_line.account_id IN (%s) and account_analytic_journal.type='general' and invoice_id is null GROUP BY account_analytic_line.account_id;"%acc_set) + res = {} + for account_id, sum in cr.fetchall(): + res[account_id] = round(sum,2) + for id in ids: + res[id] = round(res.get(id, 0.0),2) + return res + + # OK !!!! + def _hours_quantity_calc(self, cr, uid, ids, name, arg, context={}): + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + acc_set = ",".join(map(str, ids2)) + cr.execute("select account_analytic_line.account_id,sum(unit_amount) from account_analytic_line join account_analytic_journal on account_analytic_line.journal_id = account_analytic_journal.id where account_analytic_line.account_id IN (%s) and account_analytic_journal.type='general' GROUP BY account_analytic_line.account_id"%acc_set) + res = {} + for account_id, sum in cr.fetchall(): + res[account_id] = round(sum,2) + for id in ids: + res[id] = round(res.get(id, 0.0),2) + return res + + + # OK !!! + def _total_cost_calc(self, cr, uid, ids, name, arg, context={}): + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + acc_set = ",".join(map(str, ids2)) + cr.execute("""select + account_analytic_line.account_id,sum(amount) + from + account_analytic_line join account_analytic_journal on account_analytic_line.journal_id = account_analytic_journal.id + where + account_analytic_line.account_id IN (%s) and amount<0 + GROUP BY + account_analytic_line.account_id"""%acc_set) + res = {} + for account_id, sum in cr.fetchall(): + res[account_id] = round(sum,2) + for id in ids: + res[id] = round(res.get(id, 0.0),2) + return res + # OK !!! + def _ca_theorical_calc(self, cr, uid, ids, name, arg, context={}): + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + acc_set = ",".join(map(str, ids2)) + # First part with expense and purchase + cr.execute("""select + account_analytic_line.account_id,sum(amount) + from + account_analytic_line join account_analytic_journal on account_analytic_line.journal_id = account_analytic_journal.id + where + account_analytic_line.account_id IN (%s) and (lower(account_analytic_journal.name) like 'expense%%' or account_analytic_journal.type like 'purchase') + GROUP BY + account_analytic_line.account_id"""%acc_set) + res = {} + for account_id, sum in cr.fetchall(): + res[account_id] = round(sum,2) + # Second part with timesheet (with invoice factor) + acc_set = ",".join(map(str, ids2)) + cr.execute(""" + select + account_analytic_line.account_id as account_id,sum((account_analytic_line.unit_amount * pt.list_price)-(account_analytic_line.unit_amount * pt.list_price*hr.factor)) as somme + from + account_analytic_line join account_analytic_journal on account_analytic_line.journal_id = account_analytic_journal.id + join product_product pp on (account_analytic_line.product_id = pp.id) + join product_template pt on (pp.product_tmpl_id = pt.id) + join account_analytic_account a on (a.id=account_analytic_line.account_id) + join hr_timesheet_invoice_factor hr on (hr.id=a.to_invoice) + where + account_analytic_line.account_id IN (%s) and account_analytic_journal.type='general' and a.to_invoice IS NOT NULL + GROUP BY + account_analytic_line.account_id"""%acc_set) + res2 = {} + for account_id, sum in cr.fetchall(): + res2[account_id] = round(sum,2) + # sum both result on account_id + for id in ids: + res[id] = round(res.get(id, 0.0),2) + round(res2.get(id, 0.0),2) + return res + + # OK !!! + def _last_worked_date_calc (self, cr, uid, ids, name, arg, context={}): + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + acc_set = ",".join(map(str, ids2)) + cr.execute("select account_analytic_line.account_id, max(date) from account_analytic_line where account_id IN (%s) and invoice_id is null GROUP BY account_analytic_line.account_id;"%acc_set) + res = {} + for account_id, sum in cr.fetchall(): + res[account_id] = sum + for id in ids: + res[id] = res.get(id, '') + return res + + # OK !!! + def _last_invoice_date_calc (self, cr, uid, ids, name, arg, context={}): + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + acc_set = ",".join(map(str, ids2)) + cr.execute ("select account_analytic_line.account_id,date(max(account_invoice.date_invoice)) from account_analytic_line join account_invoice on account_analytic_line.invoice_id = account_invoice.id where account_analytic_line.account_id IN (%s) and account_analytic_line.invoice_id is not null GROUP BY account_analytic_line.account_id"%acc_set) + res = {} + for account_id, sum in cr.fetchall(): + res[account_id] = sum + for id in ids: + res[id] = res.get(id, '') + return res + + # OK !!! + def _last_worked_invoiced_date_calc (self, cr, uid, ids, name, arg, context={}): + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + acc_set = ",".join(map(str, ids2)) + cr.execute("select account_analytic_line.account_id, max(date) from account_analytic_line where account_id IN (%s) and invoice_id is not null GROUP BY account_analytic_line.account_id;"%acc_set) + res = {} + for account_id, sum in cr.fetchall(): + res[account_id] = sum + for id in ids: + res[id] = res.get(id, '') + return res + + def _remaining_hours_calc(self, cr, uid, ids, name, arg, context={}): + res = {} + for account in self.browse(cr, uid, ids): + if account.quantity_max <> 0: + res[account.id] = account.quantity_max - account.hours_quantity + else: + res[account.id]=0.0 + for id in ids: + res[id] = round(res.get(id, 0.0),2) + return res + def _hours_qtt_invoiced_calc(self, cr, uid, ids, name, arg, context={}): + res = {} + for account in self.browse(cr, uid, ids): + res[account.id] = account.hours_quantity - account.hours_qtt_non_invoiced + if res[account.id] < 0: + res[account.id]=0.0 + for id in ids: + res[id] = round(res.get(id, 0.0),2) + return res + def _revenue_per_hour_calc(self, cr, uid, ids, name, arg, context={}): + res = {} + for account in self.browse(cr, uid, ids): + if account.hours_qtt_invoiced == 0: + res[account.id]=0.0 + else: + res[account.id] = account.ca_invoiced / account.hours_qtt_invoiced + for id in ids: + res[id] = round(res.get(id, 0.0),2) + return res + def _real_margin_rate_calc(self, cr, uid, ids, name, arg, context={}): + res = {} + for account in self.browse(cr, uid, ids): + if account.ca_invoiced == 0: + res[account.id]=0.0 + else: + res[account.id] = (account.real_margin / account.ca_invoiced) * 100 + for id in ids: + res[id] = round(res.get(id, 0.0),2) + return res + def _remaining_ca_calc(self, cr, uid, ids, name, arg, context={}): + res = {} + for account in self.browse(cr, uid, ids): + if account.amount_max <> 0: + res[account.id] = account.amount_max - account.ca_invoiced + else: + res[account.id]=0.0 + for id in ids: + res[id] = round(res.get(id, 0.0),2) + return res + def _real_margin_calc(self, cr, uid, ids, name, arg, context={}): + res = {} + for account in self.browse(cr, uid, ids): + res[account.id] = account.ca_invoiced + account.total_cost + for id in ids: + res[id] = round(res.get(id, 0.0),2) + return res + def _theorical_margin_calc(self, cr, uid, ids, name, arg, context={}): + res = {} + for account in self.browse(cr, uid, ids): + res[account.id] = account.ca_theorical + account.total_cost + for id in ids: + res[id] = round(res.get(id, 0.0),2) + return res + + _columns ={ + 'ca_invoiced': fields.function(_ca_invoiced_calc, method=True, type='float', string='Invoiced amount'), + 'total_cost': fields.function(_total_cost_calc, method=True, type='float', string='Total cost'), + 'ca_to_invoice': fields.function(_ca_to_invoice_calc, method=True, type='float', string='Uninvoiced amount'), + 'ca_theorical': fields.function(_ca_theorical_calc, method=True, type='float', string='Theorical revenue'), + 'hours_quantity': fields.function(_hours_quantity_calc, method=True, type='float', string='Hours tot'), + 'last_invoice_date': fields.function(_last_invoice_date_calc, method=True, type='date', string='Last invoice date'), + 'last_worked_invoiced_date': fields.function(_last_worked_invoiced_date_calc, method=True, type='date', string='Last invoiced worked date'), + 'last_worked_date': fields.function(_last_worked_date_calc, method=True, type='date', string='Last worked date'), + 'hours_qtt_non_invoiced': fields.function(_hours_qtt_non_invoiced_calc, method=True, type='float', string='Uninvoiced hours'), + 'hours_qtt_invoiced': fields.function(_hours_qtt_invoiced_calc, method=True, type='float', string='Invoiced hours'), + 'remaining_hours': fields.function(_remaining_hours_calc, method=True, type='float', string='Remaining hours'), + 'remaining_ca': fields.function(_remaining_ca_calc, method=True, type='float', string='Remaining revenue'), + 'revenue_per_hour': fields.function(_revenue_per_hour_calc, method=True, type='float', string='Revenue per hours (real)'), + 'real_margin': fields.function(_real_margin_calc, method=True, type='float', string='Real margin'), + 'theorical_margin': fields.function(_theorical_margin_calc, method=True, type='float', string='Theorical margin'), + 'real_margin_rate': fields.function(_real_margin_rate_calc, method=True, type='float', string='Real margin rate (%)'), + 'month_ids': fields.one2many('account_analytic_analysis.summary.month', 'account_id', 'Month', readonly=True), + 'user_ids': fields.one2many('account_analytic_analysis.summary.user', 'account_id', 'User', readonly=True), + } +account_analytic_account() + +class account_analytic_account_summary_user(osv.osv): + _name = "account_analytic_analysis.summary.user" + _description = "Hours summary by user" + _order='name' + _auto = False + _columns = { + 'account_id': fields.many2one('account.analytic.account', 'Analytic Account', readonly=True), + 'unit_amount': fields.float('Total Time', digits=(16,2), readonly=True), + 'name' : fields.many2one('res.users','User'), + } + def init(self, cr): + cr.execute(""" + create or replace view account_analytic_analysis_summary_user as ( + select + id, + unit_amount, + account_id, + name from ( + select + min(account_analytic_line.id) as id, + user_id as name, + account_id, + sum(unit_amount) as unit_amount + from + account_analytic_line + join + account_analytic_journal on account_analytic_line.journal_id = account_analytic_journal.id + where + account_analytic_journal.type = 'general' + group by + account_id, user_id + order by + user_id,account_id asc )as + sous_account_analytic_analysis_summary_user + order by + name,account_id)""") +account_analytic_account_summary_user() + +class account_analytic_account_summary_month(osv.osv): + _name = "account_analytic_analysis.summary.month" + _description = "Hours summary by month" + _auto = False + _columns = { + 'account_id': fields.many2one('account.analytic.account', 'Analytic Account', readonly=True), + 'unit_amount': fields.float('Total Time', digits=(16,2), readonly=True), + 'name': fields.char('Month', size=25, readonly=True), + } + def init(self, cr): + cr.execute("""create or replace view account_analytic_analysis_summary_month as ( + select id, unit_amount,account_id, sort_month,month as name from ( + select + min(account_analytic_line.id) as id, + date_trunc('month', date) as sort_month, + account_id, + to_char(date,'Mon YYYY') as month, + sum(unit_amount) as unit_amount + from + account_analytic_line join account_analytic_journal on account_analytic_line.journal_id = account_analytic_journal.id + where + account_analytic_journal.type = 'general' + group by + sort_month, month, account_id + order by + sort_month,account_id asc + )as sous_account_analytic_analysis_summary_month order by sort_month,account_id)""") + +account_analytic_account_summary_month() + +class analytic_account_category(osv.osv): + def _check_recursion(self, cr, uid, ids): + level = 100 + while len(ids): + cr.execute('select distinct parent_id from account_analytic_account_category where id in ('+','.join(map(str,ids))+')') + ids = filter(None, map(lambda x:x[0], cr.fetchall())) + if not level: + return False + level -= 1 + return True + def name_get(self, cr, uid, ids, context={}): + if not len(ids): + return [] + reads = self.read(cr, uid, ids, ['name','parent_id'], context) + res = [] + for record in reads: + name = record['name'] + if record['parent_id']: + name = record['parent_id'][1]+' / '+name + res.append((record['id'], name)) + return res + def _name_get_fnc(self, cr, uid, ids, prop, unknow_none, unknow_dict): + res = self.name_get(cr, uid, ids) + return dict(res) + _name = "account.analytic.account.category" + _columns ={ + 'name': fields.char('Category Name', required=True, size=64), + 'parent_id': fields.many2one('account.analytic.account.category', 'Parent Category', select=True), + 'complete_name': fields.function(_name_get_fnc, method=True, type="char", string='Name'), + 'child_ids': fields.one2many('account.analytic.account.category', 'parent_id', 'Childs Category'), + 'active' : fields.boolean('Active'), + } + _constraints = [ + (_check_recursion, 'Error ! You can not create recursive categories.', ['parent_id']) + ] + _defaults = { + 'active' : lambda *a: 1, + } +analytic_account_category() + + diff --git a/addons/account_analytic_analysis/account_analytic_analysis_menu.xml b/addons/account_analytic_analysis/account_analytic_analysis_menu.xml new file mode 100644 index 00000000000..7b39bb709f1 --- /dev/null +++ b/addons/account_analytic_analysis/account_analytic_analysis_menu.xml @@ -0,0 +1,124 @@ + + + #--------------------------------------------------------------------------------------------------------- + # Definition Action + #--------------------------------------------------------------------------------------------------------- + + + + My managed projects + account.analytic.account + form + [('user_id','=',uid)] + + + + + + My open managed projects + account.analytic.account + form + [('user_id','=',uid),('state','=','open')] + + + + + My pending managed projects + account.analytic.account + form + [('user_id','=',uid),('state','=','pending')] + + + + + + + Overpassed projects + account.analytic.account + form + [('date','<=',time.strftime('%Y-%m-%d')),('state','=','open')] + + + + + + + All analytic projects + account.analytic.account + form + + [] + + + + + + + + Draft analytic projects + account.analytic.account + form + + [('state','=','draft')] + + + + + + Open analytic projects + account.analytic.account + form + + [('state','=','open')] + + + + + Pending analytic projects + account.analytic.account + form + + [('state','=','pending')] + + + + + + Simplified view analytic projects + account.analytic.account + form + + [] + + + + + + diff --git a/addons/account_analytic_analysis/account_analytic_analysis_view.xml b/addons/account_analytic_analysis/account_analytic_analysis_view.xml new file mode 100644 index 00000000000..e0147f2e31e --- /dev/null +++ b/addons/account_analytic_analysis/account_analytic_analysis_view.xml @@ -0,0 +1,113 @@ + + + + #--------------------------------------------------------------------------------------------------------- + # Analytic Account form + #--------------------------------------------------------------------------------------------------------- + + # Remove information on Account data => because they move on analysis sheet + # -------------------------------------------------------------------------- + # create a page with invoicing informations + # -------------------------------------------------------------------------- + + account.analytic.account.invoice.form.inherit + account.analytic.account + form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #--------------------------------------------------------------------------------------------------------- + # Add information on Account analytic list for the project management + #--------------------------------------------------------------------------------------------------------- + + account.analytic.account.tree + account.analytic.account + + tree + + + + + + + + + account.analytic.account.tree + account.analytic.account + + tree + + + + + + + + + + + account.analytic.account.simplified.tree + account.analytic.account + tree + + + + + + + + + + + + + + + diff --git a/addons/base_setup/wizard/wizard_base_setup.py b/addons/base_setup/wizard/wizard_base_setup.py index a12487fd3b5..ed51c509d38 100644 --- a/addons/base_setup/wizard/wizard_base_setup.py +++ b/addons/base_setup/wizard/wizard_base_setup.py @@ -64,7 +64,7 @@ view_form_company = """ - + @@ -76,9 +76,9 @@ view_form_company = """ - - - + + + """ diff --git a/addons/board_project/__terp__.py b/addons/board_project/__terp__.py index ee1495372c1..a73163fbd2e 100644 --- a/addons/board_project/__terp__.py +++ b/addons/board_project/__terp__.py @@ -5,7 +5,7 @@ "category":"Board", "depends":["project","report_timesheet","board","report_analytic_line"], "demo_xml":["board_project_demo.xml"], - "update_xml":["board_project_view.xml"], + "update_xml":["board_project_view.xml", "board_project_manager_view.xml"], "description": """ This module implements a dashboard for project member that includes: * List of my open tasks diff --git a/addons/board_project/board_project_manager_view.xml b/addons/board_project/board_project_manager_view.xml index ba34b0d9961..c39865efef2 100644 --- a/addons/board_project/board_project_manager_view.xml +++ b/addons/board_project/board_project_manager_view.xml @@ -6,84 +6,57 @@ Project managers - - project.task.tree - project.task - tree - - - - - - - - - - - - - - My open tasks - project.task - form - tree,graph - [('user_id','=',uid),('state','=','open')] - - - - My task's deadlines - project.task - form - tree,graph - [('user_id','=',uid),('state','=','open'),('date_deadline','<>',False)] - - + # + # Board for project managers + # + - - Public notes - board.note - form - tree - [('type','=','Project')] - + - - board.project.form + + + board.project.manager.form board.board form -
+ - - + -