[MERGE] account_analytic_analysis fixes

- fix search views
- fix contract reminder

bzr revid: al@openerp.com-20130215005023-lxmeckktnxlzhcxj
This commit is contained in:
Antony Lesuisse 2013-02-15 01:50:23 +01:00
commit b37e69799d
9 changed files with 233 additions and 217 deletions

View File

@ -18,6 +18,7 @@
<field name="parent_id" invisible="1"/>
<field name="state" invisible="1"/>
<field name="type" invisible="1"/>
<field name="template_id" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</field>

View File

@ -20,7 +20,6 @@
##############################################################################
import account_analytic_analysis
import cron_account_analytic_account
import res_config
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -38,7 +38,6 @@ Adds menu to show relevant information to each manager.You can also view the rep
'security/ir.model.access.csv',
'security/account_analytic_analysis_security.xml',
'account_analytic_analysis_view.xml',
'account_analytic_analysis_menu.xml',
'account_analytic_analysis_cron.xml',
'res_config_view.xml',
],

View File

@ -18,6 +18,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import datetime
import time
from openerp.osv import osv, fields
from openerp.osv.orm import intersect, except_orm
@ -484,7 +486,41 @@ class account_analytic_account(osv.osv):
res['value']['to_invoice'] = template.to_invoice.id
res['value']['pricelist_id'] = template.pricelist_id.id
return res
account_analytic_account()
def cron_account_analytic_account(self, cr, uid, context=None):
remind = {}
def fill_remind(key, domain, write_pending=False):
base_domain = [
('partner_id', '!=', False),
('manager_id', '!=', False),
('manager_id.email', '!=', False),
]
base_domain.extend(domain)
accounts_ids = self.search(cr, uid, base_domain, context=context, order='name asc')
accounts = self.browse(cr, uid, accounts_ids, context=context)
for account in accounts:
if write_pending:
account.write({'state' : 'pending'}, context=context)
remind_user = remind.setdefault(account.manager_id.id, {})
remind_type = remind_user.setdefault(key, {})
remind_partner = remind_type.setdefault(account.partner_id, []).append(account)
# Already expired
fill_remind("old", [('state', 'in', ['pending'])])
# Expires now
fill_remind("new", [('state', 'in', ['draft', 'open']), '|', '&', ('date', '!=', False), ('date', '<=', time.strftime('%Y-%m-%d')), ('is_overdue_quantity', '=', True)], True)
# Expires in less than 30 days
fill_remind("future", [('state', 'in', ['draft', 'open']), ('date', '!=', False), ('date', '<', (datetime.datetime.now() + datetime.timedelta(30)).strftime("%Y-%m-%d"))])
template_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_analytic_analysis', 'account_analytic_cron_email_template')[1]
for user_id, data in remind.items():
context["data"] = data
self.pool.get('email.template').send_mail(cr, uid, template_id, user_id, context=context)
return True
class account_analytic_account_summary_user(osv.osv):
_name = "account_analytic_analysis.summary.user"
@ -538,8 +574,6 @@ class account_analytic_account_summary_user(osv.osv):
lu.user_id as "user",
unit_amount
from lu, mu)''')
account_analytic_account_summary_user()
class account_analytic_account_summary_month(osv.osv):
_name = "account_analytic_analysis.summary.month"
@ -600,6 +634,4 @@ class account_analytic_account_summary_month(osv.osv):
'GROUP BY d.month, d.account_id ' \
')')
account_analytic_account_summary_month()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,15 +1,77 @@
<?xml version="1.0" encoding='UTF-8'?>
<openerp>
<data>
<record id="account_analytic_cron_email_template" model="email.template">
<field name="name">Contract expiration reminder</field>
<field name="email_from">${user.email or ''}</field>
<field name="subject">Contract expiration reminder ${user.company_id.name}</field>
<field name="email_to">${object.email}</field>
<field name="lang">${object.lang}</field>
<field name="model_id" ref="base.model_res_users"/>
<field name="auto_delete" eval="True"/>
<field name="body_html"><![CDATA[
Hello ${user.name},
% macro account_table(values):
<table cellspacing="1" border="1" cellpadding="4">
<tr>
<th>Customer</th>
<th>Contract</th>
<th>Dates</th>
<th>Prepaid Units</th>
<th>Contact</th>
</tr>
% for partner, accounts in values:
% for account in accounts:
<tr>
<td>${partner.name}</td>
<td>${account.name}</td>
<td>${account.date_start} to ${account.date and account.date or '???'}</td>
<td>
% if account.quantity_max != 0.0:
${account.quantity}/${account.quantity_max} hours
% endif
</td>
<td>${account.partner_id.phone or ''}, ${account.partner_id.email or ''}</td>
</tr>
% endfor
% endfor
</table>
% endmacro
% if "new" in ctx["data"]:
<h2>The following contracts just expired: </h2>
${account_table(ctx["data"]["new"].iteritems())}
% endif
% if "old" in ctx["data"]:
<h2>The following expired contracts are still not processed: </h2>
${account_table(ctx["data"]["old"].iteritems())}
% endif
% if "future" in ctx["data"]:
<h2>The following contracts will expire in less than one month: </h2>
${account_table(ctx["data"]["future"].iteritems())}
% endif
</pre>
]]></field>
</record>
<!--
-->
<record model="ir.cron" id="account_analytic_cron">
<field name="name">Analytic Account Report for Sales</field>
<field name="name">Contract expiration reminder</field>
<field name="interval_number">1</field>
<field name="interval_type">weeks</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall"/>
<field eval="'account.analytic.account'" name="model"/>
<field eval="'cron_account_analytic_account'" name="function"/>
<field eval="'()'" name="args"/>
<field name="doall" eval="False"/>
<field name="model" eval="'account.analytic.account'"/>
<field name="function" eval="'cron_account_analytic_account'"/>
<field name="args" eval="'()'" />
</record>
</data>
</openerp>

View File

@ -1,104 +0,0 @@
<openerp>
<data>
<menuitem id="base.menu_invoiced" name="Invoicing" parent="base.menu_base_partner" sequence="5"/>
<record id="action_hr_tree_invoiced_all" model="ir.actions.act_window">
<field name="name">Time &amp; Materials to Invoice</field>
<field name="res_model">account.analytic.line</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('invoice_id','=',False)]</field>
<field name="context">{'search_default_to_invoice': 1, 'search_default_sales': 1}</field>
<field name="search_view_id" ref="account.view_account_analytic_line_filter"/>
<field name="help" type="html">
<p>
You will find here timesheets and purchases you did for
contracts that can be reinvoiced to the customer. If you want
to record new activities to invoice, you should use the timesheet
menu instead.
</p>
</field>
</record>
<menuitem action="action_hr_tree_invoiced_all" id="menu_action_hr_tree_invoiced_all" parent="base.menu_invoiced" sequence="5"/>
<record id="view_account_analytic_account_overdue_search" model="ir.ui.view">
<field name="name">account.analytic.account.search</field>
<field name="model">account.analytic.account</field>
<field name="arch" type="xml">
<search string="Contracts">
<field name="name" filter_domain="['|', ('name','ilike',self),('code','ilike',self)]" string="Contract"/>
<field name="date"/>
<field name="partner_id"/>
<field name="manager_id"/>
<field name="parent_id"/>
<filter name="open" string="Open" domain="[('state','in',('open','draft'))]" help="Contracts in progress"/>
<filter name="pending" string="Pending" domain="[('state','=','pending')]" help="Pending contracts to renew with your customer"/>
<filter string="To Renew" domain="['|', '&amp;', ('date', '!=', False), ('date', '&lt;=', time.strftime('%%Y-%%m-%%d')), ('is_overdue_quantity', '=', True)]" name="renew"
help="The contracts to be renewed because the deadline is passed or the working hours are higher than the allocated hours" />
<separator/>
<filter string="Customer Contracts" help="Contracts assigned to a customer." name="has_partner" domain="[('partner_id', '!=', False)]"/>
<filter string="Contracts not assigned" help="Contracts that are not assigned to an account manager." domain="[('manager_id', '=', False)]"/>
<separator/>
<group expand="0" string="Group By...">
<filter string="Status" domain="[]" context="{'group_by':'state'}"/>
<filter string="Account Manager" domain="[]" context="{'group_by':'manager_id'}"/>
<filter string="Partner" domain="[]" context="{'group_by':'partner_id'}"/>
<filter string="Parent" domain="[]" context="{'group_by':'parent_id'}"/>
<filter string="Start Date" domain="[]" context="{'group_by' : 'date_start'}" />
<filter string="End Date" domain="[]" context="{'group_by' : 'date'}" />
</group>
</search>
</field>
</record>
<record id="action_account_analytic_overdue" model="ir.actions.act_window">
<field name="name">Contracts to Renew</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{'search_default_manager_id':uid, 'search_default_pending':1, 'search_default_renew':1}</field>
<field name="domain">[('type','=','contract')]</field>
<field name="search_view_id" ref="view_account_analytic_account_overdue_search"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to define a new contract.
</p><p>
You will find here the contracts to be renewed because the
end date is passed or the working effort is higher than the
maximum authorized one.
</p><p>
OpenERP automatically sets contracts to be renewed in a pending
state. After the negociation, the salesman should close or renew
pending contracts.
</p>
</field>
</record>
<menuitem action="action_account_analytic_overdue" id="menu_action_account_analytic_overdue" sequence="50" parent="base.menu_invoiced"/>
<record id="action_account_analytic_overdue_all" model="ir.actions.act_window">
<field name="name">Contracts</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{'default_type':'contract', 'search_default_open':1, 'search_default_pending':1, 'default_manager_id':uid}</field>
<field name="domain">[('type','=','contract')]</field>
<field name="search_view_id" ref="view_account_analytic_account_overdue_search"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new contract.
</p><p>
Use contracts to follow tasks, issues, timesheets or invoicing based on
work done, expenses and/or sales orders. OpenERP will automatically manage
the alerts for the renewal of the contracts to the right salesperson.
</p>
</field>
</record>
<menuitem id="base.menu_sales" name="Sales"
parent="base.menu_base_partner"
sequence="1"/>
<menuitem action="action_account_analytic_overdue_all" id="menu_action_account_analytic_overdue_all" sequence="7" parent="base.menu_sales"/>
</data>
</openerp>

View File

@ -1,17 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!--
Analytic Account form
-->
<record model="ir.actions.act_window" id="action_sales_order">
<field name="name">Sales Orders</field>
<field name="res_model">sale.order</field>
<field name="src_model">account.analytic.account</field>
</record>
<!-- Inherited Analytic Account form for contracts -->
<record id="account_analytic_account_form_form" model="ir.ui.view">
<field name="name">account.analytic.account.invoice.form.inherit</field>
<field name="model">account.analytic.account</field>
@ -142,19 +138,7 @@
</field>
</record>
<record id="view_account_analytic_account_tree_c2c_3" model="ir.ui.view">
<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="arch" type="xml">
<field name="date" position="before">
<field name="last_invoice_date"/>
<field name="toinvoice_total"/>
<field name="remaining_hours"/>
</field>
</field>
</record>
<!-- Inherited Analytic Account form for template required -->
<record id="view_account_analytic_account_template_required" model="ir.ui.view">
<field name="name">account.analytic.account.form.template.required</field>
<field name="model">account.analytic.account</field>
@ -167,6 +151,130 @@
</field>
</record>
<!-- Inherited Analytic Account list for contracts -->
<record id="view_account_analytic_account_tree_c2c_3" model="ir.ui.view">
<field name="name">account.analytic.account.list.contract</field>
<field name="model">account.analytic.account</field>
<field name="inherit_id" ref="account.view_account_analytic_account_list"/>
<field name="arch" type="xml">
<field name="date" position="before">
<field name="last_invoice_date"/>
<field name="toinvoice_total"/>
<field name="remaining_hours"/>
</field>
</field>
</record>
<!-- Analytic Account search view for contract -->
<record id="view_account_analytic_account_overdue_search" model="ir.ui.view">
<field name="name">account.analytic.account.search</field>
<field name="model">account.analytic.account</field>
<field name="arch" type="xml">
<search string="Contracts">
<field name="name" filter_domain="['|', ('name','ilike',self),('code','ilike',self)]" string="Contract"/>
<field name="date"/>
<field name="partner_id"/>
<field name="manager_id"/>
<field name="parent_id"/>
<filter name="open" string="In Progress" domain="[('state','in',('open','draft'))]" help="Contracts in progress (open, draft)"/>
<filter name="pending" string="To Renew" domain="[('state','=','pending')]" help="Pending contracts"/>
<filter name="closed" string="Closed" domain="[('state','=','pending')]" help="Closed contracts"/>
<filter name="cancelled" string="Cancelled" domain="[('state','=','cancel')]" help="Cancelled contracts"/>
<separator/>
<filter
string="Expired or consumed"
domain="[('state','in',('open','draft','pending')), '|', '&amp;', ('date', '!=', False), ('date', '&lt;=', time.strftime('%%Y-%%m-%%d')), ('is_overdue_quantity', '=', True)]"
help="End date passed or prepaid unit consumed" />
<filter
string="Expiring soon"
domain="[('date', '!=', False), ('date', '&lt;=', (context_today() + datetime.timedelta(30)).strftime('%%Y-%%m-%%d') )]"
help="End date is in the next month" />
<separator/>
<filter string="Customer Contracts" help="Contracts assigned to a customer." name="has_partner" domain="[('partner_id', '!=', False)]"/>
<filter string="Contracts not assigned" help="Contracts that are not assigned to an account manager." domain="[('manager_id', '=', False)]"/>
<separator/>
<group expand="0" string="Group By...">
<filter string="Status" domain="[]" context="{'group_by':'state'}"/>
<filter string="Account Manager" domain="[]" context="{'group_by':'manager_id'}"/>
<filter string="Partner" domain="[]" context="{'group_by':'partner_id'}"/>
<filter string="Parent" domain="[]" context="{'group_by':'parent_id'}"/>
<filter string="Template" domain="[]" context="{'group_by':'template_id'}"/>
<filter string="Start Date" domain="[]" context="{'group_by' : 'date_start'}" />
<filter string="End Date" domain="[]" context="{'group_by' : 'date'}" />
</group>
</search>
</field>
</record>
<!-- Action Sales/Sales/Contracts -->
<record id="action_account_analytic_overdue_all" model="ir.actions.act_window">
<field name="name">Contracts</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{'default_type':'contract', 'search_default_open':1, 'search_default_pending':1, 'default_manager_id':uid}</field>
<field name="domain">[('type','=','contract')]</field>
<field name="search_view_id" ref="view_account_analytic_account_overdue_search"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new contract.
</p><p>
Use contracts to follow tasks, issues, timesheets or invoicing based on
work done, expenses and/or sales orders. OpenERP will automatically manage
the alerts for the renewal of the contracts to the right salesperson.
</p>
</field>
</record>
<menuitem id="base.menu_sales" name="Sales" parent="base.menu_base_partner" sequence="1"/>
<menuitem action="action_account_analytic_overdue_all" id="menu_action_account_analytic_overdue_all" sequence="7" parent="base.menu_sales"/>
<!-- Action Sales/Invoicing/Time and Material to Invoice -->
<record id="action_hr_tree_invoiced_all" model="ir.actions.act_window">
<field name="name">Time &amp; Materials to Invoice</field>
<field name="res_model">account.analytic.line</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('invoice_id','=',False)]</field>
<field name="context">{'search_default_to_invoice': 1, 'search_default_sales': 1}</field>
<field name="search_view_id" ref="account.view_account_analytic_line_filter"/>
<field name="help" type="html">
<p>
You will find here timesheets and purchases you did for
contracts that can be reinvoiced to the customer. If you want
to record new activities to invoice, you should use the timesheet
menu instead.
</p>
</field>
</record>
<menuitem id="base.menu_invoiced" name="Invoicing" parent="base.menu_base_partner" sequence="5"/>
<menuitem action="action_hr_tree_invoiced_all" id="menu_action_hr_tree_invoiced_all" parent="base.menu_invoiced" sequence="5"/>
<!-- Action Sales/Invoicing/Contract to renew -->
<record id="action_account_analytic_overdue" model="ir.actions.act_window">
<field name="name">Contracts to Renew</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{'search_default_manager_id':uid, 'search_default_pending':1, 'search_default_renew':1}</field>
<field name="domain">[('type','=','contract')]</field>
<field name="search_view_id" ref="view_account_analytic_account_overdue_search"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to define a new contract.
</p><p>
You will find here the contracts to be renewed because the
end date is passed or the working effort is higher than the
maximum authorized one.
</p><p>
OpenERP automatically sets contracts to be renewed in a pending
state. After the negociation, the salesman should close or renew
pending contracts.
</p>
</field>
</record>
<menuitem action="action_account_analytic_overdue" id="menu_action_account_analytic_overdue" sequence="50" parent="base.menu_invoiced"/>
<!-- Action Sales/Configuration/Contract template -->
<record id="template_of_contract_action" model="ir.actions.act_window">
<field name="name">Contract Template</field>
<field name="type">ir.actions.act_window</field>
@ -184,8 +292,8 @@
terms and conditions of the contract.
</p>
</field>
</record>
<menuitem action="template_of_contract_action" id="menu_template_of_contract_action" parent="base.menu_base_config"/>
</data>
</openerp>

View File

@ -1,79 +0,0 @@
#!/usr/bin/env python
from mako.template import Template
import time
try:
import cStringIO as StringIO
except ImportError:
import StringIO
from openerp import tools
from openerp.osv import osv
MAKO_TEMPLATE = u"""Hello ${user.name},
Here is a list of contracts that have to be renewed for two
possible reasons:
- the end of contract date is passed
- the customer consumed more hours than expected
Can you contact the customer in order to sell a new or renew its contract.
The contract has been set with a pending state, can you update the status
of the analytic account following this rule:
- Set Done: if the customer does not want to renew
- Set Open: if the customer purchased an extra contract
Here is the list of contracts to renew:
% for partner, accounts in partners.iteritems():
* ${partner.name}
% for account in accounts:
- Name: ${account.name}
% if account.quantity_max != 0.0:
- Quantity: ${account.quantity}/${account.quantity_max} hours
% endif
- Dates: ${account.date_start} to ${account.date and account.date or '???'}
- Contacts:
${account.partner_id.name}, ${account.partner_id.phone or ''}, ${account.partner_id.email or ''}
% endfor
% endfor
You can use the report in the menu: Sales > Invoicing > Overdue Accounts
Regards,
--
OpenERP
"""
class analytic_account(osv.osv):
_inherit = 'account.analytic.account'
def cron_account_analytic_account(self, cr, uid, context=None):
domain = [
('name', 'not ilike', 'maintenance'),
('partner_id', '!=', False),
('user_id', '!=', False),
('user_id.email', '!=', False),
('state', 'in', ('draft', 'open')),
'|', ('date', '<', time.strftime('%Y-%m-%d')), ('date', '=', False),
]
account_ids = self.search(cr, uid, domain, context=context, order='name asc')
accounts = self.browse(cr, uid, account_ids, context=context)
users = dict()
for account in accounts:
users.setdefault(account.user_id, dict()).setdefault(account.partner_id, []).append(account)
account.write({'state' : 'pending'}, context=context)
for user, data in users.iteritems():
subject = '[OPENERP] Reporting: Analytic Accounts'
body = Template(MAKO_TEMPLATE).render_unicode(user=user, partners=data)
tools.email_send('noreply@openerp.com', [user.email, ], subject, body)
return True
analytic_account()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -196,7 +196,7 @@ class account_analytic_account(osv.osv):
'date_start': fields.date('Start Date'),
'date': fields.date('Date End', select=True),
'company_id': fields.many2one('res.company', 'Company', required=False), #not required because we want to allow different companies to use the same chart of account, except for leaf accounts.
'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'), ('cancelled', 'Cancelled'),('pending','To Renew'),('close','Closed')], 'Status', required=True, track_visibility='onchange'),
'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'),('pending','To Renew'),('close','Closed'),('cancelled', 'Cancelled')], 'Status', required=True, track_visibility='onchange'),
'currency_id': fields.function(_currency, fnct_inv=_set_company_currency, #the currency_id field is readonly except if it's a view account and if there is no company
store = {
'res.company': (_get_analytic_account, ['currency_id'], 10),
@ -349,6 +349,4 @@ class account_analytic_line(osv.osv):
(_check_no_view, 'You cannot create analytic line on view account.', ['account_id']),
]
account_analytic_line()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: