New module:

account_analytic_analysis: stats on analytic accounts
Dashboards for projects:
	Project member
	Project manager

bzr revid: fp@tinyerp.com-d809ba846377547fc784c8b3a3e99b7549249a3c
This commit is contained in:
Fabien Pinckaers 2007-05-30 20:22:11 +00:00
parent 20fbfdd27d
commit 070458069b
12 changed files with 750 additions and 86 deletions

View File

@ -9,10 +9,8 @@
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<tree string="Analytic Account" colors="red:date and (date&lt;=current_date); red:quantity_max and (quantity_max&gt;quantity)">
<!--<tree string="Analytic Account" colors="red:date and (date&lt;=current_date)">-->
<field name="code" />
<field name="complete_name"/>
<field name="partner_id" />
<field name="quantity" />
<field name="quantity_max" />
<field name="date" />
@ -29,7 +27,6 @@
<tree string="Analytic Account" colors="red:date and (date&lt;=current_date); red:quantity_max and (quantity_max&gt;quantity)">
<field name="name"/>
<field name="code"/>
<field name="partner_id" />
<field name="date" />
<field name="company_currency_id"/>
<field name="debit" />
@ -53,7 +50,7 @@
<field name="code" select="1"/>
<field name="parent_id" on_change="on_change_parent(parent_id)" />
<field name="company_id" select="2"/>
<field name="type" select="1" />
<field name="type" select="2" />
<field name="partner_id" select="1"/>
<newline/>
<field name="date_start" />
@ -105,7 +102,7 @@
<field name="amount" select="2"/>
<field name="date" select="1"/>
<field name="account_id" select="1"/>
<field name="journal_id" select="1"/>
<field name="journal_id" select="2"/>
<field name="general_account_id" select="2"/>
<field name="move_id" select="2"/>
<field name="unit_amount" select="2"/>
@ -206,8 +203,8 @@
<form string="Analytic Journal">
<field name="name" select="1"/>
<field name="code" select="1"/>
<field name="type" select="1" />
<field name="active" select="1" />
<field name="type" select="2" />
<field name="active" select="2" />
</form>
</field>
</record>

View File

@ -0,0 +1,29 @@
##############################################################################
#
# Copyright (c) 2004 TINY SPRL. (http://tiny.be) All Rights Reserved.
# Fabien Pinckaers <fp@tiny.Be>
#
# 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

View File

@ -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
}

View File

