diff --git a/addons/account_check_writing/account_voucher.py b/addons/account_check_writing/account_voucher.py
index 8e1ad2e1fbf..e4933708f7a 100644
--- a/addons/account_check_writing/account_voucher.py
+++ b/addons/account_check_writing/account_voucher.py
@@ -49,9 +49,21 @@ class account_voucher(osv.osv):
if 'value' in default:
amount = 'amount' in default['value'] and default['value']['amount'] or amount
+ # Currency complete name is not available in res.currency model
+ # Exceptions done here (EUR, USD, BRL) cover 75% of cases
+ # For other currencies, display the currency code
+ currency = self.pool['res.currency'].browse(cr, uid, currency_id, context=context)
+ if currency.name.upper() == 'EUR':
+ currency_name = 'Euro'
+ elif currency.name.upper() == 'USD':
+ currency_name = 'Dollars'
+ elif currency.name.upper() == 'BRL':
+ currency_name = 'reais'
+ else:
+ currency_name = currency.name
#TODO : generic amount_to_text is not ready yet, otherwise language (and country) and currency can be passed
#amount_in_word = amount_to_text(amount, context=context)
- amount_in_word = amount_to_text(amount)
+ amount_in_word = amount_to_text(amount, currency=currency_name)
default['value'].update({'amount_in_word':amount_in_word})
if journal_id:
allow_check_writing = self.pool.get('account.journal').browse(cr, uid, journal_id, context=context).allow_check_writing
diff --git a/addons/account_check_writing/report/check_print.py b/addons/account_check_writing/report/check_print.py
index 57360025623..add79fcc35a 100644
--- a/addons/account_check_writing/report/check_print.py
+++ b/addons/account_check_writing/report/check_print.py
@@ -34,7 +34,6 @@ class report_print_check(report_sxw.rml_parse):
'fill_stars' : self.fill_stars,
})
def fill_stars(self, amount):
- amount = amount.replace('Dollars','')
if len(amount) < 100:
stars = 100 - len(amount)
return ' '.join([amount,'*'*stars])
diff --git a/addons/account_payment/account_payment_view.xml b/addons/account_payment/account_payment_view.xml
index 982de455063..0a2e907fcfd 100644
--- a/addons/account_payment/account_payment_view.xml
+++ b/addons/account_payment/account_payment_view.xml
@@ -41,7 +41,7 @@
-
+
diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py
index ef4c9379c82..d6ad6efdd90 100644
--- a/addons/account_voucher/account_voucher.py
+++ b/addons/account_voucher/account_voucher.py
@@ -746,7 +746,7 @@ class account_voucher(osv.osv):
ids = context['move_line_ids']
invoice_id = context.get('invoice_id', False)
company_currency = journal.company_id.currency_id.id
- move_line_found = False
+ move_lines_found = []
#order the lines by most old first
ids.reverse()
@@ -761,21 +761,20 @@ class account_voucher(osv.osv):
if line.invoice.id == invoice_id:
#if the invoice linked to the voucher line is equal to the invoice_id in context
#then we assign the amount on that line, whatever the other voucher lines
- move_line_found = line.id
- break
+ move_lines_found.append(line.id)
elif currency_id == company_currency:
#otherwise treatments is the same but with other field names
if line.amount_residual == price:
#if the amount residual is equal the amount voucher, we assign it to that voucher
#line, whatever the other voucher lines
- move_line_found = line.id
+ move_lines_found.append(line.id)
break
#otherwise we will split the voucher amount on each line (by most old first)
total_credit += line.credit or 0.0
total_debit += line.debit or 0.0
elif currency_id == line.currency_id.id:
if line.amount_residual_currency == price:
- move_line_found = line.id
+ move_lines_found.append(line.id)
break
total_credit += line.credit and line.amount_currency or 0.0
total_debit += line.debit and line.amount_currency or 0.0
@@ -800,15 +799,16 @@ class account_voucher(osv.osv):
'move_line_id':line.id,
'account_id':line.account_id.id,
'amount_original': amount_original,
- 'amount': (move_line_found == line.id) and min(abs(price), amount_unreconciled) or 0.0,
+ 'amount': (line.id in move_lines_found) and min(abs(price), amount_unreconciled) or 0.0,
'date_original':line.date,
'date_due':line.date_maturity,
'amount_unreconciled': amount_unreconciled,
'currency_id': line_currency_id,
}
+ price -= rs['amount']
#in case a corresponding move_line hasn't been found, we now try to assign the voucher amount
#on existing invoices: we split voucher amount by most old first, but only for lines in the same currency
- if not move_line_found:
+ if not move_lines_found:
if currency_id == line_currency_id:
if line.credit:
amount = min(amount_unreconciled, abs(total_debit))
diff --git a/addons/document/report/document_report.py b/addons/document/report/document_report.py
index c9df78e4272..a4133f46387 100644
--- a/addons/document/report/document_report.py
+++ b/addons/document/report/document_report.py
@@ -31,7 +31,7 @@ class report_document_user(osv.osv):
'name': fields.char('Year', size=64,readonly=True),
'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'), ('05','May'), ('06','June'),
('07','July'), ('08','August'), ('09','September'), ('10','October'), ('11','November'), ('12','December')],'Month',readonly=True),
- 'user_id':fields.integer('Owner', readonly=True),
+ 'user_id': fields.many2one('res.users', 'Owner', readonly=True),
'user': fields.related('user_id', 'name', type='char', size=64, readonly=True),
'directory': fields.char('Directory',size=64,readonly=True),
'datas_fname': fields.char('File Name',size=64,readonly=True),
diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py
index 6e19b1eb8aa..904481096d3 100644
--- a/addons/email_template/email_template.py
+++ b/addons/email_template/email_template.py
@@ -411,7 +411,17 @@ class email_template(osv.osv):
# create a mail_mail based on values, without attachments
values = self.generate_email(cr, uid, template_id, res_id, context=context)
assert values.get('email_from'), 'email_from is missing or empty after template rendering, send_mail() cannot proceed'
- del values['partner_to'] # TODO Properly use them.
+
+ # process partner_to field that is a comma separated list of partner_ids -> recipient_ids
+ # NOTE: only usable if force_send is True, because otherwise the value is
+ # not stored on the mail_mail, and therefore lost -> fixed in v8
+ values['recipient_ids'] = []
+ partner_to = values.pop('partner_to', '')
+ if partner_to:
+ # placeholders could generate '', 3, 2 due to some empty field values
+ tpl_partner_ids = [pid for pid in partner_to.split(',') if pid]
+ values['recipient_ids'] += [(4, pid) for pid in self.pool['res.partner'].exists(cr, SUPERUSER_ID, tpl_partner_ids, context=context)]
+
attachment_ids = values.pop('attachment_ids', [])
attachments = values.pop('attachments', [])
msg_id = mail_mail.create(cr, uid, values, context=context)
@@ -420,11 +430,11 @@ class email_template(osv.osv):
# manage attachments
for attachment in attachments:
attachment_data = {
- 'name': attachment[0],
- 'datas_fname': attachment[0],
- 'datas': attachment[1],
- 'res_model': 'mail.message',
- 'res_id': mail.mail_message_id.id,
+ 'name': attachment[0],
+ 'datas_fname': attachment[0],
+ 'datas': attachment[1],
+ 'res_model': 'mail.message',
+ 'res_id': mail.mail_message_id.id,
}
context.pop('default_type', None)
attachment_ids.append(ir_attachment.create(cr, uid, attachment_data, context=context))
diff --git a/addons/email_template/tests/test_ir_actions.py b/addons/email_template/tests/test_ir_actions.py
index d323ee36c1f..9b408a45316 100644
--- a/addons/email_template/tests/test_ir_actions.py
+++ b/addons/email_template/tests/test_ir_actions.py
@@ -33,7 +33,7 @@ class TestServerActionsEmail(TestServerActionsBase):
'name': 'TestTemplate',
'email_from': 'myself@example.com',
'email_to': 'brigitte@example.com',
- 'partner_to': '[%s]' % self.test_partner_id,
+ 'partner_to': '%s' % self.test_partner_id,
'model_id': self.res_partner_model_id,
'subject': 'About ${object.name}',
'body_html': '
Dear ${object.name}, your parent is ${object.parent_id and object.parent_id.name or "False"}
',
diff --git a/addons/email_template/tests/test_mail.py b/addons/email_template/tests/test_mail.py
index ccc8a49b875..a43bbe79713 100644
--- a/addons/email_template/tests/test_mail.py
+++ b/addons/email_template/tests/test_mail.py
@@ -21,6 +21,7 @@
import base64
from openerp.addons.mail.tests.common import TestMail
+from openerp.tools import mute_logger
class test_message_compose(TestMail):
@@ -200,3 +201,44 @@ class test_message_compose(TestMail):
# Generate messsage with default email and partner on template
mail_value = mail_compose.generate_email_for_composer(cr, uid, email_template_id, uid)
self.assertEqual(set(mail_value['partner_ids']), set(send_to), 'mail.message partner_ids list created by template is incorrect')
+
+ @mute_logger('openerp.osv.orm', 'openerp.osv.orm')
+ def test_10_email_templating(self):
+ """ Tests designed for the mail.compose.message wizard updated by email_template. """
+ cr, uid, context = self.cr, self.uid, {}
+
+ # create the email.template on mail.group model
+ group_model_id = self.registry('ir.model').search(cr, uid, [('model', '=', 'mail.group')])[0]
+ email_template = self.registry('email.template')
+ email_template_id = email_template.create(cr, uid, {
+ 'model_id': group_model_id,
+ 'name': 'Pigs Template',
+ 'email_from': 'Raoul Grosbedon ',
+ 'subject': '${object.name}',
+ 'body_html': '${object.description}',
+ 'user_signature': True,
+ 'email_to': 'b@b.b c@c.c',
+ 'email_cc': 'd@d.d',
+ 'partner_to': '${user.partner_id.id},%s,%s,-1' % (self.user_raoul.partner_id.id, self.user_bert.partner_id.id)
+ })
+
+ # not force send: email_recipients is not taken into account
+ msg_id = email_template.send_mail(cr, uid, email_template_id, self.group_pigs_id, context=context)
+ mail = self.mail_mail.browse(cr, uid, msg_id, context=context)
+ self.assertEqual(mail.subject, 'Pigs', 'email_template: send_mail: wrong subject')
+ self.assertEqual(mail.email_to, 'b@b.b c@c.c', 'email_template: send_mail: wrong email_to')
+ self.assertEqual(mail.email_cc, 'd@d.d', 'email_template: send_mail: wrong email_cc')
+ self.assertEqual(
+ set([partner.id for partner in mail.recipient_ids]),
+ set((self.partner_admin_id, self.user_raoul.partner_id.id, self.user_bert.partner_id.id)),
+ 'email_template: send_mail: wrong management of partner_to')
+
+ # force send: take email_recipients into account
+ email_template.send_mail(cr, uid, email_template_id, self.group_pigs_id, force_send=True, context=context)
+ sent_emails = self._build_email_kwargs_list
+ email_to_lst = [
+ ['b@b.b', 'c@c.c'], ['"Followers of Pigs" '],
+ ['"Followers of Pigs" '], ['"Followers of Pigs" ']]
+ self.assertEqual(len(sent_emails), 4, 'email_template: send_mail: 3 valid email recipients + email_to -> should send 4 emails')
+ for email in sent_emails:
+ self.assertIn(email['email_to'], email_to_lst, 'email_template: send_mail: wrong email_recipients')
diff --git a/addons/email_template/wizard/mail_compose_message.py b/addons/email_template/wizard/mail_compose_message.py
index bae7a0d8f9c..cd417a19d3c 100644
--- a/addons/email_template/wizard/mail_compose_message.py
+++ b/addons/email_template/wizard/mail_compose_message.py
@@ -19,7 +19,7 @@
#
##############################################################################
-from openerp import tools
+from openerp import tools, SUPERUSER_ID
from openerp.osv import osv, fields
@@ -143,9 +143,9 @@ class mail_compose_message(osv.TransientModel):
partner_ids.append(partner_id)
partner_to = rendered_values.pop('partner_to', '')
if partner_to:
- for partner_id in partner_to.split(','):
- if partner_id: # placeholders could generate '', 3, 2 due to some empty field values
- partner_ids.append(int(partner_id))
+ # placeholders could generate '', 3, 2 due to some empty field values
+ tpl_partner_ids = [pid for pid in partner_to.split(',') if pid]
+ partner_ids += self.pool['res.partner'].exists(cr, SUPERUSER_ID, tpl_partner_ids, context=context)
return partner_ids
def generate_email_for_composer_batch(self, cr, uid, template_id, res_ids, context=None):
diff --git a/addons/hr_holidays/report/holidays_summary_report.py b/addons/hr_holidays/report/holidays_summary_report.py
index d39ae53d5b6..adf09a63c85 100644
--- a/addons/hr_holidays/report/holidays_summary_report.py
+++ b/addons/hr_holidays/report/holidays_summary_report.py
@@ -96,7 +96,7 @@ class report_custom(report_rml):
res=cr.fetchone()[0]
date_xml=[]
date_today=time.strftime('%Y-%m-%d %H:%M:%S')
- date_xml +=['' % (res,date_today)]
+ date_xml +=['' % (to_xml(res),date_today)]
cr.execute("SELECT id, name, color_name FROM hr_holidays_status ORDER BY id")
legend=cr.fetchall()
@@ -128,7 +128,7 @@ class report_custom(report_rml):
# date_xml=[]
for l in range(0,len(legend)):
date_xml += ['' % (l+1,legend[l][0],_(legend[l][1]),legend[l][2])]
- date_xml += ['' % (som.strftime('%B'), som.year),'']
+ date_xml += ['' % (ustr(som.strftime('%B')), som.year),'']
cell=1
if day_diff.days>=30:
diff --git a/addons/hr_payroll/hr_payroll.py b/addons/hr_payroll/hr_payroll.py
index e7d4cef594a..c0df993c4bc 100644
--- a/addons/hr_payroll/hr_payroll.py
+++ b/addons/hr_payroll/hr_payroll.py
@@ -143,8 +143,9 @@ class hr_contract(osv.osv):
@param contract_ids: list of contracts
@return: the structures linked to the given contracts, ordered by hierachy (parent=False first, then first level children and so on) and without duplicata
"""
- all_structures = []
- structure_ids = [contract.struct_id.id for contract in self.browse(cr, uid, contract_ids, context=context)]
+ structure_ids = [contract.struct_id.id for contract in self.browse(cr, uid, contract_ids, context=context) if contract.struct_id]
+ if not structure_ids:
+ return []
return list(set(self.pool.get('hr.payroll.structure')._get_parent_structure(cr, uid, structure_ids, context=context)))
diff --git a/addons/hr_timesheet/report/users_timesheet.py b/addons/hr_timesheet/report/users_timesheet.py
index d8c4927947d..0d3f23e6bd3 100644
--- a/addons/hr_timesheet/report/users_timesheet.py
+++ b/addons/hr_timesheet/report/users_timesheet.py
@@ -106,7 +106,7 @@ class report_custom(report_rml):
%s
%s
- ''' % (str(rml_obj.formatLang(time.strftime("%Y-%m-%d"),date=True))+' ' + str(time.strftime("%H:%M")),registry['res.users'].browse(cr,uid,uid).company_id.name)
+ ''' % (str(rml_obj.formatLang(time.strftime("%Y-%m-%d"),date=True))+' ' + str(time.strftime("%H:%M")),toxml(registry['res.users'].browse(cr,uid,uid).company_id.name))
xml='''
diff --git a/addons/project/project.py b/addons/project/project.py
index 2e7b0a267e4..0f5c8dbef50 100644
--- a/addons/project/project.py
+++ b/addons/project/project.py
@@ -478,7 +478,7 @@ def Project():
""" % (
project.id,
project.date_start or time.strftime('%Y-%m-%d'), working_days,
- '|'.join(['User_'+str(x) for x in puids])
+ '|'.join(['User_'+str(x) for x in puids]) or 'None'
)
vacation = calendar_id and tuple(resource_pool.compute_vacation(cr, uid, calendar_id, context=context)) or False
if vacation:
@@ -788,7 +788,7 @@ class task(osv.osv):
}),
'progress': fields.function(_hours_get, string='Working Time Progress (%)', multi='hours', group_operator="avg", help="If the task has a progress of 99.99% you should close the task if it's finished or reevaluate the time",
store = {
- 'project.task': (lambda self, cr, uid, ids, c={}: ids, ['work_ids', 'remaining_hours', 'planned_hours','state'], 10),
+ 'project.task': (lambda self, cr, uid, ids, c={}: ids, ['work_ids', 'remaining_hours', 'planned_hours', 'state', 'stage_id'], 10),
'project.task.work': (_get_task, ['hours'], 10),
}),
'delay_hours': fields.function(_hours_get, string='Delay Hours', multi='hours', help="Computed as difference between planned hours by the project manager and the total hours of the task.",
diff --git a/addons/purchase/report/purchase_report_view.xml b/addons/purchase/report/purchase_report_view.xml
index 909663f43bb..58270f0ccd1 100644
--- a/addons/purchase/report/purchase_report_view.xml
+++ b/addons/purchase/report/purchase_report_view.xml
@@ -71,10 +71,8 @@
-
-