[MERGE] improvement project-issue

bzr revid: tfr@openerp.com-20110407114145-xvr27pjquxwk9ff0
This commit is contained in:
Thibault Francois 2011-04-07 13:41:45 +02:00
parent 1a45ff614d
commit b11a71fd87
13 changed files with 191 additions and 70 deletions

View File

@ -205,7 +205,7 @@ class account_analytic_account(osv.osv):
def check_recursion(self, cr, uid, ids, parent=None):
return super(account_analytic_account, self)._check_recursion(cr, uid, ids, parent=parent)
_order = 'date_start desc,parent_id desc,code'
_order = 'name asc'
_constraints = [
(check_recursion, 'Error! You can not create recursive analytic accounts.', ['parent_id']),
]

View File

@ -279,10 +279,22 @@ class document_file(osv.osv):
else:
if vals.get('file_size'):
del vals['file_size']
if not self._check_duplication(cr, uid, vals):
raise osv.except_osv(_('ValidateError'), _('File name must be unique!'))
result = super(document_file, self).create(cr, uid, vals, context)
cr.commit() # ?
result = self._check_duplication(cr, uid, vals)
if not result:
domain = [
('res_id', '=', vals['res_id']),
('res_model', '=', vals['res_model']),
('datas_fname', '=', vals['datas_fname']),
]
attach_ids = self.search(cr, uid, domain, context=context)
super(document_file, self).write(cr, uid, attach_ids,
{'datas' : vals['datas']},
context=context)
result = attach_ids[0]
else:
#raise osv.except_osv(_('ValidateError'), _('File name must be unique!'))
result = super(document_file, self).create(cr, uid, vals, context)
cr.commit() # ?
return result
def __get_partner_id(self, cr, uid, res_model, res_id, context=None):

View File

@ -92,6 +92,7 @@ class email_template_mailbox(osv.osv):
self.unlink(cr, uid, [id], context=context)
# Remove attachments for this mail
attachment_pool.unlink(cr, uid, values['attachments_ids'], context=context)
return result
else:
self.write(cr, uid, id, {'folder':'sent', 'state':'na', 'date_mail':time.strftime("%Y-%m-%d %H:%M:%S")}, context)
self.historise(cr, uid, [id], "Email sent successfully", context)

View File

@ -201,7 +201,7 @@
</record>
<menuitem name="Email Templates" id="menu_email_template_all"
parent="menu_email_template_configuration" action="action_email_template_tree_all" />
parent="menu_email_template" action="action_email_template_tree_all" />
<!-- Email Template menu in Tools -->
<menuitem name="Email Templates" id="menu_email_template_all_tools"

View File

