diff --git a/addons/account/demo/account_minimal.xml b/addons/account/demo/account_minimal.xml
index abae5562b2c..e18dab2d332 100644
--- a/addons/account/demo/account_minimal.xml
+++ b/addons/account/demo/account_minimal.xml
@@ -82,21 +82,21 @@
- Assets - (test)
- X10
- view
-
-
-
+ Assets - (test)
+ X10
+ view
+
+
+
- Liabilities - (test)
- X11
- view
-
-
-
+ Liabilities - (test)
+ X11
+ view
+
+
+
@@ -208,23 +208,32 @@
- Income - (test)
- X20
- view
-
-
-
+ Income - (test)
+ X20
+ view
+
+
+
+
+
+
+ Foreign Exchange Gain - (test)
+ X201
+ other
+
+
+
- Expense - (test)
- X21
- view
-
-
-
+ Expense - (test)
+ X21
+ view
+
+
+
-
+
X200
Revenue - (test)
@@ -273,6 +282,14 @@
+
+ Foreign Exchange Loss - (test)
+ X2111
+ other
+
+
+
+
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index 0e078820062..bffb1fc53b8 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -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
diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml
index 39c65cb6faf..590aa9931ee 100644
--- a/addons/crm/crm_lead_view.xml
+++ b/addons/crm/crm_lead_view.xml
@@ -91,7 +91,7 @@
-
+
+
+
diff --git a/addons/crm/wizard/crm_send_email.py b/addons/crm/wizard/crm_send_email.py
index 83b1959b196..27bc9328b61 100644
--- a/addons/crm/wizard/crm_send_email.py
+++ b/addons/crm/wizard/crm_send_email.py
@@ -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()
diff --git a/addons/crm/wizard/crm_send_email_view.xml b/addons/crm/wizard/crm_send_email_view.xml
index 3dfde724bdf..df7218cbc02 100644
--- a/addons/crm/wizard/crm_send_email_view.xml
+++ b/addons/crm/wizard/crm_send_email_view.xml
@@ -12,6 +12,7 @@
-
diff --git a/addons/crm_fundraising/report/crm_fundraising_report_view.xml b/addons/crm_fundraising/report/crm_fundraising_report_view.xml
index 4a5e05b28e1..8bf5a993925 100644
--- a/addons/crm_fundraising/report/crm_fundraising_report_view.xml
+++ b/addons/crm_fundraising/report/crm_fundraising_report_view.xml
@@ -198,7 +198,7 @@
-
diff --git a/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml b/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml
index 1ebdb041a9a..0ee5d565a08 100644
--- a/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml
+++ b/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml
@@ -179,7 +179,7 @@
-
diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py
index 730502bc549..07dce405c07 100644
--- a/addons/email_template/email_template.py
+++ b/addons/email_template/email_template.py
@@ -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,
diff --git a/addons/l10n_chart_uk_minimal/account_chart.xml b/addons/l10n_chart_uk_minimal/account_chart.xml
index 804568afecc..17eae399ef8 100644
--- a/addons/l10n_chart_uk_minimal/account_chart.xml
+++ b/addons/l10n_chart_uk_minimal/account_chart.xml
@@ -22,21 +22,21 @@
- Assets
- 10
- view
-
-
-
+ Assets
+ 10
+ view
+
+
+
- Liabilities
- 11
- view
-
-
-
+ Liabilities
+ 11
+ view
+
+
+
@@ -156,21 +156,30 @@
- Income
- 20
- view
-
-
-
+ Income
+ 20
+ view
+
+
+
+
+
+
+ Foreign Exchange Gain
+ X201
+ other
+
+
+
- Expense
- 21
- view
-
-
-
+ Expense
+ 21
+ view
+
+
+
@@ -225,10 +234,18 @@
+
+ Foreign Exchange Loss - (test)
+ X2111
+ other
+
+
+
+
+
-
diff --git a/addons/marketing_campaign/marketing_campaign.py b/addons/marketing_campaign/marketing_campaign.py
index 3b72f183f89..83e5ed4f19f 100644
--- a/addons/marketing_campaign/marketing_campaign.py
+++ b/addons/marketing_campaign/marketing_campaign.py
@@ -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
#
diff --git a/addons/marketing_campaign/marketing_campaign_view.xml b/addons/marketing_campaign/marketing_campaign_view.xml
index 4ac70292c32..1d07fc1e99c 100644
--- a/addons/marketing_campaign/marketing_campaign_view.xml
+++ b/addons/marketing_campaign/marketing_campaign_view.xml
@@ -228,7 +228,12 @@
-
+
+
+
+
+
+
diff --git a/addons/project_long_term/project_long_term.py b/addons/project_long_term/project_long_term.py
index f1b4ab804c9..e1233bc413e 100644
--- a/addons/project_long_term/project_long_term.py
+++ b/addons/project_long_term/project_long_term.py
@@ -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 = [