[IMP] project,project_issue,sale: display the current contract state on some various objects like issues or tasks.

Implements a dynamic widget for selection fields to display this state with color codes.
This commit is contained in:
Gaurav Panchal
2015-05-08 11:20:54 +02:00
committed by Richard Mathot
parent 42316d5aa5
commit 3fe06da634
12 changed files with 62 additions and 24 deletions
+10 -7
View File
@@ -28,6 +28,15 @@ from openerp.tools.translate import _
import openerp.addons.decimal_precision as dp import openerp.addons.decimal_precision as dp
from openerp.exceptions import UserError from openerp.exceptions import UserError
ANALYTIC_ACCOUNT_STATE = [
('template', 'Template'),
('draft','New'),
('open','In Progress'),
('pending','To Renew'),
('close','Closed'),
('cancelled', 'Cancelled')
]
class account_analytic_account(osv.osv): class account_analytic_account(osv.osv):
_name = 'account.analytic.account' _name = 'account.analytic.account'
_inherit = ['mail.thread'] _inherit = ['mail.thread']
@@ -191,13 +200,7 @@ class account_analytic_account(osv.osv):
'date_start': fields.date('Start Date'), 'date_start': fields.date('Start Date'),
'date': fields.date('Expiration Date', select=True, track_visibility='onchange'), 'date': fields.date('Expiration Date', select=True, track_visibility='onchange'),
'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. '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'), 'state': fields.selection(ANALYTIC_ACCOUNT_STATE, 'Status', required=True,
('draft','New'),
('open','In Progress'),
('pending','To Renew'),
('close','Closed'),
('cancelled', 'Cancelled')],
'Status', required=True,
track_visibility='onchange', copy=False), track_visibility='onchange', copy=False),
'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 '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 = { store = {
+1 -1
View File
@@ -630,7 +630,7 @@ class task(osv.osv):
project = self.pool.get('project.project').browse(cr, uid, project_id, context=context) project = self.pool.get('project.project').browse(cr, uid, project_id, context=context)
if project and project.partner_id: if project and project.partner_id:
return {'value': {'partner_id': project.partner_id.id}} return {'value': {'partner_id': project.partner_id.id}}
return {} return {'value': {'partner_id': False}}
def onchange_user_id(self, cr, uid, ids, user_id, context=None): def onchange_user_id(self, cr, uid, ids, user_id, context=None):
vals = {} vals = {}
+3 -4
View File
@@ -171,7 +171,7 @@ class project_issue(osv.Model):
project = self.pool.get('project.project').browse(cr, uid, project_id, context=context) project = self.pool.get('project.project').browse(cr, uid, project_id, context=context)
if project and project.partner_id: if project and project.partner_id:
return {'value': {'partner_id': project.partner_id.id}} return {'value': {'partner_id': project.partner_id.id}}
return {} return {'value': {'partner_id': False}}
_columns = { _columns = {
'id': fields.integer('ID', readonly=True), 'id': fields.integer('ID', readonly=True),
@@ -292,11 +292,10 @@ class project_issue(osv.Model):
""" This function returns value of partner email address based on partner """ This function returns value of partner email address based on partner
:param part: Partner's id :param part: Partner's id
""" """
result = {}
if partner_id: if partner_id:
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context) partner = self.pool['res.partner'].browse(cr, uid, partner_id, context)
result['email_from'] = partner.email return {'value': {'email_from': partner.email}}
return {'value': result} return {'value': {'email_from': False}}
def get_empty_list_help(self, cr, uid, help, context=None): def get_empty_list_help(self, cr, uid, help, context=None):
context = dict(context or {}) context = dict(context or {})
+1 -1
View File
@@ -33,7 +33,7 @@
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/> <field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
<field name="email_from"/> <field name="email_from"/>
<label for="project_id"/> <label for="project_id"/>
<div> <div name="project">
<field name="project_id" on_change="on_change_project(project_id)" class="oe_inline" context="{'default_use_issues':1}"/> <field name="project_id" on_change="on_change_project(project_id)" class="oe_inline" context="{'default_use_issues':1}"/>
<field name="can_escalate" invisible="1"/> <field name="can_escalate" invisible="1"/>
<button name="case_escalate" string="Escalate" type="object" class="oe_link" attrs="{'invisible':[('can_escalate','=',False)]}" groups="base.group_user"/> <button name="case_escalate" string="Escalate" type="object" class="oe_link" attrs="{'invisible':[('can_escalate','=',False)]}" groups="base.group_user"/>
@@ -19,6 +19,7 @@
# #
############################################################################## ##############################################################################
from openerp.addons.analytic.models import analytic
from openerp.osv import fields,osv,orm from openerp.osv import fields,osv,orm
from openerp.tools.translate import _ from openerp.tools.translate import _
@@ -43,11 +44,12 @@ class project_issue(osv.osv):
}), }),
'timesheet_ids': fields.one2many('account.analytic.line', 'issue_id', 'Timesheets'), 'timesheet_ids': fields.one2many('account.analytic.line', 'issue_id', 'Timesheets'),
'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account'), 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account'),
'contract_state': fields.related('analytic_account_id', 'state', string='Contract Status', type='selection', selection=analytic.ANALYTIC_ACCOUNT_STATE),
} }
def on_change_project(self, cr, uid, ids, project_id, context=None): def on_change_project(self, cr, uid, ids, project_id, context=None):
if not project_id: if not project_id:
return {} return {'value': {'analytic_account_id': False}}
result = super(project_issue, self).on_change_project(cr, uid, ids, project_id, context=context) result = super(project_issue, self).on_change_project(cr, uid, ids, project_id, context=context)
@@ -58,6 +60,7 @@ class project_issue(osv.osv):
account = project.analytic_account_id account = project.analytic_account_id
if account: if account:
result['value']['analytic_account_id'] = account.id result['value']['analytic_account_id'] = account.id
result['value']['contract_state'] = account.state
return result return result
@@ -17,6 +17,10 @@
domain="[('parent_id','!=',False),('partner_id', '=', partner_id),('type', '!=', 'view')]" domain="[('parent_id','!=',False),('partner_id', '=', partner_id),('type', '!=', 'view')]"
on_change='on_change_account_id(analytic_account_id)'/> on_change='on_change_account_id(analytic_account_id)'/>
</field> </field>
<xpath expr='//div[@name="project"]' position='after'>
<field name="contract_state" widget="label_selection" attrs="{'invisible': ['|', ('partner_id', '=', False), ('analytic_account_id', '=', False)]}"
options="{'classes': {'template': 'default', 'draft': 'info', 'open': 'success', 'pending': 'warning', 'close': 'danger', 'cancelled': 'warning'}}" readonly="1"/>
</xpath>
<xpath expr="//notebook/page[@name='extra_info']" position="before"> <xpath expr="//notebook/page[@name='extra_info']" position="before">
<page string="Timesheets"> <page string="Timesheets">
<field name="timesheet_ids" colspan="4" nolabel="1" context="{'default_user_id' : uid, 'default_account_id' : analytic_account_id, 'default_is_timesheet':1}" <field name="timesheet_ids" colspan="4" nolabel="1" context="{'default_user_id' : uid, 'default_account_id' : analytic_account_id, 'default_is_timesheet':1}"
@@ -22,6 +22,7 @@ import time
import datetime import datetime
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from openerp.addons.analytic.models import analytic
from openerp.osv import fields, osv from openerp.osv import fields, osv
from openerp import tools from openerp import tools
from openerp.tools.translate import _ from openerp.tools.translate import _
@@ -220,6 +221,7 @@ class task(osv.osv):
'timesheet_ids': fields.one2many('account.analytic.line', 'task_id', 'Timesheets'), 'timesheet_ids': fields.one2many('account.analytic.line', 'task_id', 'Timesheets'),
'analytic_account_id': fields.related('project_id', 'analytic_account_id', 'analytic_account_id': fields.related('project_id', 'analytic_account_id',
type='many2one', relation='account.analytic.account', string='Analytic Account', store=True), type='many2one', relation='account.analytic.account', string='Analytic Account', store=True),
'contract_state': fields.related('project_id', 'analytic_account_id', 'state', relation="account.analytic.account", string='Contract Status', type='selection', selection=analytic.ANALYTIC_ACCOUNT_STATE),
} }
_defaults = { _defaults = {
@@ -232,6 +234,16 @@ class task(osv.osv):
vals[task.id]['planned_hours'] += task.effective_hours vals[task.id]['planned_hours'] += task.effective_hours
return vals return vals
def onchange_project(self, cr, uid, ids, project_id, context=None):
result = super(task, self).onchange_project(cr, uid, ids, project_id, context=context)
if not project_id:
return result
if 'value' not in result:
result['value'] = {}
project = self.pool['project.project'].browse(cr, uid, project_id, context=context)
result['value']['contract_state'] = project.analytic_account_id.state
return result
class res_partner(osv.osv): class res_partner(osv.osv):
_inherit = 'res.partner' _inherit = 'res.partner'
@@ -150,6 +150,13 @@
<field name="model">project.task</field> <field name="model">project.task</field>
<field name="inherit_id" ref="project.view_task_form2" /> <field name="inherit_id" ref="project.view_task_form2" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="project_id" position="attributes">
<attribute name="on_change">onchange_project(project_id)</attribute>
</field>
<xpath expr='//field[@name="project_id"]' position='after'>
<field name="contract_state" widget="label_selection" attrs="{'invisible': ['|', ('project_id', '=', False), ('partner_id', '=', False)]}"
options="{'classes': {'template': 'default', 'draft': 'info', 'open': 'success', 'pending': 'warning', 'close': 'danger', 'cancelled': 'warning'}}" readonly="1"/>
</xpath>
<field name="categ_ids" position="after"> <field name="categ_ids" position="after">
<field name="analytic_account_id" invisible="1"/> <field name="analytic_account_id" invisible="1"/>
<field name="progress" widget="progressbar" <field name="progress" widget="progressbar"
+2
View File
@@ -21,6 +21,7 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
import time import time
from openerp.addons.analytic.models import analytic
from openerp.osv import fields, osv from openerp.osv import fields, osv
from openerp.tools.translate import _ from openerp.tools.translate import _
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
@@ -175,6 +176,7 @@ class sale_order(osv.osv):
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Pricelist for current sales order."), 'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Pricelist for current sales order."),
'currency_id': fields.related('pricelist_id', 'currency_id', type="many2one", relation="res.currency", string="Currency", readonly=True, required=True), 'currency_id': fields.related('pricelist_id', 'currency_id', type="many2one", relation="res.currency", string="Currency", readonly=True, required=True),
'project_id': fields.many2one('account.analytic.account', 'Contract / Analytic', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="The analytic account related to a sales order."), 'project_id': fields.many2one('account.analytic.account', 'Contract / Analytic', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="The analytic account related to a sales order."),
'contract_state': fields.related('project_id', 'state', string='Contract Status', type='selection', selection=analytic.ANALYTIC_ACCOUNT_STATE),
'order_line': fields.one2many('sale.order.line', 'order_id', 'Order Lines', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, copy=True), 'order_line': fields.one2many('sale.order.line', 'order_id', 'Order Lines', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, copy=True),
'invoice_ids': fields.many2many('account.invoice', 'sale_order_invoice_rel', 'order_id', 'invoice_id', 'Invoices', readonly=True, copy=False, help="This is the list of invoices that have been generated for this sales order. The same sales order may have been invoiced in several times (by line for example)."), 'invoice_ids': fields.many2many('account.invoice', 'sale_order_invoice_rel', 'order_id', 'invoice_id', 'Invoices', readonly=True, copy=False, help="This is the list of invoices that have been generated for this sales order. The same sales order may have been invoiced in several times (by line for example)."),
+1
View File
@@ -128,6 +128,7 @@
<field name="partner_invoice_id" groups="sale.group_delivery_invoice_address" context="{'default_type':'invoice'}"/> <field name="partner_invoice_id" groups="sale.group_delivery_invoice_address" context="{'default_type':'invoice'}"/>
<field name="partner_shipping_id" on_change="onchange_delivery_id(company_id, partner_id, partner_shipping_id, fiscal_position_id)" groups="sale.group_delivery_invoice_address" context="{'default_type':'delivery'}"/> <field name="partner_shipping_id" on_change="onchange_delivery_id(company_id, partner_id, partner_shipping_id, fiscal_position_id)" groups="sale.group_delivery_invoice_address" context="{'default_type':'delivery'}"/>
<field name="project_id" context="{'partner_id':partner_invoice_id, 'manager_id': user_id, 'default_pricelist_id':pricelist_id, 'default_name':name, 'default_type': 'contract'}" groups="sale.group_analytic_accounting" domain="[('type','in',['view','normal','contract'])]"/> <field name="project_id" context="{'partner_id':partner_invoice_id, 'manager_id': user_id, 'default_pricelist_id':pricelist_id, 'default_name':name, 'default_type': 'contract'}" groups="sale.group_analytic_accounting" domain="[('type','in',['view','normal','contract'])]"/>
<field name="contract_state" groups="sale.group_analytic_accounting" widget="label_selection" attrs="{'invisible': [('project_id', '=', False)]}" options="{'classes': {'template': 'default', 'draft': 'info', 'open': 'success', 'pending': 'warning', 'close': 'danger', 'cancelled': 'warning'}}" readonly="1"/>
</group> </group>
<group> <group>
<field name="date_order"/> <field name="date_order"/>
@@ -2,15 +2,6 @@
<openerp> <openerp>
<data> <data>
<record model="ir.ui.view" id="view_order_form_inherit">
<field name="name">sale.order.form.inherit</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<field name="project_id" position="replace"/>
</field>
</record>
<record model="ir.ui.view" id="view_order_form_inherit2"> <record model="ir.ui.view" id="view_order_form_inherit2">
<field name="name">sale.order.form.inherit2</field> <field name="name">sale.order.form.inherit2</field>
<field name="model">sale.order</field> <field name="model">sale.order</field>
+17 -1
View File
@@ -934,6 +934,21 @@ var TimezoneMismatch = FieldSelection.extend({
} }
}); });
var LabelSelection = FieldSelection.extend({
init: function(field_manager, node) {
this._super(field_manager, node);
this.classes = this.options && this.options.classes || {};
},
render_value: function() {
this._super.apply(this, arguments);
if (this.get("effective_readonly")) {
var value = this.get('value'),
bt_class = this.classes[value] || 'default';
this.$el.html(_.str.sprintf("<span class='label label-%s'>%s<span>", bt_class, this.$el.html()));
}
},
});
var FieldRadio = common.AbstractField.extend(common.ReinitializeFieldMixin, { var FieldRadio = common.AbstractField.extend(common.ReinitializeFieldMixin, {
template: 'FieldRadio', template: 'FieldRadio',
events: { events: {
@@ -1626,7 +1641,8 @@ core.form_widget_registry
.add('priority', Priority) .add('priority', Priority)
.add('kanban_state_selection', KanbanSelection) .add('kanban_state_selection', KanbanSelection)
.add('statinfo', StatInfo) .add('statinfo', StatInfo)
.add('timezone_mismatch', TimezoneMismatch); .add('timezone_mismatch', TimezoneMismatch)
.add('label_selection', LabelSelection);
/** /**