@ -0,0 +1,389 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2004 TINY SPRL. (http://tiny.be) All Rights Reserved.
# Fabien Pinckaers <fp@tiny.Be>
#
# 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()

View File

@ -0,0 +1,124 @@
<terp>
<data>
#---------------------------------------------------------------------------------------------------------
# Definition Action
#---------------------------------------------------------------------------------------------------------
<record model="ir.actions.act_window" id="action_account_analytic_managed">
<field name="name">My managed projects</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="domain">[('user_id','=',uid)]</field>
</record>
<menuitem
name="Project/Analytic projects/My managed projects"
id="menu_analytic_account_managed"
action="action_account_analytic_managed" />
<record model="ir.actions.act_window" id="action_account_analytic_managed_open">
<field name="name">My open managed projects</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="domain">[('user_id','=',uid),('state','=','open')]</field>
</record>
<menuitem
name="Project/Analytic projects/My managed projects/"
id="menu_analytic_account_to_valid_open"
action="action_account_analytic_managed_open" />
<record model="ir.actions.act_window" id="action_account_analytic_managed_pending">
<field name="name">My pending managed projects</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="domain">[('user_id','=',uid),('state','=','pending')]</field>
</record>
<menuitem
name="Project/Analytic projects/My managed projects/"
id="menu_analytic_account_to_valid_pending"
action="action_account_analytic_managed_pending" />
<record model="ir.actions.act_window" id="action_account_analytic_managed_overpassed">
<field name="name">Overpassed projects</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="domain">[('date','&lt;=',time.strftime('%Y-%m-%d')),('state','=','open')]</field>
</record>
<menuitem
name="Project/Analytic projects/Overpassed projects"
id="menu_action_account_analytic_managed_overpassed"
action="action_account_analytic_managed_overpassed" />
<record model="ir.actions.act_window" id="action_account_analytic_all">
<field name="name">All analytic projects</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="view_id" ref="account.view_account_analytic_account_list"/>
<field name="domain">[]</field>
</record>
<menuitem
name="Project/Analytic projects/"
id="menu_action_account_analytic_all"
action="action_account_analytic_all" />
<record model="ir.actions.act_window" id="action_account_analytic_all_draft">
<field name="name">Draft analytic projects</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="view_id" ref="account.view_account_analytic_account_list"/>
<field name="domain">[('state','=','draft')]</field>
</record>
<menuitem
name="Project/Analytic projects/All analytic projects/"
id="menu_action_account_analytic_all_draft"
action="action_account_analytic_all_draft" />
<record model="ir.actions.act_window" id="action_account_analytic_all_open">
<field name="name">Open analytic projects</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="view_id" ref="account.view_account_analytic_account_list"/>
<field name="domain">[('state','=','open')]</field>
</record>
<menuitem
name="Project/Analytic projects/All analytic projects/"
id="menu_action_account_analytic_all_open"
action="action_account_analytic_all_open" />
<record model="ir.actions.act_window" id="action_account_analytic_all_pending">
<field name="name">Pending analytic projects</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="view_id" ref="account.view_account_analytic_account_list"/>
<field name="domain">[('state','=','pending')]</field>
</record>
<menuitem
name="Project/Analytic projects/All analytic projects/"
id="menu_action_account_analytic_all_pending"
action="action_account_analytic_all_pending" />
<record model="ir.actions.act_window" id="action_account_analytic_all_simplified">
<field name="name">Simplified view analytic projects</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="view_id" ref="view_account_analytic_simplified"/>
<field name="domain">[]</field>
</record>
<menuitem
name="Project/Analytic projects/All analytic projects/"
id="menu_action_account_analytic_all_simplified"
action="action_account_analytic_all_simplified" />
</data>
</terp>

View File

@ -0,0 +1,113 @@
<terp>
<data>
#---------------------------------------------------------------------------------------------------------
# Analytic Account form
#---------------------------------------------------------------------------------------------------------
# Remove information on Account data => because they move on analysis sheet
# --------------------------------------------------------------------------
# create a page with invoicing informations
# --------------------------------------------------------------------------
<record model="ir.ui.view" id="hr_timesheet.account_analytic_account_form_form">
<field name="name">account.analytic.account.invoice.form.inherit</field>
<field name="model">account.analytic.account</field>
<field name="type">form</field>
<field name="inherit_id" ref="account.view_account_analytic_account_form" />
<field name="priority" eval="18"/>
<field name="arch" type="xml">
<notebook position="inside">
<page string="Analysys summary">
<separator string="Work done stats" colspan="4" />
<field name="total_cost"/>
<field name="remaining_ca"/>
<field name="ca_invoiced"/>
<field name="ca_theorical"/>
<newline/>
<!-- <field name="old"/> -->
<field name="hours_quantity"/>
<field name="hours_qtt_invoiced"/>
<field name="remaining_hours"/>
<newline/>
<separator string="Analysis stats" colspan="4" />
<field name="revenue_per_hour"/>
<field name="real_margin"/>
<field name="theorical_margin"/>
<field name="real_margin_rate"/>
<separator string="Key dates" colspan="4" />
<field name="last_invoice_date"/>
<field name="last_worked_invoiced_date" select="1"/>
<field name="last_worked_date"/>
<separator string="To be invoiced" colspan="4" />
<field name="hours_qtt_non_invoiced"/>
<field name="ca_to_invoice" select="1"/>
</page>
<page string="Stats by month">
<field name="month_ids" colspan="4" nolabel="1">
<tree string="Month">
<field name="name"/>
<field name="unit_amount" widget="float_time"/>
</tree>
</field>
</page>
<page string="Stats by user">
<field name="user_ids" colspan="4" nolabel="1">
<tree string="User">
<field name="name"/>
<field name="unit_amount" widget="float_time"/>
</tree>
</field>
</page>
</notebook>
</field>
</record>
#---------------------------------------------------------------------------------------------------------
# Add information on Account analytic list for the project management
#---------------------------------------------------------------------------------------------------------
<record model="ir.ui.view" id="view_account_analytic_account_tree_c2c_2">
<field name="name">account.analytic.account.tree</field>
<field name="model">account.analytic.account</field>
<field name="inherit_id" ref="account.view_account_analytic_account_list" />
<field name="type">tree</field>
<field name="arch" type="xml">
<field name="quantity" position="replace">
<field name="hours_quantity"/>
<field name="hours_qtt_non_invoiced"/>
</field>
</field>
</record>
<record model="ir.ui.view" id="view_account_analytic_account_tree_c2c_3">
<field name="name">account.analytic.account.tree</field>
<field name="model">account.analytic.account</field>
<field name="inherit_id" ref="account.view_account_analytic_account_list" />
<field name="type">tree</field>
<field name="arch" type="xml">
<field name="date" position="before">
<field name="last_invoice_date"/>
<field name="ca_to_invoice"/>
</field>
</field>
</record>
<record model="ir.ui.view" id="view_account_analytic_simplified">
<field name="name">account.analytic.account.simplified.tree</field>
<field name="model">account.analytic.account</field>
<field name="type">tree</field>
<field name="priority" eval="5"/>
<field name="arch" type="xml">
<tree string="Analytic accounts">
<field name="code"/>
<field name="name"/>
<field name="hours_qtt_non_invoiced"/>
<field name="remaining_hours"/>
<field name="ca_to_invoice"/>
<field name="last_invoice_date"/>
</tree>
</field>
</record>
</data>
</terp>

View File

@ -64,7 +64,7 @@ view_form_company = """<?xml version="1.0"?>
<group>
<separator string="Define main company" colspan="4"/>
<newline/>
<field name="name" align="0.0" colspan="3" required="True"/>
<field name="name" align="0.0" colspan="4" required="True"/>
<newline/>
<field name="street" align="0.0"/>
<field name="street2" align="0.0"/>
@ -76,9 +76,9 @@ view_form_company = """<?xml version="1.0"?>
<field name="phone" align="0.0"/>
<separator string="Report header" colspan="4"/>
<newline/>
<field name="rml_header1" align="0.0" colspan="3"/>
<field name="rml_footer1" align="0.0" colspan="3"/>
<field name="rml_footer2" align="0.0" colspan="3"/>
<field name="rml_header1" align="0.0" colspan="4"/>
<field name="rml_footer1" align="0.0" colspan="4"/>
<field name="rml_footer2" align="0.0" colspan="4"/>
</group>
</form>"""

View File

@ -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

View File

@ -6,84 +6,57 @@
<field name="name">Project managers</field>
</record>
<record model="ir.ui.view" id="view_task_tree">
<field name="name">project.task.tree</field>
<field name="model">project.task</field>
<field name="type">tree</field>
<field name="priority" eval="99"/>
<field name="arch" type="xml">
<tree string="My tasks" colors="red:date_deadline&lt;current_date;blue:date_deadline==current_date">
<field name="name"/>
<field name="project_id"/>
<field name="date_deadline"/>
<field name="planned_hours"/>
<field name="effective_hours"/>
<field name="priority"/>
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_view_task_tree">
<field name="name">My open tasks</field>
<field name="res_model">project.task</field>
<field name="view_type">form</field>
<field name="view_mode">tree,graph</field>
<field name="domain">[('user_id','=',uid),('state','=','open')]</field>
<field name="view_id" ref="view_task_tree" />
</record>
<record model="ir.actions.act_window" id="action_view_task_tree_deadline">
<field name="name">My task's deadlines</field>
<field name="res_model">project.task</field>
<field name="view_type">form</field>
<field name="view_mode">tree,graph</field>
<field name="domain">[('user_id','=',uid),('state','=','open'),('date_deadline','&lt;&gt;',False)]</field>
<field name="view_id" ref="view_task_tree" />
</record>
#
# Board for project managers
#
<act_window name="My projects"
domain="[('manager', '=', uid)]"
res_model="project.project"
src_model="res.users"
view_type="form"
view_mode="tree,form"
id="act_my_project"/>
<record model="ir.actions.act_window" id="action_view_board_note_tree">
<field name="name">Public notes</field>
<field name="res_model">board.note</field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="domain">[('type','=','Project')]</field>
</record>
<act_window name="My accounts to invoice"
domain="[('user_id', '=', uid)]"
res_model="account.analytic.account"
src_model="res.users"
view_type="form"
view_mode="tree,form"
view_id="view_account_analytic_simplified"
id="act_my_account"/>
<record model="ir.ui.view" id="board_project_form">
<field name="name">board.project.form</field>
<record model="ir.ui.view" id="board_project_manager_form">
<field name="name">board.project.manager.form</field>
<field name="model">board.board</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Project">
<form string="Project manager board">
<hpaned>
<child1>
<action
string="My open tasks"
name="%(action_view_task_tree)d"
string="My projects"
name="%(act_my_project)d"
colspan="4"
height="220"
width="510"/>
<action
string="My deadlines"
name="%(action_view_task_tree_deadline)d"
string="My accounts to invoice"
name="%(act_my_account)d"
height="150"
colspan="4"/>
<!--
<action
string="Public notes"
string="Last 20 tasks closed"
name="%(action_view_board_note_tree)d"
colspan="2"
colspan="4"
height="150"/>
<action
string="Public notes"
name="%(action_view_board_note_tree)d"
colspan="2"
height="150"/>
-->
</child1>
<child2>
<button
string="Menu"
@ -93,35 +66,38 @@
colspan="4"/>
<action
string="My timesheet"
name="%(report_timesheet.action_timesheet_user_stat)d"
string="My user's work"
name="%(report_analytic_line.action_account_analytic_planning_stat_my_manager_form)d"
colspan="4"/>
<action
string="My work"
name="%(report_analytic_line.action_account_analytic_planning_stat_my_form)d"
string="My timesheet"
name="%(report_timesheet.action_timesheet_user_stat_my)d"
colspan="4"/>
</child2>
</hpaned>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="open_board_sales_manager">
<field name="name">Dashboard project member</field>
<record model="ir.actions.act_window" id="open_board_project_manager">
<field name="name">Project manager board</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_project_form"/>
<field name="view_id" ref="board_project_manager_form"/>
</record>
<menuitem
name="Dashboards/Project member"
action="open_board_sales_manager"
name="Dashboards/Projects/Project manager"
action="open_board_project_manager"
sequence="1"
id="menu_board_sales_manager"/>
id="menu_board_project_manager"/>
</data>
</terp>

View File

@ -2,7 +2,7 @@
<terp>
<data>
<record model="board.note.type" id="note_project_type">
<record model="board.note.type" id="note_project_manager_type">
<field name="name">Project</field>
</record>
@ -52,7 +52,7 @@
<field name="model">board.board</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Project">
<form string="My board">
<hpaned>
<child1>
@ -87,7 +87,7 @@
colspan="4"/>
<action
string="My work"
string="My planning"
name="%(report_analytic_line.action_account_analytic_planning_stat_my_form)d"
colspan="4"/>
@ -103,7 +103,7 @@
</record>
<record model="ir.actions.act_window" id="open_board_project">
<field name="name">Dashboard project member</field>
<field name="name">Project board</field>
<field name="res_model">board.board</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
@ -112,7 +112,7 @@
</record>
<menuitem
name="Dashboards/Project member"
name="Dashboards/Projects/Project member"
action="open_board_project"
sequence="1"
id="menu_board_project"/>

View File

@ -130,6 +130,7 @@ class report_account_analytic_planning_stat(osv.osv):
_columns = {
'planning_id': fields.many2one('report_account_analytic.planning', 'Planning'),
'user_id': fields.many2one('res.users', 'User', required=True),
'manager_id': fields.many2one('res.users', 'Manager'),
'account_id': fields.many2one('account.analytic.account', 'Account', required=True),
'sum_amount': fields.float('Planned Work', required=True),
'sum_amount_real': fields.function(_sum_amount_real, method=True, string='Work made'),
@ -142,15 +143,18 @@ class report_account_analytic_planning_stat(osv.osv):
select
min(l.id) as id,
l.user_id as user_id,
a.user_id as manager_id,
l.account_id as account_id,
sum(l.amount*u.factor) as sum_amount,
l.planning_id
from
report_account_analytic_planning_line l
left join
account_analytic_account a on (a.id = l.account_id)
left join
product_uom u on (l.amount_unit = u.id)
group by
planning_id, user_id, account_id
l.planning_id, l.user_id, l.account_id, a.user_id
)
""")
report_account_analytic_planning_stat()

View File

@ -180,6 +180,18 @@
id="menu_report_account_analytic_planning_stat_my"
action="action_account_analytic_planning_stat_my_form" />
<record model="ir.actions.act_window" id="action_account_analytic_planning_stat_my_manager_form">
<field name="res_model">report_account_analytic.planning.stat</field>
<field name="view_type">form</field>
<field name="domain">[('manager_id','=',uid)]</field>
<field name="view_mode">graph,tree</field>
</record>
<menuitem
name="Human Resources/Reporting/Planning/Planning statistics of my projects"
id="menu_report_account_analytic_planning_stat_my_manager"
action="action_account_analytic_planning_stat_my_manager_form" />
</data>