@ -93,7 +93,17 @@ class marketing_campaign(osv.osv):
this campaign to be run"),
'partner_field_id': fields.many2one('ir.model.fields', 'Partner Field',
domain="[('model_id', '=', object_id), ('ttype', '=', 'many2one'), ('relation', '=', 'res.partner')]",
help="The generated workitems will be linked to the partner related to the record. If the record is the partner itself leave this field empty."),
help="The generated workitems will be linked to the partner related to the record. "\
"If the record is the partner itself leave this field empty. "\
"This is useful for reporting purposes, via the Campaign Analysis or Campaign Follow-up views."),
'unique_field_id': fields.many2one('ir.model.fields', 'Unique Field',
domain="[('model_id', '=', object_id), ('ttype', 'in', ['char','int','many2one','text','selection'])]",
help='If set, this field will help segments that work in "no duplicates" mode to avoid '\
'selecting similar records twice. Similar records are records that have the same value for '\
'this unique field. For example by choosing the "email_from" field for CRM Leads you would prevent '\
'sending the same campaign to the same email address again. If not set, the "no duplicates" segments '\
"will only avoid selecting the same record again if it entered the campaign previously. "\
"Only easily comparable fields like textfields, integers, selections or single relationships may be used."),
'mode': fields.selection([('test', 'Test Directly'),
('test_realtime', 'Test in Realtime'),
('manual', 'With Manual Confirmation'),
@ -209,11 +219,36 @@ Normal - the campaign runs normally and automatically sends all emails and repor
def copy(self, cr, uid, id, default=None, context=None):
raise osv.except_osv(_("Operation not supported"), _("Sorry, campaign duplication is not supported at the moment."))
def _find_duplicate_workitems(self, cr, uid, record, campaign_rec, context=None):
"""Finds possible duplicates workitems for a record in this campaign, based on a uniqueness
field.
:param record: browse_record to find duplicates workitems for.
:param campaign_rec: browse_record of campaign
"""
Workitems = self.pool.get('marketing.campaign.workitem')
duplicate_workitem_domain = [('res_id','=', record.id),
('campaign_id','=', campaign_rec.id)]
unique_field = campaign_rec.unique_field_id
if unique_field:
unique_value = getattr(record, unique_field.name, None)
if unique_value:
if unique_field.ttype == 'many2one':
unique_value = unique_value.id
similar_res_ids = self.pool.get(campaign_rec.object_id.model).search(cr, uid,
[(unique_field.name, '=', unique_value)], context=context)
if similar_res_ids:
duplicate_workitem_domain = [('res_id','in', similar_res_ids),
('campaign_id','=', campaign_rec.id)]
return Workitems.search(cr, uid, duplicate_workitem_domain, context=context)
marketing_campaign()
class marketing_campaign_segment(osv.osv):
_name = "marketing.campaign.segment"
_description = "Campaign Segment"
_order = "name"
def _get_next_sync(self, cr, uid, ids, fn, args, context=None):
# next auto sync date is same for all segments
@ -226,13 +261,19 @@ class marketing_campaign_segment(osv.osv):
'campaign_id': fields.many2one('marketing.campaign', 'Campaign', required=True, select=1, ondelete="cascade"),
'object_id': fields.related('campaign_id','object_id', type='many2one', relation='ir.model', string='Resource'),
'ir_filter_id': fields.many2one('ir.filters', 'Filter', ondelete="restrict",
help="Filter to select the matching resource records that belong to this segment. New filters can be created and saved using the advanced search on the list view of the Resource. If no filter is set, all records are selected without filtering. The synchronization mode may also add a criterion to the filter."),
help="Filter to select the matching resource records that belong to this segment. "\
"New filters can be created and saved using the advanced search on the list view of the Resource. "\
"If no filter is set, all records are selected without filtering. "\
"The synchronization mode may also add a criterion to the filter."),
'sync_last_date': fields.datetime('Last Synchronization', help="Date on which this segment was synchronized last time (automatically or manually)"),
'sync_mode': fields.selection([('create_date', 'Only records created after last sync'),
('write_date', 'Only records modified after last sync (no duplicates)'),
('all', 'All records (no duplicates)')],
'Synchronization mode',
help="Determines an additional criterion to add to the filter when selecting new records to inject in the campaign."),
help="Determines an additional criterion to add to the filter when selecting new records to inject in the campaign. "\
'"No duplicates" prevents selecting records which have already entered the campaign previously.'\
'If the campaign has a "unique field" set, "no duplicates" will also prevent selecting records which have '\
'the same value for the unique field as other records that already entered the campaign.'),
'state': fields.selection([('draft', 'Draft'),
('running', 'Running'),
('done', 'Done'),
@ -301,6 +342,7 @@ class marketing_campaign_segment(osv.osv):
def process_segment(self, cr, uid, segment_ids=None, context=None):
Workitems = self.pool.get('marketing.campaign.workitem')
Campaigns = self.pool.get('marketing.campaign')
if not segment_ids:
segment_ids = self.search(cr, uid, [('state', '=', 'running')], context=context)
@ -323,21 +365,20 @@ class marketing_campaign_segment(osv.osv):
object_ids = model_obj.search(cr, uid, criteria, context=context)
# XXX TODO: rewrite this loop more efficiently without doing 1 search per record!
for o_ids in model_obj.browse(cr, uid, object_ids, context=context):
# avoid duplicated workitem for the same resource
for record in model_obj.browse(cr, uid, object_ids, context=context):
# avoid duplicate workitem for the same resource
if segment.sync_mode in ('write_date','all'):
wi_ids = Workitems.search(cr, uid, [('res_id','=',o_ids.id),('segment_id','=',segment.id)], context=context)
if wi_ids:
if Campaigns._find_duplicate_workitems(cr, uid, record, segment.campaign_id, context=context):
continue
wi_vals = {
'segment_id': segment.id,
'date': action_date,
'state': 'todo',
'res_id': o_ids.id
'res_id': record.id
}
partner = self.pool.get('marketing.campaign')._get_partner_for(segment.campaign_id, o_ids)
partner = self.pool.get('marketing.campaign')._get_partner_for(segment.campaign_id, record)
if partner:
wi_vals['partner_id'] = partner.id
@ -353,6 +394,7 @@ marketing_campaign_segment()
class marketing_campaign_activity(osv.osv):
_name = "marketing.campaign.activity"
_order = "name"
_description = "Campaign Activity"
_action_types = [
@ -454,10 +496,11 @@ class marketing_campaign_activity(osv.osv):
action_context = dict(context,
active_id=workitem.res_id,
active_ids=[workitem.res_id],
active_model=workitem.object_id.model)
active_model=workitem.object_id.model,
workitem=workitem)
res = server_obj.run(cr, uid, [activity.server_action_id.id],
context=action_context)
# server action return False if the action is perfomed
# server action return False if the action is performed
# except client_action, other and python code
return res == False and True or res
@ -557,6 +600,8 @@ class marketing_campaign_workitem(osv.osv):
continue
proxy = self.pool.get(wi.object_id.model)
if not proxy.exists(cr, uid, [wi.res_id]):
continue
ng = proxy.name_get(cr, uid, [wi.res_id], context=context)
if ng:
res[wi.id] = ng[0][1]
@ -567,8 +612,14 @@ class marketing_campaign_workitem(osv.osv):
if not len(args):
return []
condition = []
final_ids = []
condition_name = None
for domain_item in args:
# we only use the first domain criterion and ignore all the rest including operators
if isinstance(domain_item, (list,tuple)) and len(domain_item) == 3 and domain_item[0] == 'res_name':
condition_name = [None, domain_item[1], domain_item[2]]
break
assert condition_name, "Invalid search domain for marketing_campaign_workitem.res_name. It should use 'res_name'"
cr.execute("""select w.id, w.res_id, m.model \
from marketing_campaign_workitem w \
@ -577,15 +628,17 @@ class marketing_campaign_workitem(osv.osv):
left join ir_model m on (m.id=c.object_id)
""")
res = cr.fetchall()
workitem_map = {}
matching_workitems = []
for id, res_id, model in res:
workitem_map.setdefault(model,{}).setdefault(res_id,set()).add(id)
for model, id_map in workitem_map.iteritems():
model_pool = self.pool.get(model)
for arg in args:
if arg[1] == 'ilike':
condition.append((model_pool._rec_name, 'ilike', arg[2]))
res_ids = model_pool.search(cr, uid, condition, context=context)
if res_id in res_ids:
final_ids.append(id)
return [('id', 'in', final_ids)]
condition_name[0] = model_pool._rec_name
condition = [('id', 'in', id_map.keys()), condition_name]
for res_id in model_pool.search(cr, uid, condition, context=context):
matching_workitems.extend(id_map[res_id])
return [('id', 'in', list(set(matching_workitems)))]
_columns = {
'segment_id': fields.many2one('marketing.campaign.segment', 'Segment', readonly=True),
@ -723,7 +776,7 @@ class marketing_campaign_workitem(osv.osv):
# manual states are not processed automatically
continue
while True:
domain = [('state', '=', 'todo'), ('date', '!=', False)]
domain = [('campaign_id', '=', camp.id), ('state', '=', 'todo'), ('date', '!=', False)]
if camp.mode in ('test_realtime', 'active'):
domain += [('date','<=', time.strftime('%Y-%m-%d %H:%M:%S'))]

View File

@ -26,6 +26,7 @@
<separator string="Resource" colspan="2" />
<field name="object_id"/>
<field name="partner_field_id"/>
<field name="unique_field_id"/>
</group>
<group colspan="2" col="2">
<separator string="Cost" colspan="2" />

View File

@ -26,6 +26,10 @@ from datetime import datetime, date
from tools.translate import _
from osv import fields, osv
class project_project(osv.osv):
_name = 'project.project'
project_project()
class project_task_type(osv.osv):
_name = 'project.task.type'
@ -35,6 +39,7 @@ class project_task_type(osv.osv):
'name': fields.char('Stage Name', required=True, size=64, translate=True),
'description': fields.text('Description'),
'sequence': fields.integer('Sequence'),
'project_ids': fields.many2many('project.project', 'project_task_type_rel', 'type_id', 'project_id', 'Projects'),
}
_defaults = {

View File

@ -43,9 +43,9 @@ project_issue_version()
class project_issue(crm.crm_case, osv.osv):
_name = "project.issue"
_description = "Project Issue"
_order = "priority, id desc"
_order = "priority, create_date desc"
_inherit = ['mailgate.thread']
def case_open(self, cr, uid, ids, *args):
"""
@param self: The object pointer
@ -56,7 +56,7 @@ class project_issue(crm.crm_case, osv.osv):
"""
res = super(project_issue, self).case_open(cr, uid, ids, *args)
self.write(cr, uid, ids, {'date_open': time.strftime('%Y-%m-%d %H:%M:%S')})
self.write(cr, uid, ids, {'date_open': time.strftime('%Y-%m-%d %H:%M:%S'), 'assigned_to' : uid})
for (id, name) in self.name_get(cr, uid, ids):
message = _("Issue '%s' has been opened.") % name
self.log(cr, uid, id, message)
@ -175,7 +175,7 @@ class project_issue(crm.crm_case, osv.osv):
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
select=True, help='Sales team to which Case belongs to.\
Define Responsible user and Email account for mail gateway.'),
'user_id': fields.many2one('res.users', 'Responsible'),
'user_id': fields.related('project_id', 'user_id', type='many2one', relation='res.users', store=True, select=1, string='Responsible'),
'partner_id': fields.many2one('res.partner', 'Partner'),
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
domain="[('partner_id','=',partner_id)]"),
@ -200,19 +200,19 @@ class project_issue(crm.crm_case, osv.osv):
'partner_name': fields.char("Employee's Name", size=64),
'partner_mobile': fields.char('Mobile', size=32),
'partner_phone': fields.char('Phone', size=32),
'type_id': fields.many2one ('project.task.type', 'Resolution'),
'type_id': fields.many2one ('project.task.type', 'Resolution', domain="[('project_ids', '=', project_id)]"),
'project_id':fields.many2one('project.project', 'Project'),
'duration': fields.float('Duration'),
'task_id': fields.many2one('project.task', 'Task', domain="[('project_id','=',project_id)]"),
'day_open': fields.function(_compute_day, string='Days to Open', \
method=True, multi='day_open', type="float", store=True),
method=True, multi='compute_day', type="float", store=True),
'day_close': fields.function(_compute_day, string='Days to Close', \
method=True, multi='day_close', type="float", store=True),
'assigned_to': fields.related('task_id', 'user_id', string = 'Assigned to', type="many2one", relation="res.users", store=True, help='This is the current user to whom the related task have been assigned'),
method=True, multi='compute_day', type="float", store=True),
'assigned_to': fields.many2one('res.users', 'Assigned to', required=False, select=1),
'working_hours_open': fields.function(_compute_day, string='Working Hours to Open the Issue', \
method=True, multi='working_days_open', type="float", store=True),
method=True, multi='compute_day', type="float", store=True),
'working_hours_close': fields.function(_compute_day, string='Working Hours to Close the Issue', \
method=True, multi='working_days_close', type="float", store=True),
method=True, multi='compute_day', type="float", store=True),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
'date_action_last': fields.datetime('Last Action', readonly=1),
'date_action_next': fields.datetime('Next Action', readonly=1),
@ -230,17 +230,30 @@ class project_issue(crm.crm_case, osv.osv):
return user.context_project_id.id
return False
def on_change_project(self, cr, uid, ids, project_id, context=None):
result = {}
if project_id:
project = self.pool.get('project.project').browse(cr, uid, project_id, context=context)
if project.user_id:
result['value'] = {'user_id' : project.user_id.id}
return result
_defaults = {
'active': 1,
'user_id': crm.crm_case._get_default_user,
#'user_id': crm.crm_case._get_default_user,
'partner_id': crm.crm_case._get_default_partner,
'partner_address_id': crm.crm_case._get_default_partner_address,
'email_from': crm.crm_case. _get_default_email,
'email_from': crm.crm_case._get_default_email,
'state': 'draft',
'section_id': crm.crm_case. _get_section,
'section_id': crm.crm_case._get_section,
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.helpdesk', context=c),
'priority': crm.AVAILABLE_PRIORITIES[2][0],
'project_id':_get_project,
'categ_id' : lambda *a: False,
#'assigned_to' : lambda obj, cr, uid, context: uid,
}
def convert_issue_task(self, cr, uid, ids, context=None):

