[MERGE] merge with main branch

bzr revid: mra@mra-laptop-20100714110708-38b5ilosf9gz3j1c
This commit is contained in:
Mustufa Rangwala
2010-07-14 16:37:08 +05:30
15 changed files with 172 additions and 131 deletions
+42 -25
View File
@@ -82,21 +82,21 @@
</record>
<record model="account.account" id="assets_view">
<field name="name">Assets - (test)</field>
<field name="code">X10</field>
<field name="type">view</field>
<field name="user_type" ref="account_type_asset"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="bal"/>
<field name="name">Assets - (test)</field>
<field name="code">X10</field>
<field name="type">view</field>
<field name="user_type" ref="account_type_asset"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="bal"/>
</record>
<record model="account.account" id="liabilities_view">
<field name="name">Liabilities - (test)</field>
<field name="code">X11</field>
<field name="type">view</field>
<field name="user_type" ref="account_type_liability"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="bal"/>
<field name="name">Liabilities - (test)</field>
<field name="code">X11</field>
<field name="type">view</field>
<field name="user_type" ref="account_type_liability"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="bal"/>
</record>
<record id="fas" model="account.account">
@@ -208,23 +208,32 @@
</record>
<record model="account.account" id="income_view">
<field name="name">Income - (test)</field>
<field name="code">X20</field>
<field name="type">view</field>
<field name="user_type" ref="account_type_income"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="gpf"/>
<field name="name">Income - (test)</field>
<field name="code">X20</field>
<field name="type">view</field>
<field name="user_type" ref="account_type_income"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="gpf"/>
</record>
<record model="account.account" id="income_fx_income">
<field name="name">Foreign Exchange Gain - (test)</field>
<field name="code">X201</field>
<field name="type">other</field>
<field name="user_type" ref="account_type_income"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="income_view"/>
</record>
<record model="account.account" id="expense_view">
<field name="name">Expense - (test)</field>
<field name="code">X21</field>
<field name="type">view</field>
<field name="user_type" ref="account_type_expense"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="gpf"/>
<field name="name">Expense - (test)</field>
<field name="code">X21</field>
<field name="type">view</field>
<field name="user_type" ref="account_type_expense"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="gpf"/>
</record>
<record id="rev" model="account.account">
<field name="code">X200</field>
<field name="name">Revenue - (test)</field>
@@ -273,6 +282,14 @@
<field name="user_type" ref="account_type_expense"/>
</record>
<record model="account.account" id="income_fx_expense">
<field name="name">Foreign Exchange Loss - (test)</field>
<field name="code">X2111</field>
<field name="type">other</field>
<field name="user_type" ref="account_type_expense"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="ovr"/>
</record>
<!-- Properties -->
<record forcecreate="True" id="property_account_receivable" model="ir.property">
+14
View File
@@ -167,6 +167,20 @@ and users"),
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
}
def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
"""This function returns value of partner email based on Partner Address
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of case IDs
@param add: Id of Partner's address
@email: Partner's email ID
"""
if not add:
return {'value': {'email_from': False, 'country_id': False}}
address = self.pool.get('res.partner.address').browse(cr, uid, add)
return {'value': {'email_from': address.email, 'phone': address.phone, 'country_id': address.country_id.id}}
def case_open(self, cr, uid, ids, *args):
"""Overrides cancel for crm_case for setting Open Date
@param self: The object pointer
+1 -1
View File
@@ -91,7 +91,7 @@
<field name="mobile"/>
<newline/>
<separator string="Links" colspan="4" col="3"/>
<field name="partner_id"/>
<field name="partner_id" on_change="onchange_partner_id(partner_id, email_from)"/>
<button
name="%(action_crm_lead2partner)d"
icon="gtk-index" type="action"
+2
View File
@@ -76,6 +76,7 @@ class crm_lead_report(osv.osv):
_columns = {
'name': fields.char('Year', size=64, required=False, readonly=True),
'user_id':fields.many2one('res.users', 'User', readonly=True),
'country_id':fields.many2one('res.country', 'Country', readonly=True),
'section_id':fields.many2one('crm.case.section', 'Section', readonly=True),
'state': fields.selection(AVAILABLE_STATES, 'State', size=16, readonly=True),
'avg_answers': fields.function(_get_data, string='Avg. Answers', method=True, type="integer"),
@@ -141,6 +142,7 @@ class crm_lead_report(osv.osv):
c.section_id,
c.categ_id,
c.partner_id,
c.country_id,
c.planned_revenue,
1 as nbr,
0 as avg_answers,
@@ -104,6 +104,7 @@
<filter string="User" name="user" icon="terp-personal"
domain="[]" context="{'group_by':'user_id'}" />
<filter string="Partner" icon="terp-personal" context="{'group_by':'partner_id'}" />
<filter string="Country" icon="terp-go-home" context="{'group_by':'country_id'}" />
<separator orientation="vertical" />
<filter string="Section" icon="terp-personal+"
domain="[]"
@@ -159,6 +160,7 @@
<field name="section_id" invisible="1" groups="base.group_extended"/>
<field name="user_id" invisible="1"/>
<field name="partner_id" invisible="1"/>
<field name="country_id" invisible="1"/>
<field name="day" invisible="1"/>
<field name="state" invisible="1"/>
<field name="stage_id" invisible="1"/>
+9 -14
View File
@@ -26,25 +26,18 @@ import base64
import tools
from crm import crm
class crm_send_new_email(osv.osv_memory):
""" Sends new email for the case"""
_name = "crm.send.mail"
crm_send_new_email()
class crm_send_new_email_attachment(osv.osv_memory):
_name = 'crm.send.mail.attachment'
_columns = {
'binary' : fields.binary('Attachment', required=True),
'name' : fields.char('Name', size=128, required=True),
'wizard_id' : fields.many2one('crm.send.mail', 'Wizard', required=True),
}
crm_send_new_email_attachment()
class crm_send_new_email2(osv.osv_memory):
class crm_send_new_email(osv.osv_memory):
""" Sends new email for the case"""
_name = "crm.send.mail"
_description = "Send new email"
@@ -52,12 +45,12 @@ class crm_send_new_email2(osv.osv_memory):
_columns = {
'email_to' : fields.char('To', size=512, required=True),
'email_from' : fields.char('From', size=128, required=True),
'reply_to' : fields.char('Reply To', size=128, required=True, help="Reply-to of the Sales team defined on this case"),
'email_cc' : fields.char('CC', size=512, help="Carbon Copy: list of recipients that will receive"\
" a copy of this mail, and future communication related to this case"),
'subject': fields.char('Subject', size=512, required=True),
'text': fields.text('Message', required=True),
'state': fields.selection(crm.AVAILABLE_STATES, string='Set New State To', required=True),
'attachment_ids' : fields.one2many('crm.send.mail.attachment', 'wizard_id'),
}
@@ -120,7 +113,7 @@ class crm_send_new_email2(osv.osv_memory):
body,
email_cc=email_cc,
attach=attach,
reply_to=case.section_id and case.section_id.reply_to,
reply_to=obj.reply_to,
openobject_id=str(case.id),
x_headers=x_headers
)
@@ -156,7 +149,7 @@ class crm_send_new_email2(osv.osv_memory):
if not context.get('model'):
raise osv.except_osv(_('Error'), _('Can not send mail!'))
res = super(crm_send_new_email2, self).default_get(cr, uid, fields, context=context)
res = super(crm_send_new_email, self).default_get(cr, uid, fields, context=context)
if context.get('mail') == 'reply':
res.update(self.get_reply_defaults(cr, uid, fields, context=context))
@@ -171,9 +164,11 @@ class crm_send_new_email2(osv.osv_memory):
for case in mod_obj.browse(cr, uid, res_id):
if 'email_to' in fields:
res.update({'email_to': tools.ustr(case.email_from)})
res.update({'email_to': case.email_from and tools.ustr(case.email_from) or ''})
if 'email_from' in fields:
res.update({'email_from': tools.ustr(user_mail_from)})
res.update({'email_from': user_mail_from and tools.ustr(user_mail_from) or ''})
if 'reply_to' in fields:
res.update({'reply_to': case.section_id.reply_to})
if 'subject' in fields:
res.update({'subject': tools.ustr(context.get('subject', case.name) or '')})
if 'email_cc' in fields:
@@ -249,5 +244,5 @@ class crm_send_new_email2(osv.osv_memory):
raise osv.except_osv(_('Error'), _('Can not send mail!'))
return True
crm_send_new_email2()
crm_send_new_email()
@@ -12,6 +12,7 @@
<form string="Send New Mail" col="4">
<group colspan="4" col="2">
<field name="email_from"/>
<field name="reply_to"/>
<field name="email_to" />
<field name="email_cc"/>
<field name="subject"/>
@@ -211,7 +211,7 @@
<field name="act_window_id" ref="action_report_crm_claim"/>
</record>
<menuitem name="Claims" id="menu_report_crm_claim_tree"
<menuitem name="Claims Analysis" id="menu_report_crm_claim_tree"
groups="base.group_extended"
action="action_report_crm_claim" parent="base.next_id_64" sequence="6"/>
@@ -198,7 +198,7 @@
<field name="act_window_id" ref="action_report_crm_fundraising"/>
</record>
<menuitem name="Fundraising"
<menuitem name="Fundraising Analysis"
action="action_report_crm_fundraising"
groups="base.group_extended"
id="menu_report_crm_fundraising_tree" parent="base.next_id_64" sequence="20"/>
@@ -179,7 +179,7 @@
<field name="act_window_id" ref="action_report_crm_helpdesk"/>
</record>
<menuitem name="Helpdesk" action="action_report_crm_helpdesk"
<menuitem name="Helpdesk Analysis" action="action_report_crm_helpdesk"
groups="base.group_extended"
id="menu_report_crm_helpdesks_tree" parent="base.next_id_64" sequence="7"/>
+4 -2
View File
@@ -62,6 +62,7 @@ import email_template_engines
import tools
import report
import pooler
import logging
def get_value(cursor, user, recid, message=None, template=None, context=None):
"""
@@ -99,6 +100,7 @@ def get_value(cursor, user, recid, message=None, template=None, context=None):
reply = templ.render(Context(env))
return reply or False
except Exception:
logging.exception("can't render %r", message)
return u""
else:
return message
@@ -543,7 +545,7 @@ class email_template(osv.osv):
if lang:
ctx = context.copy()
ctx.update({'lang':lang})
template = self.browse(cursor, user, template_id, context=ctx)
template = self.browse(cursor, user, template.id, context=ctx)
mailbox_values = {
'email_from': tools.ustr(from_account['name']) + \
"<" + tools.ustr(from_account['email_id']) + ">",
@@ -641,7 +643,7 @@ class email_template(osv.osv):
context=context
)
if template.report_template:
self._generate_attach_reports(
self.generate_attach_reports(
cursor,
user,
template,
+42 -25
View File
@@ -22,21 +22,21 @@
</record>
<record model="account.account.template" id="assets_view">
<field name="name">Assets</field>
<field name="code">10</field>
<field name="type">view</field>
<field name="user_type" ref="acct_type_asset_view"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="bal"/>
<field name="name">Assets</field>
<field name="code">10</field>
<field name="type">view</field>
<field name="user_type" ref="acct_type_asset_view"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="bal"/>
</record>
<record model="account.account.template" id="liabilities_view">
<field name="name">Liabilities</field>
<field name="code">11</field>
<field name="type">view</field>
<field name="user_type" ref="acct_type_liability_view"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="bal"/>
<field name="name">Liabilities</field>
<field name="code">11</field>
<field name="type">view</field>
<field name="user_type" ref="acct_type_liability_view"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="bal"/>
</record>
<record id="fas" model="account.account.template">
@@ -156,21 +156,30 @@
</record>
<record model="account.account.template" id="income_view">
<field name="name">Income</field>
<field name="code">20</field>
<field name="type">view</field>
<field name="user_type" ref="acct_type_income_view"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="gpf"/>
<field name="name">Income</field>
<field name="code">20</field>
<field name="type">view</field>
<field name="user_type" ref="acct_type_income_view"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="gpf"/>
</record>
<record model="account.account.template" id="income_fx_income">
<field name="name">Foreign Exchange Gain</field>
<field name="code">X201</field>
<field name="type">other</field>
<field name="user_type" ref="acct_type_income_view"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="income_view"/>
</record>
<record model="account.account.template" id="expense_view">
<field name="name">Expense</field>
<field name="code">21</field>
<field name="type">view</field>
<field name="user_type" ref="acct_type_expense_view"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="gpf"/>
<field name="name">Expense</field>
<field name="code">21</field>
<field name="type">view</field>
<field name="user_type" ref="acct_type_expense_view"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="gpf"/>
</record>
<record id="rev" model="account.account.template">
@@ -225,10 +234,18 @@
<field name="user_type" ref="account_type_expense"/>
</record>
<record model="account.account.template" id="income_fx_expense">
<field name="name">Foreign Exchange Loss - (test)</field>
<field name="code">X2111</field>
<field name="type">other</field>
<field name="user_type" ref="account_type_expense"/>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="ovr"/>
</record>
<!-- <record id="account.property_account_expense_categ" model="ir.property">
<field eval="'account.account,'+str(a_expense)" name="value"/>
</record> -->
</data>
</openerp>
+43 -57
View File
@@ -152,29 +152,44 @@ you required for the campaign"),
def signal(self, cr, uid, model, res_id, signal, context=None):
record = self.pool.get(model).browse(cr, uid, res_id, context)
return self._signal(cr, uid, record, signal, context)
def _signal(self, cr, uid, record, signal, context=None):
if not signal:
raise ValueError('signal cannot be False')
Workitems = self.pool.get('marketing.campaign.workitem')
domain = [('object_id.model', '=', model),
domain = [('object_id.model', '=', record._table._name),
('state', '=', 'running')]
campaign_ids = self.search(cr, uid, domain, context=context)
for campaign in self.browse(cr, uid, campaign_ids, context):
for activity in campaign.activity_ids:
if activity.signal != signal:
continue
wi_domain = [('activity_id', '=', activity.id),
('res_id', '=', res_id),
('state', '=', 'todo'),
('date', '=', False),
]
data = dict(activity_id=activity.id,
res_id=record.id,
state='todo')
wi_domain = [(k, '=', v) for k, v in data.items()]
wi_ids = Workitems.search(cr, uid, wi_domain, context=context)
if not wi_ids:
partner = self._get_partner_for(campaign, record)
if partner:
data['partner_id'] = partner.id
wi_id = Workitems.create(cr, uid, data, context=context)
wi_ids = [wi_id]
Workitems.process(cr, uid, wi_ids, context=context)
return True
def _signal(self, cr, uid, record, signal, context=None):
return self.signal(cr, uid, record._table._name,
record.id, signal, context)
def _get_partner_for(self, campaign, record):
partner_field = campaign.partner_field_id.name
if partner_field:
return getattr(record, partner_field)
elif campaign.model_id.model == 'res.partner':
return record
return None
marketing_campaign()
@@ -247,7 +262,6 @@ class marketing_campaign_segment(osv.osv):
uid, [('start', '=', True), ('campaign_id', '=', segment.campaign_id.id)], context=context)
model_obj = self.pool.get(segment.object_id.model)
partner_field = segment.campaign_id.partner_field_id.name
criteria = []
if segment.sync_last_date:
criteria += [(segment.sync_mode, '>', segment.sync_last_date)]
@@ -269,11 +283,7 @@ class marketing_campaign_segment(osv.osv):
'res_id': o_ids.id
}
partner = None
if partner_field:
partner = getattr(o_ids, partner_field)
elif model_obj._name == 'res.partner':
partner = o_ids
partner = self.pool.get('marketing.campaign')._get_partner_for(segment.campaign_id, o_ids)
if partner:
wi_vals['partner_id'] = partner.id
@@ -295,9 +305,7 @@ class marketing_campaign_activity(osv.osv):
('email', 'E-mail'),
('paper', 'Paper'),
('action', 'Action'),
# TODO implement the subcampaigns. The segment_id on woritems must be
# optional (thus campaign_id must be a real many2one, and a constraint
# must be set).
# TODO implement the subcampaigns.
# TODO implement the subcampaign out. disallow out transitions from
# subcampaign activities ?
#('subcampaign', 'Sub-Campaign'),
@@ -333,8 +341,9 @@ class marketing_campaign_activity(osv.osv):
'variable_cost': fields.float('Variable Cost'),
'revenue': fields.float('Revenue'),
'signal': fields.char('Signal', size=128,
help='An activity with a signal can be called \
programmatically'),
help='An activity with a signal can be called programmatically. Attention, the workitem is always created when the signal is send'),
'keep_if_condition_not_met': fields.boolean('Keep if condition not met',
help="By activating this option, the workitems that aren't processed because the condition is not met are marked as cancelled instead of being deleted.")
}
_defaults = {
@@ -342,20 +351,6 @@ class marketing_campaign_activity(osv.osv):
'condition': lambda *a: 'True',
}
def _check_signal(self, cr, uid, ids, context=None):
return all(activity.signal
for activity in self.browse(cr, uid, ids, context)
for transition in activity.from_ids
if transition.trigger == 'signal')
_constraints = [
(_check_signal,
"An incoming transition is triggered by a signal but this transition \
doesn't have one",
['signal', 'from_ids']
),
]
def search(self, cr, uid, args, offset=0, limit=None, order=None,
context=None, count=False):
if context == None:
@@ -431,7 +426,7 @@ class marketing_campaign_transition(osv.osv):
formatters = {
'auto': _('Automatic transition'),
'time': _('After %(interval_nbr)d %(interval_type)s'),
'signal': _('On signal'),
'cosmetic': _('Cosmetic'),
}
for tr in self.browse(cr, uid, ids, context=context,
fields_process=translate_selections):
@@ -462,9 +457,10 @@ class marketing_campaign_transition(osv.osv):
'trigger': fields.selection([('auto', 'Automatic'),
('time', 'Time'),
('signal','Signal')],
('cosmetic', 'Cosmetic'), # fake plastic transition
],
'Trigger', required=True,
help="How is trigger the destination workitem"),
help="How is triggered the destination workitem"),
}
_defaults = {
@@ -477,20 +473,6 @@ class marketing_campaign_transition(osv.osv):
('interval_positive', 'CHECK(interval_nbr >= 0)', 'The interval must be positive or zero')
]
def _check_signal(self, cr, uid, ids, context=None):
return all(tr.activity_to_id.signal
for tr in self.browse(cr, uid, ids, context)
if tr.trigger == 'signal')
_constraints = [
(_check_signal,
"The transition is triggered by a signal but destination activity \
doesn't have one",
['trigger', 'activity_to_ids']
),
]
marketing_campaign_transition()
class marketing_campaign_workitem(osv.osv):
@@ -510,13 +492,12 @@ class marketing_campaign_workitem(osv.osv):
return res
_columns = {
'segment_id': fields.many2one('marketing.campaign.segment', 'Segment',
required=True),
'segment_id': fields.many2one('marketing.campaign.segment', 'Segment'),
'activity_id': fields.many2one('marketing.campaign.activity','Activity',
required=True),
'campaign_id': fields.related('segment_id', 'campaign_id',
'campaign_id': fields.related('activity_id', 'campaign_id',
type='many2one', relation='marketing.campaign', string='Campaign', readonly=True),
'object_id': fields.related('segment_id', 'campaign_id', 'object_id',
'object_id': fields.related('activity_id', 'campaign_id', 'object_id',
type='many2one', relation='ir.model', string='Object', select=1),
'res_id': fields.integer('Resource ID', select=1, readonly=1),
'res_name': fields.function(_res_name_get, method=True, string='Resource Name', type="char", size=64),
@@ -564,7 +545,10 @@ class marketing_campaign_workitem(osv.osv):
campaign_mode = workitem.campaign_id.mode
if condition:
if not eval(condition, eval_context):
workitem.write({'state': 'cancelled'}, context=context)
if activity.keep_if_condition_not_met:
workitem.write({'state': 'cancelled'}, context=context)
else:
workitem.unlink(context=context)
return
result = True
if campaign_mode in ('manual', 'active'):
@@ -580,6 +564,8 @@ class marketing_campaign_workitem(osv.osv):
if result:
# process _chain
for transition in activity.to_ids:
if transition.trigger == 'cosmetic':
continue
launch_date = False
if transition.trigger == 'auto':
launch_date = datetime.now()
@@ -605,7 +591,7 @@ class marketing_campaign_workitem(osv.osv):
#
# test test_realtime manual normal (active)
# time Y N N N
# signal N N N N
# cosmetic N N N N
# auto Y Y Y Y
#
@@ -228,7 +228,12 @@
<separator string="Action" colspan="4"/>
<group colspan='4' col='4'>
<field name="condition" colspan='4'/>
<group colspan="4" col="6">
<field name="condition" colspan='5'/>
<group col='2'>
<field name="keep_if_condition_not_met" />
</group>
</group>
<field name="type" width='100'/>
<group colspan='2' col='1'>
<group attrs="{'invisible':[('type','!=','email')]}" >
@@ -93,8 +93,8 @@ class project_phase(osv.osv):
_columns = {
'name': fields.char("Name", size=64, required=True),
'date_start': fields.datetime('Start Date', help="Starting Date of the phase"),
'date_end': fields.datetime('End Date', help="Ending Date of the phase"),
'date_start': fields.date('Start Date', help="Starting Date of the phase"),
'date_end': fields.date('End Date', help="Ending Date of the phase"),
'constraint_date_start': fields.datetime('Start Date', help='force the phase to start after this date'),
'constraint_date_end': fields.datetime('End Date', help='force the phase to finish before this date'),
'project_id': fields.many2one('project.project', 'Project', required=True),
@@ -114,7 +114,7 @@ class project_phase(osv.osv):
'responsible_id': lambda obj,cr,uid,context: uid,
'state': 'draft',
'sequence': 10,
'product_uom': lambda self,cr,uid,c: self.pool.get('product.uom').search(cr, uid, [('name', '=', 'day')], context=c)[0]
'product_uom': lambda self,cr,uid,c: self.pool.get('product.uom').search(cr, uid, [('name', '=', _('Day'))], context=c)[0]
}
_order = "name"
_constraints = [