View File

@ -52,13 +52,14 @@
<field name="arch" type="xml">
<form string="Issue Tracker Form">
<group colspan="4" col="6">
<field name="name"/>
<field name="project_id" required="True"/>
<field name="categ_id" widget="selection" domain="[('object_id.model', '=', 'project.issue')]"/>
<field name="user_id"/>
<field name="assigned_to" />
<field name="name"/>
<field name="project_id" required="True" on_change="on_change_project(project_id)"/>
<field name="categ_id" widget="selection" domain="[('object_id.model', '=', 'project.issue')]"/>
<field name="user_id" invisible="1" />
<field name="assigned_to"/>
<field name="version_id" colspan="2" widget="selection"/>
<group colspan="2" col="4">
<field name="type_id" readonly="1"/>
<field name="type_id" string="Resolution" />
<button name="prev_type" string="Previous" type="object" icon="gtk-go-back" help="Change to Previous Stage"/>
<button name="next_type" string="Next" type="object" icon="gtk-go-forward" help="Change to Next Stage"/>
</group>
@ -73,7 +74,6 @@
</group>
<group col="3" colspan="2">
<separator colspan="3" string="Status"/>
<field name="version_id" colspan="3" widget="selection"/>
<field name="priority" colspan="3"/>
<field name="task_id" on_change="onchange_task_id(task_id)"/>
<button string="Convert To Task" name="convert_issue_task" icon="gtk-index" type="object"
@ -184,12 +184,11 @@
<field name="partner_id" groups="base.group_extended"/>
<field name="project_id" />
<field name="priority" string="Priority"/>
<field name="type_id" widget="selection" readonly="1"/>
<field name="type_id" widget="selection" readonly="1" string="Resolution" />
<button name="prev_type" string="Previous" type="object" icon="gtk-go-back" help="Change to Previous Stage"/>
<button name="next_type" string="Next" type="object" icon="gtk-go-forward" help="Change to Next Stage"/>
<field name="version_id" widget="selection"/>
<field name="user_id"/>
<field name="assigned_to" attrs="{'readonly':[('task_id','=',False)]}"/>
<field name="assigned_to"/>
<field name="progress" widget="progressbar" attrs="{'invisible':[('task_id','=',False)]}"/>
<field name="state"/>
<button name="case_cancel" string="Cancel" states="draft,open,pending" type="object" icon="gtk-cancel"/>
@ -218,8 +217,8 @@
<separator orientation="vertical"/>
<field name="name"/>
<field name="partner_id" groups="base.group_extended"/>
<field name="user_id">
<filter domain="[('user_id','=',False)]" help="Unassigned Issues" icon="terp-personal-" separator="1"/>
<field name="assigned_to">
<filter domain="[('assigned_to','=',False)]" help="Unassigned Issues" icon="terp-personal-" separator="1"/>
</field>
<field name="project_id"/>
</group>
@ -233,7 +232,7 @@
<newline/>
<group expand="0" string="Group By..." groups="base.group_extended">
<filter string="Responsible" icon="terp-personal"
domain="[]" context="{'group_by':'user_id'}" />
domain="[]" context="{'group_by':'assigned_to'}" />
<filter string="Partner" icon="terp-partner" domain="[]"
context="{'group_by':'partner_id'}" />
<separator orientation="vertical"/>
@ -264,7 +263,7 @@
<field name="type">calendar</field>
<field name="priority" eval="2"/>
<field name="arch" type="xml">
<calendar string="Issues" date_start="date" color="user_id" date_delay="duration">
<calendar string="Issues" date_start="date" color="assigned_to" date_delay="duration">
<field name="name"/>
<field name="partner_id"/>
</calendar>
@ -285,11 +284,11 @@
<field name="name" string="Feature description"/>
<field name="partner_id" groups="base.group_extended"/>
<field name="priority" string="Priority"/>
<field name="type_id" widget="selection" readonly="1"/>
<button name="prev_type" string="Previous" type="object" icon="gtk-go-back" help="Change to Previous Stage"/>
<button name="next_type" string="Next" type="object" icon="gtk-go-forward" help="Change to Next Stage"/>
<field name="type_id" widget="selection" readonly="1"/>
<button name="prev_type" string="Previous" type="object" icon="gtk-go-back" help="Change to Previous Stage"/>
<button name="next_type" string="Next" type="object" icon="gtk-go-forward" help="Change to Next Stage"/>
<field name="version_id"/>
<field name="user_id"/>
<field name="assigned_to"/>
<field name="state"/>
<button name="case_cancel" string="Cancel" states="draft,open,pending" type="object" icon="gtk-cancel"/>
<button name="case_close" string="Done" states="open,draft,pending" type="object" icon="gtk-jump-to"/>
@ -312,7 +311,7 @@
<separator orientation="vertical"/>
<group>
<field name="name" select='1' string="Feature description"/>
<field name="user_id" select="1"/>
<field name="assigned_to" select="1"/>
<field name="state" select="1">
<filter icon="terp-check" domain="[('state','in',('open','draft'))]" help="Current Features" name="current_feature"/>
<filter icon="terp-camera_test" domain="[('state','=','open')]" help="Open Features"/>

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@ -16,7 +16,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -101,10 +101,11 @@ class project_issue_report(osv.osv):
c.task_id,
date_trunc('day',c.create_date) as create_date,
extract('epoch' from (c.date_open-c.create_date))/(3600*24) as delay_open,
extract('epoch' from (c.date_closed-c.create_date))/(3600*24) as delay_close,
extract('epoch' from (c.date_closed-c.date_open))/(3600*24) as delay_close,
(SELECT count(id) FROM mailgate_message WHERE model='project.issue' AND res_id=c.id) AS email
FROM
project_issue c
WHERE c.categ_id IN (select id from crm_case_categ where object_id in (select id from ir_model where model = 'project.issue'))
)""")
project_issue_report()

View File

@ -28,8 +28,8 @@
<field name="nbr" string="#Project Issues" sum='#Number of Project Issues'/>
<field name="delay_open" avg='Avg Opening Delay'/>
<field name="delay_close" avg='Avg Closing Delay'/>
<field name="working_hours_open" sum='Open Working Hours'/>
<field name="working_hours_close" sum='Close Working hours'/>
<field name="working_hours_open" avg='Open Working Hours'/>
<field name="working_hours_close" avg='Close Working hours'/>
<field name="email" sum='# Emails'/>
</tree>
</field>

View File

@ -27,8 +27,36 @@ class project_issue(osv.osv):
_description = 'project issue'
_columns = {
'timesheet_ids': fields.one2many('hr.analytic.timesheet', 'issue_id', 'Timesheets'),
'analytic_account_id': fields.related('project_id', 'analytic_account_id', type='many2one', relation='account.analytic.account',string='Analytic Account')
'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account'),
}
def on_change_project(self, cr, uid, ids, project_id, context=None):
if not project_id:
return {}
result = super(project_issue, self).on_change_project(cr, uid, ids, project_id, context=context)
project = self.pool.get('project.project').browse(cr, uid, project_id, context=context)
if 'value' not in result:
result['value'] = {}
account = project.analytic_account_id
if account:
result['value']['analytic_account_id'] = account.id
return result
def on_change_account_id(self, cr, uid, ids, account_id, context=None):
if not account_id:
return {}
account = self.pool.get('account.analytic.account').browse(cr, uid, account_id, context=context)
result = {}
if account and account.state == 'pending':
result = {'warning' : {'title' : _('Analytic Account'), 'message' : _('The Analytic Account is in pending !')}}
return result
project_issue()

View File

@ -7,14 +7,22 @@
<field name="inherit_id" ref="project_issue.project_issue_form_view" />
<field name="type">form</field>
<field name="arch" type="xml">
<field name="project_id" position="attributes">
<attribute name="on_change">on_change_project(project_id)</attribute>
</field>
<xpath expr="/form/notebook" position="before">
<field name="analytic_account_id"
domain="[('parent_id','!=',False),('partner_id', '=', partner_id),('type', '!=', 'view')]"
on_change='on_change_account_id(analytic_account_id)'
groups="base.group_extended" />
</xpath>
<notebook colspan="4">
<page string="Worklogs">
<field name="analytic_account_id" invisible="1" domain="[('parent_id','!=',False)]" groups="base.group_extended"/>
<field name="timesheet_ids" colspan="4" nolabel="1" context="{'default_user_id' : user_id, 'default_account_id' : analytic_account_id}">
<field name="timesheet_ids" colspan="4" nolabel="1" context="{'default_user_id' : assigned_to, 'default_account_id' : analytic_account_id}">
<tree editable="top" string="Timesheet">
<field name="name"/>
<field name="unit_amount" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)" widget="float_time"/>
<field name="account_id" invisible="0" domain="[('partner_id', '=', parent.partner_id)]" on_change="on_change_account_id(account_id)"/>
<field name="name"/>
<field name="unit_amount" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)" widget="float_time"/>
<field name="account_id" invisible="0" domain="[('partner_id', '=', parent.partner_id)]" on_change="on_change_account_id(account_id)"/>
<field name="date"/>
<field name="user_id"/>
<field invisible="1" name="journal_id"/>