summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandhir Mayatra (OpenERP) <rma@tinyerp.com>2012-11-19 16:38:24 +0530
committerRandhir Mayatra (OpenERP) <rma@tinyerp.com>2012-11-19 16:38:24 +0530
commitd23c5c8dca985dd0fde280c9237dee85b7bb4d7a (patch)
treecf03bc2a74a1d9e93b5ef571fb78070c09c9857b
parentf4ab81afb8285a8157258232c5fb2a6745ae7f72 (diff)
parent66afff1b52b7ab6ab8c340e18960fb6367cfb714 (diff)
[MERGE]merge with trunk
bzr revid: rma@tinyerp.com-20121119110824-rj4y32rfbszqln7g
-rw-r--r--addons/account/account_analytic_line.py2
-rw-r--r--addons/account/account_bank_statement.py13
-rw-r--r--addons/account/account_invoice.py5
-rw-r--r--addons/account/account_invoice_view.xml2
-rw-r--r--addons/account/account_move_line.py6
-rw-r--r--addons/account/account_report.xml8
-rw-r--r--addons/account/account_view.xml32
-rw-r--r--addons/account/edi/invoice_action_data.xml2
-rw-r--r--addons/account/i18n/es_AR.po33
-rw-r--r--addons/account/partner_view.xml4
-rw-r--r--addons/account/report/account_financial_report.rml4
-rw-r--r--addons/account/report/account_general_ledger.py6
-rw-r--r--addons/account/report/common_report_header.py6
-rw-r--r--addons/account/test/account_report.yml12
-rw-r--r--addons/account/tests/__init__.py4
-rw-r--r--addons/account/tests/test_tax.py49
-rw-r--r--addons/account/wizard/account_financial_report_view.xml22
-rw-r--r--addons/account/wizard/account_fiscalyear_close.py2
-rw-r--r--addons/account/wizard/account_open_closed_fiscalyear.py4
-rw-r--r--addons/account/wizard/account_open_closed_fiscalyear_view.xml12
-rw-r--r--addons/account/wizard/account_report_account_balance_view.xml3
-rw-r--r--addons/account/wizard/account_report_common.py6
-rw-r--r--addons/account_accountant/account_accountant_data.xml8
-rw-r--r--addons/account_analytic_plans/account_analytic_plans_view.xml8
-rw-r--r--addons/account_anglo_saxon/invoice.py4
-rw-r--r--addons/account_asset/account_asset.py20
-rw-r--r--addons/account_bank_statement_extensions/account_bank_statement_view.xml10
-rw-r--r--addons/account_budget/account_budget_view.xml12
-rw-r--r--addons/account_check_writing/i18n/es.po10
-rw-r--r--addons/account_check_writing/i18n/lt.po199
-rw-r--r--addons/account_sequence/account_sequence_data.xml12
-rw-r--r--addons/account_voucher/account_voucher.py63
-rw-r--r--addons/account_voucher/account_voucher_data.xml8
-rw-r--r--addons/account_voucher/account_voucher_view.xml20
-rw-r--r--addons/account_voucher/i18n/nl.po10
-rw-r--r--addons/account_voucher/voucher_payment_receipt_view.xml28
-rw-r--r--addons/account_voucher/voucher_sales_purchase_view.xml2
-rw-r--r--addons/analytic/analytic.py6
-rw-r--r--addons/anonymization/security/ir.model.access.csv1
-rw-r--r--addons/audittrail/audittrail.py15
-rw-r--r--addons/audittrail/audittrail_view.xml2
-rw-r--r--addons/auth_anonymous/static/src/js/auth_anonymous.js4
-rw-r--r--addons/auth_oauth/controllers/main.py81
-rw-r--r--addons/auth_oauth/res_users.py35
-rw-r--r--addons/auth_oauth/static/src/js/auth_oauth.js17
-rw-r--r--addons/auth_signup/static/src/js/auth_signup.js10
-rw-r--r--addons/base_action_rule/i18n/es.po11
-rw-r--r--addons/base_calendar/crm_meeting_view.xml2
-rw-r--r--addons/base_gengo/wizard/base_gengo_translations.py39
-rw-r--r--addons/base_gengo/wizard/base_gengo_translations_view.xml11
-rw-r--r--addons/base_iban/base_iban.py6
-rw-r--r--addons/base_import/__openerp__.py6
-rw-r--r--addons/base_import/static/test/states.js6
-rw-r--r--addons/base_setup/__openerp__.py1
-rw-r--r--addons/base_status/base_stage.py2
-rw-r--r--addons/base_tools/i18n/hu.po30
-rw-r--r--addons/claim_from_delivery/i18n/lt.po23
-rw-r--r--addons/crm/crm.py2
-rw-r--r--addons/crm/crm_action_rule.py2
-rw-r--r--addons/crm/crm_data.xml5
-rw-r--r--addons/crm/crm_lead.py8
-rw-r--r--addons/crm/crm_view.xml31
-rw-r--r--addons/crm/i18n/es.po46
-rw-r--r--addons/crm/report/crm_phonecall_report_view.xml2
-rw-r--r--addons/crm_claim/crm_claim.py2
-rw-r--r--addons/crm_claim/crm_claim_data.xml18
-rw-r--r--addons/crm_claim/crm_claim_menu.xml2
-rw-r--r--addons/crm_claim/crm_claim_view.xml15
-rw-r--r--addons/crm_helpdesk/crm_helpdesk_view.xml2
-rw-r--r--addons/crm_partner_assign/i18n/es.po104
-rw-r--r--addons/document/nodes.py1
-rw-r--r--addons/document_ftp/ftpserver/abstracted_fs.py2
-rw-r--r--addons/document_page/wizard/document_page_show_diff.py2
-rw-r--r--addons/document_webdav/document_webdav.py3
-rw-r--r--addons/email_template/email_template.py12
-rw-r--r--addons/email_template/email_template_view.xml4
-rw-r--r--addons/email_template/tests/test_mail.py56
-rw-r--r--addons/email_template/wizard/email_template_preview_view.xml1
-rw-r--r--addons/email_template/wizard/mail_compose_message.py45
-rw-r--r--addons/email_template/wizard/mail_compose_message_view.xml31
-rw-r--r--addons/event/event_view.xml4
-rw-r--r--addons/event/static/src/css/event.css2
-rw-r--r--addons/event_sale/event_sale.py2
-rw-r--r--addons/fetchmail/fetchmail.py10
-rw-r--r--addons/fleet/fleet.py14
-rw-r--r--addons/fleet/fleet_board_view.xml2
-rw-r--r--addons/fleet/fleet_view.xml7
-rw-r--r--addons/fleet/security/ir.model.access.csv4
-rw-r--r--addons/fleet/static/src/img/icon.pngbin11334 -> 23083 bytes
-rw-r--r--addons/hr/hr.py4
-rw-r--r--addons/hr/hr_data.xml8
-rw-r--r--addons/hr/hr_view.xml4
-rw-r--r--addons/hr/i18n/es_EC.po21
-rw-r--r--addons/hr/static/src/css/hr.css3
-rw-r--r--addons/hr_attendance/report/attendance_by_month.py3
-rw-r--r--addons/hr_evaluation/hr_evaluation_data.xml8
-rw-r--r--addons/hr_expense/hr_expense.py28
-rw-r--r--addons/hr_expense/hr_expense_data.xml6
-rw-r--r--addons/hr_expense/hr_expense_view.xml2
-rw-r--r--addons/hr_holidays/hr_holidays.py12
-rw-r--r--addons/hr_holidays/hr_holidays_data.xml5
-rw-r--r--addons/hr_holidays/hr_holidays_view.xml4
-rw-r--r--addons/hr_holidays/report/holidays_summary_report.py3
-rw-r--r--addons/hr_payroll/hr_payroll.py7
-rw-r--r--addons/hr_payroll/hr_payroll_demo.xml4
-rw-r--r--addons/hr_recruitment/hr_recruitment_data.xml6
-rw-r--r--addons/hr_recruitment/hr_recruitment_view.xml6
-rw-r--r--addons/hr_timesheet/i18n/de.po62
-rw-r--r--addons/hr_timesheet/report/user_timesheet.py3
-rw-r--r--addons/hr_timesheet/wizard/hr_timesheet_print_employee.py5
-rw-r--r--addons/hr_timesheet/wizard/hr_timesheet_print_users.py5
-rw-r--r--addons/hr_timesheet_sheet/hr_timesheet_sheet_data.xml3
-rw-r--r--addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml2
-rw-r--r--addons/l10n_ar/i18n/es_AR.po20
-rw-r--r--addons/l10n_be/wizard/l10n_be_partner_vat_listing.py8
-rw-r--r--addons/l10n_be_coda/wizard/account_coda_import.py2
-rw-r--r--addons/l10n_be_hr_payroll/i18n/de.po163
-rw-r--r--addons/l10n_be_hr_payroll/i18n/es.po158
-rw-r--r--addons/l10n_be_invoice_bba/i18n/es.po141
-rw-r--r--addons/l10n_ch/bank.py15
-rw-r--r--addons/l10n_fr/fr_tax.xml4
-rw-r--r--addons/l10n_fr/plan_comptable_general.xml10
-rw-r--r--addons/l10n_in_hr_payroll/i18n/es.po942
-rw-r--r--addons/l10n_it/data/account.tax.code.template.csv3
-rw-r--r--addons/l10n_it/data/account.tax.template.csv1
-rw-r--r--addons/l10n_multilang/i18n/ar.po172
-rw-r--r--addons/l10n_nl/account_chart_netherlands.xml126
-rw-r--r--addons/l10n_pe/i18n/ar.po47
-rw-r--r--addons/lunch/lunch_demo.xml6
-rw-r--r--addons/lunch/lunch_view.xml14
-rw-r--r--addons/lunch/security/ir.model.access.csv5
-rw-r--r--addons/lunch/wizard/lunch_cancel_view.xml3
-rw-r--r--addons/lunch/wizard/lunch_order.py2
-rw-r--r--addons/lunch/wizard/lunch_order_view.xml1
-rw-r--r--addons/lunch/wizard/lunch_validation_view.xml1
-rw-r--r--addons/mail/__init__.py2
-rw-r--r--addons/mail/data/mail_demo.xml61
-rw-r--r--addons/mail/data/mail_group_data.xml11
-rw-r--r--addons/mail/mail_followers.py27
-rw-r--r--addons/mail/mail_group.py2
-rw-r--r--addons/mail/mail_group_view.xml21
-rw-r--r--addons/mail/mail_message.py331
-rw-r--r--addons/mail/mail_message_view.xml12
-rw-r--r--addons/mail/mail_thread.py134
-rw-r--r--addons/mail/mail_thread_view.xml106
-rw-r--r--addons/mail/res_partner.py19
-rw-r--r--addons/mail/res_users.py14
-rw-r--r--addons/mail/security/ir.model.access.csv9
-rw-r--r--addons/mail/security/mail_security.xml10
-rw-r--r--addons/mail/static/src/css/mail.css276
-rw-r--r--addons/mail/static/src/css/mail_group.css34
-rw-r--r--addons/mail/static/src/img/mimetypes/addresses.pngbin0 -> 3151 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/archive.pngbin0 -> 2450 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/audio.pngbin0 -> 2290 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/binary.pngbin0 -> 3060 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/calendar.pngbin0 -> 2848 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/certificate.pngbin0 -> 1643 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/disk.pngbin0 -> 3997 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/document.pngbin0 -> 2625 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/font.pngbin0 -> 3894 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/html.pngbin0 -> 3347 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/image.pngbin0 -> 2603 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/presentation.pngbin0 -> 2260 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/print.pngbin0 -> 2625 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/script.pngbin0 -> 3025 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/spreadsheet.pngbin0 -> 2693 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/text.pngbin0 -> 2086 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/unknown.pngbin0 -> 2086 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/vector.pngbin0 -> 2865 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/video.pngbin0 -> 4665 bytes
-rw-r--r--addons/mail/static/src/img/mimetypes/webimage.pngbin0 -> 2603 bytes
-rw-r--r--addons/mail/static/src/js/mail.js1155
-rw-r--r--addons/mail/static/src/js/mail_followers.js21
-rw-r--r--addons/mail/static/src/xml/mail.xml109
-rw-r--r--addons/mail/tests/__init__.py1
-rw-r--r--addons/mail/tests/test_mail.py93
-rw-r--r--addons/mail/tests/test_mail_access_rights.py10
-rw-r--r--addons/mail/tests/test_mail_mockup.py54
-rw-r--r--addons/mail/wizard/mail_compose_message.py16
-rw-r--r--addons/mail/wizard/mail_compose_message_view.xml15
-rw-r--r--addons/marketing/i18n/lt.po28
-rw-r--r--addons/mrp/mrp_data.xml8
-rw-r--r--addons/mrp/report/price.py2
-rw-r--r--addons/mrp/res_config.py4
-rw-r--r--addons/mrp/res_config_view.xml4
-rw-r--r--addons/mrp_jit/i18n/sl.po29
-rw-r--r--addons/mrp_repair/mrp_repair.py2
-rw-r--r--addons/note/__openerp__.py1
-rw-r--r--addons/note/i18n/pt_BR.po334
-rw-r--r--addons/note/note.py4
-rw-r--r--addons/note/note_view.xml2
-rw-r--r--addons/note/security/ir.rule.xml4
-rw-r--r--addons/note/static/src/css/note.css4
-rw-r--r--addons/note/static/src/css/note.sass4
-rw-r--r--addons/pad/pad.py4
-rw-r--r--addons/pad/pad_demo.xml6
-rw-r--r--addons/pad/static/src/js/pad.js1
-rw-r--r--addons/point_of_sale/point_of_sale_data.xml6
-rw-r--r--addons/point_of_sale/report/pos_receipt.py2
-rw-r--r--addons/point_of_sale/static/src/js/models.js2
-rw-r--r--addons/point_of_sale/static/src/js/screens.js6
-rw-r--r--addons/point_of_sale/static/src/js/widgets.js7
-rw-r--r--addons/point_of_sale/wizard/pos_payment.py3
-rw-r--r--addons/portal/mail_mail.py2
-rw-r--r--addons/portal/portal_demo.xml47
-rw-r--r--addons/portal/tests/test_portal.py9
-rw-r--r--addons/portal/wizard/portal_wizard.py3
-rw-r--r--addons/portal/wizard/share_wizard.py4
-rw-r--r--addons/portal_claim/security/portal_security.xml4
-rw-r--r--addons/portal_project/security/portal_security.xml4
-rw-r--r--addons/portal_project_issue/security/portal_security.xml4
-rw-r--r--addons/portal_sale/security/portal_security.xml4
-rw-r--r--addons/process/__openerp__.py2
-rw-r--r--addons/product/product.py4
-rw-r--r--addons/product_expiry/product_expiry.py18
-rw-r--r--addons/product_margin/product_margin.py7
-rw-r--r--addons/product_visible_discount/i18n/lt.po62
-rw-r--r--addons/project/project.py14
-rw-r--r--addons/project/project_data.xml8
-rw-r--r--addons/project/project_demo.xml22
-rw-r--r--addons/project/project_view.xml2
-rw-r--r--addons/project_gtd/__openerp__.py2
-rw-r--r--addons/project_gtd/project_gtd_data.xml5
-rw-r--r--addons/project_issue/project_issue_data.xml7
-rw-r--r--addons/project_issue/project_issue_demo.xml19
-rw-r--r--addons/project_long_term/project_long_term_view.xml4
-rw-r--r--addons/purchase/edi/purchase_order_action_data.xml2
-rw-r--r--addons/purchase/purchase.py27
-rw-r--r--addons/purchase/purchase_data.xml6
-rw-r--r--addons/purchase/stock_view.xml2
-rw-r--r--addons/sale/edi/sale_order_action_data.xml2
-rw-r--r--addons/sale/i18n/lv.po460
-rw-r--r--addons/sale/sale.py21
-rw-r--r--addons/sale/sale_data.xml6
-rw-r--r--addons/sale/sale_demo.xml2
-rw-r--r--addons/sale/sale_view.xml3
-rw-r--r--addons/sale_crm/wizard/crm_make_sale.py4
-rw-r--r--addons/share/wizard/share_wizard.py2
-rw-r--r--addons/stock/stock.py29
-rw-r--r--addons/stock/stock_data.xml5
-rw-r--r--addons/stock/stock_sequence.xml4
-rw-r--r--addons/stock/stock_view.xml7
-rw-r--r--addons/stock/wizard/stock_change_product_qty_view.xml2
-rw-r--r--addons/stock/wizard/stock_fill_inventory.py2
-rw-r--r--addons/web_linkedin/static/src/js/linkedin.js4
-rw-r--r--addons/web_shortcuts/static/src/js/web_shortcuts.js8
246 files changed, 5393 insertions, 1930 deletions
diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py
index f0a420f7496..066f8d1abec 100644
--- a/addons/account/account_analytic_line.py
+++ b/addons/account/account_analytic_line.py
@@ -107,7 +107,7 @@ class account_analytic_line(osv.osv):
if journal_id:
journal = analytic_journal_obj.browse(cr, uid, journal_id, context=context)
if journal.type == 'sale':
- product_price_type_ids = product_price_type_obj.search(cr, uid, [('field','=','list_price')], context)
+ product_price_type_ids = product_price_type_obj.search(cr, uid, [('field','=','list_price')], context=context)
if product_price_type_ids:
pricetype = product_price_type_obj.browse(cr, uid, product_price_type_ids, context=context)[0]
# Take the company currency as the reference one
diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py
index 8e79376aa87..4422537007f 100644
--- a/addons/account/account_bank_statement.py
+++ b/addons/account/account_bank_statement.py
@@ -486,6 +486,19 @@ class account_bank_statement(osv.osv):
default['move_line_ids'] = []
return super(account_bank_statement, self).copy(cr, uid, id, default, context=context)
+ def button_journal_entries(self, cr, uid, ids, context=None):
+ ctx = (context or {}).copy()
+ ctx['journal_id'] = self.browse(cr, uid, ids[0], context=context).journal_id.id
+ return {
+ 'view_type':'form',
+ 'view_mode':'tree',
+ 'res_model':'account.move.line',
+ 'view_id':False,
+ 'type':'ir.actions.act_window',
+ 'domain':[('statement_id','in',ids)],
+ 'context':ctx,
+ }
+
account_bank_statement()
class account_bank_statement_line(osv.osv):
diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py
index b01fc974bef..3e86c4963b7 100644
--- a/addons/account/account_invoice.py
+++ b/addons/account/account_invoice.py
@@ -402,6 +402,7 @@ class account_invoice(osv.osv):
'default_res_id': ids[0],
'default_use_template': True,
'default_template_id': template_id,
+ 'default_composition_mode': 'comment',
})
return {
'view_type': 'form',
@@ -431,7 +432,7 @@ class account_invoice(osv.osv):
if t['state'] in ('draft', 'cancel') and t['internal_number']== False:
unlink_ids.append(t['id'])
else:
- raise osv.except_osv(_('Invalid Action!'), _('You cannot delete an invoice which is open or paid. You should refund it instead.'))
+ raise osv.except_osv(_('Invalid Action!'), _('You can not delete an invoice which is not cancelled. You should refund it instead.'))
osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
return True
@@ -983,13 +984,13 @@ class account_invoice(osv.osv):
for i in line:
i[2]['period_id'] = period_id
+ ctx.update(invoice=inv)
move_id = move_obj.create(cr, uid, move, context=ctx)
new_move_name = move_obj.browse(cr, uid, move_id, context=ctx).name
# make the invoice point to that move
self.write(cr, uid, [inv.id], {'move_id': move_id,'period_id':period_id, 'move_name':new_move_name}, context=ctx)
# Pass invoice in context in method post: used if you want to get the same
# account move reference when creating the same invoice after a cancelled one:
- ctx.update({'invoice':inv})
move_obj.post(cr, uid, [move_id], context=ctx)
self._log_event(cr, uid, ids)
return True
diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml
index 4feb97c2f5f..d3697b13ea9 100644
--- a/addons/account/account_invoice_view.xml
+++ b/addons/account/account_invoice_view.xml
@@ -436,7 +436,7 @@
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
- <field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
+ <field name="message_ids" widget="mail_thread" placeholder="Share a note..."/>
</div>
</form>
</field>
diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py
index 9012b930641..302a74c27af 100644
--- a/addons/account/account_move_line.py
+++ b/addons/account/account_move_line.py
@@ -208,7 +208,7 @@ class account_move_line(osv.osv):
if type(period_id) == str:
ids = period_obj.search(cr, uid, [('name', 'ilike', period_id)])
context.update({
- 'period_id': ids[0]
+ 'period_id': ids and ids[0] or False
})
return context
@@ -582,7 +582,7 @@ class account_move_line(osv.osv):
lines = self.browse(cr, uid, ids, context=context)
for l in lines:
if l.account_id.type == 'view':
- raise osv.except_osv(_('Error!'), _('You cannot create journal items on “View” type account %s %s.') % (l.account_id.code, l.account_id.name))
+ return False
return True
def _check_no_closed(self, cr, uid, ids, context=None):
@@ -917,7 +917,7 @@ class account_move_line(osv.osv):
if lines and lines[0]:
partner_id = lines[0].partner_id and lines[0].partner_id.id or False
- if not partner_obj.has_something_to_reconcile(cr, uid, partner_id, context=context):
+ if partner_id and not partner_obj.has_something_to_reconcile(cr, uid, partner_id, context=context):
partner_obj.mark_as_reconciled(cr, uid, [partner_id], context=context)
return r_id
diff --git a/addons/account/account_report.xml b/addons/account/account_report.xml
index d258bb0b140..0017409f416 100644
--- a/addons/account/account_report.xml
+++ b/addons/account/account_report.xml
@@ -41,13 +41,5 @@
groups="group_account_user,group_account_manager"
parent="account.menu_finance_generic_reporting" sequence="3"/>
- <report id="account_account_balance_landscape"
- string="Account balance"
- model="account.account"
- name="account.account.balance.landscape"
- rml="account/report/account_balance_landscape.rml"
- auto="False"
- menu="False"/>
-
</data>
</openerp>
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index 1c7c268e905..f7d64f43405 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -302,11 +302,11 @@
<field name="domain">[('parent_id','=',False)]</field>
</record>
- <record id="view_account_gain_loss_tree" model="ir.ui.view">
+ <record id="view_account_gain_loss_tree" model="ir.ui.view">
<field name="name">Unrealized Gain or Loss</field>
<field name="model">account.account</field>
<field name="arch" type="xml">
- <tree string="Unrealized Gains and losses">
+ <tree string="Unrealized Gains and losses" create="false">
<field name="code"/>
<field name="name"/>
<field name="parent_id" invisible="1"/>
@@ -322,7 +322,7 @@
</field>
</record>
- <record id="action_account_gain_loss" model="ir.actions.act_window">
+ <record id="action_account_gain_loss" model="ir.actions.act_window">
<field name="name">Unrealized Gain or Loss</field>
<field name="res_model">account.account</field>
<field name="view_type">form</field>
@@ -650,7 +650,7 @@
<field name="ref"/>
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
<field name="type" on_change="onchange_type(partner_id, type)"/>
- <field domain="[('journal_id','=',parent.journal_id), ('company_id', '=', parent.company_id)]" name="account_id"/>
+ <field name="account_id" options='{"no_open":True}' domain="[('journal_id','=',parent.journal_id), ('company_id', '=', parent.company_id)]"/>
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '&lt;&gt;', 'view')]"/>
<field name="amount"/>
</tree>
@@ -661,7 +661,7 @@
<field name="ref"/>
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
<field name="type" on_change="onchange_type(partner_id, type)"/>
- <field domain="[('journal_id', '=', parent.journal_id), ('type', '&lt;&gt;', 'view'), ('company_id', '=', parent.company_id)]" name="account_id"/>
+ <field name="account_id" domain="[('journal_id', '=', parent.journal_id), ('type', '&lt;&gt;', 'view'), ('company_id', '=', parent.company_id)]"/>
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '&lt;&gt;', 'view')]"/>
<field name="amount"/>
<field name="sequence" readonly="0"/>
@@ -671,15 +671,24 @@
</form>
</field>
</page>
- <page string="Journal Entries" name="move_live_ids">
- <field name="move_line_ids"/>
- </page>
</notebook>
</sheet>
</form>
</field>
</record>
+ <record id="view_bank_statement_form_journal_items" model="ir.ui.view">
+ <field name="name">account.bank.statement.journal.items.form.inherit</field>
+ <field name="model">account.bank.statement</field>
+ <field name="inherit_id" ref="view_bank_statement_form"/>
+ <field name="arch" type="xml">
+ <xpath expr="//div[@name='import_buttons']" position="inside">
+ <button name="button_journal_entries"
+ string="Journal Items" type="object"
+ attrs="{'invisible':[('state','!=','confirm')]}"/>
+ </xpath>
+ </field>
+ </record>
<record id="action_bank_statement_tree" model="ir.actions.act_window">
<field name="name">Bank Statements</field>
@@ -1055,7 +1064,7 @@
</field>
</record>
- <record id="view_move_line_tree" model="ir.ui.view">
+ <record id="view_move_line_tree" model="ir.ui.view">
<field name="name">account.move.line.tree</field>
<field name="model">account.move.line</field>
<field eval="4" name="priority"/>
@@ -1850,7 +1859,7 @@
</field>
</record>
- <record id="view_subscription_search" model="ir.ui.view">
+ <record id="view_subscription_search" model="ir.ui.view">
<field name="name">account.subscription.search</field>
<field name="model">account.subscription</field>
<field name="arch" type="xml">
@@ -2159,7 +2168,8 @@
<field name="visible" />
<field name="complete_tax_set" />
</group>
- <field name="tax_template_ids" colspan="4" readonly="1" nolabel="1"/>
+ <separator string="Default Taxes" colspan="4"/>
+ <field name="tax_template_ids" colspan="4" nolabel="1"/>
<separator string="Properties" colspan="4"/>
<group col="4">
<field name="property_account_receivable" domain="[('id', 'child_of', [account_root_id])]"/>
diff --git a/addons/account/edi/invoice_action_data.xml b/addons/account/edi/invoice_action_data.xml
index 53fa03a6902..d86ebca3537 100644
--- a/addons/account/edi/invoice_action_data.xml
+++ b/addons/account/edi/invoice_action_data.xml
@@ -40,7 +40,7 @@
<field name="name">Automated Invoice Notification Mail</field>
<field name="email_from">${object.user_id.email or object.company_id.email or 'noreply@localhost'}</field>
<field name="subject">${object.company_id.name} Invoice (Ref ${object.number or 'n/a' })</field>
- <field name="email_to">${object.partner_id.email or ''}</field>
+ <field name="email_recipients">${object.partner_id.id}</field>
<field name="model_id" ref="account.model_account_invoice"/>
<field name="auto_delete" eval="True"/>
<field name="body_html"><![CDATA[
diff --git a/addons/account/i18n/es_AR.po b/addons/account/i18n/es_AR.po
index b0c29e28c5d..15a06669417 100644
--- a/addons/account/i18n/es_AR.po
+++ b/addons/account/i18n/es_AR.po
@@ -7,20 +7,20 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-02-08 00:35+0000\n"
-"PO-Revision-Date: 2011-03-17 20:16+0000\n"
+"PO-Revision-Date: 2012-11-13 15:01+0000\n"
"Last-Translator: jpdborgna <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-10-30 05:06+0000\n"
-"X-Generator: Launchpad (build 16206)\n"
+"X-Launchpad-Export-Date: 2012-11-14 04:40+0000\n"
+"X-Generator: Launchpad (build 16251)\n"
#. module: account
#: view:account.invoice.report:0
#: view:analytic.entries.report:0
msgid "last month"
-msgstr ""
+msgstr "Ultimo mes"
#. module: account
#: model:process.transition,name:account.process_transition_supplierreconcilepaid0
@@ -146,7 +146,7 @@ msgstr "Referencia"
#. module: account
#: view:account.open.closed.fiscalyear:0
msgid "Choose Fiscal Year "
-msgstr ""
+msgstr "Seleccione el año fiscal "
#. module: account
#: help:account.payment.term,active:0
@@ -159,7 +159,7 @@ msgstr ""
#: code:addons/account/account_invoice.py:1430
#, python-format
msgid "Warning!"
-msgstr ""
+msgstr "¡Advertencia!"
#. module: account
#: code:addons/account/account.py:3129
@@ -187,7 +187,7 @@ msgstr ""
#: code:addons/account/wizard/account_move_journal.py:95
#, python-format
msgid "Journal: %s"
-msgstr ""
+msgstr "Diario: %s"
#. module: account
#: help:account.analytic.journal,type:0
@@ -228,6 +228,7 @@ msgstr ""
#, python-format
msgid "Invoice '%s' is paid partially: %s%s of %s%s (%s%s remaining)"
msgstr ""
+"La factura '%s' está parcialmente pagada: %s%s de %s%s (%s%s pendiente)"
#. module: account
#: model:process.transition,note:account.process_transition_supplierentriesreconcile0
@@ -268,7 +269,7 @@ msgstr ""
#. module: account
#: view:account.fiscalyear.close.state:0
msgid "Close Fiscalyear"
-msgstr ""
+msgstr "Cerrar ejercicio fiscal"
#. module: account
#: field:account.automatic.reconcile,allow_write_off:0
@@ -335,7 +336,7 @@ msgstr ""
#. module: account
#: view:account.installer:0
msgid "Configure"
-msgstr ""
+msgstr "Configurar"
#. module: account
#: selection:account.entries.report,month:0
@@ -344,7 +345,7 @@ msgstr ""
#: selection:report.account.sales,month:0
#: selection:report.account_type.sales,month:0
msgid "June"
-msgstr ""
+msgstr "Junio"
#. module: account
#: model:ir.actions.act_window,help:account.action_account_moves_bank
@@ -378,12 +379,12 @@ msgstr "Fecha de creación"
#. module: account
#: selection:account.journal,type:0
msgid "Purchase Refund"
-msgstr ""
+msgstr "Devolución de compra"
#. module: account
#: selection:account.journal,type:0
msgid "Opening/Closing Situation"
-msgstr ""
+msgstr "Situación de apertura/cierre"
#. module: account
#: help:account.journal,currency:0
@@ -393,7 +394,7 @@ msgstr "La moneda utilizada para el extracto"
#. module: account
#: field:account.open.closed.fiscalyear,fyear_id:0
msgid "Fiscal Year to Open"
-msgstr "Año fiscal para abrir"
+msgstr "Ejercicio fiscal a abrir"
#. module: account
#: help:account.journal,sequence_id:0
@@ -495,7 +496,7 @@ msgstr ""
#. module: account
#: field:account.bank.statement,account_id:0
msgid "Account used in this journal"
-msgstr ""
+msgstr "Cuenta utilizada en este diario"
#. module: account
#: help:account.aged.trial.balance,chart_account_id:0
@@ -557,7 +558,7 @@ msgstr "Cerrar un año fiscal"
#. module: account
#: model:process.transition,note:account.process_transition_confirmstatementfromdraft0
msgid "The accountant confirms the statement."
-msgstr ""
+msgstr "El contador confirma la declaración."
#. module: account
#: report:account.account.balance:0
@@ -8156,7 +8157,7 @@ msgstr ""
#: field:account.bank.statement,balance_end_real:0
#: field:account.treasury.report,ending_balance:0
msgid "Ending Balance"
-msgstr "Balance final"
+msgstr "Saldo Final"
#. module: account
#: help:account.move.line,blocked:0
diff --git a/addons/account/partner_view.xml b/addons/account/partner_view.xml
index 4bee2002ffd..d17f8c18eee 100644
--- a/addons/account/partner_view.xml
+++ b/addons/account/partner_view.xml
@@ -6,7 +6,7 @@
<field name="name">account.fiscal.position.form</field>
<field name="model">account.fiscal.position</field>
<field name="arch" type="xml">
- <form string="Fiscal Position">
+ <form string="Fiscal Position" version="7.0">
<group col="4">
<field name="name"/>
<field name="active"/>
@@ -114,7 +114,7 @@
context="{'search_default_partner_id':[active_id], 'default_partner_id': active_id}"
src_model="res.partner"
view_type="form"
- view_mode="tree,form,calendar"/>
+ view_mode="tree,form"/>
</data>
</openerp>
diff --git a/addons/account/report/account_financial_report.rml b/addons/account/report/account_financial_report.rml
index 6f0ddd0d625..1ee8d5b1858 100644
--- a/addons/account/report/account_financial_report.rml
+++ b/addons/account/report/account_financial_report.rml
@@ -170,12 +170,12 @@
<tr>
<td><para style="terp_tblheader_General_Centre">Chart of Accounts</para></td>
<td><para style="terp_tblheader_General_Centre">Fiscal Year</para></td>
- <td><para style="terp_tblheader_General_Centre">Filter By [[ get_filter(data)!='No Filter' and get_filter(data) ]]</para></td>
+ <td><para style="terp_tblheader_General_Centre">Filter By [[ get_filter(data)!='No Filters' and get_filter(data) ]]</para></td>
</tr>
<tr>
<td><para style="terp_default_Centre_8">[[ get_account(data) or removeParentNode('para') ]]</para></td>
<td><para style="terp_default_Centre_8">[[ get_fiscalyear(data) or '' ]]</para></td>
- <td><para style="terp_default_Centre_8">[[ get_filter(data)=='No Filter' and get_filter(data) or removeParentNode('para') ]] </para>
+ <td><para style="terp_default_Centre_8">[[ get_filter(data)=='No Filters' and get_filter(data) or removeParentNode('para') ]] </para>
<blockTable colWidths="60.0,60.0" style="Table3">[[ get_filter(data)=='Date' or removeParentNode('blockTable') ]]
<tr>
<td><para style="terp_tblheader_General_Centre">Start Date</para></td>
diff --git a/addons/account/report/account_general_ledger.py b/addons/account/report/account_general_ledger.py
index 294c7fa99cf..38f2392f740 100644
--- a/addons/account/report/account_general_ledger.py
+++ b/addons/account/report/account_general_ledger.py
@@ -299,10 +299,10 @@ class general_ledger(report_sxw.rml_parse, common_report_header):
def _get_sortby(self, data):
if self.sortby == 'sort_date':
- return 'Date'
+ return self._translate('Date')
elif self.sortby == 'sort_journal_partner':
- return 'Journal & Partner'
- return 'Date'
+ return self._translate('Journal & Partner')
+ return self._translate('Date')
report_sxw.report_sxw('report.account.general.ledger', 'account.account', 'addons/account/report/account_general_ledger.rml', parser=general_ledger, header='internal')
report_sxw.report_sxw('report.account.general.ledger_landscape', 'account.account', 'addons/account/report/account_general_ledger_landscape.rml', parser=general_ledger, header='internal landscape')
diff --git a/addons/account/report/common_report_header.py b/addons/account/report/common_report_header.py
index c93c3e02ee3..c5719d98b96 100644
--- a/addons/account/report/common_report_header.py
+++ b/addons/account/report/common_report_header.py
@@ -94,10 +94,10 @@ class common_report_header(object):
def _get_filter(self, data):
if data.get('form', False) and data['form'].get('filter', False):
if data['form']['filter'] == 'filter_date':
- return 'Date'
+ return self._translate('Date')
elif data['form']['filter'] == 'filter_period':
- return 'Periods'
- return 'No Filter'
+ return self._translate('Periods')
+ return self._translate('No Filters')
def _sum_debit_period(self, period_id, journal_id=None):
journals = journal_id or self.journal_ids
diff --git a/addons/account/test/account_report.yml b/addons/account/test/account_report.yml
index 64f8ccf838f..7fe3095d47f 100644
--- a/addons/account/test/account_report.yml
+++ b/addons/account/test/account_report.yml
@@ -31,7 +31,6 @@
-
!python {model: account.account}: |
ctx={}
- ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')],'active_id':ref('account.chart0')})
data_dict = {'chart_account_id':ref('account.chart0')}
from tools import test_reports
test_reports.try_report_action(cr, uid, 'action_account_aged_balance_view',wiz_data=data_dict, context=ctx, our_module='account')
@@ -40,7 +39,6 @@
-
!python {model: account.account}: |
ctx={}
- ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')]})
data_dict = {'chart_account_id':ref('account.chart0'), 'account_report_id': ref('account_financial_report_balancesheet0')}
from tools import test_reports
test_reports.try_report_action(cr, uid, 'action_account_report',wiz_data=data_dict, context=ctx, our_module='account')
@@ -49,7 +47,6 @@
-
!python {model: account.account}: |
ctx={}
- ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')]})
data_dict = {'chart_account_id':ref('account.chart0')}
from tools import test_reports
test_reports.try_report_action(cr, uid, 'action_account_balance_menu',wiz_data=data_dict, context=ctx, our_module='account')
@@ -60,7 +57,6 @@
journal_ids = [ref('account.sales_journal'),ref('account.refund_sales_journal'),ref('account.expenses_journal'),ref('account.refund_expenses_journal'),
ref('account.bank_journal'),ref('account.check_journal'),ref('account.cash_journal')]
ctx={}
- ctx.update({'model': 'account.journal.period','active_ids':journal_ids})
data_dict = {'chart_account_id':ref('account.chart0')}
from tools import test_reports
test_reports.try_report_action(cr, uid, 'action_account_central_journal',wiz_data=data_dict, context=ctx, our_module='account')
@@ -71,7 +67,6 @@
journal_ids = [ref('account.sales_journal'),ref('account.refund_sales_journal'),ref('account.expenses_journal'),ref('account.refund_expenses_journal'),
ref('account.bank_journal'),ref('account.check_journal'),ref('account.cash_journal')]
ctx={}
- ctx.update({'model': 'account.journal.period','active_ids':journal_ids})
data_dict = {'chart_account_id':ref('account.chart0')}
from tools import test_reports
test_reports.try_report_action(cr, uid, 'action_account_general_journal',wiz_data=data_dict, context=ctx, our_module='account')
@@ -80,7 +75,6 @@
-
!python {model: account.account}: |
ctx={}
- ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')]})
data_dict = {'chart_account_id':ref('account.chart0'),'landscape':False}
from tools import test_reports
test_reports.try_report_action(cr, uid, 'action_account_general_ledger_menu',wiz_data=data_dict, context=ctx, our_module='account')
@@ -89,7 +83,6 @@
-
!python {model: account.account}: |
ctx={}
- ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')]})
data_dict = {'chart_account_id':ref('account.chart0'),'landscape':True}
from tools import test_reports
test_reports.try_report_action(cr, uid, 'action_account_general_ledger_menu',wiz_data=data_dict, context=ctx, our_module='account')
@@ -99,7 +92,6 @@
!python {model: account.journal.period}: |
journal_ids = [ref('account.sales_journal'),ref('account.refund_sales_journal'),ref('account.expenses_journal'),ref('account.refund_expenses_journal'),ref('account.bank_journal'),ref('account.check_journal'),ref('account.cash_journal')]
ctx={}
- ctx.update({'model': 'account.journal.period','active_ids':journal_ids})
data_dict = {'chart_account_id':ref('account.chart0'), 'period_from':ref('period_1'), 'period_to':ref('period_12')}
from tools import test_reports
test_reports.try_report_action(cr, uid, 'action_account_print_journal',wiz_data=data_dict, context=ctx, our_module='account')
@@ -109,7 +101,6 @@
!python {model: account.account}: |
ctx={}
data_dict = {'chart_account_id':ref('account.chart0')}
- ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')],'active_id':ref('account.chart0')})
from tools import test_reports
test_reports.try_report_action(cr, uid, 'action_account_partner_balance',wiz_data=data_dict, context=ctx, our_module='account')
-
@@ -118,7 +109,6 @@
!python {model: account.account}: |
ctx={}
data_dict = {'chart_account_id':ref('account.chart0'),'page_split': True}
- ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')],'active_id':ref('account.chart0')})
from tools import test_reports
test_reports.try_report_action(cr, uid, 'action_account_partner_ledger',wiz_data=data_dict, context=ctx, our_module='account')
-
@@ -127,7 +117,6 @@
!python {model: res.partner}: |
ctx={}
data_dict = {'chart_account_id':ref('account.chart0'),'page_split': False}
- ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')],'active_id':ref('account.chart0')})
from tools import test_reports
test_reports.try_report_action(cr, uid, 'action_account_partner_ledger',wiz_data=data_dict, context=ctx, our_module='account')
-
@@ -135,7 +124,6 @@
-
!python {model: account.account}: |
ctx={}
- ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')]})
data_dict = {'chart_account_id':ref('account.chart0'), 'target_move': 'all', 'account_report_id': ref('account_financial_report_balancesheet0')}
from tools import test_reports
test_reports.try_report_action(cr, uid, 'action_account_report',wiz_data=data_dict, context=ctx, our_module='account')
diff --git a/addons/account/tests/__init__.py b/addons/account/tests/__init__.py
new file mode 100644
index 00000000000..11fe4186db6
--- /dev/null
+++ b/addons/account/tests/__init__.py
@@ -0,0 +1,4 @@
+from . import test_tax
+
+fast_suite = [test_tax,
+ ]
diff --git a/addons/account/tests/test_tax.py b/addons/account/tests/test_tax.py
new file mode 100644
index 00000000000..a172a17e30d
--- /dev/null
+++ b/addons/account/tests/test_tax.py
@@ -0,0 +1,49 @@
+from openerp.tests.common import TransactionCase
+
+class TestTax(TransactionCase):
+ """Tests for taxes (account.tax)
+
+ We don't really need at this point to link taxes to tax codes
+ (account.tax.code) nor to companies (base.company) to check computation
+ results.
+ """
+
+ def setUp(self):
+ super(TestTax, self).setUp()
+ self.tax_model = self.registry('account.tax')
+
+ def test_programmatic_tax(self):
+ cr, uid = self.cr, self.uid
+ tax_id = self.tax_model.create(cr, uid, dict(
+ name="Programmatic tax",
+ type='code',
+ python_compute='result = 12.0',
+ python_compute_inv='result = 11.0',
+ ))
+
+ tax_records = self.tax_model.browse(cr, uid, [tax_id])
+ res = self.tax_model.compute_all(cr, uid, tax_records, 50.0, 2)
+
+ tax_detail = res['taxes'][0]
+ self.assertEquals(tax_detail['amount'], 24.0)
+ self.assertEquals(res['total_included'], 124.0)
+
+ def test_percent_tax(self):
+ """Test computations done by a 10 percent tax."""
+ cr, uid = self.cr, self.uid
+ tax_id = self.tax_model.create(cr, uid, dict(
+ name="Percent tax",
+ type='percent',
+ amount='0.1',
+ ))
+
+ tax_records = self.tax_model.browse(cr, uid, [tax_id])
+ res = self.tax_model.compute_all(cr, uid, tax_records, 50.0, 2)
+
+ tax_detail = res['taxes'][0]
+ self.assertEquals(tax_detail['amount'], 10.0)
+ self.assertEquals(res['total_included'], 110.0)
+
+ # now the inverse computation
+ res = self.tax_model.compute_inv(cr, uid, tax_records, 55.0, 2)
+ self.assertEquals(res[0]['amount'], 10.0)
diff --git a/addons/account/wizard/account_financial_report_view.xml b/addons/account/wizard/account_financial_report_view.xml
index 8388284be4a..507809e1961 100644
--- a/addons/account/wizard/account_financial_report_view.xml
+++ b/addons/account/wizard/account_financial_report_view.xml
@@ -14,15 +14,19 @@
</xpath>
<xpath expr="//notebook/page[@string='Filters']" position="after">
<page string="Comparison" attrs="{'invisible': [('enable_filter','=',False)]}">
- <field name="label_filter" attrs="{'required': [('enable_filter', '=', True)]}"/>
- <field name="fiscalyear_id_cmp"/><newline/>
- <field name="filter_cmp"/>
- <separator string="Dates" colspan="4"/>
- <field name="date_from_cmp" attrs="{'readonly':[('filter_cmp', '!=', 'filter_date')], 'required':[('filter_cmp', '=', 'filter_date')]}" colspan="4"/>
- <field name="date_to_cmp" attrs="{'readonly':[('filter_cmp', '!=', 'filter_date')], 'required':[('filter_cmp', '=', 'filter_date')]}" colspan="4"/>
- <separator string="Periods" colspan="4"/>
- <field name="period_from_cmp" domain="[('fiscalyear_id', '=', fiscalyear_id_cmp)]" attrs="{'readonly':[('filter_cmp','!=','filter_period')], 'required':[('filter_cmp', '=', 'filter_period')]}" colspan="4"/>
- <field name="period_to_cmp" domain="[('fiscalyear_id', '=', fiscalyear_id_cmp)]" attrs="{'readonly':[('filter_cmp','!=','filter_period')], 'required':[('filter_cmp', '=', 'filter_period')]}" colspan="4"/>
+ <group>
+ <field name="label_filter" attrs="{'required': [('enable_filter', '=', True)]}"/>
+ <field name="fiscalyear_id_cmp"/><newline/>
+ <field name="filter_cmp"/>
+ </group>
+ <group string="Dates" attrs="{'invisible':[('filter_cmp', '!=', 'filter_date')]}">
+ <field name="date_from_cmp" attrs="{'required':[('filter_cmp', '=', 'filter_date')]}"/>
+ <field name="date_to_cmp" attrs="{'required':[('filter_cmp', '=', 'filter_date')]}"/>
+ </group>
+ <group string="Periods" attrs="{'invisible':[('filter_cmp', '!=', 'filter_period')]}">
+ <field name="period_from_cmp" domain="[('fiscalyear_id', '=', fiscalyear_id_cmp)]" attrs="{'required':[('filter_cmp', '=', 'filter_period')]}"/>
+ <field name="period_to_cmp" domain="[('fiscalyear_id', '=', fiscalyear_id_cmp)]" attrs="{'required':[('filter_cmp', '=', 'filter_period')]}"/>
+ </group>
</page>
</xpath>
<xpath expr="//notebook/page[@string='Journals']" position="replace">
diff --git a/addons/account/wizard/account_fiscalyear_close.py b/addons/account/wizard/account_fiscalyear_close.py
index 196c14d3792..dbf815d5218 100644
--- a/addons/account/wizard/account_fiscalyear_close.py
+++ b/addons/account/wizard/account_fiscalyear_close.py
@@ -226,7 +226,7 @@ class account_fiscalyear_close(osv.osv_memory):
for account in obj_acc_account.browse(cr, uid, account_ids, context={'fiscalyear': fy_id}):
balance_in_currency = 0.0
if account.currency_id:
- cr.execute('SELECT sum(amount_currency) as balance_in_currency FROM account_move_line ' \
+ cr.execute('SELECT sum(COALESCE(amount_currency,0.0)) as balance_in_currency FROM account_move_line ' \
'WHERE account_id = %s ' \
'AND ' + query_line + ' ' \
'AND currency_id = %s', (account.id, account.currency_id.id))
diff --git a/addons/account/wizard/account_open_closed_fiscalyear.py b/addons/account/wizard/account_open_closed_fiscalyear.py
index b8d64fac0b5..1b5622a589d 100644
--- a/addons/account/wizard/account_open_closed_fiscalyear.py
+++ b/addons/account/wizard/account_open_closed_fiscalyear.py
@@ -27,7 +27,7 @@ class account_open_closed_fiscalyear(osv.osv_memory):
_description = "Choose Fiscal Year"
_columns = {
'fyear_id': fields.many2one('account.fiscalyear', \
- 'Fiscal Year to Open', required=True, help='Select Fiscal Year which you want to remove entries for its End of year entries journal'),
+ 'Fiscal Year', required=True, help='Select Fiscal Year which you want to remove entries for its End of year entries journal'),
}
def remove_entries(self, cr, uid, ids, context=None):
@@ -36,7 +36,7 @@ class account_open_closed_fiscalyear(osv.osv_memory):
data = self.browse(cr, uid, ids, context=context)[0]
period_journal = data.fyear_id.end_journal_period_id or False
if not period_journal:
- raise osv.except_osv(_('Error!'), _('You have to set the end of the fiscal year for this journal.'))
+ raise osv.except_osv(_('Error!'), _("You have to set the 'End of Year Entries Journal' for this Fiscal Year which is set after generating opening entries from 'Generate Opening Entries'."))
ids_move = move_obj.search(cr, uid, [('journal_id','=',period_journal.journal_id.id),('period_id','=',period_journal.period_id.id)])
if ids_move:
diff --git a/addons/account/wizard/account_open_closed_fiscalyear_view.xml b/addons/account/wizard/account_open_closed_fiscalyear_view.xml
index c2c271af41b..d4cfd398920 100644
--- a/addons/account/wizard/account_open_closed_fiscalyear_view.xml
+++ b/addons/account/wizard/account_open_closed_fiscalyear_view.xml
@@ -5,14 +5,18 @@
<field name="name">account.open.closed.fiscalyear.form</field>
<field name="model">account.open.closed.fiscalyear</field>
<field name="arch" type="xml">
- <form string="Choose Fiscal Year " version="7.0">
+ <form string="Cancel Fiscal Year Opening Entries" version="7.0">
+ <separator string="Cancel Fiscal Year Opening Entries"/>
+ <p class="oe_grey">
+This wizard will remove the end of year journal entries of selected fiscal year. Note that you can run this wizard many times for the same fiscal year.
+ </p>
<group>
- <field name="fyear_id" domain="[('state','=','draft')]"/>
+ <field name="fyear_id" domain="[('state','=','draft'), ('end_journal_period_id', '!=', False)]"/>
</group>
<footer>
- <button string="Open" name="remove_entries" type="object" class="oe_highlight"/>
+ <button string="Cancel Opening Entries" name="remove_entries" type="object" class="oe_highlight"/>
or
- <button string="Cancel" class="oe_link" special="cancel"/>
+ <button string="Discard" class="oe_link" special="cancel"/>
</footer>
</form>
</field>
diff --git a/addons/account/wizard/account_report_account_balance_view.xml b/addons/account/wizard/account_report_account_balance_view.xml
index b2c8ccd3011..3609ee3b4de 100644
--- a/addons/account/wizard/account_report_account_balance_view.xml
+++ b/addons/account/wizard/account_report_account_balance_view.xml
@@ -9,8 +9,7 @@
<field name="inherit_id" ref="account_common_report_view" />
<field name="arch" type="xml">
<data>
- <xpath expr="//field[@name='journal_ids']" position="replace">
- <field name="journal_ids" colspan="4" nolabel="1" required="0" readonly="1"/>
+ <xpath expr="//notebook/page[@string='Journals']" position="replace">
</xpath>
<xpath expr="//field[@name='target_move']" position="after">
<field name="display_account"/>
diff --git a/addons/account/wizard/account_report_common.py b/addons/account/wizard/account_report_common.py
index 9acc09e9026..4438484aaaf 100644
--- a/addons/account/wizard/account_report_common.py
+++ b/addons/account/wizard/account_report_common.py
@@ -119,7 +119,11 @@ class account_common_report(osv.osv_memory):
def _get_fiscalyear(self, cr, uid, context=None):
now = time.strftime('%Y-%m-%d')
- fiscalyears = self.pool.get('account.fiscalyear').search(cr, uid, [('date_start', '<', now), ('date_stop', '>', now)], limit=1 )
+ company_id = False
+ ids = context.get('active_ids', [])
+ if ids:
+ company_id = self.browse(cr, uid, ids[0], context=context).company_id.id
+ fiscalyears = self.pool.get('account.fiscalyear').search(cr, uid, [('date_start', '<', now), ('date_stop', '>', now), ('company_id', '=', company_id)], limit=1)
return fiscalyears and fiscalyears[0] or False
def _get_all_journal(self, cr, uid, context=None):
diff --git a/addons/account_accountant/account_accountant_data.xml b/addons/account_accountant/account_accountant_data.xml
index cf143b1bb58..c7d6eb80bc6 100644
--- a/addons/account_accountant/account_accountant_data.xml
+++ b/addons/account_accountant/account_accountant_data.xml
@@ -26,12 +26,10 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Accounting and Finance application installed!</field>
- <field name="body"><![CDATA[
- With OpenERP's accounting, you get instant access to your financial data, and can setup analytic accounting, forecast taxes, control budgets, easily create and send invoices, record bank statements, etc.
-
-<p>The accounting features are fully integrated with other OpenERP applications to automate all your processes: creation of customer invoices, control of supplier invoices, point-of-sale integration, automated follow-ups, etc.</p>
- ]]></field>
+ <field name="body"><![CDATA[<p>With OpenERP's accounting, you get instant access to your financial data, and can setup analytic accounting, forecast taxes, control budgets, easily create and send invoices, record bank statements, etc.</p>
+<p>The accounting features are fully integrated with other OpenERP applications to automate all your processes: creation of customer invoices, control of supplier invoices, point-of-sale integration, automated follow-ups, etc.</p>]]></field>
</record>
</data>
</openerp>
diff --git a/addons/account_analytic_plans/account_analytic_plans_view.xml b/addons/account_analytic_plans/account_analytic_plans_view.xml
index 76d6aeed7b8..e5c02c8640e 100644
--- a/addons/account_analytic_plans/account_analytic_plans_view.xml
+++ b/addons/account_analytic_plans/account_analytic_plans_view.xml
@@ -21,17 +21,17 @@
<field name="inherit_id" ref="account.view_move_form"/>
<field name="arch" type="xml">
<xpath expr="/form/sheet/notebook/page/field[@name='line_id']/tree/field[@name='analytic_account_id']" position="replace">
- <field name="analytics_id" context="{'journal_id':journal_id}" groups="analytic.group_analytic_accounting"/>
+ <field name="analytics_id" context="{'journal_id':parent.journal_id}" groups="analytic.group_analytic_accounting"/>
</xpath>
<xpath expr="/form/sheet/notebook/page/field[@name='line_id']/form/notebook/page/group/group/field[@name='analytic_account_id']" position="replace">
- <field name="analytics_id" context="{'journal_id':journal_id}" groups="analytic.group_analytic_accounting"/>
+ <field name="analytics_id" context="{'journal_id':parent.journal_id}" groups="analytic.group_analytic_accounting"/>
</xpath>
</field>
</record>
<record id="journal_col11" model="account.journal.column">
<field eval="&quot;&quot;&quot;Analytic Distribution&quot;&quot;&quot;" name="name"/>
- <field eval="11" name="sequence"/>
+ <field eval="15" name="sequence"/>
<field name="view_id" ref="account.account_journal_view"/>
<field eval="0" name="required"/>
<field eval="&quot;&quot;&quot;analytics_id&quot;&quot;&quot;" name="field"/>
@@ -276,7 +276,7 @@
</field>
</field>
</record>
- <record model="ir.ui.view" id="view_default_inherit_tree">
+ <record model="ir.ui.view" id="view_default_inherit_tree">
<field name="name">account.analytic.default.tree.plans</field>
<field name="model">account.analytic.default</field>
<field name="inherit_id" ref="account_analytic_default.view_account_analytic_default_tree"/>
diff --git a/addons/account_anglo_saxon/invoice.py b/addons/account_anglo_saxon/invoice.py
index 693283b870b..26271015b7e 100644
--- a/addons/account_anglo_saxon/invoice.py
+++ b/addons/account_anglo_saxon/invoice.py
@@ -40,7 +40,7 @@ class account_invoice_line(osv.osv):
if inv.type in ('out_invoice','out_refund'):
for i_line in inv.invoice_line:
- if i_line.product_id:
+ if i_line.product_id and i_line.product_id.valuation == 'real_time':
if inv.type == 'out_invoice':
# debit account dacc will be the output account
# first check the product, if empty check the category
@@ -87,7 +87,7 @@ class account_invoice_line(osv.osv):
})
elif inv.type in ('in_invoice','in_refund'):
for i_line in inv.invoice_line:
- if i_line.product_id:
+ if i_line.product_id and i_line.product_id.valuation == 'real_time':
if i_line.product_id.type != 'service':
# get the price difference account at the product
acc = i_line.product_id.property_account_creditor_price_difference and i_line.product_id.property_account_creditor_price_difference.id
diff --git a/addons/account_asset/account_asset.py b/addons/account_asset/account_asset.py
index ac9024fd51d..a44226e76c8 100644
--- a/addons/account_asset/account_asset.py
+++ b/addons/account_asset/account_asset.py
@@ -377,16 +377,15 @@ class account_asset_depreciation_line(osv.osv):
move_line_obj = self.pool.get('account.move.line')
currency_obj = self.pool.get('res.currency')
created_move_ids = []
+ asset_ids = []
for line in self.browse(cr, uid, ids, context=context):
- if currency_obj.is_zero(cr, uid, line.asset_id.currency_id, line.remaining_value):
- can_close = True
depreciation_date = time.strftime('%Y-%m-%d')
period_ids = period_obj.find(cr, uid, depreciation_date, context=context)
company_currency = line.asset_id.company_id.currency_id.id
current_currency = line.asset_id.currency_id.id
context.update({'date': depreciation_date})
amount = currency_obj.compute(cr, uid, current_currency, company_currency, line.amount, context=context)
- sign = line.asset_id.category_id.journal_id.type = 'purchase' and 1 or -1
+ sign = (line.asset_id.category_id.journal_id.type == 'purchase' and 1) or -1
asset_name = line.asset_id.name
reference = line.name
move_vals = {
@@ -409,8 +408,8 @@ class account_asset_depreciation_line(osv.osv):
'period_id': period_ids and period_ids[0] or False,
'journal_id': journal_id,
'partner_id': partner_id,
- 'currency_id': company_currency <> current_currency and current_currency or False,
- 'amount_currency': company_currency <> current_currency and - sign * line.amount or 0.0,
+ 'currency_id': company_currency != current_currency and current_currency or False,
+ 'amount_currency': company_currency != current_currency and - sign * line.amount or 0.0,
'date': depreciation_date,
})
move_line_obj.create(cr, uid, {
@@ -423,16 +422,19 @@ class account_asset_depreciation_line(osv.osv):
'period_id': period_ids and period_ids[0] or False,
'journal_id': journal_id,
'partner_id': partner_id,
- 'currency_id': company_currency <> current_currency and current_currency or False,
- 'amount_currency': company_currency <> current_currency and sign * line.amount or 0.0,
+ 'currency_id': company_currency != current_currency and current_currency or False,
+ 'amount_currency': company_currency != current_currency and sign * line.amount or 0.0,
'analytic_account_id': line.asset_id.category_id.account_analytic_id.id,
'date': depreciation_date,
'asset_id': line.asset_id.id
})
self.write(cr, uid, line.id, {'move_id': move_id}, context=context)
created_move_ids.append(move_id)
- if can_close:
- asset_obj.write(cr, uid, [line.asset_id.id], {'state': 'close'}, context=context)
+ asset_ids.append(line.asset_id.id)
+ # we re-evaluate the assets to determine whether we can close them
+ for asset in asset_obj.browse(cr, uid, list(set(asset_ids)), context=context):
+ if currency_obj.is_zero(cr, uid, asset.currency_id, asset.value_residual):
+ asset.write({'state': 'close'})
return created_move_ids
account_asset_depreciation_line()
diff --git a/addons/account_bank_statement_extensions/account_bank_statement_view.xml b/addons/account_bank_statement_extensions/account_bank_statement_view.xml
index 3d5560856a3..adc2963c803 100644
--- a/addons/account_bank_statement_extensions/account_bank_statement_view.xml
+++ b/addons/account_bank_statement_extensions/account_bank_statement_view.xml
@@ -72,12 +72,12 @@
<field name="date" readonly="1"/>
<field name="val_date" readonly="1"/>
<field name="name"/>
- <field name="statement_id" readonly="1"/>
+ <field name="statement_id"/>
<field name="ref" readonly="1"/>
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
<field name="type" on_change="onchange_type(partner_id, type)"/>
- <field name="account_id" domain="[('journal_id','=',journal_id)]"/>
- <field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '&lt;&gt;', 'view')]"/>
+ <field name="account_id"/>
+ <field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('type', '&lt;&gt;', 'view')]"/>
<field name="amount" readonly="1" sum="Total Amount"/>
<field name="globalisation_id" string="Glob. Id"/>
<field name="globalisation_amount" string="Glob. Am."/>
@@ -100,8 +100,8 @@
<field name="ref" readonly="0"/>
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
<field name="type" on_change="onchange_type(partner_id, type)"/>
- <field domain="[('journal_id', '=', journal_id), ('type', '&lt;&gt;', 'view')]" name="account_id"/>
- <field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '&lt;&gt;', 'view')]"/>
+ <field domain="[('type', '&lt;&gt;', 'view')]" name="account_id"/>
+ <field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('type', '&lt;&gt;', 'view')]"/>
<field name="amount"/>
<field name="globalisation_id"/>
<field name="sequence" readonly="0"/>
diff --git a/addons/account_budget/account_budget_view.xml b/addons/account_budget/account_budget_view.xml
index cb0466a1c92..35194e96b82 100644
--- a/addons/account_budget/account_budget_view.xml
+++ b/addons/account_budget/account_budget_view.xml
@@ -220,7 +220,17 @@
<menuitem parent="next_id_31"
id="menu_act_crossovered_budget_view"
action="act_crossovered_budget_view" sequence="1" />
-
+
+ <record id="view_crossovered_budget_line_search" model="ir.ui.view">
+ <field name="name">account.budget.line.search</field>
+ <field name="model">crossovered.budget.lines</field>
+ <field name="arch" type="xml">
+ <search string="Budget Lines">
+ <field name="analytic_account_id"/>
+ </search>
+ </field>
+ </record>
+
<record model="ir.ui.view" id="view_crossovered_budget_line_tree">
<field name="name">crossovered.budget.line.tree</field>
<field name="model">crossovered.budget.lines</field>
diff --git a/addons/account_check_writing/i18n/es.po b/addons/account_check_writing/i18n/es.po
index 81932642524..c473e077210 100644
--- a/addons/account_check_writing/i18n/es.po
+++ b/addons/account_check_writing/i18n/es.po
@@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-08 00:35+0000\n"
-"PO-Revision-Date: 2012-02-09 19:28+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"PO-Revision-Date: 2012-11-09 12:09+0000\n"
+"Last-Translator: Pedro Manuel Baeza <pedro.baeza@gmail.com>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-10-30 05:36+0000\n"
-"X-Generator: Launchpad (build 16206)\n"
+"X-Launchpad-Export-Date: 2012-11-10 04:59+0000\n"
+"X-Generator: Launchpad (build 16251)\n"
#. module: account_check_writing
#: selection:res.company,check_layout:0
@@ -154,7 +154,7 @@ msgstr "Compañías"
#. module: account_check_writing
#: view:res.company:0
msgid "Default Check Layout"
-msgstr ""
+msgstr "Comprobar formato por defecto"
#. module: account_check_writing
#: constraint:account.journal:0
diff --git a/addons/account_check_writing/i18n/lt.po b/addons/account_check_writing/i18n/lt.po
new file mode 100644
index 00000000000..35e98d451ad
--- /dev/null
+++ b/addons/account_check_writing/i18n/lt.po
@@ -0,0 +1,199 @@
+# Lithuanian translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2012-02-08 00:35+0000\n"
+"PO-Revision-Date: 2012-11-16 06:33+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Lithuanian <lt@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-11-17 04:37+0000\n"
+"X-Generator: Launchpad (build 16278)\n"
+
+#. module: account_check_writing
+#: selection:res.company,check_layout:0
+msgid "Check on Top"
+msgstr ""
+
+#. module: account_check_writing
+#: model:ir.actions.act_window,help:account_check_writing.action_write_check
+msgid ""
+"The check payment form allows you to track the payment you do to your "
+"suppliers specially by check. When you select a supplier, the payment method "
+"and an amount for the payment, OpenERP will propose to reconcile your "
+"payment with the open supplier invoices or bills.You can print the check"
+msgstr ""
+
+#. module: account_check_writing
+#: view:account.voucher:0
+#: model:ir.actions.report.xml,name:account_check_writing.account_print_check_bottom
+#: model:ir.actions.report.xml,name:account_check_writing.account_print_check_middle
+#: model:ir.actions.report.xml,name:account_check_writing.account_print_check_top
+msgid "Print Check"
+msgstr ""
+
+#. module: account_check_writing
+#: selection:res.company,check_layout:0
+msgid "Check in middle"
+msgstr ""
+
+#. module: account_check_writing
+#: help:res.company,check_layout:0
+msgid ""
+"Check on top is compatible with Quicken, QuickBooks and Microsoft Money. "
+"Check in middle is compatible with Peachtree, ACCPAC and DacEasy. Check on "
+"bottom is compatible with Peachtree, ACCPAC and DacEasy only"
+msgstr ""
+
+#. module: account_check_writing
+#: selection:res.company,check_layout:0
+msgid "Check on bottom"
+msgstr ""
+
+#. module: account_check_writing
+#: constraint:res.company:0
+msgid "Error! You can not create recursive companies."
+msgstr ""
+
+#. module: account_check_writing
+#: help:account.journal,allow_check_writing:0
+msgid "Check this if the journal is to be used for writing checks."
+msgstr ""
+
+#. module: account_check_writing
+#: field:account.journal,allow_check_writing:0
+msgid "Allow Check writing"
+msgstr ""
+
+#. module: account_check_writing
+#: report:account.print.check.bottom:0
+#: report:account.print.check.middle:0
+#: report:account.print.check.top:0
+msgid "Description"
+msgstr "Aprašas"
+
+#. module: account_check_writing
+#: model:ir.model,name:account_check_writing.model_account_journal
+msgid "Journal"
+msgstr "Žurnalas"
+
+#. module: account_check_writing
+#: model:ir.actions.act_window,name:account_check_writing.action_write_check
+#: model:ir.ui.menu,name:account_check_writing.menu_action_write_check
+msgid "Write Checks"
+msgstr ""
+
+#. module: account_check_writing
+#: report:account.print.check.bottom:0
+#: report:account.print.check.middle:0
+#: report:account.print.check.top:0
+msgid "Discount"
+msgstr ""
+
+#. module: account_check_writing
+#: report:account.print.check.bottom:0
+#: report:account.print.check.middle:0
+#: report:account.print.check.top:0
+msgid "Original Amount"
+msgstr ""
+
+#. module: account_check_writing
+#: view:res.company:0
+msgid "Configuration"
+msgstr ""
+
+#. module: account_check_writing
+#: field:account.voucher,allow_check:0
+msgid "Allow Check Writing"
+msgstr ""
+
+#. module: account_check_writing
+#: report:account.print.check.bottom:0
+#: report:account.print.check.middle:0
+#: report:account.print.check.top:0
+msgid "Payment"
+msgstr ""
+
+#. module: account_check_writing
+#: field:account.journal,use_preprint_check:0
+msgid "Use Preprinted Check"
+msgstr ""
+
+#. module: account_check_writing
+#: sql_constraint:res.company:0
+msgid "The company name must be unique !"
+msgstr ""
+
+#. module: account_check_writing
+#: report:account.print.check.bottom:0
+#: report:account.print.check.middle:0
+#: report:account.print.check.top:0
+msgid "Due Date"
+msgstr ""
+
+#. module: account_check_writing
+#: model:ir.model,name:account_check_writing.model_res_company
+msgid "Companies"
+msgstr ""
+
+#. module: account_check_writing
+#: view:res.company:0
+msgid "Default Check Layout"
+msgstr ""
+
+#. module: account_check_writing
+#: constraint:account.journal:0
+msgid ""
+"Configuration error! The currency chosen should be shared by the default "
+"accounts too."
+msgstr ""
+
+#. module: account_check_writing
+#: report:account.print.check.bottom:0
+#: report:account.print.check.middle:0
+msgid "Balance Due"
+msgstr ""
+
+#. module: account_check_writing
+#: report:account.print.check.bottom:0
+#: report:account.print.check.middle:0
+#: report:account.print.check.top:0
+msgid "Check Amount"
+msgstr ""
+
+#. module: account_check_writing
+#: model:ir.model,name:account_check_writing.model_account_voucher
+msgid "Accounting Voucher"
+msgstr ""
+
+#. module: account_check_writing
+#: sql_constraint:account.journal:0
+msgid "The name of the journal must be unique per company !"
+msgstr ""
+
+#. module: account_check_writing
+#: sql_constraint:account.journal:0
+msgid "The code of the journal must be unique per company !"
+msgstr ""
+
+#. module: account_check_writing
+#: field:account.voucher,amount_in_word:0
+msgid "Amount in Word"
+msgstr ""
+
+#. module: account_check_writing
+#: report:account.print.check.top:0
+msgid "Open Balance"
+msgstr ""
+
+#. module: account_check_writing
+#: field:res.company,check_layout:0
+msgid "Choose Check layout"
+msgstr ""
diff --git a/addons/account_sequence/account_sequence_data.xml b/addons/account_sequence/account_sequence_data.xml
index 1ad362b3979..b2d40412d0d 100644
--- a/addons/account_sequence/account_sequence_data.xml
+++ b/addons/account_sequence/account_sequence_data.xml
@@ -43,6 +43,18 @@
<field eval="True" name="required"/>
<field eval="2" name="sequence"/>
</record>
+ <record id="sequence_journal" model="ir.sequence.type">
+ <field name="name">Account Journal</field>
+ <field name="code">account.journal</field>
+ </record>
+
+ <record id="sequence_journal_seq" model="ir.sequence">
+ <field name="name">Account journal sequence</field>
+ <field name="code">account.journal</field>
+ <field name="prefix">AJ</field>
+ <field eval="1" name="number_next"/>
+ <field eval="1" name="number_increment"/>
+ </record>
</data>
</openerp>
diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py
index 8bd9a48b1f4..32be8c34929 100644
--- a/addons/account_voucher/account_voucher.py
+++ b/addons/account_voucher/account_voucher.py
@@ -267,6 +267,7 @@ class account_voucher(osv.osv):
_order = "date desc, id desc"
# _rec_name = 'number'
_columns = {
+ 'active': fields.boolean('Active', help="By default, reconciliation vouchers made on draft bank statements are set as inactive, which allow to hide the customer/supplier payment while the bank statement isn't confirmed."),
'type':fields.selection([
('sale','Sale'),
('purchase','Purchase'),
@@ -328,6 +329,7 @@ class account_voucher(osv.osv):
'is_multi_currency': fields.boolean('Multi Currency Voucher', help='Fields with internal purpose only that depicts if the voucher is a multi currency one or not'),
}
_defaults = {
+ 'active': True,
'period_id': _get_period,
'partner_id': _get_partner,
'journal_id':_get_journal,
@@ -381,8 +383,9 @@ class account_voucher(osv.osv):
total_tax = 0.0
if not tax[0].price_include:
- for tax_line in tax_pool.compute_all(cr, uid, tax, voucher_amount, 1).get('taxes', []):
- total_tax += tax_line.get('amount', 0.0)
+ for line in voucher.line_ids:
+ for tax_line in tax_pool.compute_all(cr, uid, tax, line.amount, 1).get('taxes', []):
+ total_tax += tax_line.get('amount', 0.0)
total += total_tax
else:
for line in voucher.line_ids:
@@ -413,31 +416,31 @@ class account_voucher(osv.osv):
line_ids = resolve_o2m_operations(cr, uid, line_pool, line_ids, ["amount"], context)
+ total_tax = 0.0
for line in line_ids:
line_amount = 0.0
line_amount = line.get('amount',0.0)
- voucher_total += line_amount
- total = voucher_total
- total_tax = 0.0
- if tax_id:
- tax = [tax_pool.browse(cr, uid, tax_id, context=context)]
- if partner_id:
- partner = partner_pool.browse(cr, uid, partner_id, context=context) or False
- taxes = position_pool.map_tax(cr, uid, partner and partner.property_account_position or False, tax)
- tax = tax_pool.browse(cr, uid, taxes, context=context)
+ if tax_id:
+ tax = [tax_pool.browse(cr, uid, tax_id, context=context)]
+ if partner_id:
+ partner = partner_pool.browse(cr, uid, partner_id, context=context) or False
+ taxes = position_pool.map_tax(cr, uid, partner and partner.property_account_position or False, tax)
+ tax = tax_pool.browse(cr, uid, taxes, context=context)
- if not tax[0].price_include:
- for tax_line in tax_pool.compute_all(cr, uid, tax, voucher_total, 1).get('taxes', []):
- total_tax += tax_line.get('amount')
- total += total_tax
+ if not tax[0].price_include:
+ for tax_line in tax_pool.compute_all(cr, uid, tax, line_amount, 1).get('taxes', []):
+ total_tax += tax_line.get('amount')
+
+ voucher_total += line_amount
+ total = voucher_total + total_tax
res.update({
- 'amount':total or voucher_total,
- 'tax_amount':total_tax
+ 'amount': total or voucher_total,
+ 'tax_amount': total_tax
})
return {
- 'value':res
+ 'value': res
}
def onchange_term_id(self, cr, uid, ids, term_id, amount):
@@ -953,6 +956,9 @@ class account_voucher(osv.osv):
if voucher_brw.number:
name = voucher_brw.number
elif voucher_brw.journal_id.sequence_id:
+ if not voucher_brw.journal_id.sequence_id.active:
+ raise osv.except_osv(_('Configuration Error !'),
+ _('Please activate the sequence of selected journal !'))
name = seq_obj.next_by_id(cr, uid, voucher_brw.journal_id.sequence_id.id, context=context)
else:
raise osv.except_osv(_('Error!'),
@@ -1504,6 +1510,15 @@ account_voucher_line()
class account_bank_statement(osv.osv):
_inherit = 'account.bank.statement'
+ def button_confirm_bank(self, cr, uid, ids, context=None):
+ voucher_obj = self.pool.get('account.voucher')
+ voucher_ids = []
+ for statement in self.browse(cr, uid, ids, context=context):
+ voucher_ids += [line.voucher_id.id for line in statement.line_ids if line.voucher_id]
+ if voucher_ids:
+ voucher_obj.write(cr, uid, voucher_ids, {'active': True}, context=context)
+ return super(account_bank_statement, self).button_confirm_bank(cr, uid, ids, context=context)
+
def button_cancel(self, cr, uid, ids, context=None):
voucher_obj = self.pool.get('account.voucher')
for st in self.browse(cr, uid, ids, context=context):
@@ -1539,6 +1554,16 @@ account_bank_statement()
class account_bank_statement_line(osv.osv):
_inherit = 'account.bank.statement.line'
+ def onchange_partner_id(self, cr, uid, ids, partner_id, context=None):
+ res = super(account_bank_statement_line, self).onchange_partner_id(cr, uid, ids, partner_id, context=context)
+ if 'value' not in res:
+ res['value'] = {}
+ res['value'].update({'voucher_id' : False})
+ return res
+
+ def onchange_amount(self, cr, uid, ids, amount, context=None):
+ return {'value' : {'voucher_id' : False}}
+
def _amount_reconciled(self, cursor, user, ids, name, args, context=None):
if not ids:
return {}
@@ -1565,7 +1590,7 @@ class account_bank_statement_line(osv.osv):
_columns = {
'amount_reconciled': fields.function(_amount_reconciled,
string='Amount reconciled', type='float'),
- 'voucher_id': fields.many2one('account.voucher', 'Payment'),
+ 'voucher_id': fields.many2one('account.voucher', 'Reconciliation'),
}
def unlink(self, cr, uid, ids, context=None):
diff --git a/addons/account_voucher/account_voucher_data.xml b/addons/account_voucher/account_voucher_data.xml
index 3d4252e697d..fc008e479e9 100644
--- a/addons/account_voucher/account_voucher_data.xml
+++ b/addons/account_voucher/account_voucher_data.xml
@@ -7,12 +7,10 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">eInvoicing &amp; Payments application installed!</field>
- <field name="body"><![CDATA[
- OpenERP's electronic invoicing accelerates the creation of invoices and collection of customer payments. Invoices are created in a few clicks and your customers receive them by email. They can pay online and/or import them in their own system.
-
-<p>You can track customer payments easily and automate follow-ups. You get an overview of the discussion with your customers on each invoice for easier traceability. For advanced accounting features, you should install the "Accounting and Finance" module.</p>
- ]]></field>
+ <field name="body"><![CDATA[<p>OpenERP's electronic invoicing accelerates the creation of invoices and collection of customer payments. Invoices are created in a few clicks and your customers receive them by email. They can pay online and/or import them in their own system.</p>
+<p>You can track customer payments easily and automate follow-ups. You get an overview of the discussion with your customers on each invoice for easier traceability. For advanced accounting features, you should install the "Accounting and Finance" module.</p>]]></field>
</record>
<!-- mail: subtypes -->
diff --git a/addons/account_voucher/account_voucher_view.xml b/addons/account_voucher/account_voucher_view.xml
index babe60b640e..2cb393f4008 100644
--- a/addons/account_voucher/account_voucher_view.xml
+++ b/addons/account_voucher/account_voucher_view.xml
@@ -200,33 +200,29 @@
<field name="arch" type="xml">
<xpath expr="//div[@name='import_buttons']" position="inside">
<button name="%(action_view_account_statement_from_invoice_lines)d"
- string="Import Invoices" type="action" icon="gtk-execute"
+ string="Import Invoices" type="action"
attrs="{'invisible':[('state','=','confirm')]}"/>
</xpath>
</field>
</record>
- <record id="view_bank_statement_tree_voucher" model="ir.ui.view">
+ <record id="view_bank_statement_form_voucher" model="ir.ui.view">
<field name="name">account.bank.statement.voucher.tree.inherit</field>
<field name="model">account.bank.statement</field>
<field name="inherit_id" ref="account.view_bank_statement_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='statement_line_ids']/field[@name='line_ids']/tree/field[@name='amount']" position="after">
- <field name="voucher_id" context="{'line_type': type, 'default_type': amount &lt; 0 and 'payment' or 'receipt', 'type': amount &lt; 0 and 'payment' or 'receipt', 'default_partner_id': partner_id, 'default_journal_id': parent.journal_id, 'default_amount': abs(amount), 'default_reference': ref, 'default_date': date, 'default_name': name}"/>
+ <field name="voucher_id" widget="many2onebutton" options="{'label':{'create':'Reconcile','edit':'Edit Reconciliation'}}" context="{'line_type': type, 'default_type': amount &lt; 0 and 'payment' or 'receipt', 'type': amount &lt; 0 and 'payment' or 'receipt', 'default_partner_id': partner_id, 'default_journal_id': parent.journal_id, 'default_amount': abs(amount), 'default_reference': ref, 'default_date': date, 'default_name': name, 'default_active': False}"/>
</xpath>
- </field>
- </record>
-
- <record id="view_bank_statement_form_voucher" model="ir.ui.view">
- <field name="name">account.bank.statement.voucher.form.inherit</field>
- <field name="model">account.bank.statement</field>
- <field name="inherit_id" ref="account.view_bank_statement_form"/>
- <field name="arch" type="xml">
<xpath expr="//page[@name='statement_line_ids']/field[@name='line_ids']/form/group/field[@name='sequence']" position="before">
- <field name="voucher_id" context="{'line_type': type, 'default_type': amount &lt; 0 and 'payment' or 'receipt', 'type': amount &lt; 0 and 'payment' or 'receipt', 'default_partner_id': partner_id, 'default_journal_id': parent.journal_id, 'default_amount': abs(amount), 'default_reference': ref, 'default_date': date, 'default_name': name}"/>
+ <field name="voucher_id" widget="many2onebutton" options="{'label':{'create':'Reconcile','edit':'Edit Reconciliation'}}" context="{'line_type': type, 'default_type': amount &lt; 0 and 'payment' or 'receipt', 'type': amount &lt; 0 and 'payment' or 'receipt', 'default_partner_id': partner_id, 'default_journal_id': parent.journal_id, 'default_amount': abs(amount), 'default_reference': ref, 'default_date': date, 'default_name': name, 'default_active': False}"/>
</xpath>
+ <field name="amount" position="attributes">
+ <attribute name="on_change">onchange_amount(amount)</attribute>
+ </field>
</field>
</record>
+
<record id="view_cash_statement_tree_voucher" model="ir.ui.view">
<field name="name">account.cash.statement.voucher.tree.inherit</field>
<field name="model">account.bank.statement</field>
diff --git a/addons/account_voucher/i18n/nl.po b/addons/account_voucher/i18n/nl.po
index 87972b2d22c..84eb08244a6 100644
--- a/addons/account_voucher/i18n/nl.po
+++ b/addons/account_voucher/i18n/nl.po
@@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-02-08 01:37+0100\n"
-"PO-Revision-Date: 2012-05-10 18:01+0000\n"
-"Last-Translator: Raphael Collet (OpenERP) <Unknown>\n"
+"PO-Revision-Date: 2012-11-17 09:57+0000\n"
+"Last-Translator: Stefan Rijnhart (Therp) <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-10-30 05:19+0000\n"
-"X-Generator: Launchpad (build 16206)\n"
+"X-Launchpad-Export-Date: 2012-11-18 04:37+0000\n"
+"X-Generator: Launchpad (build 16278)\n"
#. module: account_voucher
#: view:sale.receipt.report:0
@@ -846,7 +846,7 @@ msgstr ""
#: view:account.voucher:0
#: model:ir.model,name:account_voucher.model_account_voucher
msgid "Accounting Voucher"
-msgstr "Betalingsintentie"
+msgstr "Journaalbon"
#. module: account_voucher
#: field:account.voucher,number:0
diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml
index 881a5e38f1c..b6f367601ff 100644
--- a/addons/account_voucher/voucher_payment_receipt_view.xml
+++ b/addons/account_voucher/voucher_payment_receipt_view.xml
@@ -54,6 +54,8 @@
<form string="Bill Payment" version="7.0">
<group col="6">
<field name="partner_id" required="1" on_change="onchange_partner_id(partner_id, journal_id, amount, currency_id, type, date, context)" string="Supplier" context="{'default_customer': 0, 'search_default_supplier': 1, 'default_supplier': 1, 'invoice_currency': currency_id}"/>
+ <field name="state" invisible="1"/>
+ <field name="company_id" invisible="1"/>
<field name="amount" on_change="onchange_amount(amount, payment_rate, partner_id, journal_id, currency_id, type, date, payment_rate_currency_id, company_id, context)"/>
<field name="journal_id"
domain="[('type','in',['bank', 'cash'])]"
@@ -390,35 +392,33 @@
<field name="model">account.voucher</field>
<field name="arch" type="xml">
<form string="Receipt" version="7.0">
- <header>
- <button name="proforma_voucher" string="Validate" states="draft" invisible="context.get('line_type', False)" class="oe_highlight"/>
- <button name="cancel_voucher" string="Cancel" states="draft,proforma" invisible="context.get('line_type', False)"/>
- <button name="cancel_voucher" string="Unreconcile" type="object" states="posted" invisible="context.get('line_type', False)" confirm="Are you sure to unreconcile and cancel this record ?"/>
- <button name="action_cancel_draft" type="object" states="cancel" string="Set to Draft" invisible="context.get('line_type', False)"/>
+ <header invisible="context.get('line_type', False)">
+ <button name="proforma_voucher" string="Validate" states="draft" class="oe_highlight"/>
+ <button name="cancel_voucher" string="Cancel" states="draft,proforma"/>
+ <button name="cancel_voucher" string="Unreconcile" type="object" states="posted" confirm="Are you sure to unreconcile and cancel this record ?"/>
+ <button name="action_cancel_draft" type="object" states="cancel" string="Set to Draft"/>
<field name="state" widget="statusbar" statusbar_visible="draft,posted" statusbar_colors='{"proforma":"blue"}'/>
</header>
<sheet>
<h1 attrs="{'invisible': [('number','=',False)]}"><field name="number"/></h1>
- <group>
+ <group invisible="context.get('line_type', False)">
<group>
- <field name="partner_id" domain="[('customer','=',True)]" required="1" invisible="context.get('line_type', False)" on_change="onchange_partner_id(partner_id, journal_id, amount, currency_id, type, date, context)" string="Customer" context="{'search_default_customer': 1}"/>
+ <field name="partner_id" domain="[('customer','=',True)]" required="1" on_change="onchange_partner_id(partner_id, journal_id, amount, currency_id, type, date, context)" string="Customer" context="{'search_default_customer': 1}"/>
<field name="currency_id" invisible="1"/>
<field name="amount" class="oe_inline"
string="Paid Amount"
widget="monetary" options="{'currency_field': 'currency_id'}"
- invisible="context.get('line_type', False)"
on_change="onchange_amount(amount, payment_rate, partner_id, journal_id, currency_id, type, date, payment_rate_currency_id, company_id, context)"/>
<field name="journal_id"
domain="[('type','in',['bank', 'cash'])]"
- invisible="context.get('line_type', False)"
widget="selection"
on_change="onchange_journal(journal_id, line_cr_ids, False, partner_id, date, amount, type, company_id, context)"
string="Payment Method"/>
</group>
<group>
- <field name="date" invisible="context.get('line_type', False)" on_change="onchange_date(date, currency_id, payment_rate_currency_id, amount, company_id, context)"/>
- <field name="reference" invisible="context.get('line_type', False)" string="Payment Ref" placeholder="e.g. 003/10"/>
- <field name="name" colspan="2" invisible="context.get('line_type', False)" placeholder="e.g. Invoice SAJ/0042"/>
+ <field name="date" on_change="onchange_date(date, currency_id, payment_rate_currency_id, amount, company_id, context)"/>
+ <field name="reference" string="Payment Ref" placeholder="e.g. 003/10"/>
+ <field name="name" colspan="2" placeholder="e.g. Invoice SAJ/0042"/>
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
<field name="account_id"
@@ -430,7 +430,7 @@
</group>
<notebook>
<page string="Payment Information" groups="base.group_user">
- <label for="line_cr_ids"/>
+ <label for="line_cr_ids" invisible="context.get('line_type', False)"/>
<field name="line_cr_ids" context="{'journal_id':journal_id, 'type':type, 'partner_id':partner_id}" on_change="onchange_line_ids(line_dr_ids, line_cr_ids, amount, currency_id, type, context)">
<tree string="Invoices and outstanding transactions" editable="bottom" colors="gray:amount==0">
<field name="move_line_id" context="{'journal_id':parent.journal_id, 'partner_id':parent.partner_id}"
@@ -511,7 +511,7 @@
</page>
</notebook>
</sheet>
- <div class="oe_chatter">
+ <div class="oe_chatter" invisible="context.get('line_type', False)">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
diff --git a/addons/account_voucher/voucher_sales_purchase_view.xml b/addons/account_voucher/voucher_sales_purchase_view.xml
index dd6917358a9..0a0ad94c870 100644
--- a/addons/account_voucher/voucher_sales_purchase_view.xml
+++ b/addons/account_voucher/voucher_sales_purchase_view.xml
@@ -50,7 +50,7 @@
<field name="res_model">account.voucher</field>
<field name="view_type">form</field>
<field name="domain">[('journal_id.type', 'in', ['bank', 'cash']), ('type','=','receipt'), ('partner_id','=',partner_id)]</field>
- <field name="context">{'type':'receipt', 'partner_id': partner_id, 'default_reference':reference}</field>
+ <field name="context">{'default_type':'receipt', 'type':'receipt', 'partner_id': partner_id, 'default_reference':reference}</field>
<field name="view_id" ref="view_vendor_receipt_form"/>
<field name="target">current</field>
</record>
diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py
index 78c7e103946..708f9b3b196 100644
--- a/addons/analytic/analytic.py
+++ b/addons/analytic/analytic.py
@@ -98,6 +98,10 @@ class account_analytic_account(osv.osv):
def name_get(self, cr, uid, ids, context=None):
res = []
+ if not ids:
+ return res
+ if isinstance(ids, (int, long)):
+ ids = [ids]
for id in ids:
elmt = self.browse(cr, uid, id, context=context)
res.append((id, self._get_one_full_name(elmt)))
@@ -323,7 +327,7 @@ class account_analytic_line(osv.osv):
'date': fields.date('Date', required=True, select=True),
'amount': fields.float('Amount', required=True, help='Calculated by multiplying the quantity and the price given in the Product\'s cost price. Always expressed in the company main currency.', digits_compute=dp.get_precision('Account')),
'unit_amount': fields.float('Quantity', help='Specifies the amount of quantity to count.'),
- 'account_id': fields.many2one('account.analytic.account', 'Analytic Account', required=True, ondelete='cascade', select=True, domain=[('type','<>','view')]),
+ 'account_id': fields.many2one('account.analytic.account', 'Analytic Account', required=True, ondelete='restrict', select=True, domain=[('type','<>','view')]),
'user_id': fields.many2one('res.users', 'User'),
'company_id': fields.related('account_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True),
diff --git a/addons/anonymization/security/ir.model.access.csv b/addons/anonymization/security/ir.model.access.csv
index 745913eaa65..e758867ce46 100644
--- a/addons/anonymization/security/ir.model.access.csv
+++ b/addons/anonymization/security/ir.model.access.csv
@@ -3,3 +3,4 @@ access_ir_model_fields_anonymization_group_system,ir_model_fields_anonymization
access_ir_model_fields_anonymization_user,ir_model_fields_anonymization user,model_ir_model_fields_anonymization,,1,0,0,0
access_ir_model_fields_anonymization_history_group_system,ir_model_fields_anonymization_history group_user,model_ir_model_fields_anonymization_history,base.group_system,1,1,1,1
access_ir_model_fields_anonymization_history_user,ir_model_fields_anonymization_history user,model_ir_model_fields_anonymization_history,,1,0,0,0
+access_ir_model_fields_anonymization_migration_fix,access_ir_model_fields_anonymization_migration_fix,model_ir_model_fields_anonymization_migration_fix,,1,1,1,1
diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py
index 9232a696da8..54284dee4da 100644
--- a/addons/audittrail/audittrail.py
+++ b/addons/audittrail/audittrail.py
@@ -346,8 +346,13 @@ class audittrail_objects_proxy(object_proxy):
x2m_model_id = x2m_model_ids and x2m_model_ids[0] or False
assert x2m_model_id, _("'%s' Model does not exist..." %(field_obj._obj))
x2m_model = pool.get('ir.model').browse(cr, SUPERUSER_ID, x2m_model_id)
- #recursive call on x2m fields that need to be checked too
- data.update(self.get_data(cr, SUPERUSER_ID, pool, resource[field], x2m_model, method))
+ field_resource_ids = list(set(resource[field]))
+ if model.model == x2m_model.model:
+ # we need to remove current resource_id from the many2many to prevent an infinit loop
+ if resource_id in field_resource_ids:
+ field_resource_ids.remove(resource_id)
+ data.update(self.get_data(cr, SUPERUSER_ID, pool, field_resource_ids, x2m_model, method))
+
data[(model.id, resource_id)] = {'text':values_text, 'value': values}
return data
@@ -388,6 +393,8 @@ class audittrail_objects_proxy(object_proxy):
}
# loop on all the fields
for field_name, field_definition in pool.get(model.model)._all_columns.items():
+ if field_name in ('__last_update', 'id'):
+ continue
#if the field_list param is given, skip all the fields not in that list
if field_list and field_name not in field_list:
continue
@@ -406,6 +413,10 @@ class audittrail_objects_proxy(object_proxy):
x2m_new_values_ids = new_values.get(key, {'value': {}})['value'].get(field_name, [])
# We use list(set(...)) to remove duplicates.
res_ids = list(set(x2m_old_values_ids + x2m_new_values_ids))
+ if model.model == x2m_model.model:
+ # we need to remove current resource_id from the many2many to prevent an infinit loop
+ if resource_id in res_ids:
+ res_ids.remove(resource_id)
for res_id in res_ids:
lines.update(self.prepare_audittrail_log_line(cr, SUPERUSER_ID, pool, x2m_model, res_id, method, old_values, new_values, field_list))
# if the value value is different than the old value: record the change
diff --git a/addons/audittrail/audittrail_view.xml b/addons/audittrail/audittrail_view.xml
index c26e1b5b570..5d5bdcc6c21 100644
--- a/addons/audittrail/audittrail_view.xml
+++ b/addons/audittrail/audittrail_view.xml
@@ -99,7 +99,7 @@
<field name="res_id" readonly="1"/>
<field name="object_id" readonly="1"/>
</group>
- <field name="line_ids" mode="tree,form"
+ <field name="line_ids" mode="tree"
widget="one2many_list" readonly="1">
<form string="Log Lines" version="7.0">
<group col="4">
diff --git a/addons/auth_anonymous/static/src/js/auth_anonymous.js b/addons/auth_anonymous/static/src/js/auth_anonymous.js
index 8a78aca479c..6768bc63ff9 100644
--- a/addons/auth_anonymous/static/src/js/auth_anonymous.js
+++ b/addons/auth_anonymous/static/src/js/auth_anonymous.js
@@ -4,11 +4,11 @@ openerp.auth_anonymous = function(instance) {
start: function() {
var self = this;
return $.when(this._super()).then(function() {
- var dblist = self._db_list || [];
+ var dblist = self.db_list || [];
if (!self.session.session_is_valid() && dblist.length === 1) {
self.remember_credentials = false;
// XXX get login/pass from server (via a rpc call) ?
- return self.do_login(dblist[0], 'anonymous', 'anonymous')
+ return self.do_login(dblist[0], 'anonymous', 'anonymous');
}
});
diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py
index 26016f3f0a1..4c7c5377184 100644
--- a/addons/auth_oauth/controllers/main.py
+++ b/addons/auth_oauth/controllers/main.py
@@ -1,48 +1,101 @@
+import functools
import logging
import simplejson
-import werkzeug.urls
-import werkzeug.utils
+from werkzeug.exceptions import BadRequest
-import openerp
+from openerp import SUPERUSER_ID
+import openerp.addons.web.http as oeweb
+from openerp.addons.web.controllers.main import db_monodb, set_cookie_and_redirect, login_and_redirect
+from openerp.modules.registry import RegistryManager
_logger = logging.getLogger(__name__)
-class OAuthController(openerp.addons.web.http.Controller):
+#----------------------------------------------------------
+# helpers
+#----------------------------------------------------------
+def fragment_to_query_string(func):
+ @functools.wraps(func)
+ def wrapper(self, req, **kw):
+ if not kw:
+ return """<html><head><script>
+ var l = window.location;
+ var q = l.hash.substring(1);
+ var r = '/' + l.search;
+ if(q.length !== 0) {
+ var s = l.search ? (l.search === '?' ? '' : '&') : '?';
+ r = l.pathname + l.search + s + q;
+ }
+ window.location = r;
+ </script></head><body></body></html>"""
+ return func(self, req, **kw)
+ return wrapper
+
+
+#----------------------------------------------------------
+# Controller
+#----------------------------------------------------------
+class OAuthController(oeweb.Controller):
_cp_path = '/auth_oauth'
- @openerp.addons.web.http.jsonrequest
+ @oeweb.jsonrequest
def list_providers(self, req, dbname):
try:
- registry = openerp.modules.registry.RegistryManager.get(dbname)
+ registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
providers = registry.get('auth.oauth.provider')
- l = providers.read(cr, openerp.SUPERUSER_ID, providers.search(cr, openerp.SUPERUSER_ID, [('enabled','=',True)]))
+ l = providers.read(cr, SUPERUSER_ID, providers.search(cr, SUPERUSER_ID, [('enabled', '=', True)]))
except Exception:
l = []
return l
- @openerp.addons.web.http.httprequest
+ @oeweb.httprequest
+ @fragment_to_query_string
def signin(self, req, **kw):
state = simplejson.loads(kw['state'])
dbname = state['d']
provider = state['p']
- registry = openerp.modules.registry.RegistryManager.get(dbname)
+ context = state.get('c', {})
+ registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
try:
u = registry.get('res.users')
- credentials = u.auth_oauth(cr, openerp.SUPERUSER_ID, provider, kw)
+ credentials = u.auth_oauth(cr, SUPERUSER_ID, provider, kw, context=context)
cr.commit()
- return openerp.addons.web.controllers.main.login_and_redirect(req, *credentials)
+ return login_and_redirect(req, *credentials)
except AttributeError:
# auth_signup is not installed
- _logger.error("auth_signup not installed on database %s: oauth sign up cancelled."%dbname)
+ _logger.error("auth_signup not installed on database %s: oauth sign up cancelled." % (dbname,))
url = "/#action=login&oauth_error=1"
- except Exception,e:
+ except Exception, e:
# signup error
_logger.exception("OAuth2: %s" % str(e))
url = "/#action=login&oauth_error=2"
- return openerp.addons.web.controllers.main.set_cookie_and_redirect(req, url)
+ return set_cookie_and_redirect(req, url)
+
+ @oeweb.httprequest
+ def oea(self, req, **kw):
+ """login user via OpenERP Account provider"""
+ dbname = kw.pop('db', None)
+ if not dbname:
+ dbname = db_monodb(req)
+ if not dbname:
+ return BadRequest()
+
+ registry = RegistryManager.get(dbname)
+ with registry.cursor() as cr:
+ IMD = registry['ir.model.data']
+ model, provider_id = IMD.get_object_reference(cr, SUPERUSER_ID, 'auth_oauth', 'provider_openerp')
+ assert model == 'auth.oauth.provider'
+
+ state = {
+ 'd': dbname,
+ 'p': provider_id,
+ 'c': {'no_user_creation': True},
+ }
+
+ kw['state'] = simplejson.dumps(state)
+ return self.signin(req, **kw)
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py
index 115e3136f00..7e7b3753a4e 100644
--- a/addons/auth_oauth/res_users.py
+++ b/addons/auth_oauth/res_users.py
@@ -24,7 +24,7 @@ class res_users(osv.Model):
('uniq_users_oauth_provider_oauth_uid', 'unique(oauth_provider_id, oauth_uid)', 'OAuth UID must be unique per provider'),
]
- def auth_oauth_rpc(self, cr, uid, endpoint, access_token, context=None):
+ def _auth_oauth_rpc(self, cr, uid, endpoint, access_token, context=None):
params = urllib.urlencode({'access_token': access_token})
if urlparse.urlparse(endpoint)[4]:
url = endpoint + '&' + params
@@ -34,6 +34,17 @@ class res_users(osv.Model):
response = f.read()
return simplejson.loads(response)
+ def _auth_oauth_validate(self, cr, uid, provider, access_token, context=None):
+ """ return the validation data corresponding to the access token """
+ p = self.pool.get('auth.oauth.provider').browse(cr, uid, provider, context=context)
+ validation = self._auth_oauth_rpc(cr, uid, p.validation_endpoint, access_token)
+ if validation.get("error"):
+ raise Exception(validation['error'])
+ if p.data_endpoint:
+ data = self._auth_oauth_rpc(cr, uid, p.data_endpoint, access_token)
+ validation.update(data)
+ return validation
+
def auth_oauth(self, cr, uid, provider, params, context=None):
# Advice by Google (to avoid Confused Deputy Problem)
# if validation.audience != OUR_CLIENT_ID:
@@ -41,25 +52,21 @@ class res_users(osv.Model):
# else:
# continue with the process
access_token = params.get('access_token')
- p = self.pool.get('auth.oauth.provider').browse(cr, uid, provider, context=context)
-
- validation = self.auth_oauth_rpc(cr, uid, p.validation_endpoint, access_token)
- if validation.get("error"):
- raise Exception(validation['error'])
- if p.data_endpoint:
- data = self.auth_oauth_rpc(cr, uid, p.data_endpoint, access_token)
- validation.update(data)
+ validation = self._auth_oauth_validate(cr, uid, provider, access_token)
# required
oauth_uid = validation['user_id']
if not oauth_uid:
raise openerp.exceptions.AccessDenied()
- email = validation.get('email', 'provider_%d_user_%d' % (p.id, oauth_uid))
+ email = validation.get('email', 'provider_%d_user_%d' % (provider, oauth_uid))
+ login = email
# optional
name = validation.get('name', email)
res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid), ('oauth_provider_id', '=', provider)])
if res:
assert len(res) == 1
- self.write(cr, uid, res[0], {'oauth_access_token': access_token})
+ user = self.browse(cr, uid, res[0], context=context)
+ login = user.login
+ user.write({'oauth_access_token': access_token})
else:
# New user if signup module available
if not hasattr(self, '_signup_create_user'):
@@ -67,9 +74,9 @@ class res_users(osv.Model):
new_user = {
'name': name,
- 'login': email,
+ 'login': login,
'user_email': email,
- 'oauth_provider_id': p.id,
+ 'oauth_provider_id': provider,
'oauth_uid': oauth_uid,
'oauth_access_token': access_token,
'active': True,
@@ -77,7 +84,7 @@ class res_users(osv.Model):
# TODO pass signup token to allow attach new user to right partner
self._signup_create_user(cr, uid, new_user)
- credentials = (cr.dbname, email, access_token)
+ credentials = (cr.dbname, login, access_token)
return credentials
def check_credentials(self, cr, uid, password):
diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js
index 15683cfac2a..2aa66877d42 100644
--- a/addons/auth_oauth/static/src/js/auth_oauth.js
+++ b/addons/auth_oauth/static/src/js/auth_oauth.js
@@ -36,7 +36,10 @@ openerp.auth_oauth = function(instance) {
ev.preventDefault();
var index = $(ev.target).data('index');
var p = this.oauth_providers[index];
- var ret = location.protocol+"//"+location.host+"/";
+ var ret = _.str.sprintf('%s//%s/auth_oauth/signin', location.protocol, location.host);
+ if (instance.session.debug) {
+ ret += '?debug';
+ }
var dbname = self.$("form [name=db]").val();
var state_object = {
d: dbname,
@@ -55,16 +58,4 @@ openerp.auth_oauth = function(instance) {
},
});
- instance.web.WebClient = instance.web.WebClient.extend({
- start: function() {
- this._super.apply(this, arguments);
- var params = $.deparam(window.location.hash.substring(1));
- // alert(JSON.stringify(params));
- if (params.hasOwnProperty('access_token')) {
- var url = "/auth_oauth/signin" + '?' + $.param(params);
- window.location = url;
- }
- },
- });
-
};
diff --git a/addons/auth_signup/static/src/js/auth_signup.js b/addons/auth_signup/static/src/js/auth_signup.js
index bb249429894..3025069dece 100644
--- a/addons/auth_signup/static/src/js/auth_signup.js
+++ b/addons/auth_signup/static/src/js/auth_signup.js
@@ -41,7 +41,7 @@ openerp.auth_signup = function(instance) {
on_token_loaded: function(result) {
// select the right the database
this.selected_db = result.db;
- this.on_db_loaded({db_list: [result.db]});
+ this.on_db_loaded([result.db]);
if (result.token) {
// switch to signup mode, set user name and login
this.$el.addClass("oe_login_signup");
@@ -80,16 +80,16 @@ openerp.auth_signup = function(instance) {
this.do_warn("Login", "No database selected !");
return false;
} else if (!name) {
- this.do_warn("Login", "Please enter a name.")
+ this.do_warn("Login", "Please enter a name.");
return false;
} else if (!login) {
- this.do_warn("Login", "Please enter a username.")
+ this.do_warn("Login", "Please enter a username.");
return false;
} else if (!password || !confirm_password) {
- this.do_warn("Login", "Please enter a password and confirm it.")
+ this.do_warn("Login", "Please enter a password and confirm it.");
return false;
} else if (password !== confirm_password) {
- this.do_warn("Login", "Passwords do not match; please retype them.")
+ this.do_warn("Login", "Passwords do not match; please retype them.");
return false;
}
var params = {
diff --git a/addons/base_action_rule/i18n/es.po b/addons/base_action_rule/i18n/es.po
index ae917d28ca1..5efae77d99b 100644
--- a/addons/base_action_rule/i18n/es.po
+++ b/addons/base_action_rule/i18n/es.po
@@ -8,15 +8,14 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-08 00:36+0000\n"
-"PO-Revision-Date: 2012-05-10 17:24+0000\n"
-"Last-Translator: Jordi Esteve (www.zikzakmedia.com) "
-"<jesteve@zikzakmedia.com>\n"
+"PO-Revision-Date: 2012-11-09 12:09+0000\n"
+"Last-Translator: Pedro Manuel Baeza <pedro.baeza@gmail.com>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-10-30 05:32+0000\n"
-"X-Generator: Launchpad (build 16206)\n"
+"X-Launchpad-Export-Date: 2012-11-10 04:59+0000\n"
+"X-Generator: Launchpad (build 16251)\n"
#. module: base_action_rule
#: help:base.action.rule,act_mail_to_user:0
@@ -340,7 +339,7 @@ msgstr "Activo"
#: code:addons/base_action_rule/base_action_rule.py:329
#, python-format
msgid "No Email ID Found for your Company address!"
-msgstr ""
+msgstr "¡No se ha encontrado Id del e-mail para la dirección de su compañía!"
#. module: base_action_rule
#: field:base.action.rule,act_remind_user:0
diff --git a/addons/base_calendar/crm_meeting_view.xml b/addons/base_calendar/crm_meeting_view.xml
index 10c65ab850b..8590bcb8b49 100644
--- a/addons/base_calendar/crm_meeting_view.xml
+++ b/addons/base_calendar/crm_meeting_view.xml
@@ -221,7 +221,7 @@
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
- <field name="message_ids" widget="mail_thread"/>
+ <field name="message_ids" widget="mail_thread" placeholder="Share a message..."/>
</div>
</form>
</field>
diff --git a/addons/base_gengo/wizard/base_gengo_translations.py b/addons/base_gengo/wizard/base_gengo_translations.py
index d8a96a2ced9..bfd51480141 100644
--- a/addons/base_gengo/wizard/base_gengo_translations.py
+++ b/addons/base_gengo/wizard/base_gengo_translations.py
@@ -19,20 +19,25 @@
#
##############################################################################
-from osv import osv, fields
-from tools.translate import _
-import re
-try:
- from mygengo import MyGengo
-except ImportError:
- raise osv.except_osv(_('Gengo ImportError'), _('Please install mygengo lib from http://pypi.python.org/pypi/mygengo'))
-
import logging
-import tools
+import re
import time
+from openerp.osv import osv, fields
+from openerp import tools
+from openerp.tools.translate import _
+
_logger = logging.getLogger(__name__)
+try:
+ from mygengo import MyGengo
+except ImportError:
+ _logger.warning('Gengo library not found, Gengo features disabled. If you plan to use it, please install the mygengo library from http://pypi.python.org/pypi/mygengo')
+ class MyGengo(object):
+ def __init__(self, *args, **kwargs):
+ # no context for translations - so don't bother
+ raise ImportError('Gengo library not found, please install mygengo from http://pypi.python.org/pypi/mygengo')
+
GENGO_DEFAULT_LIMIT = 20
DEFAULT_CRON_VALS = {
@@ -48,7 +53,7 @@ class base_gengo_translations(osv.osv_memory):
_name = 'base.gengo.translations'
_columns = {
'restart_send_job': fields.boolean("Restart Sending Job"),
- 'lang_id': fields.many2one('res.lang', 'Language', help="Leave empty if you don't want to restrict the request to a single language"),
+ 'lang_id': fields.many2one('res.lang', 'Language', required=True),
}
def gengo_authentication(self, cr, uid, context=None):
@@ -62,21 +67,19 @@ class base_gengo_translations(osv.osv_memory):
by the cron) or in a dialog box (if requested by the user), thus it's important to return it
translated.
'''
-
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
if not user.company_id.gengo_public_key or not user.company_id.gengo_private_key:
- return (False, _("Invalid Gengo configuration. Gengo authentication `Public Key` or `Private Key` is missing. Complete Gengo authentication parameters under `Settings > Companies > Gengo Parameters`."))
+ return (False, _("Gengo `Public Key` or `Private Key` are missing. Enter your Gengo authentication parameters under `Settings > Companies > Gengo Parameters`."))
try:
gengo = MyGengo(
public_key=user.company_id.gengo_public_key.encode('ascii'),
private_key=user.company_id.gengo_private_key.encode('ascii'),
- sandbox=True,
)
gengo.getAccountStats()
-
return (True, gengo)
except Exception, e:
- return (False, _("Gengo Connection Error\n%s") %e)
+ _logger.exception('Gengo connection failed')
+ return (False, _("Gengo connection failed with this message:\n``%s``") % e)
def do_check_schedular(self, cr, uid, xml_id, name, fn, context=None):
"""
@@ -87,7 +90,7 @@ class base_gengo_translations(osv.osv_memory):
cron_vals.update({'name': name, "function": fn})
try:
res = []
- model, res = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base_gengo', xml_id)
+ _, res = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base_gengo', xml_id)
cron_pool.write(cr, uid, [res], cron_vals, context=context)
except:
#the cron job was not found, probably deleted previously, so we create it again using default values
@@ -108,7 +111,7 @@ class base_gengo_translations(osv.osv_memory):
supported_langs = self.pool.get('ir.translation')._get_all_supported_languages(cr, uid, context=context)
language = self.pool.get('ir.translation')._get_gengo_corresponding_language(wizard.lang_id.code)
if language not in supported_langs:
- raise osv.except_osv(_("Warning"), _('This language is not supported by the Gengo translation services.'))
+ raise osv.except_osv(_("Warning"), _('This language is not supported by the Gengo translation services.'))
#send immediately a new request for the selected language (if any)
ctx = context.copy()
@@ -207,8 +210,6 @@ class base_gengo_translations(osv.osv_memory):
Send a request to Gengo with all the term_ids in a different job, get the response and update the terms in
database accordingly.
"""
-
- user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
flag, gengo = self.gengo_authentication(cr, uid, context=context)
if flag:
request = self.pack_jobs_request(cr, uid, term_ids, context=context)
diff --git a/addons/base_gengo/wizard/base_gengo_translations_view.xml b/addons/base_gengo/wizard/base_gengo_translations_view.xml
index 09c3a77b1d5..7b6be31d042 100644
--- a/addons/base_gengo/wizard/base_gengo_translations_view.xml
+++ b/addons/base_gengo/wizard/base_gengo_translations_view.xml
@@ -6,14 +6,9 @@
<field name="model">base.gengo.translations</field>
<field name="arch" type="xml">
<form string="Gengo Request Form" version="7.0">
- <group col="4">
- <group>
- <field name="lang_id" required="1"/>
- <field name="restart_send_job"/>
- </group>
- <group>
- <label colspan="2" string="Leave empty for requesting all the terms to Gengo that needs it, regardless of their language"/>
- </group>
+ <group>
+ <field name="lang_id"/>
+ <field name="restart_send_job"/>
</group>
<footer>
<button name="act_update" string="Send" type="object" class="oe_highlight"/>
diff --git a/addons/base_iban/base_iban.py b/addons/base_iban/base_iban.py
index c29647a1176..ff492a8d34b 100644
--- a/addons/base_iban/base_iban.py
+++ b/addons/base_iban/base_iban.py
@@ -99,6 +99,8 @@ class res_partner_bank(osv.osv):
@param iban: IBAN as string
@return: True if IBAN is valid, False otherwise
"""
+ if not iban:
+ return False
iban = _format_iban(iban).lower()
if iban[:2] in _ref_iban and len(iban) != len(_format_iban(_ref_iban[iban[:2]])):
return False
@@ -128,9 +130,9 @@ class res_partner_bank(osv.osv):
def _construct_constraint_msg(self, cr, uid, ids, context=None):
def default_iban_check(iban_cn):
- return iban_cn[0] in string.ascii_lowercase and iban_cn[1] in string.ascii_lowercase
+ return iban_cn and iban_cn[0] in string.ascii_lowercase and iban_cn[1] in string.ascii_lowercase
- iban_country = self.browse(cr, uid, ids)[0].acc_number[:2].lower()
+ iban_country = self.browse(cr, uid, ids)[0].acc_number and self.browse(cr, uid, ids)[0].acc_number[:2].lower()
if default_iban_check(iban_country):
if iban_country in _ref_iban:
return _('The IBAN does not seem to be correct. You should have entered something like this %s'), \
diff --git a/addons/base_import/__openerp__.py b/addons/base_import/__openerp__.py
index 6555cd8e3e0..eb8b4561c7e 100644
--- a/addons/base_import/__openerp__.py
+++ b/addons/base_import/__openerp__.py
@@ -24,9 +24,12 @@ Re-implement openerp's file import system:
'category': 'Uncategorized',
'website': 'http://www.openerp.com',
'author': 'OpenERP SA',
- 'depends': ['base'],
+ 'depends': ['web'],
'installable': True,
'auto_install': False,
+ 'data': [
+ 'security/ir.model.access.csv',
+ ],
'css': [
'static/lib/select2/select2.css',
'static/src/css/import.css',
@@ -37,4 +40,5 @@ Re-implement openerp's file import system:
'static/src/js/import.js',
],
'qweb': ['static/src/xml/import.xml'],
+ 'test': ['static/test/states.js'],
}
diff --git a/addons/base_import/static/test/states.js b/addons/base_import/static/test/states.js
new file mode 100644
index 00000000000..3e349907a6f
--- /dev/null
+++ b/addons/base_import/static/test/states.js
@@ -0,0 +1,6 @@
+$(document).ready(function () {
+ module('foo');
+ test('dummy', function () {
+ ok(42);
+ });
+});
diff --git a/addons/base_setup/__openerp__.py b/addons/base_setup/__openerp__.py
index de2d8236ece..e74238ba59c 100644
--- a/addons/base_setup/__openerp__.py
+++ b/addons/base_setup/__openerp__.py
@@ -44,7 +44,6 @@ Shows you a list of applications features to install from.
'installable': True,
'auto_install': False,
'images': ['images/base_setup1.jpeg','images/base_setup2.jpeg','images/base_setup3.jpeg','images/base_setup4.jpeg',],
- 'js': ['static/src/js/base_setup.js'],
'css': ['static/src/css/base_setup.css'],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/base_status/base_stage.py b/addons/base_status/base_stage.py
index 867b2207a99..86edff46920 100644
--- a/addons/base_status/base_stage.py
+++ b/addons/base_status/base_stage.py
@@ -224,8 +224,6 @@ class base_stage(object):
cases = self.browse(cr, uid, ids, context=context)
for case in cases:
data = {'active': True}
- if case.stage_id and case.stage_id.state == 'draft':
- data['date_open'] = fields.datetime.now()
if not case.user_id:
data['user_id'] = uid
self.case_set(cr, uid, [case.id], 'open', data, context=context)
diff --git a/addons/base_tools/i18n/hu.po b/addons/base_tools/i18n/hu.po
new file mode 100644
index 00000000000..64e4ab45ab5
--- /dev/null
+++ b/addons/base_tools/i18n/hu.po
@@ -0,0 +1,30 @@
+# Hungarian translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2011-01-11 11:14+0000\n"
+"PO-Revision-Date: 2012-11-13 16:00+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Hungarian <hu@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-11-14 04:40+0000\n"
+"X-Generator: Launchpad (build 16251)\n"
+
+#. module: base_tools
+#: model:ir.module.module,shortdesc:base_tools.module_meta_information
+msgid "Common base for tools modules"
+msgstr ""
+
+#. module: base_tools
+#: model:ir.module.module,description:base_tools.module_meta_information
+msgid ""
+"\n"
+" "
+msgstr ""
diff --git a/addons/claim_from_delivery/i18n/lt.po b/addons/claim_from_delivery/i18n/lt.po
new file mode 100644
index 00000000000..03ac2ad03ee
--- /dev/null
+++ b/addons/claim_from_delivery/i18n/lt.po
@@ -0,0 +1,23 @@
+# Lithuanian translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2012-02-08 00:36+0000\n"
+"PO-Revision-Date: 2012-11-15 13:45+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Lithuanian <lt@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-11-16 04:36+0000\n"
+"X-Generator: Launchpad (build 16272)\n"
+
+#. module: claim_from_delivery
+#: model:ir.actions.act_window,name:claim_from_delivery.action_claim_from_delivery
+msgid "Claim"
+msgstr ""
diff --git a/addons/crm/crm.py b/addons/crm/crm.py
index eb602b98c09..368656224ac 100644
--- a/addons/crm/crm.py
+++ b/addons/crm/crm.py
@@ -115,7 +115,6 @@ class crm_case_section(osv.osv):
'code': fields.char('Code', size=8),
'active': fields.boolean('Active', help="If the active field is set to "\
"true, it will allow you to hide the sales team without removing it."),
- 'allow_unlink': fields.boolean('Allow Delete', help="Allows to delete non draft cases"),
'change_responsible': fields.boolean('Reassign Escalated', help="When escalating to this team override the salesman with the team leader."),
'user_id': fields.many2one('res.users', 'Team Leader'),
'member_ids':fields.many2many('res.users', 'sale_member_rel', 'section_id', 'member_id', 'Team Members'),
@@ -137,7 +136,6 @@ class crm_case_section(osv.osv):
_defaults = {
'active': 1,
- 'allow_unlink': 1,
'stage_ids': _get_stage_common,
'alias_domain': False, # always hide alias during creation
}
diff --git a/addons/crm/crm_action_rule.py b/addons/crm/crm_action_rule.py
index 910a1fca169..4a8ee98fbae 100644
--- a/addons/crm/crm_action_rule.py
+++ b/addons/crm/crm_action_rule.py
@@ -79,7 +79,7 @@ class base_action_rule(osv.osv):
write['section_id'] = action.act_section_id.id
if hasattr(action, 'act_categ_id') and action.act_categ_id:
- write['categ_ids'] = [4, action.act_categ_id.id]
+ write['categ_ids'] = [(4, action.act_categ_id.id)]
model_obj.write(cr, uid, [obj.id], write, context)
return res
diff --git a/addons/crm/crm_data.xml b/addons/crm/crm_data.xml
index 9dfbd5f9948..f2bf56e34ac 100644
--- a/addons/crm/crm_data.xml
+++ b/addons/crm/crm_data.xml
@@ -58,9 +58,10 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">CRM application installed!</field>
- <field name="body">From the top Sales menu you can track leads and opportunities, get accurate forecast on your sales pipeline, plan meetings and phonecalls, get realtime statistics and efficiently organize the communication with your prospects.
-To manage quotations and sale orders, install the "Sales Management" application.</field>
+ <field name="body"><![CDATA[<p>From the top Sales menu you can track leads and opportunities, get accurate forecast on your sales pipeline, plan meetings and phonecalls, get realtime statistics and efficiently organize the communication with your prospects.</p>
+<p>To manage quotations and sale orders, install the "Sales Management" application.</p>]]></field>
</record>
<record model="mail.alias" id="default_sales_alias">
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index 64ba9476701..547b25af27c 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -779,14 +779,6 @@ class crm_lead(base_stage, format_address, osv.osv):
}
return res
- def unlink(self, cr, uid, ids, context=None):
- for lead in self.browse(cr, uid, ids, context):
- if (not lead.section_id.allow_unlink) and (lead.state != 'draft'):
- raise osv.except_osv(_('Error!'),
- _("You cannot delete lead '%s' because it is not in 'Draft' state. " \
- "You can still cancel it, instead of deleting it.") % lead.name)
- return super(crm_lead, self).unlink(cr, uid, ids, context)
-
def write(self, cr, uid, ids, vals, context=None):
if vals.get('stage_id') and not vals.get('probability'):
# change probability of lead(s) if required by stage
diff --git a/addons/crm/crm_view.xml b/addons/crm/crm_view.xml
index 5e2034d6373..99d3752529e 100644
--- a/addons/crm/crm_view.xml
+++ b/addons/crm/crm_view.xml
@@ -24,9 +24,9 @@
parent="base.menu_base_config" sequence="45" groups="base.group_sale_salesman"/>
<menuitem id="base.next_id_64" name="Sales"
- parent="base.menu_reporting" sequence="1" />
+ parent="base.menu_reporting" sequence="1"/>
- <menuitem id="base.menu_sales_configuration_misc" name="Miscellaneous" parent="base.menu_base_config" sequence="75"/>
+ <menuitem id="base.menu_sales_configuration_misc" name="Miscellaneous" parent="base.menu_base_config" sequence="81"/>
<!-- crm.case.channel -->
@@ -86,7 +86,7 @@
<field name="parent_id"/>
<field name="code"/>
</group>
-
+
<group>
<field name="user_id"/>
<field name="resource_calendar_id"/>
@@ -102,7 +102,6 @@
<field name="alias_name" class="oe_inline" attrs="{'required': [('alias_id', '!=', False)]}"/>@<field name="alias_domain" class="oe_inline"/>
</div>
<field name="change_responsible"/>
- <field name="allow_unlink"/>
</group>
<separator string="Team Members"/>
<field name="member_ids" widget="many2many_kanban">
@@ -163,7 +162,7 @@
<field name="view_id" ref="crm_case_section_view_tree"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
- Click to define a new sales team.
+ Click to define a new sales team.
</p><p>
Use sales team to organize your different salespersons or
departments into separate teams. Each team will work in
@@ -203,7 +202,7 @@
<form string="Stage" version="7.0">
<group col="4">
<field name="name"/>
- <field name="state" />
+ <field name="state"/>
<field name="probability"/>
<field name="type"/>
<field name="on_change"/>
@@ -228,7 +227,7 @@
</record>
- <!-- Case Categories Form View -->
+ <!-- Case Categories Form View -->
<record id="crm_case_categ-view" model="ir.ui.view">
<field name="name">crm.case.categ.form</field>
@@ -238,7 +237,7 @@
<group>
<field name="name"/>
<field name="section_id"/>
- <field name="object_id" invisible="1" />
+ <field name="object_id" invisible="1"/>
</group>
</form>
</field>
@@ -297,7 +296,7 @@
<menuitem action="crm_case_resource_type_act"
id="menu_crm_case_resource_type_act" sequence="4"
groups="base.group_no_one"
- parent="base.menu_crm_config_lead" />
+ parent="base.menu_crm_config_lead"/>
<record id="crm_case_section_act_tree" model="ir.actions.act_window">
<field name="name">Cases by Sales Team</field>
@@ -354,13 +353,13 @@
<button name="process_start"
states="not running"
string="Compute Segmentation" type="object"
- icon="gtk-execute" />
+ icon="gtk-execute"/>
<button name="process_stop" states="running"
string="Stop Process" type="object"
- icon="gtk-cancel" />
+ icon="gtk-cancel"/>
<button name="process_continue" states="running"
string="Continue Process" type="object"
- icon="gtk-go-forward" />
+ icon="gtk-go-forward"/>
<field name="state" widget="statusbar"/>
</header>
<group col="4">
@@ -412,7 +411,7 @@
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
- Click to define a new customer segmentation.
+ Click to define a new customer segmentation.
</p><p>
Create specific categories which you can assign to your
contacts to better manage your interactions with them. The
@@ -425,7 +424,7 @@
<menuitem action="crm_segmentation_tree-act"
id="menu_crm_segmentation-act"
groups="base.group_no_one" sequence="15"
- parent="base.menu_base_config" />
+ parent="base.menu_base_config"/>
<!-- menu for the working time -->
<menuitem action="resource.action_resource_calendar_form" id="menu_action_resource_calendar_form" parent="resource.menu_resource_config" sequence="1"/>
@@ -466,11 +465,11 @@
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
-
+
<menuitem action="action_crm_payment_mode"
id="menu_crm_payment_mode_act"
groups="base.group_no_one"
name="Payment Modes"
- parent="base.menu_crm_config_lead" />
+ parent="base.menu_crm_config_lead"/>
</data>
</openerp>
diff --git a/addons/crm/i18n/es.po b/addons/crm/i18n/es.po
index fe2f139f682..a72a6ec2305 100644
--- a/addons/crm/i18n/es.po
+++ b/addons/crm/i18n/es.po
@@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-02-08 01:37+0100\n"
-"PO-Revision-Date: 2012-02-10 17:48+0000\n"
-"Last-Translator: Carlos Ch. <Unknown>\n"
+"PO-Revision-Date: 2012-11-09 12:10+0000\n"
+"Last-Translator: Pedro Manuel Baeza <pedro.baeza@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-10-30 04:57+0000\n"
-"X-Generator: Launchpad (build 16206)\n"
+"X-Launchpad-Export-Date: 2012-11-10 04:59+0000\n"
+"X-Generator: Launchpad (build 16251)\n"
#. module: crm
#: view:crm.lead.report:0
@@ -172,7 +172,7 @@ msgstr "Mes esperado de cierre"
#. module: crm
#: view:crm.lead2opportunity.partner.mass:0
msgid "Assigned Opportunities to"
-msgstr ""
+msgstr "Oportunidades asignadas a"
#. module: crm
#: view:crm.lead:0 field:crm.lead,partner_id:0 view:crm.lead.report:0
@@ -598,7 +598,7 @@ msgstr "Fecha de fin"
#. module: crm
#: view:crm.opportunity2phonecall:0 view:crm.phonecall2phonecall:0
msgid "Schedule/Log a Call"
-msgstr ""
+msgstr "Planificar/Registrar una llamada"
#. module: crm
#: constraint:base.action.rule:0
@@ -792,7 +792,7 @@ msgstr "Siguiente"
#. module: crm
#: field:crm.segmentation,som_interval:0
msgid "Days per Period"
-msgstr ""
+msgstr "Días por periodo"
#. module: crm
#: field:crm.meeting,byday:0
@@ -959,7 +959,7 @@ msgstr "Días para abrir"
#. module: crm
#: view:crm.meeting:0
msgid "Show Time as"
-msgstr ""
+msgstr "Mostrar hora como"
#. module: crm
#: view:crm.phonecall2partner:0
@@ -1342,7 +1342,7 @@ msgstr "Fecha escritura"
#. module: crm
#: view:crm.meeting:0
msgid "End of Recurrency"
-msgstr ""
+msgstr "Fin de recurrencia"
#. module: crm
#: view:crm.meeting:0
@@ -1392,6 +1392,12 @@ msgid ""
" \n"
"If the call needs to be done then the state is set to 'Not Held'."
msgstr ""
+"El estado se establece a 'Para hacer' cuando se crea el caso.\n"
+"Si es caso está en marcha, el estado se establece a 'Abierto.\n"
+"Cuando la llamada se termina, el estado se establece en 'Realizada'. "
+" \n"
+"Si la llamada está pendiente de ser realizada, entonces el estado se "
+"establece en 'Pendiente'."
#. module: crm
#: selection:crm.meeting,week_list:0
@@ -1449,7 +1455,7 @@ msgstr "Oportunidades por categorías"
#. module: crm
#: model:crm.case.section,name:crm.section_sales_marketing_department
msgid "Sales Marketing Department"
-msgstr ""
+msgstr "Departamento de ventas y marketing"
#. module: crm
#: view:crm.phonecall.report:0
@@ -1900,7 +1906,7 @@ msgstr "Responder a"
#. module: crm
#: view:crm.case.section:0
msgid "Select Stages for this Sales Team"
-msgstr ""
+msgstr "Seleccione etapas para este equipo de ventas"
#. module: crm
#: view:board.board:0
@@ -2015,7 +2021,7 @@ msgstr "Ubicación"
#. module: crm
#: model:ir.model,name:crm.model_crm_lead2opportunity_partner_mass
msgid "Mass Lead To Opportunity Partner"
-msgstr ""
+msgstr "Transformación masiva de iniciativa a oportunidad"
#. module: crm
#: view:crm.lead:0
@@ -2777,7 +2783,7 @@ msgstr "e-mail del contacto"
#. module: crm
#: field:crm.lead,referred:0
msgid "Referred by"
-msgstr ""
+msgstr "Referido por"
#. module: crm
#: view:crm.lead:0 model:ir.model,name:crm.model_crm_add_note
@@ -3541,7 +3547,7 @@ msgstr "Nuevas oportunidades"
#: code:addons/crm/crm_action_rule.py:61
#, python-format
msgid "No E-Mail Found for your Company address!"
-msgstr ""
+msgstr "No se encontró dirección de e-mail para el contacto de su compañía"
#. module: crm
#: field:crm.lead.report,email:0
@@ -3561,7 +3567,7 @@ msgstr "Oportunidades por usuario y equipo"
#. module: crm
#: view:crm.phonecall:0
msgid "Reset to Todo"
-msgstr ""
+msgstr "Cambiar a 'Para hacer'"
#. module: crm
#: field:crm.case.section,working_hours:0
@@ -3643,6 +3649,10 @@ msgid ""
"partner. From the phone call form, you can trigger a request for another "
"call, a meeting or an opportunity."
msgstr ""
+"Esta herramienta permite registrar sus llamadas entrantes sobre la marcha. "
+"Cada llamada que recibe aparecerá en el formulario de la empresa para trazar "
+"cada contacto que tiene con una empresa. Desde el formulario de llamadas, "
+"puede lanzar una petición para otra llamada, una reunión u oportunidad."
#. module: crm
#: selection:crm.lead.report,creation_month:0
@@ -3673,6 +3683,10 @@ msgid ""
"channels that will be maintained at the creation of a document in the "
"system. Some examples of channels can be: Website, Phone Call, Reseller, etc."
msgstr ""
+"Controle el origen de sus iniciativas y oportunidades de venta mediante la "
+"creación de canales específicos que se usarán en la creación de documentos "
+"en el sistema. Algunos ejemplos de canales son: Sitio web, llamada "
+"telefónica, distribuidores, ..."
#. module: crm
#: selection:crm.lead2opportunity.partner,name:0
@@ -3740,7 +3754,7 @@ msgstr "Año"
#. module: crm
#: constraint:res.partner:0
msgid "Error ! You cannot create recursive associated members."
-msgstr ""
+msgstr "¡Error! No puede crear miembros asociados recursivamente."
#. module: crm
#: model:crm.case.resource.type,name:crm.type_lead8
diff --git a/addons/crm/report/crm_phonecall_report_view.xml b/addons/crm/report/crm_phonecall_report_view.xml
index a2120aef6ab..1f1a4f91046 100644
--- a/addons/crm/report/crm_phonecall_report_view.xml
+++ b/addons/crm/report/crm_phonecall_report_view.xml
@@ -91,7 +91,7 @@
<field name="res_model">crm.phonecall.report</field>
<field name="view_type">form</field>
<field name="view_mode">tree,graph</field>
- <field name="context">{"search_default_year":1,"search_default_User":1,"search_default_This Month":1,'group_by_no_leaf':1,'group_by':[]}</field>
+ <field name="context">{"search_default_year":1,"search_default_Salesperson":1,"search_default_This Month":1,'group_by_no_leaf':1,'group_by':[]}</field>
<field name="view_id" ref="view_report_crm_phonecall_tree"/>
<field name="search_view_id" ref="view_report_crm_phonecall_filter"/>
<field name="help">From this report, you can analyse the performance of your sales team, based on their phone calls. You can group or filter the information according to several criteria and drill down the information, by adding more groups in the report.</field>
diff --git a/addons/crm_claim/crm_claim.py b/addons/crm_claim/crm_claim.py
index e4d5f5999cb..8308e5420d0 100644
--- a/addons/crm_claim/crm_claim.py
+++ b/addons/crm_claim/crm_claim.py
@@ -105,7 +105,7 @@ class crm_claim(base_stage, osv.osv):
'email_from': fields.char('Email', size=128, help="Destination email for email gateway."),
'partner_phone': fields.char('Phone', size=32),
'stage_id': fields.many2one ('crm.claim.stage', 'Stage',
- domain="['|', ('section_ids', '=', section_id), ('case_default', '=', True)]"),
+ domain="['&',('fold', '=', False),'|', ('section_ids', '=', section_id), ('case_default', '=', True)]"),
'cause': fields.text('Root Cause'),
'state': fields.related('stage_id', 'state', type="selection", store=True,
selection=crm.AVAILABLE_STATES, string="Status", readonly=True,
diff --git a/addons/crm_claim/crm_claim_data.xml b/addons/crm_claim/crm_claim_data.xml
index 33bd280c364..ed0558f72e9 100644
--- a/addons/crm_claim/crm_claim_data.xml
+++ b/addons/crm_claim/crm_claim_data.xml
@@ -43,38 +43,32 @@
-->
<record model="crm.claim.stage" id="stage_claim1">
- <field name="name">Draft claim</field>
+ <field name="name">New</field>
<field name="state">draft</field>
<field name="sequence">26</field>
<field name="case_default" eval="True"/>
</record>
<record model="crm.claim.stage" id="stage_claim5">
- <field name="name">Actions Defined</field>
+ <field name="name">In Progress</field>
<field name="state">open</field>
<field name="sequence">27</field>
<field name="case_default" eval="True"/>
</record>
<record model="crm.claim.stage" id="stage_claim2">
- <field name="name">Actions Done</field>
+ <field name="name">Settled</field>
<field name="state">done</field>
<field name="sequence">28</field>
<field name="case_default" eval="True"/>
</record>
<record model="crm.claim.stage" id="stage_claim3">
- <field name="name">Refused</field>
- <field name="state">done</field>
+ <field name="name">Rejected</field>
+ <field name="state">cancel</field>
<field name="sequence">29</field>
<field name="case_default" eval="True"/>
<field name="case_refused" eval="True"/>
<field name="fold" eval="True"/>
</record>
- <record model="crm.claim.stage" id="stage_claim3">
- <field name="name">Cancelled</field>
- <field name="state">cancel</field>
- <field name="sequence">30</field>
- <field name="case_default" eval="True"/>
- <field name="fold" eval="True"/>
- </record>
+
</data>
</openerp>
diff --git a/addons/crm_claim/crm_claim_menu.xml b/addons/crm_claim/crm_claim_menu.xml
index 3782a3a7c00..4c0eca3d0f7 100644
--- a/addons/crm_claim/crm_claim_menu.xml
+++ b/addons/crm_claim/crm_claim_menu.xml
@@ -52,7 +52,7 @@
<!-- Claim Stages -->
<menuitem id="base.menu_definitions" name="Configuration" parent="base.menu_main_pm" sequence="60"/>
<menuitem id="base.menu_project_config_project" name="Stages" parent="base.menu_definitions" sequence="1"/>
- <menuitem id="menu_claim_stage_view" name="Claim Stages" action="crm_claim_stage_act" parent="base.menu_project_config_project" sequence="20"/>
+ <menuitem id="menu_claim_stage_view" name="Stages" action="crm_claim_stage_act" parent="menu_config_claim" sequence="20"/>
</data>
</openerp>
diff --git a/addons/crm_claim/crm_claim_view.xml b/addons/crm_claim/crm_claim_view.xml
index 2b5ca4b1556..85507a32c0f 100644
--- a/addons/crm_claim/crm_claim_view.xml
+++ b/addons/crm_claim/crm_claim_view.xml
@@ -102,16 +102,11 @@
<field name="arch" type="xml">
<form string="Claim" version="7.0">
<header>
- <button name="case_open" string="Open" type="object" class="oe_highlight"
- states="draft,pending" groups="base.group_user"/>
- <button name="case_close" string="Done" type="object" class="oe_highlight"
- states="open,pending" groups="base.group_user"/>
- <button name="case_reset" string="Reset to Draft" type="object" groups="base.group_user"
- states="cancel,done"/>
- <button name="case_cancel" string="Cancel" type="object" groups="base.group_user"
+ <button name="case_close" string="Settle" type="object" class="oe_highlight"
+ states="draft,open,pending" groups="base.group_user"/>
+ <button name="case_cancel" string="Reject" type="object" groups="base.group_user"
states="draft,open,pending"/>
- <field name="stage_id" widget="statusbar"
- on_change="onchange_stage_id(stage_id)"/>
+ <field name="stage_id" widget="statusbar" clickable="True"/>
</header>
<sheet string="Claims">
<group>
@@ -173,7 +168,7 @@
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
- <field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
+ <field name="message_ids" widget="mail_thread" placeholder="Share a note..."/>
</div>
</form>
</field>
diff --git a/addons/crm_helpdesk/crm_helpdesk_view.xml b/addons/crm_helpdesk/crm_helpdesk_view.xml
index 52f006ca7b2..1640b9d0318 100644
--- a/addons/crm_helpdesk/crm_helpdesk_view.xml
+++ b/addons/crm_helpdesk/crm_helpdesk_view.xml
@@ -95,7 +95,7 @@
</notebook>
</sheet>
<div class="oe_chatter">
- <field name="message_ids" widget="mail_thread"/>
+ <field name="message_ids" widget="mail_thread" placeholder="Share a note..."/>
<field name="message_follower_ids" widget="mail_followers"/>
</div>
</form>
diff --git a/addons/crm_partner_assign/i18n/es.po b/addons/crm_partner_assign/i18n/es.po
index 1f1fb3dee6f..4f6521a6421 100644
--- a/addons/crm_partner_assign/i18n/es.po
+++ b/addons/crm_partner_assign/i18n/es.po
@@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-08 00:36+0000\n"
-"PO-Revision-Date: 2011-01-16 17:13+0000\n"
-"Last-Translator: mgaja (GrupoIsep.com) <Unknown>\n"
+"PO-Revision-Date: 2012-11-09 12:10+0000\n"
+"Last-Translator: Pedro Manuel Baeza <pedro.baeza@gmail.com>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-10-30 05:33+0000\n"
-"X-Generator: Launchpad (build 16206)\n"
+"X-Launchpad-Export-Date: 2012-11-10 04:59+0000\n"
+"X-Generator: Launchpad (build 16251)\n"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,send_to:0
@@ -25,12 +25,12 @@ msgstr "Enviar a"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,subtype:0
msgid "Message type"
-msgstr ""
+msgstr "Tipo de mensaje"
#. module: crm_partner_assign
#: help:crm.lead.forward.to.partner,auto_delete:0
msgid "Permanently delete emails after sending"
-msgstr ""
+msgstr "Eliminar permanentemente los emails depués de su envío"
#. module: crm_partner_assign
#: field:crm.lead.report.assign,delay_close:0
@@ -40,7 +40,7 @@ msgstr "Retraso para cerrar"
#. module: crm_partner_assign
#: help:crm.lead.forward.to.partner,email_to:0
msgid "Message recipients"
-msgstr ""
+msgstr "Destinatarios del mensaje"
#. module: crm_partner_assign
#: field:crm.lead.report.assign,planned_revenue:0
@@ -61,7 +61,7 @@ msgstr "Agrupar por..."
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,template_id:0
msgid "Template"
-msgstr ""
+msgstr "Plantilla"
#. module: crm_partner_assign
#: view:crm.lead:0
@@ -76,12 +76,12 @@ msgstr "Geo localizar"
#. module: crm_partner_assign
#: help:crm.lead.forward.to.partner,body:0
msgid "Plain-text version of the message"
-msgstr ""
+msgstr "Versión en texto plano del mensaje"
#. module: crm_partner_assign
#: view:crm.lead.forward.to.partner:0
msgid "Body"
-msgstr ""
+msgstr "Cuerpo"
#. module: crm_partner_assign
#: selection:crm.lead.report.assign,month:0
@@ -101,7 +101,7 @@ msgstr "Demora cierre"
#. module: crm_partner_assign
#: view:crm.partner.report.assign:0
msgid "#Partner"
-msgstr ""
+msgstr "Nº empresa"
#. module: crm_partner_assign
#: selection:crm.lead.forward.to.partner,history:0
@@ -137,7 +137,7 @@ msgstr "Más alta"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,body:0
msgid "Text contents"
-msgstr ""
+msgstr "Contenido del texto"
#. module: crm_partner_assign
#: view:crm.lead.report.assign:0
@@ -148,7 +148,7 @@ msgstr "Día"
#. module: crm_partner_assign
#: help:crm.lead.forward.to.partner,message_id:0
msgid "Message unique identifier"
-msgstr ""
+msgstr "Identificador único del mensaje"
#. module: crm_partner_assign
#: selection:crm.lead.forward.to.partner,history:0
@@ -167,6 +167,8 @@ msgid ""
"Add here all attachments of the current document you want to include in the "
"Email."
msgstr ""
+"Añada aquí todos los datos adjuntos del documento que quiere incluir en el "
+"correo."
#. module: crm_partner_assign
#: selection:crm.lead.report.assign,state:0
@@ -195,17 +197,17 @@ msgstr ""
#. module: crm_partner_assign
#: help:crm.lead.forward.to.partner,body_html:0
msgid "Rich-text/HTML version of the message"
-msgstr ""
+msgstr "Versión en texto enriquecido / HTML del mensaje"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,auto_delete:0
msgid "Auto Delete"
-msgstr ""
+msgstr "Auto eliminar"
#. module: crm_partner_assign
#: help:crm.lead.forward.to.partner,email_bcc:0
msgid "Blind carbon copy message recipients"
-msgstr ""
+msgstr "Destinatarios de la copia oculta"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,partner_id:0
@@ -254,7 +256,7 @@ msgstr "Sección"
#. module: crm_partner_assign
#: view:crm.lead.forward.to.partner:0
msgid "Send"
-msgstr ""
+msgstr "Enviar"
#. module: crm_partner_assign
#: view:res.partner:0
@@ -286,7 +288,7 @@ msgstr "Tipo"
#. module: crm_partner_assign
#: view:crm.partner.report.assign:0
msgid "Name"
-msgstr ""
+msgstr "Nombre"
#. module: crm_partner_assign
#: selection:crm.lead.report.assign,priority:0
@@ -299,11 +301,13 @@ msgid ""
"Type of message, usually 'html' or 'plain', used to select plaintext or rich "
"text contents accordingly"
msgstr ""
+"Tipo de mensaje, normalmente 'html' o 'plano', utilizado para seleccionar "
+"contenidos en texto plano o en texto enriquecido"
#. module: crm_partner_assign
#: view:crm.lead.report.assign:0
msgid "Assign Date"
-msgstr ""
+msgstr "Fecha de asignación"
#. module: crm_partner_assign
#: view:crm.lead.report.assign:0
@@ -318,7 +322,7 @@ msgstr "Fecha creación"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,res_id:0
msgid "Related Document ID"
-msgstr ""
+msgstr "ID del docuemtno relacionado"
#. module: crm_partner_assign
#: view:crm.lead.report.assign:0
@@ -349,7 +353,7 @@ msgstr "Etapa"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,model:0
msgid "Related Document model"
-msgstr ""
+msgstr "Modelo del documento relacionado"
#. module: crm_partner_assign
#: code:addons/crm_partner_assign/wizard/crm_forward_to_partner.py:192
@@ -392,7 +396,7 @@ msgstr "Cerrar"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,use_template:0
msgid "Use Template"
-msgstr ""
+msgstr "Usar plantilla"
#. module: crm_partner_assign
#: model:ir.actions.act_window,name:crm_partner_assign.action_report_crm_opportunity_assign
@@ -464,12 +468,12 @@ msgstr "nº oportunidades"
#. module: crm_partner_assign
#: view:crm.lead:0
msgid "Team"
-msgstr ""
+msgstr "Equipo"
#. module: crm_partner_assign
#: view:crm.lead:0
msgid "Referred Partner"
-msgstr ""
+msgstr "Empresa referida"
#. module: crm_partner_assign
#: selection:crm.lead.report.assign,state:0
@@ -490,7 +494,7 @@ msgstr "Cerrado"
#. module: crm_partner_assign
#: model:ir.actions.act_window,name:crm_partner_assign.action_crm_send_mass_forward
msgid "Mass forward to partner"
-msgstr ""
+msgstr "Envío masivo a empresa"
#. module: crm_partner_assign
#: view:res.partner:0
@@ -570,7 +574,7 @@ msgstr "Longitud Geo"
#. module: crm_partner_assign
#: field:crm.partner.report.assign,opp:0
msgid "# of Opportunity"
-msgstr ""
+msgstr "Nº oportunidad"
#. module: crm_partner_assign
#: view:crm.lead.report.assign:0
@@ -600,12 +604,12 @@ msgstr "Empresa a la que este caso ha sido reenviado/asignado."
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,date:0
msgid "Date"
-msgstr ""
+msgstr "Fecha"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,body_html:0
msgid "Rich-text contents"
-msgstr ""
+msgstr "Contenido en texto enriquecido"
#. module: crm_partner_assign
#: view:crm.lead.report.assign:0
@@ -620,18 +624,18 @@ msgstr "res.empresa.nivel"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,message_id:0
msgid "Message-Id"
-msgstr ""
+msgstr "Id del mensaje"
#. module: crm_partner_assign
#: view:crm.lead.forward.to.partner:0
#: field:crm.lead.forward.to.partner,attachment_ids:0
msgid "Attachments"
-msgstr ""
+msgstr "Adjuntos"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,email_cc:0
msgid "Cc"
-msgstr ""
+msgstr "Cc"
#. module: crm_partner_assign
#: selection:crm.lead.report.assign,month:0
@@ -641,7 +645,7 @@ msgstr "Septiembre"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,references:0
msgid "References"
-msgstr ""
+msgstr "Referencias"
#. module: crm_partner_assign
#: view:crm.lead.report.assign:0
@@ -668,7 +672,7 @@ msgstr "Abierto"
#. module: crm_partner_assign
#: help:crm.lead.forward.to.partner,email_cc:0
msgid "Carbon copy message recipients"
-msgstr ""
+msgstr "Destinatarios de la copia"
#. module: crm_partner_assign
#: help:crm.lead.forward.to.partner,headers:0
@@ -676,6 +680,8 @@ msgid ""
"Full message headers, e.g. SMTP session headers (usually available on "
"inbound messages only)"
msgstr ""
+"Cabeceras completas del mensaje, por ejemplo las cabeceras de sesión SMTP "
+"(normalmente disponibles sólo en mensajes entrantes)"
#. module: crm_partner_assign
#: field:res.partner,date_localization:0
@@ -698,11 +704,13 @@ msgid ""
"Message sender, taken from user preferences. If empty, this is not a mail "
"but a message."
msgstr ""
+"Remitente del mensaje, proveniente de las preferencias del usuario. Si está "
+"vacío, esto no es correo electrónico, sino un mensaje."
#. module: crm_partner_assign
#: field:crm.partner.report.assign,nbr:0
msgid "# of Partner"
-msgstr ""
+msgstr "Nº empresa"
#. module: crm_partner_assign
#: view:crm.lead.forward.to.partner:0
@@ -713,7 +721,7 @@ msgstr "Reenviar a empresa"
#. module: crm_partner_assign
#: field:crm.partner.report.assign,name:0
msgid "Partner name"
-msgstr ""
+msgstr "Nombre de la empresa"
#. module: crm_partner_assign
#: selection:crm.lead.report.assign,month:0
@@ -728,7 +736,7 @@ msgstr "Ingreso estimado"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,reply_to:0
msgid "Reply-To"
-msgstr ""
+msgstr "Responder a"
#. module: crm_partner_assign
#: field:crm.lead,partner_assigned_id:0
@@ -748,7 +756,7 @@ msgstr "Oportunidad"
#. module: crm_partner_assign
#: view:crm.lead.forward.to.partner:0
msgid "Send Mail"
-msgstr ""
+msgstr "Enviar correo"
#. module: crm_partner_assign
#: field:crm.lead.report.assign,partner_id:0
@@ -776,7 +784,7 @@ msgstr "País"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,headers:0
msgid "Message headers"
-msgstr ""
+msgstr "Cabeceras del mensaje"
#. module: crm_partner_assign
#: view:res.partner:0
@@ -786,7 +794,7 @@ msgstr "Convertir en oportunidad"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,email_bcc:0
msgid "Bcc"
-msgstr ""
+msgstr "Cco"
#. module: crm_partner_assign
#: view:crm.lead:0
@@ -802,7 +810,7 @@ msgstr "Abril"
#: model:ir.actions.act_window,name:crm_partner_assign.action_report_crm_partner_assign
#: model:ir.ui.menu,name:crm_partner_assign.menu_report_crm_partner_assign_tree
msgid "Partnership Analysis"
-msgstr ""
+msgstr "Análisis de la relación"
#. module: crm_partner_assign
#: model:ir.model,name:crm_partner_assign.model_crm_lead
@@ -817,7 +825,7 @@ msgstr "Pendiente"
#. module: crm_partner_assign
#: view:crm.partner.report.assign:0
msgid "Partner assigned Analysis"
-msgstr ""
+msgstr "Análisis de la empresa asignada"
#. module: crm_partner_assign
#: model:ir.model,name:crm_partner_assign.model_crm_lead_report_assign
@@ -828,11 +836,12 @@ msgstr "Informe de iniciativas CRM"
#: help:crm.lead.forward.to.partner,references:0
msgid "Message references, such as identifiers of previous messages"
msgstr ""
+"Referencias del mensaje, tales como identificadores de mensajes anteriores"
#. module: crm_partner_assign
#: constraint:res.partner:0
msgid "Error ! You cannot create recursive associated members."
-msgstr ""
+msgstr "¡Error! No puede crear miembros asociados recursivamente."
#. module: crm_partner_assign
#: selection:crm.lead.forward.to.partner,history:0
@@ -847,12 +856,12 @@ msgstr "Secuencia"
#. module: crm_partner_assign
#: model:ir.model,name:crm_partner_assign.model_crm_partner_report_assign
msgid "CRM Partner Report"
-msgstr ""
+msgstr "Informe de la empresa CRM"
#. module: crm_partner_assign
#: model:ir.model,name:crm_partner_assign.model_crm_lead_forward_to_partner
msgid "Email composition wizard"
-msgstr ""
+msgstr "Asistente de composición de e-mail"
#. module: crm_partner_assign
#: selection:crm.lead.report.assign,priority:0
@@ -873,7 +882,7 @@ msgstr "Fecha de creación"
#. module: crm_partner_assign
#: field:crm.lead.forward.to.partner,filter_id:0
msgid "Filters"
-msgstr ""
+msgstr "Filtros"
#. module: crm_partner_assign
#: view:crm.lead.report.assign:0
@@ -884,7 +893,7 @@ msgstr "Año"
#. module: crm_partner_assign
#: help:crm.lead.forward.to.partner,reply_to:0
msgid "Preferred response address for the message"
-msgstr ""
+msgstr "Dirección de correo de respuesta preferida para este mensaje"
#~ msgid "Reply-to of the Sales team defined on this case"
#~ msgstr "\"Responder a\" del equipo de ventas definido en este caso"
@@ -941,3 +950,6 @@ msgstr ""
#~ "partners o asesores,\n"
#~ "basándose en geo-localización.\n"
#~ " "
+
+#~ msgid "E-mail composition wizard"
+#~ msgstr "Asistente de composición de e-mail"
diff --git a/addons/document/nodes.py b/addons/document/nodes.py
index 6bcb2237a9e..aeb2e64fc97 100644
--- a/addons/document/nodes.py
+++ b/addons/document/nodes.py
@@ -823,6 +823,7 @@ class node_res_dir(node_class):
uid = self.context.uid
ctx = self.context.context.copy()
ctx.update(self.dctx)
+ ctx.update(self.context.extra_ctx)
where = []
if self.domain:
app = safe_eval(self.domain, ctx)
diff --git a/addons/document_ftp/ftpserver/abstracted_fs.py b/addons/document_ftp/ftpserver/abstracted_fs.py
index dbda715f614..326c62f7a92 100644
--- a/addons/document_ftp/ftpserver/abstracted_fs.py
+++ b/addons/document_ftp/ftpserver/abstracted_fs.py
@@ -272,7 +272,7 @@ class abstracted_fs(object):
if path.startswith('/'):
path = path[1:]
- p_parts = path.split('/') # hard-code the unix sep here, by spec.
+ p_parts = path.split(os.sep)
assert '..' not in p_parts
diff --git a/addons/document_page/wizard/document_page_show_diff.py b/addons/document_page/wizard/document_page_show_diff.py
index ab5572768f4..13e8e79b3b7 100644
--- a/addons/document_page/wizard/document_page_show_diff.py
+++ b/addons/document_page/wizard/document_page_show_diff.py
@@ -43,7 +43,7 @@ class showdiff(osv.osv_memory):
elif len(ids) == 1:
old = history.browse(cr, uid, ids[0])
- nids = history.search(cr, uid, [('document_id', '=', old.document_id.id)])
+ nids = history.search(cr, uid, [('page_id', '=', old.page_id.id)])
nids.sort()
diff = history.getDiff(cr, uid, ids[0], nids[-1])
else:
diff --git a/addons/document_webdav/document_webdav.py b/addons/document_webdav/document_webdav.py
index 3b604d6cffb..cb1315140a3 100644
--- a/addons/document_webdav/document_webdav.py
+++ b/addons/document_webdav/document_webdav.py
@@ -51,9 +51,10 @@ class document_davdir(osv.osv):
# that might be not worth preparing.
nctx.extra_ctx['webdav_path'] = '/'+config.get_misc('webdav','vdir','webdav')
usr_obj = self.pool.get('res.users')
- res = usr_obj.read(cr, uid, uid, ['login'])
+ res = usr_obj.read(cr, uid, uid, ['login','lang'])
if res:
nctx.extra_ctx['username'] = res['login']
+ nctx.extra_ctx['lang'] = res['lang']
# TODO group
return
diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py
index 73337d92ab0..a9bee623f66 100644
--- a/addons/email_template/email_template.py
+++ b/addons/email_template/email_template.py
@@ -28,8 +28,6 @@ from osv import osv
from osv import fields
import tools
from tools.translate import _
-from tools.html_sanitize import html_sanitize
-from tools import append_content_to_html
from urllib import quote as quote
_logger = logging.getLogger(__name__)
@@ -118,7 +116,8 @@ class email_template(osv.osv):
"of the message"),
'subject': fields.char('Subject', translate=True, help="Subject (placeholders may be used here)",),
'email_from': fields.char('From', help="Sender address (placeholders may be used here)"),
- 'email_to': fields.char('To', help="Comma-separated recipient addresses (placeholders may be used here)"),
+ 'email_to': fields.char('To (Emails)', help="Comma-separated recipient addresses (placeholders may be used here)"),
+ 'email_recipients': fields.char('To (Partners)', help="Comma-separated ids of recipient partners (placeholders may be used here)"),
'email_cc': fields.char('Cc', help="Carbon copy recipients (placeholders may be used here)"),
'reply_to': fields.char('Reply-To', help="Preferred response address (placeholders may be used here)"),
'mail_server_id': fields.many2one('ir.mail_server', 'Outgoing Mail Server', readonly=False,
@@ -286,16 +285,16 @@ class email_template(osv.osv):
template = self.get_email_template(cr, uid, template_id, res_id, context)
values = {}
for field in ['subject', 'body_html', 'email_from',
- 'email_to', 'email_cc', 'reply_to']:
+ 'email_to', 'email_recipients', 'email_cc', 'reply_to']:
values[field] = self.render_template(cr, uid, getattr(template, field),
template.model, res_id, context=context) \
or False
if template.user_signature:
signature = self.pool.get('res.users').browse(cr, uid, uid, context).signature
- values['body_html'] = append_content_to_html(values['body_html'], signature)
+ values['body_html'] = tools.append_content_to_html(values['body_html'], signature)
if values['body_html']:
- values['body'] = html_sanitize(values['body_html'])
+ values['body'] = tools.html_sanitize(values['body_html'])
values.update(mail_server_id=template.mail_server_id.id or False,
auto_delete=template.auto_delete,
@@ -346,6 +345,7 @@ class email_template(osv.osv):
values = self.generate_email(cr, uid, template_id, res_id, context=context)
assert 'email_from' in values, 'email_from is missing or empty after template rendering, send_mail() cannot proceed'
attachments = values.pop('attachments') or {}
+ del values['email_recipients'] # TODO Properly use them.
msg_id = mail_mail.create(cr, uid, values, context=context)
# link attachments
attachment_ids = []
diff --git a/addons/email_template/email_template_view.xml b/addons/email_template/email_template_view.xml
index 448655a3121..4cddb31c8e1 100644
--- a/addons/email_template/email_template_view.xml
+++ b/addons/email_template/email_template_view.xml
@@ -29,7 +29,8 @@
<group>
<group string="Addressing">
<field name="email_from" required="1"/>
- <field name="email_to" required="1"/>
+ <field name="email_to"/>
+ <field name="email_recipients"/>
<field name="email_cc"/>
<field name="reply_to"/>
<field name="user_signature"/>
@@ -77,6 +78,7 @@
<field name="subject"/>
<field name="email_from"/>
<field name="email_to"/>
+ <field name="email_recipients"/>
<field name="report_name"/>
</tree>
</field>
diff --git a/addons/email_template/tests/test_mail.py b/addons/email_template/tests/test_mail.py
index 7af05f38b0e..7c69295ce9f 100644
--- a/addons/email_template/tests/test_mail.py
+++ b/addons/email_template/tests/test_mail.py
@@ -20,10 +20,10 @@
##############################################################################
import base64
-from openerp.addons.mail.tests import test_mail
+from openerp.addons.mail.tests import test_mail_mockup
-class test_message_compose(test_mail.TestMailMockups):
+class test_message_compose(test_mail_mockup.TestMailMockups):
def setUp(self):
super(test_message_compose, self).setUp()
@@ -52,8 +52,8 @@ class test_message_compose(test_mail.TestMailMockups):
# Mail data
_subject1 = 'Pigs'
_subject2 = 'Bird'
- _body_html1 = 'Fans of Pigs, unite !\n<pre>Admin</pre>\n'
- _body_html2 = 'I am angry !\n<pre>Admin</pre>\n'
+ _body_html1 = 'Fans of Pigs, unite !\n<p>Admin</p>\n'
+ _body_html2 = 'I am angry !\n<p>Admin</p>\n'
_attachments = [
{'name': 'First', 'datas_fname': 'first.txt', 'datas': base64.b64encode('My first attachment')},
{'name': 'Second', 'datas_fname': 'second.txt', 'datas': base64.b64encode('My second attachment')}
@@ -63,11 +63,16 @@ class test_message_compose(test_mail.TestMailMockups):
# Create template on mail.group, with attachments
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', 'subject': '${object.name}',
- 'body_html': '${object.description}', 'user_signature': True,
+ email_template_id = email_template.create(cr, uid, {
+ 'model_id': group_model_id,
+ 'name': 'Pigs Template',
+ 'subject': '${object.name}',
+ 'body_html': '${object.description}',
+ 'user_signature': True,
'attachment_ids': [(0, 0, _attachments[0]), (0, 0, _attachments[1])],
- 'email_to': 'b@b.b c@c.c', 'email_cc': 'd@d.d'})
+ 'email_to': 'b@b.b c@c.c',
+ 'email_cc': 'd@d.d'
+ })
# ----------------------------------------
# CASE1: comment and save as template
@@ -76,9 +81,9 @@ class test_message_compose(test_mail.TestMailMockups):
# 1. Comment on pigs
compose_id = mail_compose.create(cr, uid,
{'subject': 'Forget me subject', 'body': '<p>Dummy body</p>'},
- {'default_composition_mode': 'comment', 'default_model': 'mail.group',
+ {'default_composition_mode': 'comment',
+ 'default_model': 'mail.group',
'default_res_id': self.group_pigs_id,
- 'default_template_id': email_template_id,
'active_ids': [self.group_pigs_id, self.group_bird_id]})
compose = mail_compose.browse(cr, uid, compose_id)
@@ -97,8 +102,10 @@ class test_message_compose(test_mail.TestMailMockups):
# 1. Comment on pigs
compose_id = mail_compose.create(cr, uid,
{'subject': 'Forget me subject', 'body': 'Dummy body'},
- {'default_composition_mode': 'comment', 'default_model': 'mail.group',
+ {'default_composition_mode': 'comment',
+ 'default_model': 'mail.group',
'default_res_id': self.group_pigs_id,
+ 'default_use_template': False,
'default_template_id': email_template_id,
'active_ids': [self.group_pigs_id, self.group_bird_id]})
compose = mail_compose.browse(cr, uid, compose_id)
@@ -135,8 +142,10 @@ class test_message_compose(test_mail.TestMailMockups):
# 1. Mass_mail on pigs and bird, with a default_partner_ids set to check he is correctly added
compose_id = mail_compose.create(cr, uid,
{'subject': 'Forget me subject', 'body': 'Dummy body'},
- {'default_composition_mode': 'mass_mail', 'default_model': 'mail.group',
+ {'default_composition_mode': 'mass_mail',
+ 'default_model': 'mail.group',
'default_res_id': self.group_pigs_id,
+ 'default_use_template': False,
'default_template_id': email_template_id,
'default_partner_ids': [p_a_id],
'active_ids': [self.group_pigs_id, self.group_bird_id]})
@@ -170,3 +179,26 @@ class test_message_compose(test_mail.TestMailMockups):
partner_ids = self.res_partner.search(cr, uid, [('email', 'in', ['b@b.b', 'c@c.c', 'd@d.d'])])
self.assertEqual(set(message_pigs_pids), set(partner_ids), 'mail.message on pigs incorrect number of notified_partner_ids')
self.assertEqual(set(message_bird_pids), set(partner_ids), 'mail.message on bird notified_partner_ids incorrect')
+
+ # ----------------------------------------
+ # CASE4: test newly introduced email_recipients field
+ # ----------------------------------------
+
+ # get already-created partners back
+ p_b_id = self.res_partner.search(cr, uid, [('email', '=', 'b@b.b')])[0]
+ p_c_id = self.res_partner.search(cr, uid, [('email', '=', 'c@c.c')])[0]
+ p_d_id = self.res_partner.search(cr, uid, [('email', '=', 'd@d.d')])[0]
+ # modify template: use email_recipients, use template and email address in email_to to test all features together
+ user_model_id = self.registry('ir.model').search(cr, uid, [('model', '=', 'res.users')])[0]
+ email_template.write(cr, uid, [email_template_id], {
+ 'model_id': user_model_id,
+ 'body_html': '${object.login}',
+ 'email_to': '${object.email} c@c',
+ 'email_recipients': '%i,%i' % (p_b_id, p_c_id),
+ 'email_cc': 'd@d',
+ })
+ # patner by email + partner by id (no double)
+ send_to = [p_a_id, p_b_id, p_c_id, p_d_id]
+ # 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')
diff --git a/addons/email_template/wizard/email_template_preview_view.xml b/addons/email_template/wizard/email_template_preview_view.xml
index f91535a17a5..8dd4bc92ba7 100644
--- a/addons/email_template/wizard/email_template_preview_view.xml
+++ b/addons/email_template/wizard/email_template_preview_view.xml
@@ -17,6 +17,7 @@
<group>
<field name="email_from" readonly="1"/>
<field name="email_to" readonly="1"/>
+ <field name="email_recipients" readonly="1"/>
<field name="email_cc" readonly="1" attrs="{'invisible':[('email_cc','=',False)]}"/>
<field name="reply_to" readonly="1" attrs="{'invisible':[('reply_to','=',False)]}"/>
<field name="subject" readonly="1"/>
diff --git a/addons/email_template/wizard/mail_compose_message.py b/addons/email_template/wizard/mail_compose_message.py
index fe6f85da544..e9141029166 100644
--- a/addons/email_template/wizard/mail_compose_message.py
+++ b/addons/email_template/wizard/mail_compose_message.py
@@ -25,6 +25,21 @@ from osv import osv
from osv import fields
+def _reopen(self, res_id, model):
+ return {'type': 'ir.actions.act_window',
+ 'view_mode': 'form',
+ 'view_type': 'form',
+ 'res_id': res_id,
+ 'res_model': self._name,
+ 'target': 'new',
+ # save original model in context, because selecting the list of available
+ # templates requires a model in context
+ 'context': {
+ 'default_model': model,
+ },
+ }
+
+
class mail_compose_message(osv.TransientModel):
_inherit = 'mail.compose.message'
@@ -42,18 +57,17 @@ class mail_compose_message(osv.TransientModel):
else:
model = context.get('default_model', context.get('active_model'))
- if model:
- record_ids = email_template_obj.search(cr, uid, [('model', '=', model)], context=context)
- return email_template_obj.name_get(cr, uid, record_ids, context) + [(False, '')]
- return []
+ record_ids = email_template_obj.search(cr, uid, [('model', '=', model)], context=context)
+ return email_template_obj.name_get(cr, uid, record_ids, context) + [(False, '')]
def default_get(self, cr, uid, fields, context=None):
if context is None:
context = {}
result = super(mail_compose_message, self).default_get(cr, uid, fields, context=context)
result['template_id'] = context.get('default_template_id', context.get('mail.compose.template_id', False))
+
# pre-render the template if any
- if result.get('use_template'):
+ if result.get('use_template') and result.get('template_id'):
onchange_res = self.onchange_use_template(cr, uid, [], result.get('use_template'), result.get('template_id'),
result.get('composition_mode'), result.get('model'), result.get('res_id'), context=context)
result.update(onchange_res['value'])
@@ -65,6 +79,10 @@ class mail_compose_message(osv.TransientModel):
'template_id': fields.selection(_get_templates, 'Template', size=-1),
}
+ _defaults = {
+ 'use_template': True,
+ }
+
def onchange_template_id(self, cr, uid, ids, use_template, template_id, composition_mode, model, res_id, context=None):
""" - use_template not set: return default_get
- use_template set in mass_mailing: we cannot render, so return the template values
@@ -84,6 +102,7 @@ class mail_compose_message(osv.TransientModel):
'datas_fname': attach_fname,
'res_model': model,
'res_id': res_id,
+ 'type': 'binary', # overwrite the context default_value
}
values['attachment_ids'].append(ir_attach_obj.create(cr, uid, data_attach, context=context))
else:
@@ -104,7 +123,7 @@ class mail_compose_message(osv.TransientModel):
onchange_res['partner_ids'] = [(4, partner_id) for partner_id in onchange_res.pop('partner_ids', [])]
onchange_res['attachment_ids'] = [(4, attachment_id) for attachment_id in onchange_res.pop('attachment_ids', [])]
record.write(onchange_res)
- return True
+ return _reopen(self, record.id, record.model)
def onchange_use_template(self, cr, uid, ids, use_template, template_id, composition_mode, model, res_id, context=None):
""" onchange_use_template (values: True or False). If use_template is
@@ -136,8 +155,8 @@ class mail_compose_message(osv.TransientModel):
'attachment_ids': [(6, 0, [att.id for att in record.attachment_ids])]
}
template_id = email_template.create(cr, uid, values, context=context)
- record.write({'template_id': template_id, 'use_template': True})
- return True
+ record.write(record.onchange_template_id(True, template_id, record.composition_mode, record.model, record.res_id)['value'])
+ return _reopen(self, record.id, record.model)
#------------------------------------------------------
# Wizard validation and send
@@ -148,15 +167,23 @@ class mail_compose_message(osv.TransientModel):
mail.compose.message, transform email_cc and email_to into partner_ids """
template_values = self.pool.get('email.template').generate_email(cr, uid, template_id, res_id, context=context)
# filter template values
- fields = ['body', 'body_html', 'subject', 'email_to', 'email_cc', 'attachments']
+ fields = ['body', 'body_html', 'subject', 'email_to', 'email_recipients', 'email_cc', 'attachments']
values = dict((field, template_values[field]) for field in fields if template_values.get(field))
values['body'] = values.pop('body_html', '')
# transform email_to, email_cc into partner_ids
values['partner_ids'] = []
+
mails = tools.email_split(values.pop('email_to', '') + ' ' + values.pop('email_cc', ''))
for mail in mails:
partner_id = self.pool.get('res.partner').find_or_create(cr, uid, mail, context=context)
values['partner_ids'].append(partner_id)
+ email_recipients = values.pop('email_recipients', '')
+ if email_recipients:
+ for partner_id in email_recipients.split(','):
+ values['partner_ids'].append(int(partner_id))
+
+ values['partner_ids'] = list(set(values['partner_ids']))
+
return values
def render_message(self, cr, uid, wizard, res_id, context=None):
diff --git a/addons/email_template/wizard/mail_compose_message_view.xml b/addons/email_template/wizard/mail_compose_message_view.xml
index 05d0e8dffa1..5afaf9745e1 100644
--- a/addons/email_template/wizard/mail_compose_message_view.xml
+++ b/addons/email_template/wizard/mail_compose_message_view.xml
@@ -8,23 +8,22 @@
<field name="inherit_id" ref="mail.email_compose_message_wizard_form"/>
<field name="arch" type="xml">
<data>
- <xpath expr="//form/group" position="after">
- <group attrs="{'invisible':[('use_template','=',False)]}">
- <field name="use_template" invisible="1"
- on_change="onchange_use_template(use_template, template_id, composition_mode, model, res_id, context)"/>
- <field name="template_id"
- on_change="onchange_template_id(use_template, template_id, composition_mode, model, res_id, context)"/>
- </group>
+ <xpath expr="//field[@name='content_subtype']" position="after">
+ <field name="use_template" invisible="1"
+ on_change="onchange_use_template(use_template, template_id, composition_mode, model, res_id, context)"/>
</xpath>
- <xpath expr="//form/footer/button" position="after">
- <button icon="/email_template/static/src/img/email_template.png"
- type="object" name="toggle_template" string=""
- help="Use a message template"
- attrs="{'invisible':[('content_subtype','!=','html')]}"/>
- <button icon="/email_template/static/src/img/email_template_save.png"
- type="object" name="save_as_template" string=""
- help="Save as a new template"
- attrs="{'invisible':[('content_subtype','!=','html')]}"/>
+ <xpath expr="//footer" position="inside">
+ <group class="oe_right" col="1">
+ <div attrs="{'invisible':[('use_template','=',False)]}">Use template
+ <field name="template_id" attrs="{'invisible':[('use_template','=',False)]}"
+ nolabel="1"
+ on_change="onchange_template_id(use_template, template_id, composition_mode, model, res_id, context)"/>
+ </div>
+ <button icon="/email_template/static/src/img/email_template_save.png"
+ type="object" name="save_as_template" string="Save as new template" class="oe_link"
+ help="Save as a new template"
+ attrs="{'invisible':[('content_subtype','!=','html')]}"/>
+ </group>
</xpath>
</data>
</field>
diff --git a/addons/event/event_view.xml b/addons/event/event_view.xml
index 85e3020512e..696c0e2876b 100644
--- a/addons/event/event_view.xml
+++ b/addons/event/event_view.xml
@@ -205,7 +205,7 @@
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
- <field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
+ <field name="message_ids" widget="mail_thread" placeholder="Share a note..."/>
</div>
</form>
</field>
@@ -473,7 +473,7 @@
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
- <field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
+ <field name="message_ids" widget="mail_thread" placeholder="Share a note..."/>
</div>
</form>
</field>
diff --git a/addons/event/static/src/css/event.css b/addons/event/static/src/css/event.css
index f49f5474fa6..ff5bfaba19b 100644
--- a/addons/event/static/src/css/event.css
+++ b/addons/event/static/src/css/event.css
@@ -14,11 +14,13 @@
border-bottom-left-radius:3px;
border-bottom-right-radius:3px;
font-size: 12px;
+ border-collapse: separate;
text-align: center;
font-weight: bold;
color: #8A89BA;
-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
background-color: #FFFFFF;
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
}
.oe_event_month_year{
border-bottom-left-radius:3px;
diff --git a/addons/event_sale/event_sale.py b/addons/event_sale/event_sale.py
index 2dd40a7c285..f4d7fcaa013 100644
--- a/addons/event_sale/event_sale.py
+++ b/addons/event_sale/event_sale.py
@@ -39,7 +39,7 @@ class sale_order_line(osv.osv):
_columns = {
'event_id': fields.many2one('event.event', 'Event', help="Choose an event and it will automatically create a registration for this event."),
#those 2 fields are used for dynamic domains and filled by onchange
- 'event_type_id': fields.related('event_type_id', type='many2one', relation="event.type", string="Event Type"),
+ 'event_type_id': fields.related('product_id','event_type_id', type='many2one', relation="event.type", string="Event Type"),
'event_ok': fields.related('product_id', 'event_ok', string='event_ok', type='boolean'),
}
diff --git a/addons/fetchmail/fetchmail.py b/addons/fetchmail/fetchmail.py
index e0023697594..68f05dfeee2 100644
--- a/addons/fetchmail/fetchmail.py
+++ b/addons/fetchmail/fetchmail.py
@@ -243,20 +243,20 @@ class mail_mail(osv.osv):
def create(self, cr, uid, values, context=None):
if context is None:
- context={}
+ context = {}
fetchmail_server_id = context.get('fetchmail_server_id')
if fetchmail_server_id:
values['fetchmail_server_id'] = fetchmail_server_id
- res = super(mail_mail,self).create(cr, uid, values, context=context)
+ res = super(mail_mail, self).create(cr, uid, values, context=context)
return res
def write(self, cr, uid, ids, values, context=None):
if context is None:
- context={}
+ context = {}
fetchmail_server_id = context.get('fetchmail_server_id')
if fetchmail_server_id:
- values['fetchmail_server_id'] = server_id
- res = super(mail_mail,self).write(cr, uid, ids, values, context=context)
+ values['fetchmail_server_id'] = fetchmail_server_id
+ res = super(mail_mail, self).write(cr, uid, ids, values, context=context)
return res
diff --git a/addons/fleet/fleet.py b/addons/fleet/fleet.py
index d531b00bc43..be0e8b34351 100644
--- a/addons/fleet/fleet.py
+++ b/addons/fleet/fleet.py
@@ -56,7 +56,10 @@ class fleet_vehicle_cost(osv.Model):
def _year_get_fnc(self, cr, uid, ids, name, unknow_none, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
- res[record.id] = str(time.strptime(record.date, tools.DEFAULT_SERVER_DATE_FORMAT).tm_year)
+ if (record.date):
+ res[record.id] = str(time.strptime(record.date, tools.DEFAULT_SERVER_DATE_FORMAT).tm_year)
+ else:
+ res[record.id] = _('Unknown')
return res
def _cost_name_get_fnc(self, cr, uid, ids, name, unknow_none, context=None):
@@ -253,7 +256,6 @@ class fleet_vehicle(osv.Model):
def _search_get_overdue_contract_reminder(self, cr, uid, obj, name, args, context):
res = []
- today = fields.date.today(self, cr, uid, context=context)
for field, operator, value in args:
assert operator in ('=', '!=', '<>') and value in (True, False), 'Operation not supported'
if (operator == '=' and value == True) or (operator in ('<>', '!=') and value == False):
@@ -343,7 +345,7 @@ class fleet_vehicle(osv.Model):
'seats': fields.integer('Seats Number', help='Number of seats of the vehicle'),
'doors': fields.integer('Doors Number', help='Number of doors of the vehicle'),
'tag_ids' :fields.many2many('fleet.vehicle.tag', 'fleet_vehicle_vehicle_tag_rel', 'vehicle_tag_id','tag_id', 'Tags'),
- 'odometer': fields.function(_get_odometer, fnct_inv=_set_odometer, type='float', string='Odometer Value', help='Odometer measure of the vehicle at the moment of this log'),
+ 'odometer': fields.function(_get_odometer, fnct_inv=_set_odometer, type='float', string='Last Odometer', help='Odometer measure of the vehicle at the moment of this log'),
'odometer_unit': fields.selection([('kilometers', 'Kilometers'),('miles','Miles')], 'Odometer Unit', help='Unit of the odometer ',required=True),
'transmission': fields.selection([('manual', 'Manual'), ('automatic', 'Automatic')], 'Transmission', help='Transmission Used by the vehicle'),
'fuel_type': fields.selection([('gasoline', 'Gasoline'), ('diesel', 'Diesel'), ('electric', 'Electric'), ('hybrid', 'Hybrid')], 'Fuel Type', help='Fuel Used by the vehicle'),
@@ -718,7 +720,7 @@ class fleet_vehicle_log_contract(osv.Model):
'start_date': datetime.datetime.strftime(str_to_datetime(element.expiration_date) + datetime.timedelta(days=1), tools.DEFAULT_SERVER_DATE_FORMAT),
'expiration_date': datetime.datetime.strftime(enddate + diffdate, tools.DEFAULT_SERVER_DATE_FORMAT),
}
- newid = super(fleet_vehicle_log_contract, self).copy(cr, uid, [element.id], default, context=context)
+ newid = super(fleet_vehicle_log_contract, self).copy(cr, uid, element.id, default, context=context)
mod, modid = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fleet', 'fleet_vehicle_log_contract_form')
return {
'name':_("Renew Contract"),
@@ -769,8 +771,8 @@ class fleet_vehicle_log_contract(osv.Model):
'start_date': fields.date('Contract Start Date', help='Date when the coverage of the contract begins'),
'expiration_date': fields.date('Contract Expiration Date', help='Date when the coverage of the contract expirates (by default, one year after begin date)'),
'days_left': fields.function(get_days_left, type='integer', string='Warning Date'),
- 'insurer_id' :fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
- 'purchaser_id': fields.many2one('res.partner', 'Contractor', domain="['|', ('customer','=',True), ('employee','=',True)]",help='Person to which the contract is signed for'),
+ 'insurer_id' :fields.many2one('res.partner', 'Supplier'),
+ 'purchaser_id': fields.many2one('res.partner', 'Contractor', help='Person to which the contract is signed for'),
'ins_ref': fields.char('Contract Reference', size=64),
'state': fields.selection([('open', 'In Progress'), ('toclose','To Close'), ('closed', 'Terminated')], 'Status', readonly=True, help='Choose wheter the contract is still valid or not'),
'notes': fields.text('Terms and Conditions', help='Write here all supplementary informations relative to this contract'),
diff --git a/addons/fleet/fleet_board_view.xml b/addons/fleet/fleet_board_view.xml
index 425d5c5b8eb..760fc1cf583 100644
--- a/addons/fleet/fleet_board_view.xml
+++ b/addons/fleet/fleet_board_view.xml
@@ -43,7 +43,7 @@
<field name="view_id" ref="fleet_vehicle_kanban"></field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
- <field name="domain">['|',('contract_renewal_due_soon','>',0),('contract_renewal_overdue','>',0)]</field>
+ <field name="domain">['|',('contract_renewal_due_soon','=',True),('contract_renewal_overdue','=',True)]</field>
<field name="help" type="html">
<p>
Here are displayed vehicles for which one or more contracts need to be renewed. If you see this message, then there is no contracts to renew.
diff --git a/addons/fleet/fleet_view.xml b/addons/fleet/fleet_view.xml
index bb15440ba37..bed4cd872fa 100644
--- a/addons/fleet/fleet_view.xml
+++ b/addons/fleet/fleet_view.xml
@@ -227,7 +227,6 @@
<record model='ir.ui.view' id='fleet_vehicle_tree'>
<field name="name">fleet.vehicle.tree</field>
<field name="model">fleet.vehicle</field>
- <field name="sequence">1</field>
<field name="arch" type="xml">
<tree string="Vehicle" version="7.0" colors="orange:contract_renewal_due_soon and not contract_renewal_overdue;red:contract_renewal_overdue">
<field name="license_plate" />
@@ -256,7 +255,7 @@
<field name="location"/>
<field name="state" />
<field name="state" />
- <filter name="alert_true" domain="['|',('contract_renewal_due_soon','>',0),('contract_renewal_overdue','>',0)]" string="Has Alert(s)"/>
+ <filter name="alert_true" domain="['|',('contract_renewal_due_soon','=',True),('contract_renewal_overdue','=',True)]" string="Has Alert(s)"/>
</search>
</field>
</record>
@@ -522,7 +521,7 @@
<field name="name">fleet.vehicle.odometer.tree</field>
<field name="model">fleet.vehicle.odometer</field>
<field name="arch" type="xml">
- <tree string="Odometer Logs" version="7.0" editable="bottom">
+ <tree string="Odometer Logs" version="7.0" editable="top">
<field name="date" />
<field name="vehicle_id" on_change="on_change_vehicle(vehicle_id)"/>
<field name="value" />
@@ -563,7 +562,7 @@
<field name="name">Vehicles Odometer</field>
<field name="res_model">fleet.vehicle.odometer</field>
<field name="view_type">form</field>
- <field name="view_mode">tree,form,graph</field>
+ <field name="view_mode">tree,graph</field>
<field name="context">{"search_default_groupby_vehicle" : True}</field>
<field name="help" type="html">
<p>
diff --git a/addons/fleet/security/ir.model.access.csv b/addons/fleet/security/ir.model.access.csv
index 0c50a6fbee3..823b3cb2945 100644
--- a/addons/fleet/security/ir.model.access.csv
+++ b/addons/fleet/security/ir.model.access.csv
@@ -8,4 +8,6 @@ fleet_vehicle_access_right,fleet_vehicle_access_right,model_fleet_vehicle,,1,1,1
fleet_vehicle_log_fuel_access_right,fleet_vehicle_log_fuel_access_right,model_fleet_vehicle_log_fuel,,1,1,1,1
fleet_vehicle_log_services_access_right,fleet_vehicle_log_services_access_right,model_fleet_vehicle_log_services,,1,1,1,1
fleet_vehicle_log_contract_access_right,fleet_vehicle_log_contract_access_right,model_fleet_vehicle_log_contract,,1,1,1,1
-fleet_service_type_access_right,fleet_service_type_access_right,model_fleet_service_type,,1,1,1,1 \ No newline at end of file
+fleet_service_type_access_right,fleet_service_type_access_right,model_fleet_service_type,,1,1,1,1
+access_fleet_vehicle_cost,access_fleet_vehicle_cost,model_fleet_vehicle_cost,,1,1,1,1
+access_fleet_contract_state,access_fleet_contract_state,model_fleet_contract_state,,1,1,1,1
diff --git a/addons/fleet/static/src/img/icon.png b/addons/fleet/static/src/img/icon.png
index 3db7ae9fa49..5b41e43c5bd 100644
--- a/addons/fleet/static/src/img/icon.png
+++ b/addons/fleet/static/src/img/icon.png
Binary files differ
diff --git a/addons/hr/hr.py b/addons/hr/hr.py
index d57fcf49ab2..5f3a5653307 100644
--- a/addons/hr/hr.py
+++ b/addons/hr/hr.py
@@ -158,6 +158,8 @@ class hr_employee(osv.osv):
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
_columns = {
+ #we need a related field in order to be able to sort the employee by name
+ 'name_related': fields.related('resource_id', 'name', type='char', string='Name', readonly=True, store=True),
'country_id': fields.many2one('res.country', 'Nationality'),
'birthday': fields.date("Date of Birth"),
'ssnid': fields.char('SSN No', size=32, help='Social Security Number'),
@@ -207,6 +209,8 @@ class hr_employee(osv.osv):
'last_login': fields.related('user_id', 'date', type='datetime', string='Latest Connection', readonly=1),
}
+ _order='name_related'
+
def create(self, cr, uid, data, context=None):
employee_id = super(hr_employee, self).create(cr, uid, data, context=context)
try:
diff --git a/addons/hr/hr_data.xml b/addons/hr/hr_data.xml
index 514cf1f80f6..25c882f2201 100644
--- a/addons/hr/hr_data.xml
+++ b/addons/hr/hr_data.xml
@@ -6,11 +6,11 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Employee Directory application installed!</field>
- <field name="body">Manage your human resources with OpenERP: employees and their hierarchy, HR departments and job positions.
-
-More HR features are available via extra applications: Recruitment Process (manage job positions and recruitment), Timesheet Validation (record timesheets and attendance),
-Leave Management (keep track of employee leaves), Expense Management (manage employee expenses), Employee Appraisals (organize employee surveys, where employees evaluate their subordinates or their manager).</field>
+ <field name="body"><![CDATA[<p>Manage your human resources with OpenERP: employees and their hierarchy, HR departments and job positions.</p>
+<p>More HR features are available via extra applications: Recruitment Process (manage job positions and recruitment), Timesheet Validation (record timesheets and attendance),
+Leave Management (keep track of employee leaves), Expense Management (manage employee expenses), Employee Appraisals (organize employee surveys, where employees evaluate their subordinates or their manager).</p>]]></field>
</record>
<record id="employee" model="hr.employee">
diff --git a/addons/hr/hr_view.xml b/addons/hr/hr_view.xml
index c4a622d7a4f..8918c5012c3 100644
--- a/addons/hr/hr_view.xml
+++ b/addons/hr/hr_view.xml
@@ -288,7 +288,7 @@
</record>
<record id="open_view_categ_form" model="ir.actions.act_window">
- <field name="name">Categories of Employee</field>
+ <field name="name">Categories of Employees</field>
<field name="res_model">hr.employee.category</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
@@ -342,8 +342,8 @@
<group>
<group>
<field name="no_of_employee" groups="base.group_user"/>
- <field name="expected_employees" groups="base.group_user"/>
<field name="no_of_recruitment" on_change="on_change_expected_employee(no_of_recruitment,no_of_employee)"/>
+ <field name="expected_employees" groups="base.group_user"/>
</group>
<group>
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
diff --git a/addons/hr/i18n/es_EC.po b/addons/hr/i18n/es_EC.po
index 32e81b6d14d..bfbbb7fa180 100644
--- a/addons/hr/i18n/es_EC.po
+++ b/addons/hr/i18n/es_EC.po
@@ -8,15 +8,14 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-08 01:37+0100\n"
-"PO-Revision-Date: 2012-01-03 02:55+0000\n"
-"Last-Translator: Christopher Ormaza - (Ecuadorenlinea.net) "
-"<chris.ormaza@gmail.com>\n"
+"PO-Revision-Date: 2012-11-10 17:20+0000\n"
+"Last-Translator: Cristian Salamea (Gnuthink) <ovnicraft@gmail.com>\n"
"Language-Team: Spanish (Ecuador) <es_EC@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-10-30 05:17+0000\n"
-"X-Generator: Launchpad (build 16206)\n"
+"X-Launchpad-Export-Date: 2012-11-11 04:57+0000\n"
+"X-Generator: Launchpad (build 16251)\n"
#. module: hr
#: model:process.node,name:hr.process_node_openerpuser0
@@ -199,6 +198,8 @@ msgstr "Mujer"
msgid ""
"Expected number of employees for this job position after new recruitment."
msgstr ""
+"Número de Empleados para este puesto de trabajo después de las nuevas "
+"contrataciones"
#. module: hr
#: model:ir.ui.menu,name:hr.menu_open_view_attendance_reason_new_config
@@ -291,7 +292,7 @@ msgstr "Categorías"
#. module: hr
#: field:hr.job,expected_employees:0
msgid "Total Employees"
-msgstr ""
+msgstr "Total de Empleados"
#. module: hr
#: selection:hr.employee,marital:0
@@ -435,7 +436,7 @@ msgstr "Estado"
#: model:ir.actions.act_window,name:hr.open_view_categ_tree
#: model:ir.ui.menu,name:hr.menu_view_employee_category_tree
msgid "Categories Structure"
-msgstr ""
+msgstr "Estructura de categorías"
#. module: hr
#: field:hr.employee,partner_id:0
@@ -465,7 +466,7 @@ msgstr "¡Error! No se puede crear una jerarquía recursiva de empleados."
#. module: hr
#: model:ir.actions.act_window,name:hr.action2
msgid "Subordinate Hierarchy"
-msgstr ""
+msgstr "Jerarquía subirdinada"
#. module: hr
#: model:ir.actions.act_window,help:hr.view_department_form_installer
@@ -715,12 +716,12 @@ msgstr "Subordinados"
#. module: hr
#: field:hr.job,no_of_employee:0
msgid "Number of employees currently occupying this job position."
-msgstr ""
+msgstr "Número de empleados ocupando actualmente este puesto de trabajo"
#. module: hr
#: field:hr.job,no_of_recruitment:0
msgid "Number of new employees you expect to recruit."
-msgstr ""
+msgstr "Número de empleados que espera contratar"
#~ msgid "Working Time Categories"
#~ msgstr "Categorías de Horarios de Trabajo"
diff --git a/addons/hr/static/src/css/hr.css b/addons/hr/static/src/css/hr.css
index 00ef92c0fd8..f395f9939e5 100644
--- a/addons/hr/static/src/css/hr.css
+++ b/addons/hr/static/src/css/hr.css
@@ -18,10 +18,11 @@
-o-border-radius: 3px;
-ms-border-radius: 3px;
border-radius: 3px;
+ border-collapse: separate;
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
-o-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
- -box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
+ box-shadow: 0 1px 4px 3px rgba(0, 0, 0, 0.4);
}
.oe_employee_picture {
diff --git a/addons/hr_attendance/report/attendance_by_month.py b/addons/hr_attendance/report/attendance_by_month.py
index f104b9c287a..6d41869ff23 100644
--- a/addons/hr_attendance/report/attendance_by_month.py
+++ b/addons/hr_attendance/report/attendance_by_month.py
@@ -31,6 +31,7 @@ from report.interface import toxml
from report import report_sxw
from tools import ustr
from tools.translate import _
+from tools import to_xml
one_day = relativedelta(days=1)
month2name = [0, 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
@@ -111,7 +112,7 @@ class report_custom(report_rml):
<date>%s</date>
<company>%s</company>
</header>
- ''' % (str(rml_obj.formatLang(time.strftime("%Y-%m-%d"),date=True))+' ' + str(time.strftime("%H:%M")),pooler.get_pool(cr.dbname).get('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")),to_xml(pooler.get_pool(cr.dbname).get('res.users').browse(cr,uid,uid).company_id.name))
first_date = str(month)
som = datetime.strptime(first_date, '%Y-%m-%d %H:%M:%S')
diff --git a/addons/hr_evaluation/hr_evaluation_data.xml b/addons/hr_evaluation/hr_evaluation_data.xml
index 01915de76a0..2afb5200091 100644
--- a/addons/hr_evaluation/hr_evaluation_data.xml
+++ b/addons/hr_evaluation/hr_evaluation_data.xml
@@ -11,9 +11,9 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Employee Appraisals application installed!</field>
- <field name="body">Manage employee reviews: you can define an appraisal campaign with several steps, with specific evaluation surveys according to hierarchy levels.
-Evaluations filled by employees may be exported as pdf files.</field>
+ <field name="body"><![CDATA[<p>Manage employee reviews: you can define an appraisal campaign with several steps, with specific evaluation surveys according to hierarchy levels. Evaluations filled by employees may be exported as pdf files.</p>]]></field>
</record>
<record id="survey_2" model="survey">
@@ -811,8 +811,8 @@ Once the form had been filled, the employee send it to his supervisor.
<field name="comment_valid_err_msg">The comment you entered is in an invalid format.</field>
<field name="descriptive_text">* His direct reports will be invited through OpenERP to express a feedback on their supervisor's leadership and to give their opinion about their own engagement and effectiveness, the continuous improvement and openness in action in the company, ...
-* The employees will send back their anonymous answers to OpenERP. The data will be handled by the HR manager and a brief summary of the data will be sent to the concerned supervisor, to his team and to the supervisor's supervisor.
-* The appraiser should rate the employee’s major work accomplishments and performance according to the metric provided below :
+* The employees will send back their anonymous answers to OpenERP. The data will be handled by the HR manager and a brief summary of the data will be sent to the concerned supervisor, to his team and to the supervisor's supervisor.
+* The appraiser should rate the employee’s major work accomplishments and performance according to the metric provided below :
1 - Significantly exceeds standards and expectations required of the position
2 - Exceeds standards and expectations
diff --git a/addons/hr_expense/hr_expense.py b/addons/hr_expense/hr_expense.py
index c9961fa8a1d..ccb8af68e21 100644
--- a/addons/hr_expense/hr_expense.py
+++ b/addons/hr_expense/hr_expense.py
@@ -64,22 +64,22 @@ class hr_expense_expense(osv.osv):
_description = "Expense"
_order = "id desc"
_columns = {
- 'name': fields.char('Description', size=128),
+ 'name': fields.char('Description', size=128, required=True, readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}),
'id': fields.integer('Sheet ID', readonly=True),
- 'date': fields.date('Date', select=True),
+ 'date': fields.date('Date', select=True, readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}),
'journal_id': fields.many2one('account.journal', 'Force Journal', help = "The journal used when the expense is done."),
- 'employee_id': fields.many2one('hr.employee', "Employee", required=True),
+ 'employee_id': fields.many2one('hr.employee', "Employee", required=True, readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}),
'user_id': fields.many2one('res.users', 'User', required=True),
'date_confirm': fields.date('Confirmation Date', select=True, help="Date of the confirmation of the sheet expense. It's filled when the button Confirm is pressed."),
'date_valid': fields.date('Validation Date', select=True, help="Date of the acceptation of the sheet expense. It's filled when the button Accept is pressed."),
- 'user_valid': fields.many2one('res.users', 'Validation By'),
+ 'user_valid': fields.many2one('res.users', 'Validation By', readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}),
'account_move_id': fields.many2one('account.move', 'Ledger Posting'),
'line_ids': fields.one2many('hr.expense.line', 'expense_id', 'Expense Lines', readonly=True, states={'draft':[('readonly',False)]} ),
'note': fields.text('Note'),
'amount': fields.function(_amount, string='Total Amount', digits_compute= dp.get_precision('Account')),
'voucher_id': fields.many2one('account.voucher', "Employee's Receipt"),
- 'currency_id': fields.many2one('res.currency', 'Currency', required=True),
- 'department_id':fields.many2one('hr.department','Department'),
+ 'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}),
+ 'department_id':fields.many2one('hr.department','Department', readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}),
'company_id': fields.many2one('res.company', 'Company', required=True),
'state': fields.selection([
('draft', 'New'),
@@ -100,6 +100,12 @@ class hr_expense_expense(osv.osv):
'currency_id': _get_currency,
}
+ def unlink(self, cr, uid, ids, context=None):
+ for rec in self.browse(cr, uid, ids, context=context):
+ if rec.state != 'draft':
+ raise osv.except_osv(_('Warning!'),_('You can only delete draft expenses!'))
+ return super(hr_expense_expense, self).unlink(cr, uid, ids, context)
+
def onchange_currency_id(self, cr, uid, ids, currency_id=False, company_id=False, context=None):
res = {'value': {'journal_id': False}}
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type','=','purchase'), ('currency','=',currency_id), ('company_id', '=', company_id)], context=context)
@@ -236,16 +242,6 @@ class product_product(osv.osv):
'hr_expense_ok': fields.boolean('Can be Expensed', help="Specify if the product can be selected in an HR expense line."),
}
- def on_change_hr_expense_ok(self, cr, uid, id, hr_expense_ok):
-
- if not hr_expense_ok:
- return {}
- data_obj = self.pool.get('ir.model.data')
- cat_id = data_obj._get_id(cr, uid, 'hr_expense', 'cat_expense')
- categ_id = data_obj.browse(cr, uid, cat_id).res_id
- res = {'value' : {'type':'service','sale_ok' :False,'categ_id':categ_id }}
- return res
-
product_product()
class hr_expense_line(osv.osv):
diff --git a/addons/hr_expense/hr_expense_data.xml b/addons/hr_expense/hr_expense_data.xml
index 2a9f3ae0a56..f54156ac5ec 100644
--- a/addons/hr_expense/hr_expense_data.xml
+++ b/addons/hr_expense/hr_expense_data.xml
@@ -6,10 +6,10 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Expense Management application installed!</field>
- <field name="body">Manage your employees' expenses, after due validation by their manager and the accountant, then generate and pay the corresponding invoices.
-
-This feature is also linked to analytic accounting and compatible with timesheet invoices, so you will be able to automatically re-invoice project-related expenses to your customers.</field>
+ <field name="body"><![CDATA[<p>Manage your employees' expenses, after due validation by their manager and the accountant, then generate and pay the corresponding invoices.</p>
+<p>This feature is also linked to analytic accounting and compatible with timesheet invoices, so you will be able to automatically re-invoice project-related expenses to your customers.</p>]]></field>
</record>
<!-- Resource: product.uom.categ -->
diff --git a/addons/hr_expense/hr_expense_view.xml b/addons/hr_expense/hr_expense_view.xml
index 74b77009aae..d4b7cbae1ce 100644
--- a/addons/hr_expense/hr_expense_view.xml
+++ b/addons/hr_expense/hr_expense_view.xml
@@ -195,7 +195,7 @@
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="arch" type="xml">
<div name="options" position="inside">
- <field name="hr_expense_ok" on_change="on_change_hr_expense_ok(hr_expense_ok)"/>
+ <field name="hr_expense_ok"/>
<label for="hr_expense_ok"/>
</div>
</field>
diff --git a/addons/hr_holidays/hr_holidays.py b/addons/hr_holidays/hr_holidays.py
index 419b1bb8335..92b1d57ce15 100644
--- a/addons/hr_holidays/hr_holidays.py
+++ b/addons/hr_holidays/hr_holidays.py
@@ -90,6 +90,18 @@ class hr_holidays_status(osv.osv):
'color_name': 'red',
'active': True,
}
+
+ def name_get(self, cr, uid, ids, context=None):
+ if not ids:
+ return []
+ res = []
+ for record in self.browse(cr, uid, ids, context=context):
+ name = record.name
+ if not record.limit:
+ name = name + (' (%d/%d)' % (record.leaves_taken or 0.0, record.max_leaves or 0.0))
+ res.append((record.id, name))
+ return res
+
hr_holidays_status()
class hr_holidays(osv.osv):
diff --git a/addons/hr_holidays/hr_holidays_data.xml b/addons/hr_holidays/hr_holidays_data.xml
index afe2e69e697..5af0c60fc44 100644
--- a/addons/hr_holidays/hr_holidays_data.xml
+++ b/addons/hr_holidays/hr_holidays_data.xml
@@ -11,9 +11,10 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Leave Management application installed!</field>
- <field name="body">Manage employee leaves from the top menu "Human Resources". Employees can create leave requests that are validated by their manager and/or HR officers.
-Once validated, they are visible in the employee's calendar. HR officers can define leave types and allocate leaves to employees and employee categories.</field>
+ <field name="body"><![CDATA[<p>Manage employee leaves from the top menu "Human Resources". Employees can create leave requests that are validated by their manager and/or HR officers.</p>
+<p>Once validated, they are visible in the employee's calendar. HR officers can define leave types and allocate leaves to employees and employee categories.</p>]]></field>
</record>
diff --git a/addons/hr_holidays/hr_holidays_view.xml b/addons/hr_holidays/hr_holidays_view.xml
index ef300741139..752d278baed 100644
--- a/addons/hr_holidays/hr_holidays_view.xml
+++ b/addons/hr_holidays/hr_holidays_view.xml
@@ -122,7 +122,7 @@
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
- <field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
+ <field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
@@ -159,7 +159,7 @@
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
- <field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
+ <field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
diff --git a/addons/hr_holidays/report/holidays_summary_report.py b/addons/hr_holidays/report/holidays_summary_report.py
index 8a782075853..cadd3a22ce6 100644
--- a/addons/hr_holidays/report/holidays_summary_report.py
+++ b/addons/hr_holidays/report/holidays_summary_report.py
@@ -31,6 +31,7 @@ import time
from report import report_sxw
from tools import ustr
from tools.translate import _
+from tools import to_xml
def lengthmonth(year, month):
if month == 2 and ((year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0))):
@@ -240,7 +241,7 @@ class report_custom(report_rml):
<date>%s</date>
<company>%s</company>
</header>
- ''' % (str(rml_obj.formatLang(time.strftime("%Y-%m-%d"),date=True))+' ' + str(time.strftime("%H:%M")),pooler.get_pool(cr.dbname).get('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")),to_xml(pooler.get_pool(cr.dbname).get('res.users').browse(cr,uid,uid).company_id.name))
# Computing the xml
xml='''<?xml version="1.0" encoding="UTF-8" ?>
diff --git a/addons/hr_payroll/hr_payroll.py b/addons/hr_payroll/hr_payroll.py
index 53c84c65ee6..c0e4bc39321 100644
--- a/addons/hr_payroll/hr_payroll.py
+++ b/addons/hr_payroll/hr_payroll.py
@@ -326,6 +326,7 @@ class hr_payslip(osv.osv):
return self.write(cr, uid, ids, {'paid': True, 'state': 'done'}, context=context)
def hr_verify_sheet(self, cr, uid, ids, context=None):
+ self.compute_sheet(cr, uid, ids, context)
return self.write(cr, uid, ids, {'state': 'verify'}, context=context)
def refund_sheet(self, cr, uid, ids, context=None):
@@ -358,6 +359,12 @@ class hr_payslip(osv.osv):
def check_done(self, cr, uid, ids, context=None):
return True
+ def unlink(self, cr, uid, ids, context=None):
+ for payslip in self.browse(cr, uid, ids, context=context):
+ if payslip.state not in ['draft','cancel']:
+ raise osv.except_osv(_('Warning!'),_('You cannot delete a payslip which is not draft or cancelled!'))
+ return super(hr_payslip, self).unlink(cr, uid, ids, context)
+
#TODO move this function into hr_contract module, on hr.employee object
def get_contract(self, cr, uid, employee, date_from, date_to, context=None):
"""
diff --git a/addons/hr_payroll/hr_payroll_demo.xml b/addons/hr_payroll/hr_payroll_demo.xml
index 836814860c1..a22809b00e3 100644
--- a/addons/hr_payroll/hr_payroll_demo.xml
+++ b/addons/hr_payroll/hr_payroll_demo.xml
@@ -75,7 +75,7 @@
<record id="hr_salary_rule_meal_voucher" model="hr.salary.rule">
<field name="amount_select">fix</field>
<field eval="10" name="amount_fix"/>
- <field name="quantity">worked_days.WORK100.number_of_days</field>
+ <field name="quantity">worked_days.WORK100 and worked_days.WORK100.number_of_days</field>
<field name="code">MA</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="register_id" ref="hr_meal_voucher_register"/>
@@ -89,7 +89,7 @@
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="name">Get 1% of sales</field>
<field name="sequence" eval="17"/>
- <field name="amount_python_compute">result = (inputs.SALEURO.amount + inputs.SALASIA.amount) * 0.01</field>
+ <field name="amount_python_compute">result = ((inputs.SALEURO and inputs.SALEURO.amount) + (inputs.SALASIA and inputs.SALASIA.amount)) * 0.01</field>
</record>
<!-- Rule Inputs -->
diff --git a/addons/hr_recruitment/hr_recruitment_data.xml b/addons/hr_recruitment/hr_recruitment_data.xml
index 330c86652dd..adaeed81205 100644
--- a/addons/hr_recruitment/hr_recruitment_data.xml
+++ b/addons/hr_recruitment/hr_recruitment_data.xml
@@ -6,10 +6,10 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Recruitment Process application installed!</field>
- <field name="body">Manage job positions and your company's recruitment process. This application is integrated with the Survey application to help you define interviews for different jobs.
-
-You can automatically receive job application though an email gateway, see the Human Resources settings.</field>
+ <field name="body"><![CDATA[<p>Manage job positions and your company's recruitment process. This application is integrated with the Survey application to help you define interviews for different jobs.</p>
+<p>You can automatically receive job application though an email gateway, see the Human Resources settings.</p>]]></field>
</record>
<!-- Meeting Types (for interview meetings) -->
diff --git a/addons/hr_recruitment/hr_recruitment_view.xml b/addons/hr_recruitment/hr_recruitment_view.xml
index 03561da569e..c3281b43b94 100644
--- a/addons/hr_recruitment/hr_recruitment_view.xml
+++ b/addons/hr_recruitment/hr_recruitment_view.xml
@@ -106,7 +106,7 @@
<field name="arch" type="xml">
<form string="Jobs - Recruitment Form" version="7.0">
<header>
- <button name="case_close_with_emp" string="Hire" type="object"
+ <button name="case_close_with_emp" string="Hire &amp; Create Employee" type="object"
states="draft,open,pending,done" class="oe_highlight"/>
<button name="case_cancel" string="Refuse" type="object"
states="draft,open,pending" class="oe_highlight"/>
@@ -184,7 +184,7 @@
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
- <field name="message_ids" widget="mail_thread"/>
+ <field name="message_ids" widget="mail_thread" placeholder="Share a message..."/>
</div>
</form>
</field>
@@ -333,7 +333,7 @@
<field name="model">hr.job</field>
<field name="inherit_id" ref="hr.view_hr_job_form"/>
<field name="arch" type="xml">
- <field name="no_of_recruitment" version="7.0" position="after">
+ <field name="expected_employees" version="7.0" position="after">
<label for="survey_id" groups="base.group_user"/>
<div groups="base.group_user">
<field name="survey_id" class="oe_inline" domain="[('type','=','Human Resources')]"/>
diff --git a/addons/hr_timesheet/i18n/de.po b/addons/hr_timesheet/i18n/de.po
index e60d95cb75f..a1ac73f5d7a 100644
--- a/addons/hr_timesheet/i18n/de.po
+++ b/addons/hr_timesheet/i18n/de.po
@@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev_rc3\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-02-08 00:36+0000\n"
-"PO-Revision-Date: 2012-05-10 17:22+0000\n"
-"Last-Translator: Ferdinand-camptocamp <Unknown>\n"
+"PO-Revision-Date: 2012-11-18 00:40+0000\n"
+"Last-Translator: Felix Schubert <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-10-30 05:11+0000\n"
-"X-Generator: Launchpad (build 16206)\n"
+"X-Launchpad-Export-Date: 2012-11-19 04:37+0000\n"
+"X-Generator: Launchpad (build 16278)\n"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:43
@@ -37,7 +37,7 @@ msgstr "Kein Mitarbeiter für diesen Benutzer definiert!"
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
msgid "Group By..."
-msgstr "Gruppierung..."
+msgstr "Gruppieren nach"
#. module: hr_timesheet
#: model:ir.actions.act_window,help:hr_timesheet.action_hr_timesheet_sign_in
@@ -66,7 +66,7 @@ msgstr "Analytisches Journal"
#. module: hr_timesheet
#: view:hr.sign.out.project:0
msgid "Stop Working"
-msgstr "Beende Arbeit"
+msgstr "Arbeitsende"
#. module: hr_timesheet
#: model:ir.actions.act_window,name:hr_timesheet.action_hr_timesheet_employee
@@ -172,13 +172,13 @@ msgstr "Warnung !"
#: code:addons/hr_timesheet/wizard/hr_timesheet_sign_in_out.py:132
#, python-format
msgid "UserError"
-msgstr "BenutzerFehler"
+msgstr "Benutzer Fehler"
#. module: hr_timesheet
#: code:addons/hr_timesheet/wizard/hr_timesheet_sign_in_out.py:77
#, python-format
msgid "No cost unit defined for this employee !"
-msgstr "Keine Kosten Einheit für diesen Mitarbeiter definiert!"
+msgstr "Kein Stundensatz für diesen Mitarbeiter definiert!"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:43
@@ -254,7 +254,7 @@ msgstr "Juli"
#: field:hr.sign.in.project,date:0
#: field:hr.sign.out.project,date_start:0
msgid "Starting Date"
-msgstr "Anfangsdatum"
+msgstr "Start Datum"
#. module: hr_timesheet
#: view:hr.employee:0
@@ -271,8 +271,8 @@ msgstr ""
#: help:hr.employee,product_id:0
msgid "Specifies employee's designation as a product with type 'service'."
msgstr ""
-"Spezifiziere ein Produkt mit dem Typ 'Dienstleistungen' bei den "
-"Mitarbeitereinstellungen auf dem Aktenreiter 'Zeiterfassung'."
+"Definiert ein Produkt mit dem Typ \"Dienstleistung\" in den Einstellungen "
+"für den Mitarbeiter"
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
@@ -318,7 +318,7 @@ msgstr "Aufgabenbeschreibung"
#. module: hr_timesheet
#: view:account.analytic.account:0
msgid "Invoice Analysis"
-msgstr "Statistik Rechnungen"
+msgstr "Rechnungsanalyse"
#. module: hr_timesheet
#: model:ir.actions.report.xml,name:hr_timesheet.report_user_timesheet
@@ -334,7 +334,7 @@ msgstr "Anmelden / Abmelden bei Projekt"
#. module: hr_timesheet
#: model:ir.actions.act_window,name:hr_timesheet.action_define_analytic_structure
msgid "Define your Analytic Structure"
-msgstr "Definieren Sie die Strukture der Analysekonten"
+msgstr "Definiere die Struktur der Analytischen Konten"
#. module: hr_timesheet
#: view:hr.sign.in.project:0
@@ -348,14 +348,14 @@ msgid ""
"Analytic journal is not defined for employee %s \n"
"Define an employee for the selected user and assign an analytic journal!"
msgstr ""
-"Analytisches Journal ist für diesen Mitarbeiter nicht definiert: %s\n"
-"Definiere einen Mitarbeiter für den ausgewählten Benutzer und weise dann "
-"noch ein analytisches Konto zu!"
+"Es wurde kein Analytisches Journal für diesen Mitarbeiter definiert: %s\n"
+"Weise einen Mitarbeiter dem ausgewählten Benutzer und ein analytisches Konto "
+"zu!"
#. module: hr_timesheet
#: view:hr.sign.in.project:0
msgid "(Keep empty for current time)"
-msgstr "(Leer lassen für aktuelle Zeit)"
+msgstr "(Frei lassen für den aktuellen Zeitpunkt)"
#. module: hr_timesheet
#: view:hr.employee:0
@@ -369,9 +369,9 @@ msgid ""
"analyse costs and revenues. In OpenERP, analytic accounts are also used to "
"track customer contracts."
msgstr ""
-"Um Erlöse und Kosten zu analysiren, benötigen Sie einen strukturierte "
-"Analyse Kontenplan. In OpenERP wird damit auch die Entwicklung der "
-"Kundenkontrakte verfolgt."
+"Um Erlöse und Kosten zu analysieren, sollten Sie einen strukturierte "
+"analytischen Kontenplan erstellen. In OpenERP können damit auch "
+"Kundenverträge verfolgt werden."
#. module: hr_timesheet
#: field:hr.analytic.timesheet,line_id:0
@@ -424,7 +424,7 @@ msgstr ""
#. module: hr_timesheet
#: field:hr.sign.out.project,date:0
msgid "Closing Date"
-msgstr "Ende Datum"
+msgstr "Enddatum"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:40
@@ -475,12 +475,12 @@ msgstr "Mitarbeiter Nr."
#. module: hr_timesheet
#: view:hr.sign.out.project:0
msgid "General Information"
-msgstr "Grundinformation"
+msgstr "Allgemeine Informationen"
#. module: hr_timesheet
#: model:ir.actions.act_window,name:hr_timesheet.action_hr_timesheet_my
msgid "My Current Timesheet"
-msgstr ""
+msgstr "Meine Zeiterfassung"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:40
@@ -524,8 +524,8 @@ msgid ""
"Through this menu you can register and follow your workings hours by project "
"every day."
msgstr ""
-"Mit diesem Menüpunkt können Sie sich registrieren und die Arbeitsstunden je "
-"Projekt und Tage verfoglen."
+"Mit diesem Menüpunkt können Sie die Arbeitsstunden pro Projekt und Tage "
+"verfolgen."
#. module: hr_timesheet
#: field:hr.sign.in.project,server_date:0
@@ -561,12 +561,12 @@ msgstr "Mai"
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
msgid "Total time"
-msgstr "Gesamtzeit"
+msgstr "Gesamtdauer"
#. module: hr_timesheet
#: view:hr.sign.in.project:0
msgid "(local time on the server side)"
-msgstr "(Ortszeit auf dem Server)"
+msgstr "(Ortszeit auf Serverseite)"
#. module: hr_timesheet
#: model:ir.model,name:hr_timesheet.model_hr_sign_in_project
@@ -585,7 +585,7 @@ msgstr "Februar"
#. module: hr_timesheet
#: model:ir.model,name:hr_timesheet.model_hr_sign_out_project
msgid "Sign Out By Project"
-msgstr "Anmelden / Abmelden Projekte"
+msgstr "Anmelden / Abmelden Projekt"
#. module: hr_timesheet
#: view:hr.analytical.timesheet.users:0
@@ -617,7 +617,7 @@ msgid ""
"No analytic account defined on the project.\n"
"Please set one or we can not automatically fill the timesheet."
msgstr ""
-"Kein Analytisches Konto für Projekt definiert.\n"
+"Kein Analytisches Konto für das Projekt definiert.\n"
"Bitte definieren Sie ein Konto, damit wir automatisch die Zeiterfassung "
"buchen können."
@@ -630,12 +630,12 @@ msgstr "Benutzer"
#. module: hr_timesheet
#: view:hr.sign.in.project:0
msgid "Start Working"
-msgstr "Beginne Arbeit"
+msgstr "Arbeitsbeginn"
#. module: hr_timesheet
#: view:account.analytic.account:0
msgid "Stats by user"
-msgstr "Arbeitszeiten nach Mitarbeitern"
+msgstr "Auswertung nach Mitarbeiter"
#. module: hr_timesheet
#: code:addons/hr_timesheet/wizard/hr_timesheet_print_employee.py:42
diff --git a/addons/hr_timesheet/report/user_timesheet.py b/addons/hr_timesheet/report/user_timesheet.py
index 7699f94f41b..8d2a7d35678 100644
--- a/addons/hr_timesheet/report/user_timesheet.py
+++ b/addons/hr_timesheet/report/user_timesheet.py
@@ -28,6 +28,7 @@ import time
import pooler
from report import report_sxw
from tools import ustr
+from tools import to_xml
def lengthmonth(year, month):
if month == 2 and ((year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0))):
@@ -94,7 +95,7 @@ class report_custom(report_rml):
<date>%s</date>
<company>%s</company>
</header>
- ''' % (str(rml_obj.formatLang(time.strftime("%Y-%m-%d"),date=True))+' ' + str(time.strftime("%H:%M")),pooler.get_pool(cr.dbname).get('res.users').browse(cr,uid,user_id).company_id.name)
+ ''' % (str(rml_obj.formatLang(time.strftime("%Y-%m-%d"),date=True))+' ' + str(time.strftime("%H:%M")),to_xml(pooler.get_pool(cr.dbname).get('res.users').browse(cr,uid,user_id).company_id.name))
account_xml = []
for account, telems in accounts.iteritems():
diff --git a/addons/hr_timesheet/wizard/hr_timesheet_print_employee.py b/addons/hr_timesheet/wizard/hr_timesheet_print_employee.py
index 75bb089bbc7..96ce23fb855 100644
--- a/addons/hr_timesheet/wizard/hr_timesheet_print_employee.py
+++ b/addons/hr_timesheet/wizard/hr_timesheet_print_employee.py
@@ -27,8 +27,9 @@ class analytical_timesheet_employee(osv.osv_memory):
_name = 'hr.analytical.timesheet.employee'
_description = 'Print Employee Timesheet & Print My Timesheet'
_columns = {
- 'month': fields.selection([(x, datetime.date(2000, x, 1).strftime('%B')) for x in range(1, 13)],
- 'Month', required=True),
+ 'month': fields.selection([(1,'January'), (2,'February'), (3,'March'), (4,'April'),
+ (5,'May'), (6,'June'), (7,'July'), (8,'August'), (9,'September'),
+ (10,'October'), (11,'November'), (12,'December')], 'Month', required=True),
'year': fields.integer('Year', required=True),
'employee_id': fields.many2one('hr.employee', 'Employee', required=True)
diff --git a/addons/hr_timesheet/wizard/hr_timesheet_print_users.py b/addons/hr_timesheet/wizard/hr_timesheet_print_users.py
index 865ccacb393..2a91bb607a4 100644
--- a/addons/hr_timesheet/wizard/hr_timesheet_print_users.py
+++ b/addons/hr_timesheet/wizard/hr_timesheet_print_users.py
@@ -27,8 +27,9 @@ class analytical_timesheet_employees(osv.osv_memory):
_name = 'hr.analytical.timesheet.users'
_description = 'Print Employees Timesheet'
_columns = {
- 'month': fields.selection([(x, datetime.date(2000, x, 1).strftime('%B')) for x in range(1, 13)],
- 'Month', required=True),
+ 'month': fields.selection([(1,'January'), (2,'February'), (3,'March'), (4,'April'),
+ (5,'May'), (6,'June'), (7,'July'), (8,'August'), (9,'September'),
+ (10,'October'), (11,'November'), (12,'December')], 'Month', required=True),
'year': fields.integer('Year', required=True),
'employee_ids': fields.many2many('hr.employee', 'timesheet_employee_rel', 'timesheet_id', 'employee_id', 'employees', required=True)
}
diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_data.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_data.xml
index 87edf949972..095a92c032d 100644
--- a/addons/hr_timesheet_sheet/hr_timesheet_sheet_data.xml
+++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_data.xml
@@ -6,8 +6,9 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Timesheet Validation application installed!</field>
- <field name="body">From the top menu "Human Resources", enter and validate timesheets and attendances.</field>
+ <field name="body"><![CDATA[<p>From the top menu "Human Resources", enter and validate timesheets and attendances.</p>]]></field>
</record>
<record id="ir_actions_server_timsheet_sheet" model="ir.actions.server">
diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml
index ee5a329c800..6de6be6c08d 100644
--- a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml
+++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml
@@ -162,7 +162,7 @@
</notebook>
</sheet>
<div class="oe_chatter">
- <field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
+ <field name="message_ids" widget="mail_thread"/>
<field name="message_follower_ids" widget="mail_followers"/>
</div>
</form>
diff --git a/addons/l10n_ar/i18n/es_AR.po b/addons/l10n_ar/i18n/es_AR.po
index 2260a43cf74..1f2b2dd250a 100644
--- a/addons/l10n_ar/i18n/es_AR.po
+++ b/addons/l10n_ar/i18n/es_AR.po
@@ -1,21 +1,21 @@
-# Spanish (Paraguay) translation for openobject-addons
-# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
+# Spanish (Argentina) translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openobject-addons package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:15+0000\n"
-"PO-Revision-Date: 2011-03-21 16:23+0000\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: Spanish (Paraguay) <es_PY@li.org>\n"
+"PO-Revision-Date: 2012-11-13 15:04+0000\n"
+"Last-Translator: Eduardo Alberto Calvo <Unknown>\n"
+"Language-Team: Spanish (Argentina) <es_AR@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2011-03-22 04:36+0000\n"
-"X-Generator: Launchpad (build 12559)\n"
+"X-Launchpad-Export-Date: 2012-11-14 04:40+0000\n"
+"X-Generator: Launchpad (build 16251)\n"
#. module: l10n_ar
#: model:ir.module.module,description:l10n_ar.module_meta_information
@@ -31,7 +31,7 @@ msgstr ""
#. module: l10n_ar
#: model:ir.module.module,shortdesc:l10n_ar.module_meta_information
msgid "Argentinian Chart of Account"
-msgstr "Plan de cuentas de la Argentina"
+msgstr "Plan de cuentas de Argentina"
#. module: l10n_ar
#: model:ir.actions.todo,note:l10n_ar.config_call_account_template_in_minimal
@@ -45,7 +45,7 @@ msgid ""
"Chart of Accounts from a Chart Template."
msgstr ""
"Generar el plan contable a partir de una plantilla de plan contable. Se le "
-"pedirá el nombre de la compañía, la plantilla de plan contable a utilizar, "
+"pedirá el nombre de la compañia, la plantilla de plan contable a utilizar, "
"el número de dígitos para generar el código de las cuentas y de la cuenta "
"bancaria, la moneda para crear los diarios. Así pues, se genere una copia "
"exacta de la plantilla de plan contable.\n"
diff --git a/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py b/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py
index d15b300597e..53948945e04 100644
--- a/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py
+++ b/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py
@@ -65,6 +65,8 @@ class partner_vat(osv.osv_memory):
partners = []
partner_ids = obj_partner.search(cr, uid, [('vat_subjected', '!=', False), ('vat','ilike','BE%')], context=context)
+ if not partner_ids:
+ raise osv.except_osv(_('Error'),_('No belgian contact with a VAT number in your database.'))
cr.execute("""SELECT sub1.partner_id, sub1.name, sub1.vat, sub1.turnover, sub2.vat_amount
FROM (SELECT l.partner_id, p.name, p.vat, SUM(CASE WHEN c.code ='49' THEN -l.tax_amount ELSE l.tax_amount END) as turnover
FROM account_move_line l
@@ -190,7 +192,7 @@ class partner_vat_list(osv.osv_memory):
addr = obj_partner.address_get(cr, uid, [obj_cmpny.partner_id.id], ['invoice'])
if addr.get('invoice',False):
ads = obj_partner.browse(cr, uid, [addr['invoice']], context=context)[0]
- phone = ads.phone.replace(' ','') or ''
+ phone = ads.phone and ads.phone.replace(' ','') or ''
email = ads.email or ''
name = ads.name or ''
city = ads.city or ''
@@ -259,6 +261,8 @@ class partner_vat_list(osv.osv_memory):
# Turnover and Farmer tags are not included
client_datas = self._get_datas(cr, uid, ids, context=context)
+ if not client_datas:
+ raise osv.except_osv(_('Data Insufficient!'),_('No data available for the client.'))
data_client_info = ''
for amount_data in client_datas:
data_client_info += """
@@ -309,6 +313,8 @@ class partner_vat_list(osv.osv_memory):
datas['year'] = context['year']
datas['limit_amount'] = context['limit_amount']
datas['client_datas'] = self._get_datas(cr, uid, ids, context=context)
+ if not datas['client_datas']:
+ raise osv.except_osv(_('Error!'),_('No record to print.'))
return {
'type': 'ir.actions.report.xml',
'report_name': 'partner.vat.listing.print',
diff --git a/addons/l10n_be_coda/wizard/account_coda_import.py b/addons/l10n_be_coda/wizard/account_coda_import.py
index ca89cf78325..46c545f0f48 100644
--- a/addons/l10n_be_coda/wizard/account_coda_import.py
+++ b/addons/l10n_be_coda/wizard/account_coda_import.py
@@ -28,6 +28,7 @@ import logging
import re
from traceback import format_exception
from sys import exc_info
+from base_iban import base_iban
_logger = logging.getLogger(__name__)
class account_coda_import(osv.osv_memory):
@@ -398,6 +399,7 @@ class account_coda_import(osv.osv_memory):
st_line['account_id'] = transfer_acc
match = True
elif find_partner:
+ counterparty_number = base_iban._pretty_iban(base_iban._format_iban(counterparty_number))
bank_ids = partner_bank_obj.search(cr,uid,[('acc_number','=', counterparty_number)])
if not match and find_partner and bank_ids:
if len(bank_ids) > 1:
diff --git a/addons/l10n_be_hr_payroll/i18n/de.po b/addons/l10n_be_hr_payroll/i18n/de.po
new file mode 100644
index 00000000000..6c95585909e
--- /dev/null
+++ b/addons/l10n_be_hr_payroll/i18n/de.po
@@ -0,0 +1,163 @@
+# German translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2012-02-08 00:36+0000\n"
+"PO-Revision-Date: 2012-11-18 21:44+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: German <de@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-11-19 04:37+0000\n"
+"X-Generator: Launchpad (build 16278)\n"
+
+#. module: l10n_be_hr_payroll
+#: help:hr.employee,disabled_spouse_bool:0
+msgid "if recipient spouse is declared disabled by law"
+msgstr ""
+"Wenn Ehepartner des Empfängers gesetzlich als Behindert anerkannt wurde"
+
+#. module: l10n_be_hr_payroll
+#: help:hr.employee,disabled_children_bool:0
+msgid "if recipient children is/are declared disabled by law"
+msgstr ""
+"Wenn Kind(er) des Empfängers gesetzlich als behindert anerkannt ist (sind)"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,misc_onss_deduction:0
+msgid "Miscellaneous exempt ONSS "
+msgstr "Diverse Ausnahmen (ONSS) "
+
+#. module: l10n_be_hr_payroll
+#: model:ir.model,name:l10n_be_hr_payroll.model_hr_employee
+msgid "Employee"
+msgstr "Angestellte/r"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,disabled_spouse_bool:0
+msgid "Disabled Spouse"
+msgstr "Als Behindert anerkannter Ehepartner"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,retained_net_amount:0
+msgid "Net retained "
+msgstr "Einbehalten Netto "
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,resident_bool:0
+msgid "Nonresident"
+msgstr "Im Ausland wohnhaft"
+
+#. module: l10n_be_hr_payroll
+#: help:hr.employee,resident_bool:0
+msgid "if recipient lives in a foreign country"
+msgstr "Wenn Empfänger in anderem Land wohnhaft ist"
+
+#. module: l10n_be_hr_payroll
+#: view:hr.employee:0
+msgid "if spouse has professionnel income or not"
+msgstr "Ob Ehepartner berufliches Einkommen hat oder nicht"
+
+#. module: l10n_be_hr_payroll
+#: view:hr.contract:0
+msgid "Miscellaneous"
+msgstr "Verschiedenes"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,insurance_employee_deduction:0
+msgid "Insurance Group - by worker "
+msgstr "Vericherungsgruppe nach Mitarbeiter "
+
+#. module: l10n_be_hr_payroll
+#: selection:hr.employee,spouse_fiscal_status:0
+msgid "With Income"
+msgstr "Mit Einkommen"
+
+#. module: l10n_be_hr_payroll
+#: selection:hr.employee,spouse_fiscal_status:0
+msgid "Without Income"
+msgstr "Ohne Einkommen"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,disabled_children_number:0
+msgid "Number of disabled children"
+msgstr "Anzahl behinderter Kinder"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,additional_net_amount:0
+msgid "Net supplements"
+msgstr "Netto-Zulagen"
+
+#. module: l10n_be_hr_payroll
+#: constraint:hr.employee:0
+msgid "Error ! You cannot create recursive Hierarchy of Employees."
+msgstr ""
+"Fehler ! Sie können keine rekursive Hierachie bei Mitarbeitern definieren."
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,car_company_amount:0
+msgid "Company car employer"
+msgstr "Firmenfahrzeug des Arbeitgebers"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,misc_advantage_amount:0
+msgid "Benefits of various nature "
+msgstr "Geldwerte Vorteile verschiedener Art "
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,car_employee_deduction:0
+msgid "Company Car Deduction for Worker"
+msgstr "Abzüge beim Mitarbeiter für Firmenfahrzeug"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,disabled_children_bool:0
+msgid "Disabled Children"
+msgstr "Behinderte Kinder"
+
+#. module: l10n_be_hr_payroll
+#: model:ir.model,name:l10n_be_hr_payroll.model_hr_contract
+msgid "Contract"
+msgstr "Vertrag"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,meal_voucher_amount:0
+msgid "Check Value Meal "
+msgstr "Verköstigungswert prüfen "
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,travel_reimbursement_amount:0
+msgid "Reimbursement of travel expenses"
+msgstr "Erstattung von Reisespesen"
+
+#. module: l10n_be_hr_payroll
+#: constraint:hr.contract:0
+msgid "Error! contract start-date must be lower then contract end-date."
+msgstr ""
+"Fehler! Datum des Vertragsbeginns muss zeitlich vor dem Datum des "
+"Vertragsendes sein."
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,spouse_fiscal_status:0
+msgid "Tax status for spouse"
+msgstr "Steuerklasse des Ehepartners"
+
+#. module: l10n_be_hr_payroll
+#: view:hr.contract:0
+msgid "by Worker"
+msgstr "nach Mitarbeiter"
+
+#. module: l10n_be_hr_payroll
+#: view:hr.employee:0
+msgid "number of dependent children declared as disabled"
+msgstr "Anzahl anhängiger, als behindert anerkannter Kinder"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,meal_voucher_employee_deduction:0
+msgid "Check Value Meal - by worker "
+msgstr "Verköstigungswerte - nach Mitarbeitern "
diff --git a/addons/l10n_be_hr_payroll/i18n/es.po b/addons/l10n_be_hr_payroll/i18n/es.po
new file mode 100644
index 00000000000..c0deb99952c
--- /dev/null
+++ b/addons/l10n_be_hr_payroll/i18n/es.po
@@ -0,0 +1,158 @@
+# Spanish translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2012-02-08 00:36+0000\n"
+"PO-Revision-Date: 2012-11-12 16:09+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Spanish <es@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-11-13 05:17+0000\n"
+"X-Generator: Launchpad (build 16251)\n"
+
+#. module: l10n_be_hr_payroll
+#: help:hr.employee,disabled_spouse_bool:0
+msgid "if recipient spouse is declared disabled by law"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: help:hr.employee,disabled_children_bool:0
+msgid "if recipient children is/are declared disabled by law"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,misc_onss_deduction:0
+msgid "Miscellaneous exempt ONSS "
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: model:ir.model,name:l10n_be_hr_payroll.model_hr_employee
+msgid "Employee"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,disabled_spouse_bool:0
+msgid "Disabled Spouse"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,retained_net_amount:0
+msgid "Net retained "
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,resident_bool:0
+msgid "Nonresident"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: help:hr.employee,resident_bool:0
+msgid "if recipient lives in a foreign country"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: view:hr.employee:0
+msgid "if spouse has professionnel income or not"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: view:hr.contract:0
+msgid "Miscellaneous"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,insurance_employee_deduction:0
+msgid "Insurance Group - by worker "
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: selection:hr.employee,spouse_fiscal_status:0
+msgid "With Income"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: selection:hr.employee,spouse_fiscal_status:0
+msgid "Without Income"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,disabled_children_number:0
+msgid "Number of disabled children"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,additional_net_amount:0
+msgid "Net supplements"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: constraint:hr.employee:0
+msgid "Error ! You cannot create recursive Hierarchy of Employees."
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,car_company_amount:0
+msgid "Company car employer"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,misc_advantage_amount:0
+msgid "Benefits of various nature "
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,car_employee_deduction:0
+msgid "Company Car Deduction for Worker"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,disabled_children_bool:0
+msgid "Disabled Children"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: model:ir.model,name:l10n_be_hr_payroll.model_hr_contract
+msgid "Contract"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,meal_voucher_amount:0
+msgid "Check Value Meal "
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,travel_reimbursement_amount:0
+msgid "Reimbursement of travel expenses"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: constraint:hr.contract:0
+msgid "Error! contract start-date must be lower then contract end-date."
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,spouse_fiscal_status:0
+msgid "Tax status for spouse"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: view:hr.contract:0
+msgid "by Worker"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: view:hr.employee:0
+msgid "number of dependent children declared as disabled"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,meal_voucher_employee_deduction:0
+msgid "Check Value Meal - by worker "
+msgstr ""
diff --git a/addons/l10n_be_invoice_bba/i18n/es.po b/addons/l10n_be_invoice_bba/i18n/es.po
new file mode 100644
index 00000000000..42f11478e9d
--- /dev/null
+++ b/addons/l10n_be_invoice_bba/i18n/es.po
@@ -0,0 +1,141 @@
+# Spanish translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2012-02-08 00:36+0000\n"
+"PO-Revision-Date: 2012-11-12 16:43+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Spanish <es@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-11-13 05:17+0000\n"
+"X-Generator: Launchpad (build 16251)\n"
+
+#. module: l10n_be_invoice_bba
+#: sql_constraint:account.invoice:0
+msgid "Invoice Number must be unique per Company!"
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: model:ir.model,name:l10n_be_invoice_bba.model_account_invoice
+msgid "Invoice"
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: constraint:res.partner:0
+msgid "Error ! You cannot create recursive associated members."
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: constraint:account.invoice:0
+msgid "Invalid BBA Structured Communication !"
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: selection:res.partner,out_inv_comm_algorithm:0
+msgid "Random"
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: help:res.partner,out_inv_comm_type:0
+msgid "Select Default Communication Type for Outgoing Invoices."
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: help:res.partner,out_inv_comm_algorithm:0
+msgid ""
+"Select Algorithm to generate the Structured Communication on Outgoing "
+"Invoices."
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: code:addons/l10n_be_invoice_bba/invoice.py:114
+#: code:addons/l10n_be_invoice_bba/invoice.py:140
+#, python-format
+msgid ""
+"The daily maximum of outgoing invoices with an automatically generated BBA "
+"Structured Communications has been exceeded!\n"
+"Please create manually a unique BBA Structured Communication."
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: code:addons/l10n_be_invoice_bba/invoice.py:155
+#, python-format
+msgid "Error!"
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: code:addons/l10n_be_invoice_bba/invoice.py:126
+#, python-format
+msgid ""
+"The Partner should have a 3-7 digit Reference Number for the generation of "
+"BBA Structured Communications!\n"
+"Please correct the Partner record."
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: code:addons/l10n_be_invoice_bba/invoice.py:113
+#: code:addons/l10n_be_invoice_bba/invoice.py:125
+#: code:addons/l10n_be_invoice_bba/invoice.py:139
+#: code:addons/l10n_be_invoice_bba/invoice.py:167
+#: code:addons/l10n_be_invoice_bba/invoice.py:177
+#: code:addons/l10n_be_invoice_bba/invoice.py:202
+#, python-format
+msgid "Warning!"
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: selection:res.partner,out_inv_comm_algorithm:0
+msgid "Customer Reference"
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: field:res.partner,out_inv_comm_type:0
+msgid "Communication Type"
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: code:addons/l10n_be_invoice_bba/invoice.py:178
+#: code:addons/l10n_be_invoice_bba/invoice.py:203
+#, python-format
+msgid ""
+"The BBA Structured Communication has already been used!\n"
+"Please create manually a unique BBA Structured Communication."
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: selection:res.partner,out_inv_comm_algorithm:0
+msgid "Date"
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: model:ir.model,name:l10n_be_invoice_bba.model_res_partner
+msgid "Partner"
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: code:addons/l10n_be_invoice_bba/invoice.py:156
+#, python-format
+msgid ""
+"Unsupported Structured Communication Type Algorithm '%s' !\n"
+"Please contact your OpenERP support channel."
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: field:res.partner,out_inv_comm_algorithm:0
+msgid "Communication Algorithm"
+msgstr ""
+
+#. module: l10n_be_invoice_bba
+#: code:addons/l10n_be_invoice_bba/invoice.py:168
+#, python-format
+msgid ""
+"Empty BBA Structured Communication!\n"
+"Please fill in a unique BBA Structured Communication."
+msgstr ""
diff --git a/addons/l10n_ch/bank.py b/addons/l10n_ch/bank.py
index 79dcb1a6834..4e4c0e0aa8c 100644
--- a/addons/l10n_ch/bank.py
+++ b/addons/l10n_ch/bank.py
@@ -52,21 +52,6 @@ class ResPartnerBank(osv.osv):
'my_bank': fields.boolean('Use my account to print BVR ?', help="Check to print BVR invoices"),
}
- def name_get(self, cursor, uid, ids, context=None):
- if not len(ids):
- return []
- bank_type_obj = self.pool.get('res.partner.bank.type')
-
- type_ids = bank_type_obj.search(cursor, uid, [])
- bank_type_names = {}
- for bank_type in bank_type_obj.browse(cursor, uid, type_ids,
- context=context):
- bank_type_names[bank_type.code] = bank_type.name
- res = []
- for r in self.read(cursor, uid, ids, ['name','state'], context):
- res.append((r['id'], r['name']+' : '+bank_type_names.get(r['state'], '')))
- return res
-
def _prepare_name(self, bank):
"Hook to get bank number of bank account"
res = u''
diff --git a/addons/l10n_fr/fr_tax.xml b/addons/l10n_fr/fr_tax.xml
index fc5d4608f45..36c5feb47b6 100644
--- a/addons/l10n_fr/fr_tax.xml
+++ b/addons/l10n_fr/fr_tax.xml
@@ -131,8 +131,8 @@
<field name="tax_code_id" ref="tax_acq_196"/>
<field name="tax_sign" eval="-1"/>
- <field name="account_collected_id" ref="pcg_44566"/>
- <field name="account_paid_id" ref="pcg_44566"/>
+ <field name="account_collected_id" ref="pcg_445662"/>
+ <field name="account_paid_id" ref="pcg_445662"/>
<field name="ref_base_code_id" ref="tax_acq_196_ht"/>
<field name="ref_base_sign" eval="1"/>
diff --git a/addons/l10n_fr/plan_comptable_general.xml b/addons/l10n_fr/plan_comptable_general.xml
index 525dabfcc8a..268f4bd6336 100644
--- a/addons/l10n_fr/plan_comptable_general.xml
+++ b/addons/l10n_fr/plan_comptable_general.xml
@@ -3903,7 +3903,7 @@
<field name="name">Associés - Comptes courants</field>
<field name="code">455</field>
<field name="type">view</field>
- <field name="user_type" ref="account.data_account_type_view"/>
+ <field name="user_type" ref="account.data_account_type_payable"/>
<field name="note">Pour frais avancés personnellement</field>
<field name="parent_id" ref="pcg_45"/>
<field name="reconcile" eval="True"/>
@@ -3912,8 +3912,8 @@
<record id="pcg_4551" model="account.account.template">
<field name="name">Principal</field>
<field name="code">4551</field>
- <field name="type">receivable</field>
- <field name="user_type" ref="account.data_account_type_receivable"/>
+ <field name="type">payable</field>
+ <field name="user_type" ref="account.data_account_type_payable"/>
<field name="parent_id" ref="pcg_455"/>
<field name="reconcile" eval="True"/>
</record>
@@ -3921,8 +3921,8 @@
<record id="pcg_4558" model="account.account.template">
<field name="name">Intérêts courus</field>
<field name="code">4558</field>
- <field name="type">receivable</field>
- <field name="user_type" ref="account.data_account_type_receivable"/>
+ <field name="type">payable</field>
+ <field name="user_type" ref="account.data_account_type_payable"/>
<field name="parent_id" ref="pcg_455"/>
<field name="reconcile" eval="True"/>
</record>
diff --git a/addons/l10n_in_hr_payroll/i18n/es.po b/addons/l10n_in_hr_payroll/i18n/es.po
new file mode 100644
index 00000000000..52f443733fb
--- /dev/null
+++ b/addons/l10n_in_hr_payroll/i18n/es.po
@@ -0,0 +1,942 @@
+# Spanish translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2012-08-17 06:46+0000\n"
+"PO-Revision-Date: 2012-11-12 17:08+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Spanish <es@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-11-13 05:17+0000\n"
+"X-Generator: Launchpad (build 16251)\n"
+
+#. module: l10n_in_hr_payroll
+#: report:salary.detail.byyear:0
+msgid "E-mail Address"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:payment.advice.report,employee_bank_no:0
+msgid "Employee Bank Account"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:payment.advice.report:0
+msgid "Payment Advices which are in draft state"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:salary.detail.byyear:0
+msgid "Title"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:payroll.advice:0
+msgid "Payment Advice from"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.model,name:l10n_in_hr_payroll.model_yearly_salary_detail
+msgid "Hr Salary Employee By Category Report"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:salary.detail.byyear:0
+msgid "Employees Salary Details"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:salary.detail.byyear:0
+msgid "Allowances with Basic:"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:salary.detail.byyear:0
+msgid "Department"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:salary.detail.byyear:0
+msgid "Deductions:"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:payroll.advice:0
+msgid "A/C no."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.contract,driver_salay:0
+msgid "Driver Salary"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_yearly_salary_detail
+#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.yearly_salary
+#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_yearly_salary_detail
+msgid "Yearly Salary by Employee"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.actions.act_window,name:l10n_in_hr_payroll.act_hr_emp_payslip_list
+msgid "Payslips"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:payment.advice.report,month:0
+msgid "March"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid "("
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+#: field:hr.payroll.advice,company_id:0
+#: field:hr.payroll.advice.line,company_id:0
+#: view:payment.advice.report:0
+#: field:payment.advice.report,company_id:0
+msgid "Company"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:payroll.advice:0
+msgid "The Manager"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+msgid "Letter Details"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid ","
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+msgid "Set to Draft"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: help:hr.employee,number_of_year:0
+msgid "Total years of work experience"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:payroll.advice:0
+msgid "to"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:payroll.advice:0
+msgid "Total :"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payslip.run,available_advice:0
+msgid "Made Payment Advice?"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:payment.advice.report:0
+msgid "Advices which are paid using NEFT transfer"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: help:hr.contract,tds:0
+msgid "Amount for Tax Deduction at Source"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payslip
+msgid "Pay Slip"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:payment.advice.report:0
+#: field:payment.advice.report,day:0
+msgid "Day"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:payment.advice.report:0
+msgid "Month of Payment Advices"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: constraint:hr.payslip:0
+msgid "Payslip 'Date From' must be before 'Date To'."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice,batch_id:0
+msgid "Batch"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid "Code"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+msgid "Other Information"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:hr.payroll.advice,state:0
+#: selection:payment.advice.report,state:0
+msgid "Cancelled"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:payroll.advice:0
+msgid "For"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid "Details by Salary Rule Category:"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: help:hr.contract,voluntary_provident_fund:0
+msgid "VPF computed as percentage(%)"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice,number:0
+#: report:paylip.details.in:0
+msgid "Reference"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+#: view:payment.advice.report:0
+msgid "Group By..."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.contract,medical_insurance:0
+msgid "Medical Insurance"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid "Identification No"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:hr.payroll.advice,state:0
+#: selection:payment.advice.report,state:0
+msgid "Confirmed"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:salary.detail.byyear:0
+#: report:salary.employee.bymonth:0
+msgid "From"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice.line,bysal:0
+#: field:payment.advice.report,bysal:0
+#: report:payroll.advice:0
+msgid "By Salary"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+#: view:payment.advice.report:0
+msgid "Confirm"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice,chaque_nos:0
+#: field:payment.advice.report,cheque_nos:0
+msgid "Cheque Numbers"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: constraint:res.company:0
+msgid "Error! You can not create recursive companies."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_salary_employee_month
+#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.hr_salary_employee_bymonth
+#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_salary_employee_month
+msgid "Yearly Salary by Head"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:184
+#, python-format
+msgid "You can not confirm Payment advice without advice lines."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice,state:0
+#: field:payment.advice.report,state:0
+msgid "State"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:payroll.advice:0
+msgid "Yours Sincerely"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: help:hr.contract,medical_insurance:0
+msgid "Deduction towards company provided medical insurance"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payroll_advice_line
+msgid "Bank Advice Lines"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid "Email"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: help:hr.payslip.run,available_advice:0
+msgid ""
+"If this box is checked which means that Payment Advice exists for current "
+"batch"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:158
+#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:184
+#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:240
+#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:257
+#, python-format
+msgid "Error !"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.salary.employee.month:0
+#: view:yearly.salary.detail:0
+msgid "Print"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payslip_run
+msgid "Payslip Batches"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice.line,debit_credit:0
+#: report:payroll.advice:0
+msgid "C/D"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:salary.employee.bymonth:0
+msgid "Yearly Salary Details"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.payroll_advice
+msgid "Print Advice"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice,line_ids:0
+msgid "Employee Salary"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:payment.advice.report,month:0
+msgid "July"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:res.company:0
+msgid "Configuration"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_view_hr_bank_advice_tree
+#: model:ir.ui.menu,name:l10n_in_hr_payroll.hr_menu_payment_advice
+msgid "Payment Advices"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_payment_advice_report_all
+#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_reporting_payment_advice
+#: view:payment.advice.report:0
+msgid "Advices Analysis"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.salary.employee.month:0
+msgid ""
+"This wizard will print report which displays employees break-up of Net Head "
+"for a specified dates."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice.line,ifsc:0
+msgid "IFSC"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid "Date To"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.contract,tds:0
+msgid "TDS"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.employee,join_date:0
+msgid "Join Date"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+msgid "Confirm Advices"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: constraint:hr.contract:0
+msgid "Error! Contract start-date must be less than contract end-date."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:res.company,dearness_allowance:0
+msgid "Dearness Allowance"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:payment.advice.report,month:0
+msgid "August"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.contract:0
+msgid "Deduction"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+msgid "Search Payment advice"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:payroll.advice:0
+msgid "SI. No."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:payment.advice.report:0
+msgid "Payment Advices which are in confirm state"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:payment.advice.report,month:0
+msgid "December"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+msgid "Confirm Sheet"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:payment.advice.report:0
+#: field:payment.advice.report,month:0
+msgid "Month"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:salary.detail.byyear:0
+msgid "Employee Code"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:hr.contract,city_type:0
+msgid "Non Metro"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.salary.employee.month:0
+#: view:yearly.salary.detail:0
+msgid "or"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.model,name:l10n_in_hr_payroll.model_hr_salary_employee_month
+msgid "Hr Salary Employee By Month Report"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.salary.employee.month,category_id:0
+msgid "Category"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:240
+#, python-format
+msgid ""
+"Payment advice already exists for %s, 'Set to Draft' to create a new advice."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payslip.run:0
+msgid "To Advice"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.employee,number_of_year:0
+msgid "No. of Years of Service"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid "Note"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid "Salary Rule Category"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+#: selection:hr.payroll.advice,state:0
+#: view:payment.advice.report:0
+#: selection:payment.advice.report,state:0
+msgid "Draft"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid "Date From"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.contract,voluntary_provident_fund:0
+msgid "Voluntary Provident Fund"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:salary.detail.byyear:0
+msgid "Employee Name"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.model,name:l10n_in_hr_payroll.model_payment_advice_report
+msgid "Payment Advice Analysis"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+#: view:payment.advice.report:0
+msgid "Status"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.contract,city_type:0
+msgid "Type of City"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: help:res.company,dearness_allowance:0
+msgid "Check this box if your company provide Dearness Allowance to employee"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice.line,ifsc_code:0
+#: field:payment.advice.report,ifsc_code:0
+#: report:payroll.advice:0
+msgid "IFSC Code"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:payment.advice.report,month:0
+msgid "June"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:payment.advice.report:0
+#: field:payment.advice.report,nbr:0
+msgid "# Payment Lines"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.payslip_details_report
+msgid "PaySlip Details"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+msgid "Payment Lines"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice,date:0
+#: field:payment.advice.report,date:0
+msgid "Date"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:payment.advice.report,month:0
+msgid "November"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:payment.advice.report:0
+msgid "Extended Filters..."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.actions.act_window,help:l10n_in_hr_payroll.action_payment_advice_report_all
+msgid "This report performs analysis on Payment Advices"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:payment.advice.report,month:0
+msgid "October"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+#: report:salary.detail.byyear:0
+msgid "Designation"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:payment.advice.report,month:0
+msgid "January"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:yearly.salary.detail:0
+msgid "Pay Head Employee Breakup"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.model,name:l10n_in_hr_payroll.model_res_company
+msgid "Companies"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+#: report:payroll.advice:0
+msgid "Authorized Signature"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: model:ir.model,name:l10n_in_hr_payroll.model_hr_contract
+msgid "Contract"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice.line:0
+msgid "Advice Lines"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:payroll.advice:0
+msgid "To,"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: help:hr.contract,driver_salay:0
+msgid "Check this box if you provide allowance for driver"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+#: field:hr.payroll.advice.line,advice_id:0
+#: field:hr.payslip,advice_id:0
+#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payroll_advice
+msgid "Bank Advice"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:salary.detail.byyear:0
+msgid "Other No."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+msgid "Draft Advices"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: help:hr.payroll.advice,neft:0
+msgid "Check this box if your company use online transfer for salary"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:salary.detail.byyear:0
+msgid "To"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:payment.advice.report,number:0
+msgid "Number"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:payment.advice.report,month:0
+msgid "September"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+#: view:hr.salary.employee.month:0
+#: view:yearly.salary.detail:0
+msgid "Cancel"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:payment.advice.report:0
+msgid "Day of Payment Advices"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: constraint:hr.employee:0
+msgid "Error! You cannot create recursive hierarchy of Employee(s)."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:yearly.salary.detail:0
+msgid ""
+"This wizard will print report which display a pay head employee breakup for "
+"a specified dates."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payslip.run:0
+msgid "Payslip Batches ready to be Adviced"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid "Pay Slip Details"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:payment.advice.report:0
+msgid "Total Salary"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice.line,employee_id:0
+#: model:ir.model,name:l10n_in_hr_payroll.model_hr_employee
+#: view:payment.advice.report:0
+#: field:payment.advice.report,employee_id:0
+msgid "Employee"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+msgid "Compute Advice"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: help:hr.employee,join_date:0
+msgid "Joining date of employee"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:payroll.advice:0
+msgid "Dear Sir/Madam,"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice,note:0
+msgid "Description"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid ")"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:res.company:0
+msgid "Payroll"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:payment.advice.report:0
+msgid "NEFT"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+#: report:salary.detail.byyear:0
+msgid "Address"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+#: field:hr.payroll.advice,bank_id:0
+#: view:payment.advice.report:0
+#: field:payment.advice.report,bank_id:0
+#: report:payroll.advice:0
+#: report:salary.detail.byyear:0
+msgid "Bank"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.salary.employee.month,end_date:0
+#: field:yearly.salary.detail,date_to:0
+msgid "End Date"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:payment.advice.report,month:0
+msgid "February"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: sql_constraint:res.company:0
+msgid "The company name must be unique !"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payroll.advice:0
+#: field:hr.payroll.advice,name:0
+#: report:paylip.details.in:0
+#: field:payment.advice.report,name:0
+#: report:salary.employee.bymonth:0
+msgid "Name"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:hr.contract,city_type:0
+msgid "Metro"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.salary.employee.month:0
+#: field:hr.salary.employee.month,employee_ids:0
+#: view:yearly.salary.detail:0
+#: field:yearly.salary.detail,employee_ids:0
+msgid "Employees"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid "Bank Account"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:payment.advice.report,month:0
+msgid "April"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:payroll.advice:0
+msgid "Name of the Employe"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:158
+#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:257
+#, python-format
+msgid "Please define bank account for the %s employee"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.salary.employee.month,start_date:0
+#: field:yearly.salary.detail,date_from:0
+msgid "Start Date"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.contract:0
+msgid "Allowance"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: help:hr.payroll.advice,bank_id:0
+msgid "Select the Bank from which the salary is going to be paid"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.salary.employee.month:0
+msgid "Employee Pay Head Breakup"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:salary.detail.byyear:0
+msgid "Phone No."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+msgid "Credit"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice.line,name:0
+#: report:payroll.advice:0
+msgid "Bank Account No."
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: help:hr.payroll.advice,date:0
+msgid "Advice Date is used to search Payslips"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: selection:payment.advice.report,month:0
+msgid "May"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:hr.payslip.run:0
+msgid "Create Advice"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:payment.advice.report:0
+#: field:payment.advice.report,year:0
+msgid "Year"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: field:hr.payroll.advice,neft:0
+#: field:payment.advice.report,neft:0
+msgid "NEFT Transaction"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:paylip.details.in:0
+#: report:salary.detail.byyear:0
+#: report:salary.employee.bymonth:0
+msgid "Total"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: report:payroll.advice:0
+msgid "form period"
+msgstr ""
+
+#. module: l10n_in_hr_payroll
+#: view:payment.advice.report:0
+msgid "Year of Payment Advices"
+msgstr ""
diff --git a/addons/l10n_it/data/account.tax.code.template.csv b/addons/l10n_it/data/account.tax.code.template.csv
index 290396052f4..d6d6667f43b 100644
--- a/addons/l10n_it/data/account.tax.code.template.csv
+++ b/addons/l10n_it/data/account.tax.code.template.csv
@@ -60,6 +60,3 @@ IVC21det40,template_ivacode_pagata_21det40,IVA a credito 21% detraibile 40%,temp
IVC21Idet40,template_impcode_pagata_21det40,IVA a credito 21% detraibile 40% (imponibile),template_impcode_pagata
IVC21det50,template_ivacode_pagata_21det50,IVA a credito 21% detraibile 50%,template_ivacode_pagata
IVC21Idet50,template_impcode_pagata_21det50,IVA a credito 21% detraibile 50% (imponibile),template_impcode_pagata
-Rit,template_ra,Ritenute d'acconto,vat_code_chart_root
-RitD20,template_ritcode_20,Ritenute a debito 20%,template_ra
-RitD20I,template_ritimpcode_20,Ritenute a debito 20% (imponibile),template_ra
diff --git a/addons/l10n_it/data/account.tax.template.csv b/addons/l10n_it/data/account.tax.template.csv
index 36c4f99db79..641f495dd72 100644
--- a/addons/l10n_it/data/account.tax.template.csv
+++ b/addons/l10n_it/data/account.tax.template.csv
@@ -62,4 +62,3 @@ id,description,chart_template_id:id,name,sequence,amount,parent_id:id,child_depe
21I5,21I5,l10n_it_chart_template_generic,IVA al 21% detraibile al 50%,,0.21,,True,percent,,,purchase,template_impcode_pagata_21det50,,template_impcode_pagata_21det50,,,,False,-1,-1
21I5b,21I5b,l10n_it_chart_template_generic,IVA al 21% detraibile al 50% (I),1,0.5,21I5,False,percent,,,purchase,,,,,,,False,,
21I5a,21I5a,l10n_it_chart_template_generic,IVA al 21% detraibile al 50% (D),2,0,21I5,False,balance,1601,1601,purchase,,template_ivacode_pagata_21det50,,template_ivacode_pagata_21det50,,,False,,
-rit-20,rit-20,l10n_it_chart_template_generic,Ritenuta d'acconto al 20% (debito),,-0.2,,False,percent,2602,2602,purchase,template_ritimpcode_20,template_ritcode_20,template_ritimpcode_20,template_ritcode_20,-1,1,False,1,-1
diff --git a/addons/l10n_multilang/i18n/ar.po b/addons/l10n_multilang/i18n/ar.po
new file mode 100644
index 00000000000..6ff075befb6
--- /dev/null
+++ b/addons/l10n_multilang/i18n/ar.po
@@ -0,0 +1,172 @@
+# Arabic translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2012-02-08 01:06+0000\n"
+"PO-Revision-Date: 2012-11-16 19:54+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Arabic <ar@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-11-17 04:37+0000\n"
+"X-Generator: Launchpad (build 16278)\n"
+
+#. module: l10n_multilang
+#: model:ir.model,name:l10n_multilang.model_account_fiscal_position_template
+msgid "Template for Fiscal Position"
+msgstr "قوالب للمركز المالي"
+
+#. module: l10n_multilang
+#: sql_constraint:account.account:0
+msgid "The code of the account must be unique per company !"
+msgstr "يجب ان يكون كود الحساب فريداً لكل شركة !"
+
+#. module: l10n_multilang
+#: constraint:account.account.template:0
+msgid ""
+"Configuration Error!\n"
+"You can not define children to an account with internal type different of "
+"\"View\"! "
+msgstr ""
+"خطأ في الإعدادات!\n"
+" لاتستطيع تعريف أطفال لحساب من نوع داخلي مختلف ل\"العرض\"! "
+
+#. module: l10n_multilang
+#: model:ir.model,name:l10n_multilang.model_account_analytic_journal
+msgid "Analytic Journal"
+msgstr "يومية تحليلية"
+
+#. module: l10n_multilang
+#: constraint:account.account.template:0
+msgid "Error ! You can not create recursive account templates."
+msgstr "خطأ ! لا يمكنك انشاء قوالب الحاسب العودية."
+
+#. module: l10n_multilang
+#: model:ir.model,name:l10n_multilang.model_account_journal
+msgid "Journal"
+msgstr "يومية"
+
+#. module: l10n_multilang
+#: model:ir.model,name:l10n_multilang.model_account_chart_template
+msgid "Templates for Account Chart"
+msgstr "القوالب لجدول الحساب"
+
+#. module: l10n_multilang
+#: sql_constraint:account.tax:0
+msgid "The description must be unique per company!"
+msgstr "وصف لكل شركة يجب ان تكون فريد!"
+
+#. module: l10n_multilang
+#: constraint:account.tax.code.template:0
+msgid "Error ! You can not create recursive Tax Codes."
+msgstr "خطأ ! لايمكنك إنشاء اكواد ضريبية متداخلة."
+
+#. module: l10n_multilang
+#: model:ir.model,name:l10n_multilang.model_account_tax_template
+msgid "account.tax.template"
+msgstr "account.tax.template"
+
+#. module: l10n_multilang
+#: model:ir.model,name:l10n_multilang.model_account_tax
+msgid "account.tax"
+msgstr "account.tax"
+
+#. module: l10n_multilang
+#: model:ir.model,name:l10n_multilang.model_account_account
+msgid "Account"
+msgstr "حساب"
+
+#. module: l10n_multilang
+#: model:ir.model,name:l10n_multilang.model_wizard_multi_charts_accounts
+msgid "wizard.multi.charts.accounts"
+msgstr "wizard.multi.charts.accounts"
+
+#. module: l10n_multilang
+#: constraint:account.journal:0
+msgid ""
+"Configuration error! The currency chosen should be shared by the default "
+"accounts too."
+msgstr ""
+"خطأ في الإعدادات! يجب أن تكون العملة المختارة مشتركة للحسابات الإفتراضية "
+"أيضأً."
+
+#. module: l10n_multilang
+#: model:ir.model,name:l10n_multilang.model_account_account_template
+msgid "Templates for Accounts"
+msgstr "قوالب للحسابات"
+
+#. module: l10n_multilang
+#: help:account.chart.template,spoken_languages:0
+msgid ""
+"State here the languages for which the translations of templates could be "
+"loaded at the time of installation of this localization module and copied in "
+"the final object when generating them from templates. You must provide the "
+"language codes separated by ';'"
+msgstr ""
+
+#. module: l10n_multilang
+#: constraint:account.account:0
+msgid "Error ! You can not create recursive accounts."
+msgstr "خطأ ! لا يمكن إنشاء حسابات تكرارية."
+
+#. module: l10n_multilang
+#: constraint:account.account:0
+msgid ""
+"Configuration Error! \n"
+"You can not select an account type with a deferral method different of "
+"\"Unreconciled\" for accounts with internal type \"Payable/Receivable\"! "
+msgstr ""
+"التكوين الخطأ!\n"
+"لا يمكنك اختيار نوع الحساب باستخدام طريقة التأجيل المختلفه \"عدم "
+"المساواه\" للحسابات من النوع الداخلي \"الدفع / القبض\" "
+
+#. module: l10n_multilang
+#: sql_constraint:account.journal:0
+msgid "The name of the journal must be unique per company !"
+msgstr "يجب ان يكون الاسم لليومية فريد لكل شركة!"
+
+#. module: l10n_multilang
+#: model:ir.model,name:l10n_multilang.model_account_analytic_account
+msgid "Analytic Account"
+msgstr "حسابات تحليلية"
+
+#. module: l10n_multilang
+#: sql_constraint:account.journal:0
+msgid "The code of the journal must be unique per company !"
+msgstr "يجب ان يكون الكود لليومية فريد لكل شركة !"
+
+#. module: l10n_multilang
+#: model:ir.model,name:l10n_multilang.model_account_fiscal_position
+msgid "Fiscal Position"
+msgstr "الوضع المالي"
+
+#. module: l10n_multilang
+#: constraint:account.account:0
+msgid ""
+"Configuration Error! \n"
+"You can not define children to an account with internal type different of "
+"\"View\"! "
+msgstr ""
+"خطأ في الإعدادات!\n"
+"لا يمكنك تحديد فرع لحساب مع نوع داخلي مختلف من \"عرض\"! "
+
+#. module: l10n_multilang
+#: constraint:account.analytic.account:0
+msgid "Error! You can not create recursive analytic accounts."
+msgstr "خطأ! لا يمكنك إنشاء حسابات تحليلية متكررة."
+
+#. module: l10n_multilang
+#: model:ir.model,name:l10n_multilang.model_account_tax_code_template
+msgid "Tax Code Template"
+msgstr "قالب رمز الضريبة"
+
+#. module: l10n_multilang
+#: field:account.chart.template,spoken_languages:0
+msgid "Spoken Languages"
+msgstr "اللغات المنطوقة"
diff --git a/addons/l10n_nl/account_chart_netherlands.xml b/addons/l10n_nl/account_chart_netherlands.xml
index 96100d9a442..f736c6f4895 100644
--- a/addons/l10n_nl/account_chart_netherlands.xml
+++ b/addons/l10n_nl/account_chart_netherlands.xml
@@ -1424,7 +1424,7 @@
<field name="reconcile" eval="True"/>
<field ref="a_15" name="parent_id"/>
</record>
- <record id="vat_payable6" model="account.account.template">
+ <record id="vat_payable_low" model="account.account.template">
<field name="name">Btw af te dragen laag</field>
<field name="code">1601</field>
<field name="type">other</field>
@@ -1432,7 +1432,7 @@
<field name="reconcile" eval="False"/>
<field ref="a_15" name="parent_id"/>
</record>
- <record id="vat_payable19" model="account.account.template">
+ <record id="vat_payable_high" model="account.account.template">
<field name="name">Btw af te dragen hoog</field>
<field name="code">1602</field>
<field name="type">other</field>
@@ -1448,7 +1448,7 @@
<field name="reconcile" eval="False"/>
<field ref="a_15" name="parent_id"/>
</record>
- <record id="vat_refund6" model="account.account.template">
+ <record id="vat_refund_low" model="account.account.template">
<field name="name">Btw te vorderen laag</field>
<field name="code">1611</field>
<field name="type">other</field>
@@ -1456,7 +1456,7 @@
<field name="reconcile" eval="False"/>
<field ref="a_15" name="parent_id"/>
</record>
- <record id="vat_refund19" model="account.account.template">
+ <record id="vat_refund_high" model="account.account.template">
<field name="name">Btw te vorderen hoog</field>
<field name="code">1612</field>
<field name="type">other</field>
@@ -3909,7 +3909,7 @@
<record id="btw_code_1a" model="account.tax.code.template">
<field name="code">1a</field>
<field name="parent_id" ref="btw_code_binnenland"/>
- <field name="name">Leveringen/diensten belast met 19% (BTW)</field>
+ <field name="name">Leveringen/diensten belast met 21% (BTW)</field>
</record>
<record id="btw_code_1b" model="account.tax.code.template">
<field name="code">1b</field>
@@ -4021,7 +4021,7 @@
<record id="omz_code_1a" model="account.tax.code.template">
<field name="code">1a</field>
<field name="parent_id" ref="omz_code_binnenland"/>
- <field name="name">Leveringen/diensten belast met 19% (omzet)</field>
+ <field name="name">Leveringen/diensten belast met 21% (omzet)</field>
</record>
<record id="omz_code_1b" model="account.tax.code.template">
<field name="code">1b</field>
@@ -4149,22 +4149,22 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field name="description">6% BTW</field>
<field eval="0.06" name="amount"/>
<field name="type">percent</field>
- <field name="account_collected_id" ref="vat_payable6"/>
- <field name="account_paid_id" ref="vat_refund6"/>
+ <field name="account_collected_id" ref="vat_payable_low"/>
+ <field name="account_paid_id" ref="vat_refund_low"/>
<field name="base_code_id" ref="omz_code_1b"/>
<field name="tax_code_id" ref="btw_code_1b"/>
<field name="ref_base_code_id" ref="omz_code_1b"/>
<field name="ref_tax_code_id" ref="btw_code_1b"/>
<field name="type_tax_use">sale</field>
</record>
- <record id="btw_19" model="account.tax.template">
+ <record id="btw_21" model="account.tax.template">
<field name="chart_template_id" ref="l10nnl_chart_template"/>
<field name="name">Verkopen/omzet hoog</field>
- <field name="description">19% BTW</field>
- <field eval="0.19" name="amount"/>
+ <field name="description">21% BTW</field>
+ <field eval="0.21" name="amount"/>
<field name="type">percent</field>
- <field name="account_collected_id" ref="vat_payable19"/>
- <field name="account_paid_id" ref="vat_refund19"/>
+ <field name="account_collected_id" ref="vat_payable_high"/>
+ <field name="account_paid_id" ref="vat_refund_high"/>
<field name="base_code_id" ref="omz_code_1a"/>
<field name="tax_code_id" ref="btw_code_1a"/>
<field name="ref_base_code_id" ref="omz_code_1a"/>
@@ -4176,10 +4176,10 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field name="chart_template_id" ref="l10nnl_chart_template"/>
<field name="name">Verkopen/omzet overig</field>
<field name="description">variabel BTW</field>
- <field eval="0.19" name="amount"/>
+ <field eval="0.21" name="amount"/>
<field name="type">percent</field>
- <field name="account_collected_id" ref="vat_payable19"/>
- <field name="account_paid_id" ref="vat_refund19"/>
+ <field name="account_collected_id" ref="vat_payable_high"/>
+ <field name="account_paid_id" ref="vat_refund_high"/>
<field name="base_code_id" ref="omz_code_1a"/>
<field name="tax_code_id" ref="btw_code_1a"/>
<field name="ref_base_code_id" ref="omz_code_1c"/>
@@ -4194,20 +4194,20 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field name="description">6% BTW</field>
<field eval="0.06" name="amount"/>
<field name="type">percent</field>
- <field name="account_collected_id" ref="vat_refund6"/>
- <field name="account_paid_id" ref="vat_payable6"/>
+ <field name="account_collected_id" ref="vat_refund_low"/>
+ <field name="account_paid_id" ref="vat_payable_low"/>
<field name="tax_code_id" ref="btw_code_5b"/>
<field name="ref_tax_code_id" ref="btw_code_5b"/>
<field name="type_tax_use">purchase</field>
</record>
- <record id="btw_19_buy" model="account.tax.template">
+ <record id="btw_21_buy" model="account.tax.template">
<field name="chart_template_id" ref="l10nnl_chart_template"/>
<field name="name">BTW te vorderen hoog (inkopen)</field>
- <field name="description">19% BTW</field>
- <field eval="0.19" name="amount"/>
+ <field name="description">21% BTW</field>
+ <field eval="0.21" name="amount"/>
<field name="type">percent</field>
- <field name="account_collected_id" ref="vat_refund19"/>
- <field name="account_paid_id" ref="vat_payable19"/>
+ <field name="account_collected_id" ref="vat_refund_high"/>
+ <field name="account_paid_id" ref="vat_payable_high"/>
<field name="tax_code_id" ref="btw_code_5b"/>
<field name="ref_tax_code_id" ref="btw_code_5b"/>
<field name="type_tax_use">purchase</field>
@@ -4216,10 +4216,10 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field name="chart_template_id" ref="l10nnl_chart_template"/>
<field name="name">BTW te vorderen overig (inkopen)</field>
<field name="description">variabel BTW</field>
- <field eval="0.19" name="amount"/>
+ <field eval="0.21" name="amount"/>
<field name="type">percent</field>
- <field name="account_collected_id" ref="vat_refund19"/>
- <field name="account_paid_id" ref="vat_payable19"/>
+ <field name="account_collected_id" ref="vat_refund_high"/>
+ <field name="account_paid_id" ref="vat_payable_high"/>
<field name="tax_code_id" ref="btw_code_5b"/>
<field name="ref_tax_code_id" ref="btw_code_5b"/>
<field name="type_tax_use">purchase</field>
@@ -4240,8 +4240,8 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<record id="btw_ink_0" model="account.tax.template">
<field name="chart_template_id" ref="l10nnl_chart_template"/>
<field name="name">BTW af te dragen verlegd (inkopen)</field>
- <field name="description">19% BTW verlegd</field>
- <field eval="0.19" name="amount"/>
+ <field name="description">21% BTW verlegd</field>
+ <field eval="0.21" name="amount"/>
<field name="type">percent</field>
<field name="account_collected_id" ref="vat_payable_verlegd"/>
<field name="account_paid_id" ref="vat_refund_verlegd"/>
@@ -4277,8 +4277,8 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<record id="btw_ink2_0" model="account.tax.template">
<field name="chart_template_id" ref="l10nnl_chart_template"/>
<field name="name">BTW te vorderen verlegd (inkopen)</field>
- <field name="description">19% BTW verlegd</field>
- <field eval="0.19" name="amount"/>
+ <field name="description">21% BTW verlegd</field>
+ <field eval="0.21" name="amount"/>
<field name="type">percent</field>
<field name="account_collected_id" ref="vat_refund_verlegd"/>
<field name="account_paid_id" ref="vat_payable_verlegd"/>
@@ -4330,8 +4330,8 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field eval="-1.00" name="amount"/>
<field name="type">percent</field>
<field name="parent_id" ref="btw_I_6"/>
- <field name="account_collected_id" ref="vat_payable6"/>
- <field name="account_paid_id" ref="vat_payable6"/>
+ <field name="account_collected_id" ref="vat_payable_low"/>
+ <field name="account_paid_id" ref="vat_payable_low"/>
<field eval="btw_code_4b" name="tax_code_id"/>
<field eval="btw_code_4b" name="ref_tax_code_id"/>
<field name="type_tax_use">purchase</field>
@@ -4342,43 +4342,43 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field eval="1.00" name="amount"/>
<field name="type">percent</field>
<field name="parent_id" ref="btw_I_6"/>
- <field name="account_collected_id" ref="vat_refund6"/>
- <field name="account_paid_id" ref="vat_refund6"/>
+ <field name="account_collected_id" ref="vat_refund_low"/>
+ <field name="account_paid_id" ref="vat_refund_low"/>
<field eval="btw_code_5b" name="tax_code_id"/>
<field eval="btw_code_5b" name="ref_tax_code_id"/>
<field name="type_tax_use">purchase</field>
</record>
- <record id="btw_I_19" model="account.tax.template">
+ <record id="btw_I_21" model="account.tax.template">
<field name="chart_template_id" ref="l10nnl_chart_template"/>
<field name="name">Inkopen import binnen EU hoog</field>
- <field name="description">19% BTW import binnen EU</field>
- <field eval="0.19" name="amount"/>
+ <field name="description">21% BTW import binnen EU</field>
+ <field eval="0.21" name="amount"/>
<field name="type">percent</field>
<field eval="True" name="child_depend"/>
<field eval="omz_code_4b" name="base_code_id"/>
<field eval="omz_code_4b" name="ref_base_code_id"/>
<field name="type_tax_use">purchase</field>
</record>
- <record id="btw_I_19_1" model="account.tax.template">
+ <record id="btw_I_21_1" model="account.tax.template">
<field name="chart_template_id" ref="l10nnl_chart_template"/>
<field name="name">Inkopen import binnen EU hoog(1)</field>
<field eval="-1.00" name="amount"/>
<field name="type">percent</field>
- <field name="parent_id" ref="btw_I_19"/>
- <field name="account_collected_id" ref="vat_payable19"/>
- <field name="account_paid_id" ref="vat_payable19"/>
+ <field name="parent_id" ref="btw_I_21"/>
+ <field name="account_collected_id" ref="vat_payable_high"/>
+ <field name="account_paid_id" ref="vat_payable_high"/>
<field eval="btw_code_4b" name="tax_code_id"/>
<field eval="btw_code_4b" name="ref_tax_code_id"/>
<field name="type_tax_use">purchase</field>
</record>
- <record id="btw_I_19_2" model="account.tax.template">
+ <record id="btw_I_21_2" model="account.tax.template">
<field name="chart_template_id" ref="l10nnl_chart_template"/>
<field name="name">Inkopen import binnen EU hoog(2)</field>
<field eval="1.00" name="amount"/>
<field name="type">percent</field>
- <field name="parent_id" ref="btw_I_19"/>
- <field name="account_collected_id" ref="vat_refund19"/>
- <field name="account_paid_id" ref="vat_refund19"/>
+ <field name="parent_id" ref="btw_I_21"/>
+ <field name="account_collected_id" ref="vat_refund_high"/>
+ <field name="account_paid_id" ref="vat_refund_high"/>
<field eval="btw_code_5b" name="tax_code_id"/>
<field eval="btw_code_5b" name="ref_tax_code_id"/>
<field name="type_tax_use">purchase</field>
@@ -4400,8 +4400,8 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field eval="-1.00" name="amount"/>
<field name="type">percent</field>
<field name="parent_id" ref="btw_I_overig"/>
- <field name="account_collected_id" ref="vat_payable19"/>
- <field name="account_paid_id" ref="vat_payable19"/>
+ <field name="account_collected_id" ref="vat_payable_high"/>
+ <field name="account_paid_id" ref="vat_payable_high"/>
<field eval="btw_code_4b" name="tax_code_id"/>
<field eval="btw_code_4b" name="ref_tax_code_id"/>
<field name="type_tax_use">purchase</field>
@@ -4412,8 +4412,8 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field eval="1.00" name="amount"/>
<field name="type">percent</field>
<field name="parent_id" ref="btw_I_overig"/>
- <field name="account_collected_id" ref="vat_refund19"/>
- <field name="account_paid_id" ref="vat_refund19"/>
+ <field name="account_collected_id" ref="vat_refund_high"/>
+ <field name="account_paid_id" ref="vat_refund_high"/>
<field eval="btw_code_5b" name="tax_code_id"/>
<field eval="btw_code_5b" name="ref_tax_code_id"/>
<field name="type_tax_use">purchase</field>
@@ -4463,8 +4463,8 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field eval="-1.00" name="amount"/>
<field name="type">percent</field>
<field name="parent_id" ref="btw_E1"/>
- <field name="account_collected_id" ref="vat_payable6"/>
- <field name="account_paid_id" ref="vat_payable6"/>
+ <field name="account_collected_id" ref="vat_payable_low"/>
+ <field name="account_paid_id" ref="vat_payable_low"/>
<field eval="btw_code_4a" name="tax_code_id"/>
<field eval="btw_code_4a" name="ref_tax_code_id"/>
<field name="type_tax_use">purchase</field>
@@ -4475,8 +4475,8 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field eval="1.00" name="amount"/>
<field name="type">percent</field>
<field name="parent_id" ref="btw_E1"/>
- <field name="account_collected_id" ref="vat_refund6"/>
- <field name="account_paid_id" ref="vat_refund6"/>
+ <field name="account_collected_id" ref="vat_refund_low"/>
+ <field name="account_paid_id" ref="vat_refund_low"/>
<field eval="btw_code_5b" name="tax_code_id"/>
<field eval="btw_code_5b" name="ref_tax_code_id"/>
<field name="type_tax_use">purchase</field>
@@ -4485,7 +4485,7 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field name="chart_template_id" ref="l10nnl_chart_template"/>
<field name="name">Inkopen import buiten EU hoog</field>
<field name="description">BTW import buiten EU</field>
- <field eval="0.19" name="amount"/>
+ <field eval="0.21" name="amount"/>
<field name="type">percent</field>
<field eval="True" name="child_depend"/>
<field eval="omz_code_4a" name="base_code_id"/>
@@ -4498,8 +4498,8 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field eval="-1.00" name="amount"/>
<field name="type">percent</field>
<field name="parent_id" ref="btw_E2"/>
- <field name="account_collected_id" ref="vat_payable19"/>
- <field name="account_paid_id" ref="vat_payable19"/>
+ <field name="account_collected_id" ref="vat_payable_high"/>
+ <field name="account_paid_id" ref="vat_payable_high"/>
<field eval="btw_code_4a" name="tax_code_id"/>
<field eval="btw_code_4a" name="ref_tax_code_id"/>
<field name="type_tax_use">purchase</field>
@@ -4510,8 +4510,8 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field eval="1.00" name="amount"/>
<field name="type">percent</field>
<field name="parent_id" ref="btw_E2"/>
- <field name="account_collected_id" ref="vat_refund19"/>
- <field name="account_paid_id" ref="vat_refund19"/>
+ <field name="account_collected_id" ref="vat_refund_high"/>
+ <field name="account_paid_id" ref="vat_refund_high"/>
<field eval="btw_code_5b" name="tax_code_id"/>
<field eval="btw_code_5b" name="ref_tax_code_id"/>
<field name="type_tax_use">purchase</field>
@@ -4520,7 +4520,7 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field name="chart_template_id" ref="l10nnl_chart_template"/>
<field name="name">Inkopen import buiten EU overig</field>
<field name="description">BTW import buiten EU</field>
- <field eval="0.19" name="amount"/>
+ <field eval="0.21" name="amount"/>
<field name="type">percent</field>
<field eval="True" name="child_depend"/>
<field eval="omz_code_4a" name="base_code_id"/>
@@ -4533,8 +4533,8 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field eval="-1.00" name="amount"/>
<field name="type">percent</field>
<field name="parent_id" ref="btw_E_overig"/>
- <field name="account_collected_id" ref="vat_payable19"/>
- <field name="account_paid_id" ref="vat_payable19"/>
+ <field name="account_collected_id" ref="vat_payable_high"/>
+ <field name="account_paid_id" ref="vat_payable_high"/>
<field eval="btw_code_4a" name="tax_code_id"/>
<field eval="btw_code_4a" name="ref_tax_code_id"/>
<field name="type_tax_use">purchase</field>
@@ -4545,8 +4545,8 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge
<field eval="1.00" name="amount"/>
<field name="type">percent</field>
<field name="parent_id" ref="btw_E_overig"/>
- <field name="account_collected_id" ref="vat_refund19"/>
- <field name="account_paid_id" ref="vat_refund19"/>
+ <field name="account_collected_id" ref="vat_refund_high"/>
+ <field name="account_paid_id" ref="vat_refund_high"/>
<field eval="btw_code_5b" name="tax_code_id"/>
<field eval="btw_code_5b" name="ref_tax_code_id"/>
<field name="type_tax_use">purchase</field>
diff --git a/addons/l10n_pe/i18n/ar.po b/addons/l10n_pe/i18n/ar.po
new file mode 100644
index 00000000000..90dcc9a47f6
--- /dev/null
+++ b/addons/l10n_pe/i18n/ar.po
@@ -0,0 +1,47 @@
+# Arabic translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2011-01-11 11:15+0000\n"
+"PO-Revision-Date: 2012-11-16 18:58+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Arabic <ar@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-11-17 04:37+0000\n"
+"X-Generator: Launchpad (build 16278)\n"
+
+#. module: l10n_pe
+#: model:ir.module.module,description:l10n_pe.module_meta_information
+msgid ""
+"\n"
+" Peruvian Accounting : chart of Account\n"
+" "
+msgstr ""
+
+#. module: l10n_pe
+#: model:ir.module.module,shortdesc:l10n_pe.module_meta_information
+msgid "Peruvian Chart of Account"
+msgstr ""
+
+#. module: l10n_pe
+#: model:ir.actions.todo,note:l10n_pe.config_call_account_template_in_minimal
+msgid ""
+"Generate Chart of Accounts from a Chart Template. You will be asked to pass "
+"the name of the company, the chart template to follow, the no. of digits to "
+"generate the code for your accounts and Bank account, currency to create "
+"Journals. Thus,the pure copy of chart Template is generated.\n"
+"\tThis is the same wizard that runs from Financial "
+"Management/Configuration/Financial Accounting/Financial Accounts/Generate "
+"Chart of Accounts from a Chart Template."
+msgstr ""
+"إعداد شجرة الحسابات من قالب. ستم سؤالك عن اسم المنشأة، القالب المتبع، و "
+"إعداد أكواد الحسابات و البنوك، بالإضافة إلي يوميات العملة. و لذلك سيكون هناك "
+"قالب جديد. \n"
+"\tهذه لإعداد الحسابات."
diff --git a/addons/lunch/lunch_demo.xml b/addons/lunch/lunch_demo.xml
index a9b03137bf2..9e92291b62d 100644
--- a/addons/lunch/lunch_demo.xml
+++ b/addons/lunch/lunch_demo.xml
@@ -21,12 +21,10 @@
<record model="res.partner" id="partner_coin_gourmand">
<field name="name">Coin gourmand</field>
- <field name="supplier_lunch">True</field>
</record>
<record model="res.partner" id="partner_pizza_inn">
<field name="name">Pizza Inn</field>
- <field name="supplier_lunch">True</field>
</record>
<record model="lunch.product" id="product_cheese_ham">
@@ -106,7 +104,6 @@
<field name="date" eval="time.strftime('2012-10-23')"/>
<field name="order_line_ids" eval="[]"/>
<field name="state">new</field>
- <field name='company_id'>1</field>
</record>
<record model="lunch.order" id="order_2">
@@ -114,7 +111,6 @@
<field name="date" eval="time.strftime('2012-10-22')"/>
<field name="order_line_ids" eval="[]"/>
<field name="state">confirmed</field>
- <field name='company_id'>1</field>
</record>
<record model="lunch.order" id="order_3">
@@ -122,7 +118,6 @@
<field name="date" eval="time.strftime('2012-10-24')"/>
<field name="order_line_ids" eval="[]"/>
<field name="state">cancelled</field>
- <field name='company_id'>1</field>
</record>
<record model="lunch.order.line" id="order_line_1">
@@ -175,7 +170,6 @@
<record model="lunch.alert" id="alert_1">
<field name="message">Lunch must be ordered before 10h30 am</field>
- <field name="day">days</field>
</record>
</data>
diff --git a/addons/lunch/lunch_view.xml b/addons/lunch/lunch_view.xml
index 32b978dfab0..ea9356bddc5 100644
--- a/addons/lunch/lunch_view.xml
+++ b/addons/lunch/lunch_view.xml
@@ -12,7 +12,6 @@
<record model="ir.ui.view" id="lunch_order_line_search_view">
<field name="name">Search</field>
<field name="model">lunch.order.line</field>
- <field name="type">search</field>
<field name="arch" type="xml">
<search string="Search">
<field name="name" filter_domain="['|', ('name', 'ilike', self), ('note', 'ilike', self)]"/>
@@ -34,7 +33,6 @@
<record id="view_lunch_employee_payment_filter" model="ir.ui.view">
<field name='name'>lunch employee payment</field>
<field name='model'>lunch.cashmove</field>
- <field name='type'>search</field>
<field name='arch' type='xml'>
<search string="lunch employee payment">
<field name="description"/>
@@ -49,7 +47,6 @@
<record id="view_lunch_cashmove_filter" model="ir.ui.view">
<field name='name'>lunch cashmove</field>
<field name='model'>lunch.cashmove</field>
- <field name='type'>search</field>
<field name='arch' type='xml'>
<search string="lunch cashmove">
<field name="description"/>
@@ -65,7 +62,6 @@
<record id="view_search_my_order" model="ir.ui.view">
<field name='name'>lunch orders</field>
<field name='model'>lunch.order</field>
- <field name='type'>search</field>
<field name='arch' type='xml'>
<search string="lunch orders">
<field name="date"/>
@@ -79,7 +75,6 @@
<record model="ir.ui.view" id="alert_search_view">
<field name="name">Search</field>
<field name="model">lunch.alert</field>
- <field name="type">search</field>
<field name="arch" type="xml">
<search string="Search">
<field name="message"/>
@@ -243,7 +238,6 @@
<record model="ir.ui.view" id="product_category_form_view">
<field name="name">Product category Form</field>
<field name="model">lunch.product.category</field>
- <field name="type">form</field>
<field name="arch" type="xml">
<form string="Products Form" version="7.0">
<sheet>
@@ -285,7 +279,6 @@
<record model="ir.ui.view" id="orders_order_lines_tree_view">
<field name="name">Order lines Tree</field>
<field name="model">lunch.order.line</field>
- <field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Order lines Tree">
<field name='date'/>
@@ -306,7 +299,6 @@
<record model="ir.ui.view" id="orders_tree_view">
<field name="name">Orders Tree View</field>
<field name="model">lunch.order</field>
- <field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Orders Tree">
<field name="date"/>
@@ -360,7 +352,6 @@
<record model="ir.ui.view" id="products_tree_view">
<field name="name">Products Tree</field>
<field name="model">lunch.product</field>
- <field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Products Tree">
<field name="name"/>
@@ -375,7 +366,6 @@
<record model="ir.ui.view" id="products_form_view">
<field name="name">Products Form</field>
<field name="model">lunch.product</field>
- <field name="type">form</field>
<field name="arch" type="xml">
<form string="Products Form" version="7.0">
<header>
@@ -398,7 +388,6 @@
<record model="ir.ui.view" id="casmove_tree_view">
<field name="name">cashmove tree</field>
<field name="model">lunch.cashmove</field>
- <field name="type">tree</field>
<field name="arch" type="xml">
<tree string="cashmove tree">
<field name="date"/>
@@ -412,7 +401,6 @@
<record model="ir.ui.view" id="casmove_form_view">
<field name="name">cashmove form</field>
<field name="model">lunch.cashmove</field>
- <field name="type">form</field>
<field name="arch" type="xml">
<form string="cashmove form" version="7.0">
<sheet>
@@ -432,7 +420,6 @@
<record model="ir.ui.view" id="alert_tree_view">
<field name="name">alert tree</field>
<field name="model">lunch.alert</field>
- <field name="type">tree</field>
<field name="arch" type="xml">
<tree string="alert tree">
<field name="message"/>
@@ -446,7 +433,6 @@
<record model="ir.ui.view" id="alert_form_view">
<field name="name">alert form</field>
<field name="model">lunch.alert</field>
- <field name="type">form</field>
<field name="arch" type="xml">
<form string="alert tree" version="7.0">
<sheet>
diff --git a/addons/lunch/security/ir.model.access.csv b/addons/lunch/security/ir.model.access.csv
index 026a43e0a61..22966129142 100644
--- a/addons/lunch/security/ir.model.access.csv
+++ b/addons/lunch/security/ir.model.access.csv
@@ -10,4 +10,7 @@ order_line_user,"Order Line user",model_lunch_order_line,group_lunch_user,1,1,1,
cashmove_user,"Cashmove user",model_lunch_cashmove,group_lunch_user,1,0,0,0
product_user,"Product user",model_lunch_product,group_lunch_user,1,0,0,0
product_category_user,"Product category user",model_lunch_product_category,group_lunch_user,1,0,0,0
-alert_user,"Alert user",model_lunch_alert,group_lunch_user,1,0,0,0 \ No newline at end of file
+alert_user,"Alert user",model_lunch_alert,group_lunch_user,1,0,0,0
+access_report_order_line,access_report_order_line,model_report_lunch_order_line,,1,1,1,1
+access_lunch_validation,access_lunch_validation,model_lunch_validation,,1,1,1,1
+access_lunch_cancel,access_lunch_cancel,model_lunch_cancel,,1,1,1,1
diff --git a/addons/lunch/wizard/lunch_cancel_view.xml b/addons/lunch/wizard/lunch_cancel_view.xml
index 4df5c8739e9..acc0cfc9f13 100644
--- a/addons/lunch/wizard/lunch_cancel_view.xml
+++ b/addons/lunch/wizard/lunch_cancel_view.xml
@@ -4,7 +4,6 @@
<record model="ir.ui.view" id="cancel_order_lines_view">
<field name="name">cancel order lines</field>
<field name="model">lunch.cancel</field>
- <field name="type">form</field>
<field name="arch" type="xml">
<form string="cancel order lines" version="7.0">
<separator string="Are you sure you want to cancel these meals?"/>
@@ -29,4 +28,4 @@
view_mode="form" target="new" view_type="form" view_id="cancel_order_lines_view"/>
</data>
-</openerp> \ No newline at end of file
+</openerp>
diff --git a/addons/lunch/wizard/lunch_order.py b/addons/lunch/wizard/lunch_order.py
index 20de4adc263..767497bcc4b 100644
--- a/addons/lunch/wizard/lunch_order.py
+++ b/addons/lunch/wizard/lunch_order.py
@@ -20,7 +20,7 @@
##############################################################################
from osv import osv, fields
-class lunch_order_order(osv.Model):
+class lunch_order_order(osv.TransientModel):
""" lunch order meal """
_name = 'lunch.order.order'
_description = 'Wizard to order a meal'
diff --git a/addons/lunch/wizard/lunch_order_view.xml b/addons/lunch/wizard/lunch_order_view.xml
index 990add2564e..ba2d372a543 100644
--- a/addons/lunch/wizard/lunch_order_view.xml
+++ b/addons/lunch/wizard/lunch_order_view.xml
@@ -4,7 +4,6 @@
<record model="ir.ui.view" id="order_order_lines_view">
<field name="name">Order meal</field>
<field name="model">lunch.order.order</field>
- <field name="type">form</field>
<field name="arch" type="xml">
<form string="Order meal" version="7.0">
<separator string="Are you sure you want to order these meals?"/>
diff --git a/addons/lunch/wizard/lunch_validation_view.xml b/addons/lunch/wizard/lunch_validation_view.xml
index 5e9fb92956f..bec141d2d4a 100644
--- a/addons/lunch/wizard/lunch_validation_view.xml
+++ b/addons/lunch/wizard/lunch_validation_view.xml
@@ -4,7 +4,6 @@
<record model="ir.ui.view" id="validate_order_lines_view">
<field name="name">validate order lines</field>
<field name="model">lunch.validation</field>
- <field name="type">form</field>
<field name="arch" type="xml">
<form string="validate order lines" version="7.0">
<separator string="Did your received these meals?"/>
diff --git a/addons/mail/__init__.py b/addons/mail/__init__.py
index 003369be38f..b34993ffd32 100644
--- a/addons/mail/__init__.py
+++ b/addons/mail/__init__.py
@@ -22,12 +22,12 @@
import mail_message_subtype
import mail_alias
import mail_followers
+import mail_vote
import mail_favorite
import mail_message
import mail_mail
import mail_thread
import mail_group
-import mail_vote
import res_partner
import res_users
import report
diff --git a/addons/mail/data/mail_demo.xml b/addons/mail/data/mail_demo.xml
index bda93fc485d..a5eaa63956a 100644
--- a/addons/mail/data/mail_demo.xml
+++ b/addons/mail/data/mail_demo.xml
@@ -2,49 +2,90 @@
<openerp>
<data noupdate="1">
+ <!-- Update demo user to avoid mail bombing -->
+ <record id="base.partner_demo" model="res.partner">
+ <field name="notification_email_send">none</field>
+ </record>
+
+ <!-- Pushed to all employees -->
<record id="message_blogpost0" model="mail.message">
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
- <field name="body">Your monthly meal vouchers arrived. You can get them at Christine's office.
-This month you also get 250 EUR of eco-vouchers if you have been in the company for more than a year.</field>
+ <field name="body"><![CDATA[<p>Your monthly meal vouchers arrived. You can get them at Christine's office.</p>]]></field>
<field name="type">comment</field>
<field name="subtype_id" ref="mt_comment"/>
+ <field name="author_id" ref="base.partner_root"/>
</record>
-
<record id="message_blogpost0_comment0" model="mail.message">
<field name="model">mail.group</field>
<field name="res_id" ref="group_all_employees"/>
- <field name="body"><![CDATA[Great.]]></field>
+ <field name="body"><![CDATA[<p>Oh, I had forgotten. This month you also get 250 EUR of eco-vouchers if you have been in the company for more than a year.</p>]]></field>
<field name="parent_id" ref="message_blogpost0"/>
<field name="type">comment</field>
<field name="subtype_id" ref="mt_comment"/>
+ <field name="author_id" ref="base.partner_root"/>
</record>
-
<record id="message_blogpost0_comment1" model="mail.message">
<field name="model">mail.group</field>
<field name="res_id" ref="group_all_employees"/>
- <field name="body">Thanks, but where is Christine's office, if I may ask? (I'm new here)</field>
+ <field name="body"><![CDATA[<p>Thanks! Could you please remind me where is Christine's office, if I may ask? I'm new here!</p>]]></field>
<field name="parent_id" ref="message_blogpost0"/>
<field name="type">comment</field>
<field name="subtype_id" ref="mt_comment"/>
+ <field name="author_id" ref="base.partner_demo"/>
</record>
-
+ <!-- This one is starred for having mailboxes with demo data -->
<record id="message_blogpost0_comment2" model="mail.message">
<field name="model">mail.group</field>
<field name="res_id" ref="group_all_employees"/>
- <field name="body">Building B3, second floor on the right :-)</field>
+ <field name="body"><![CDATA[<p>Building B3, second floor on the right :-).</p>]]></field>
<field name="parent_id" ref="message_blogpost0"/>
<field name="type">comment</field>
<field name="subtype_id" ref="mt_comment"/>
+ <field name="author_id" ref="base.partner_root"/>
+ <field name="favorite_user_ids" eval="[(6, 0, [ref('base.user_root'), ref('base.user_demo')])]"/>
</record>
-
<record id="message_blogpost0_comment3" model="mail.message">
<field name="model">mail.group</field>
<field name="res_id" ref="group_all_employees"/>
- <field name="body">Great news, I need to buy a new fridge, I think I can pay it with the eco-vouchers!</field>
+ <field name="body"><![CDATA[<p>Many thanks. Actually that's good news, next year I'll have to buy a new fridge, I think I will pay it with the eco-vouchers!</p>]]></field>
<field name="parent_id" ref="message_blogpost0"/>
<field name="type">comment</field>
<field name="subtype_id" ref="mt_comment"/>
+ <field name="author_id" ref="base.partner_demo"/>
+ </record>
+
+ <!-- Demo user and admin conversation -->
+ <record id="message_discussion" model="mail.message">
+ <field name="body">Hello Demo User! I was wondering whether you had some issues with our secret task about putting cats everywhere in OpenERP.</field>
+ <field name="type">comment</field>
+ <field name="subtype_id" ref="mt_comment"/>
+ <field name="author_id" ref="base.partner_root"/>
+ <field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo')])]"/>
+ </record>
+ <record id="message_discussion_answer1" model="mail.message">
+ <field name="body">No specific issues, I think everything is clear.</field>
+ <field name="parent_id" ref="message_discussion"/>
+ <field name="type">comment</field>
+ <field name="subtype_id" ref="mt_comment"/>
+ <field name="author_id" ref="base.partner_demo"/>
+ <field name="partner_ids" eval="[(6, 0, [ref('base.partner_root')])]"/>
+ </record>
+ <record id="message_discussion_answer2" model="mail.message">
+ <field name="body">Ow, just to be sure... we were talking about lolcats, right ?</field>
+ <field name="parent_id" ref="message_discussion"/>
+ <field name="type">comment</field>
+ <field name="subtype_id" ref="mt_comment"/>
+ <field name="author_id" ref="base.partner_demo"/>
+ <field name="partner_ids" eval="[(6, 0, [ref('base.partner_root')])]"/>
+ </record>
+ <record id="message_discussion_answer3" model="mail.message">
+ <field name="body">Absolutely!</field>
+ <field name="parent_id" ref="message_discussion"/>
+ <field name="type">comment</field>
+ <field name="subtype_id" ref="mt_comment"/>
+ <field name="author_id" ref="base.partner_root"/>
+ <field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo')])]"/>
</record>
</data>
diff --git a/addons/mail/data/mail_group_data.xml b/addons/mail/data/mail_group_data.xml
index 11d0ee7d04b..64d989f9e9d 100644
--- a/addons/mail/data/mail_group_data.xml
+++ b/addons/mail/data/mail_group_data.xml
@@ -9,7 +9,7 @@
<record model="mail.group" id="group_all_employees">
<field name="name">Whole Company</field>
<field name="group_ids" eval="[(4, ref('base.group_user'))]"/>
- <field name="description">Discussion about best sales practices and deals.</field>
+ <field name="description">General announces for all employees.</field>
</record>
<!-- notify all employees of module installation -->
@@ -17,12 +17,11 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Welcome to OpenERP!</field>
- <field name="body">Your homepage is a summary of messages you received and key information about documents you follow.
-
-The top menu bar contains all applications you installed. You can use this &lt;i&gt;Settings&lt;/i&gt; menu to install more applications, activate others features or give access to new users.
-
-To setup your preferences (name, email signature, avatar), click on the top right corner.</field>
+ <field name="body"><![CDATA[<p>Your homepage is a summary of messages you received and key information about documents you follow.</p><p>
+The top menu bar contains all applications you installed. You can use the <i>Settings</i> menu to install more applications, activate others features or give access to new users.</p><p>
+To setup your preferences (name, email signature, avatar), click on the top right corner.</p>]]></field>
</record>
</data>
</openerp>
diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py
index e8cf2648f29..8d3876ec91f 100644
--- a/addons/mail/mail_followers.py
+++ b/addons/mail/mail_followers.py
@@ -61,10 +61,10 @@ class mail_notification(osv.Model):
_columns = {
'partner_id': fields.many2one('res.partner', string='Contact',
- ondelete='cascade', required=True),
- 'read': fields.boolean('Read'),
+ ondelete='cascade', required=True, select=1),
+ 'read': fields.boolean('Read', select=1),
'message_id': fields.many2one('mail.message', string='Message',
- ondelete='cascade', required=True),
+ ondelete='cascade', required=True, select=1),
}
_defaults = {
@@ -84,11 +84,13 @@ class mail_notification(osv.Model):
return False
def set_message_read(self, cr, uid, msg_ids, read=None, context=None):
- """ Set a message and its child messages as (un)read for uid.
+ """ Set messages as (un)read. Technically, the notifications related
+ to uid are set to (un)read. If for some msg_ids there are missing
+ notifications (i.e. due to load more or thread parent fetching),
+ they are created.
- :param bool read: read / unread
+ :param bool read: (un)read notification
"""
- # TDE note: use child_of or front-end send correct values ?
user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
notif_ids = self.search(cr, uid, [
('partner_id', '=', user_pid),
@@ -100,10 +102,9 @@ class mail_notification(osv.Model):
return self.write(cr, uid, notif_ids, {'read': read}, context=context)
# some messages do not have notifications: find which one, create notification, update read status
- exist_notification = dict.fromkeys(msg_ids, False)
- for notification in self.browse(cr, uid, notif_ids, context=context):
- exist_notification[notification.message_id] = True
- for msg_id in exist_notification.keys():
+ notified_msg_ids = [notification.message_id.id for notification in self.browse(cr, uid, notif_ids, context=context)]
+ to_create_msg_ids = list(set(msg_ids) - set(notified_msg_ids))
+ for msg_id in to_create_msg_ids:
self.create(cr, uid, {'partner_id': user_pid, 'read': read, 'message_id': msg_id}, context=context)
return self.write(cr, uid, notif_ids, {'read': read}, context=context)
@@ -156,10 +157,10 @@ class mail_notification(osv.Model):
# add signature
body_html = msg.body
# if quote_context:
- # body_html = tools.append_content_to_html(body_html, quote_context, plaintext=False)
- signature = msg.author_id and msg.author_id.user_ids[0].signature or ''
+ # body_html = tools.append_content_to_html(body_html, quote_context, plaintext=False)
+ signature = msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0].signature or ''
if signature:
- body_html = tools.append_content_to_html(body_html, signature)
+ body_html = tools.append_content_to_html(body_html, signature, plaintext=True, container_tag='div')
mail_values = {
'mail_message_id': msg.id,
diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py
index d4c9c565bf3..b163882577b 100644
--- a/addons/mail/mail_group.py
+++ b/addons/mail/mail_group.py
@@ -130,7 +130,7 @@ class mail_group(osv.Model):
params = {
'search_view_id': search_ref and search_ref[1] or False,
'domain': [('model', '=', 'mail.group'), ('res_id', '=', mail_group_id)],
- 'context': {'default_model': 'mail.group', 'default_res_id': mail_group_id},
+ 'context': {'default_model': 'mail.group', 'default_res_id': mail_group_id, 'search_default_message_unread': True},
'res_model': 'mail.message',
'thread_level': 1,
}
diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml
index 2028e8d1b18..4a880a13c14 100644
--- a/addons/mail/mail_group_view.xml
+++ b/addons/mail/mail_group_view.xml
@@ -32,17 +32,18 @@
</div>
<div class="oe_group_details">
<h4><a type="open"><field name="name"/></a></h4>
- <ul>
- <li><t t-raw="record.message_summary.raw_value"/></li>
- <li t-if="! record.message_is_follower.raw_value"><a name="action_follow" string="Join" type="object" class="oe_group_join">Not following</a></li>
- <li t-if="record.message_is_follower.raw_value"><a name="action_unfollow" string="Leave" type="object" class="oe_group_leave">Following</a></li>
- </ul>
+ <div class="oe_grey">
+ <field name="description"/>
+ </div>
+ <div class="oe_kanban_footer_left">
+ <t t-raw="record.message_summary.raw_value"/>
+ </div>
+ <div class="oe_group_button">
+ <button t-if="record.message_is_follower.raw_value" name="action_unfollow" type="object" class="oe_group_join">Unfollow</button>
+ <button t-if="! record.message_is_follower.raw_value" name="action_follow" type="object">Join Group</button>
+ </div>
</div>
</div>
- <script>
- $('.oe_group_join').mouseover(function () { $(this).html('Follow'); }).mouseleave(function () { $(this).html('Not following'); });
- $('.oe_group_leave').mouseover(function () { $(this).html('Unfollow'); }).mouseleave(function () { $(this).html('Following'); });
- </script>
</t>
</templates>
</kanban>
@@ -83,7 +84,7 @@
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
- <field name="message_ids" widget="mail_thread" options='{"thread_level": 1}'/>
+ <field name="message_ids" widget="mail_thread" options='{"thread_level": 1}' placeholder="Send a message to the group..."/>
</div>
</form>
</field>
diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py
index bd0ade31b68..9fd476d9d7f 100644
--- a/addons/mail/mail_message.py
+++ b/addons/mail/mail_message.py
@@ -25,6 +25,7 @@ import tools
from email.header import decode_header
from openerp import SUPERUSER_ID
from openerp.osv import osv, orm, fields
+from openerp.tools import html_email_clean
from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
@@ -50,8 +51,9 @@ class mail_message(osv.Model):
_description = 'Message'
_inherit = ['ir.needaction_mixin']
_order = 'id desc'
+ _rec_name = 'record_name'
- _message_read_limit = 10
+ _message_read_limit = 30
_message_read_fields = ['id', 'parent_id', 'model', 'res_id', 'body', 'subject', 'date', 'to_read', 'email_from',
'type', 'vote_user_ids', 'attachment_ids', 'author_id', 'partner_ids', 'record_name', 'favorite_user_ids']
_message_record_name_length = 18
@@ -120,21 +122,26 @@ class mail_message(osv.Model):
"message, comment for other messages such as user replies"),
'email_from': fields.char('From',
help="Email address of the sender. This field is set when no matching partner is found for incoming emails."),
- 'author_id': fields.many2one('res.partner', 'Author',
+ 'author_id': fields.many2one('res.partner', 'Author', select=1,
+ ondelete='set null',
help="Author of the message. If not set, email_from may hold an email address that did not match any partner."),
'partner_ids': fields.many2many('res.partner', string='Recipients'),
'notified_partner_ids': fields.many2many('res.partner', 'mail_notification',
- 'message_id', 'partner_id', 'Recipients'),
+ 'message_id', 'partner_id', 'Notified partners',
+ help='Partners that have a notification pushing this message in their mailboxes'),
'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel',
'message_id', 'attachment_id', 'Attachments'),
- 'parent_id': fields.many2one('mail.message', 'Parent Message', select=True, ondelete='set null', help="Initial thread message."),
+ 'parent_id': fields.many2one('mail.message', 'Parent Message', select=True,
+ ondelete='set null', help="Initial thread message."),
'child_ids': fields.one2many('mail.message', 'parent_id', 'Child Messages'),
'model': fields.char('Related Document Model', size=128, select=1),
'res_id': fields.integer('Related Document ID', select=1),
'record_name': fields.function(_get_record_name, type='char',
store=True, string='Message Record Name',
help="Name get of the related document."),
- 'notification_ids': fields.one2many('mail.notification', 'message_id', 'Notifications'),
+ 'notification_ids': fields.one2many('mail.notification', 'message_id',
+ string='Notifications',
+ help='Technical field holding the message notifications. Use notified_partner_ids to access notified partners.'),
'subject': fields.char('Subject'),
'date': fields.datetime('Date'),
'message_id': fields.char('Message-Id', help='Message unique identifier', select=1, readonly=1),
@@ -142,7 +149,8 @@ class mail_message(osv.Model):
'to_read': fields.function(_get_to_read, fnct_search=_search_to_read,
type='boolean', string='To read',
help='Functional field to search for messages the current user has to read'),
- 'subtype_id': fields.many2one('mail.message.subtype', 'Subtype'),
+ 'subtype_id': fields.many2one('mail.message.subtype', 'Subtype',
+ ondelete='set null', select=1,),
'vote_user_ids': fields.many2many('res.users', 'mail_vote',
'message_id', 'user_id', string='Votes',
help='Users that voted for this message'),
@@ -200,67 +208,99 @@ class mail_message(osv.Model):
# Message loading for web interface
#------------------------------------------------------
- def _message_get_dict(self, cr, uid, message, context=None):
- """ Return a dict representation of the message. This representation is
- used in the JS client code, to display the messages.
+ def _message_read_dict_postprocess(self, cr, uid, messages, message_tree, context=None):
+ """ Post-processing on values given by message_read. This method will
+ handle partners in batch to avoid doing numerous queries.
- :param dict message: read result of a mail.message
+ :param list messages: list of message, as get_dict result
+ :param dict message_tree: {[msg.id]: msg browse record}
"""
- # TDE note: this method should be optimized, to lessen the number of queries, will be done ASAP
- is_author = False
- if message['author_id']:
- is_author = message['author_id'][0] == self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=None)['partner_id'][0]
- author_id = message['author_id']
- elif message['email_from']:
- author_id = (0, message['email_from'])
-
- has_voted = False
- if uid in message.get('vote_user_ids'):
- has_voted = True
-
- is_favorite = False
- if uid in message.get('favorite_user_ids'):
- is_favorite = True
-
- is_private = True
- if message.get('model') and message.get('res_id'):
- is_private = False
-
- try:
- attachment_ids = [{'id': attach[0], 'name': attach[1]} for attach in self.pool.get('ir.attachment').name_get(cr, uid, message['attachment_ids'], context=context)]
- except (orm.except_orm, osv.except_osv):
+ res_partner_obj = self.pool.get('res.partner')
+ ir_attachment_obj = self.pool.get('ir.attachment')
+ pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=None)['partner_id'][0]
+
+ # 1. Aggregate partners (author_id and partner_ids) and attachments
+ partner_ids = set()
+ attachment_ids = set()
+ for key, message in message_tree.iteritems():
+ if message.author_id:
+ partner_ids |= set([message.author_id.id])
+ if message.partner_ids:
+ partner_ids |= set([partner.id for partner in message.partner_ids])
+ if message.attachment_ids:
+ attachment_ids |= set([attachment.id for attachment in message.attachment_ids])
+
+ # Filter author_ids uid can see
+ # partner_ids = self.pool.get('res.partner').search(cr, uid, [('id', 'in', partner_ids)], context=context)
+ partners = res_partner_obj.name_get(cr, uid, list(partner_ids), context=context)
+ partner_tree = dict((partner[0], partner) for partner in partners)
+
+ # 2. Attachments
+ attachments = ir_attachment_obj.read(cr, uid, list(attachment_ids), ['id', 'datas_fname'], context=context)
+ attachments_tree = dict((attachment['id'], {'id': attachment['id'], 'filename': attachment['datas_fname']}) for attachment in attachments)
+
+ # 3. Update message dictionaries
+ for message_dict in messages:
+ message_id = message_dict.get('id')
+ message = message_tree[message_id]
+ if message.author_id:
+ author = partner_tree[message.author_id.id]
+ else:
+ author = (0, message.email_from)
+ partner_ids = []
+ for partner in message.partner_ids:
+ if partner.id in partner_tree:
+ partner_ids.append(partner_tree[partner.id])
attachment_ids = []
+ for attachment in message.attachment_ids:
+ if attachment.id in attachments_tree:
+ attachment_ids.append(attachments_tree[attachment.id])
+ message_dict.update({
+ 'is_author': pid == author[0],
+ 'author_id': author,
+ 'partner_ids': partner_ids,
+ 'attachment_ids': attachment_ids,
+ })
+ return True
- # TDE note: should we send partner_ids ?
- # TDE note: shouldn't we separated followers and other partners ? costly to compute maybe ,
- try:
- partner_ids = self.pool.get('res.partner').name_get(cr, uid, message['partner_ids'], context=context)
- except (orm.except_orm, osv.except_osv):
- partner_ids = []
+ def _message_read_dict(self, cr, uid, message, parent_id=False, context=None):
+ """ Return a dict representation of the message. This representation is
+ used in the JS client code, to display the messages. Partners and
+ attachments related stuff will be done in post-processing in batch.
+
+ :param dict message: mail.message browse record
+ """
+ # private message: no model, no res_id
+ is_private = False
+ if not message.model or not message.res_id:
+ is_private = True
+ # votes and favorites: res.users ids, no prefetching should be done
+ vote_nb = len(message.vote_user_ids)
+ has_voted = uid in [user.id for user in message.vote_user_ids]
+ is_favorite = uid in [user.id for user in message.favorite_user_ids]
+
+ return {'id': message.id,
+ 'type': message.type,
+ 'body': html_email_clean(message.body),
+ 'model': message.model,
+ 'res_id': message.res_id,
+ 'record_name': message.record_name,
+ 'subject': message.subject,
+ 'date': message.date,
+ 'to_read': message.to_read,
+ 'parent_id': parent_id,
+ 'is_private': is_private,
+ 'author_id': False,
+ 'is_author': False,
+ 'partner_ids': [],
+ 'vote_nb': vote_nb,
+ 'has_voted': has_voted,
+ 'is_favorite': is_favorite,
+ 'attachment_ids': [],
+ }
- return {
- 'id': message['id'],
- 'type': message['type'],
- 'attachment_ids': attachment_ids,
- 'body': message['body'],
- 'model': message['model'],
- 'res_id': message['res_id'],
- 'record_name': message['record_name'],
- 'subject': message['subject'],
- 'date': message['date'],
- 'author_id': author_id,
- 'is_author': is_author,
- 'partner_ids': partner_ids,
- 'parent_id': False,
- 'vote_nb': len(message['vote_user_ids']),
- 'has_voted': has_voted,
- 'is_private': is_private,
- 'is_favorite': is_favorite,
- 'to_read': message['to_read'],
- }
-
- def _message_read_add_expandables(self, cr, uid, message_list, read_messages,
- thread_level=0, message_loaded_ids=[], domain=[], parent_id=False, context=None, limit=None):
+ def _message_read_add_expandables(self, cr, uid, messages, message_tree, parent_tree,
+ message_unload_ids=[], thread_level=0, domain=[], parent_id=False, context=None):
""" Create expandables for message_read, to load new messages.
1. get the expandable for new threads
if display is flat (thread_level == 0):
@@ -275,96 +315,82 @@ class mail_message(osv.Model):
for each hole in the child list based on message displayed,
create an expandable
- :param list message_list:list of message structure for the Chatter
+ :param list messages: list of message structure for the Chatter
widget to which expandables are added
- :param dict read_messages: dict [id]: read result of the messages to
- easily have access to their values, given their ID
+ :param dict message_tree: dict [id]: browse record of this message
+ :param dict parent_tree: dict [parent_id]: [child_ids]
+ :param list message_unload_ids: list of message_ids we do not want
+ to load
:return bool: True
"""
- def _get_expandable(domain, message_nb, parent_id, id, model):
+ def _get_expandable(domain, message_nb, parent_id, max_limit):
return {
'domain': domain,
'nb_messages': message_nb,
'type': 'expandable',
'parent_id': parent_id,
- 'id': id,
- # TDE note: why do we need model sometimes, and sometimes not ???
- 'model': model,
+ 'max_limit': max_limit,
}
- # all_not_loaded_ids = []
- id_list = sorted(read_messages.keys())
- if not id_list:
- return message_list
+ if not messages:
+ return True
+ message_ids = sorted(message_tree.keys())
# 1. get the expandable for new threads
if thread_level == 0:
- exp_domain = domain + [('id', '<', min(message_loaded_ids + id_list))]
+ exp_domain = domain + [('id', '<', min(message_unload_ids + message_ids))]
else:
- exp_domain = domain + ['!', ('id', 'child_of', message_loaded_ids + id_list)]
+ exp_domain = domain + ['!', ('id', 'child_of', message_unload_ids + parent_tree.keys())]
ids = self.search(cr, uid, exp_domain, context=context, limit=1)
if ids:
- message_list.append(_get_expandable(exp_domain, -1, parent_id, -1, None))
+ # inside a thread: prepend
+ if parent_id:
+ messages.insert(0, _get_expandable(exp_domain, -1, parent_id, True))
+ # new threads: append
+ else:
+ messages.append(_get_expandable(exp_domain, -1, parent_id, True))
# 2. get the expandables for new messages inside threads if display is not flat
if thread_level == 0:
return True
- for message_id in id_list:
- message = read_messages[message_id]
+ for message_id in message_ids:
+ message = message_tree[message_id]
- # message is not a thread header (has a parent_id)
- # TDE note: parent_id is false is there is a parent we can not see -> ok
- if message.get('parent_id'):
+ # generate only for thread header messages (TDE note: parent_id may be False is uid cannot see parent_id, seems ok)
+ if message.parent_id:
continue
- # TDE note: check search is correctly implemented in mail.message
- not_loaded_ids = self.search(cr, uid, [
- ('id', 'child_of', message['id']),
- ('id', 'not in', message_loaded_ids),
- ], context=context, limit=self._message_read_more_limit)
- if not not_loaded_ids:
+ # check there are message for expandable
+ child_ids = set([child.id for child in message.child_ids]) - set(message_unload_ids)
+ child_ids = sorted(list(child_ids), reverse=True)
+ if not child_ids:
continue
- # all_not_loaded_ids += not_loaded_ids
- # group childs not read
- id_min, id_max, nb = max(not_loaded_ids), 0, 0
- for not_loaded_id in not_loaded_ids:
- if not read_messages.get(not_loaded_id):
+ # make groups of unread messages
+ id_min, id_max, nb = max(child_ids), 0, 0
+ for child_id in child_ids:
+ if not child_id in message_ids:
nb += 1
- if id_min > not_loaded_id:
- id_min = not_loaded_id
- if id_max < not_loaded_id:
- id_max = not_loaded_id
+ if id_min > child_id:
+ id_min = child_id
+ if id_max < child_id:
+ id_max = child_id
elif nb > 0:
exp_domain = [('id', '>=', id_min), ('id', '<=', id_max), ('id', 'child_of', message_id)]
- message_list.append(_get_expandable(exp_domain, nb, message_id, id_min, message.get('model')))
- id_min, id_max, nb = max(not_loaded_ids), 0, 0
+ messages.append(_get_expandable(exp_domain, nb, message_id, False))
+ id_min, id_max, nb = max(child_ids), 0, 0
else:
- id_min, id_max, nb = max(not_loaded_ids), 0, 0
+ id_min, id_max, nb = max(child_ids), 0, 0
if nb > 0:
exp_domain = [('id', '>=', id_min), ('id', '<=', id_max), ('id', 'child_of', message_id)]
- message_list.append(_get_expandable(exp_domain, nb, message_id, id_min, message.get('model')))
-
- # message_loaded_ids = list(set(message_loaded_ids + read_messages.keys() + all_not_loaded_ids))
+ idx = [msg.get('id') for msg in messages].index(message_id) + 1
+ # messages.append(_get_expandable(exp_domain, nb, message_id, id_min))
+ messages.insert(idx, _get_expandable(exp_domain, nb, message_id, False))
return True
- def _get_parent(self, cr, uid, message, context=None):
- """ Tools method that tries to get the parent of a mail.message. If
- no parent, or if uid has no access right on the parent, False
- is returned.
-
- :param dict message: read result of a mail.message
- """
- if not message['parent_id']:
- return False
- parent_id = message['parent_id'][0]
- try:
- return self.read(cr, uid, parent_id, self._message_read_fields, context=context)
- except (orm.except_orm, osv.except_osv):
- return False
-
- def message_read(self, cr, uid, ids=None, domain=None, message_unload_ids=None, thread_level=0, context=None, parent_id=False, limit=None):
+ def message_read(self, cr, uid, ids=None, domain=None, message_unload_ids=None,
+ thread_level=0, context=None, parent_id=False, limit=None):
""" Read messages from mail.message, and get back a list of structured
messages to be displayed as discussion threads. If IDs is set,
fetch these records. Otherwise use the domain to fetch messages.
@@ -388,46 +414,56 @@ class mail_message(osv.Model):
ancestors and expandables
:return list: list of message structure for the Chatter widget
"""
- # print 'message_read', ids, domain, message_unload_ids, thread_level, context, parent_id, limit
assert thread_level in [0, 1], 'message_read() thread_level should be 0 (flat) or 1 (1 level of thread); given %s.' % thread_level
domain = domain if domain is not None else []
message_unload_ids = message_unload_ids if message_unload_ids is not None else []
if message_unload_ids:
domain += [('id', 'not in', message_unload_ids)]
limit = limit or self._message_read_limit
- read_messages = {}
+ message_tree = {}
message_list = []
+ parent_tree = {}
# no specific IDS given: fetch messages according to the domain, add their parents if uid has access to
if ids is None:
ids = self.search(cr, uid, domain, context=context, limit=limit)
- for message in self.read(cr, uid, ids, self._message_read_fields, context=context):
- message_id = message['id']
-
- # if not in tree and not in message_loaded list
- if not message_id in read_messages and not message_id in message_unload_ids:
- read_messages[message_id] = message
- message_list.append(self._message_get_dict(cr, uid, message, context=context))
-
- # get the older ancestor the user can read, update its ancestor field
- if not thread_level:
- message_list[-1]['parent_id'] = parent_id
- continue
- parent = self._get_parent(cr, uid, message, context=context)
- while parent and parent.get('id') != parent_id:
- message_list[-1]['parent_id'] = parent.get('id')
- message = parent
- parent = self._get_parent(cr, uid, message, context=context)
- # if in thread: add its ancestor to the list of messages
- if not message['id'] in read_messages and not message['id'] in message_unload_ids:
- read_messages[message['id']] = message
- message_list.append(self._message_get_dict(cr, uid, message, context=context))
- # get the child expandable messages for the tree
- message_list = sorted(message_list, key=lambda k: k['id'])
- self._message_read_add_expandables(cr, uid, message_list, read_messages, thread_level=thread_level,
- message_loaded_ids=message_unload_ids, domain=domain, parent_id=parent_id, context=context, limit=limit)
+ # fetch parent if threaded, sort messages
+ for message in self.browse(cr, uid, ids, context=context):
+ message_id = message.id
+ if message_id in message_tree:
+ continue
+ message_tree[message_id] = message
+ # find parent_id
+ if thread_level == 0:
+ tree_parent_id = parent_id
+ else:
+ tree_parent_id = message_id
+ parent = message
+ while parent.parent_id and parent.parent_id.id != parent_id:
+ parent = parent.parent_id
+ tree_parent_id = parent.id
+ if not parent.id in message_tree:
+ message_tree[parent.id] = parent
+ # newest messages first
+ parent_tree.setdefault(tree_parent_id, [])
+ if tree_parent_id != message_id:
+ parent_tree[tree_parent_id].append(self._message_read_dict(cr, uid, message_tree[message_id], parent_id=tree_parent_id, context=context))
+
+ if thread_level:
+ for key, message_id_list in parent_tree.iteritems():
+ message_id_list.sort(key=lambda item: item['id'])
+ message_id_list.insert(0, self._message_read_dict(cr, uid, message_tree[key], context=context))
+
+ parent_list = parent_tree.items()
+ parent_list = sorted(parent_list, key=lambda item: max([msg.get('id') for msg in item[1]]) if item[1] else item[0], reverse=True)
+ message_list = [message for (key, msg_list) in parent_list for message in msg_list]
+
+ # get the child expandable messages for the tree
+ self._message_read_dict_postprocess(cr, uid, message_list, message_tree, context=context)
+ self._message_read_add_expandables(cr, uid, message_list, message_tree, parent_tree,
+ thread_level=thread_level, message_unload_ids=message_unload_ids, domain=domain, parent_id=parent_id, context=context)
return message_list
# TDE Note: do we need this ?
@@ -461,7 +497,6 @@ class mail_message(osv.Model):
- otherwise: remove the id
"""
# Rules do not apply to administrator
- # print '_search', uid, args
if uid == SUPERUSER_ID:
return super(mail_message, self)._search(cr, uid, args, offset=offset, limit=limit, order=order,
context=context, count=count, access_rights_uid=access_rights_uid)
@@ -599,6 +634,8 @@ class mail_message(osv.Model):
def create(self, cr, uid, values, context=None):
if not values.get('message_id') and values.get('res_id') and values.get('model'):
values['message_id'] = tools.generate_tracking_message_id('%(res_id)s-%(model)s' % values)
+ elif not values.get('message_id'):
+ values['message_id'] = tools.generate_tracking_message_id('private')
newid = super(mail_message, self).create(cr, uid, values, context)
self._notify(cr, SUPERUSER_ID, newid, context=context)
return newid
@@ -729,7 +766,7 @@ class mail_message(osv.Model):
], context=context)
fol_objs = fol_obj.read(cr, uid, fol_ids, ['partner_id'], context=context)
partners_to_notify |= set(fol['partner_id'][0] for fol in fol_objs)
- # when writing to a wall
+ # remove me from notified partners, unless the message is written on my own wall
if message.get('author_id') and message.get('model') == "res.partner" and message.get('res_id') == message.get('author_id')[0]:
partners_to_notify |= set([message.get('author_id')[0]])
elif message.get('author_id'):
diff --git a/addons/mail/mail_message_view.xml b/addons/mail/mail_message_view.xml
index 93b35797fd5..7d2e9483773 100644
--- a/addons/mail/mail_message_view.xml
+++ b/addons/mail/mail_message_view.xml
@@ -59,21 +59,26 @@
<field name="type"/>
<field name="author_id"/>
<field name="partner_ids"/>
+ <filter string="Read"
+ name="message_read" help="Show messages to read"
+ domain="[('to_read', '=', False)]"/>
<filter string="Unread"
name="message_unread" help="Show messages to read"
domain="[('to_read', '=', True)]"/>
+ <separator/>
<filter string="Comments"
name="comments" help="Comments"
domain="[('type', '=', 'comment')]"/>
- <filter string="Has attachments"
- name="attachments"
- domain="[('attachment_ids', '!=', False)]"/>
<filter string="Notifications"
name="notifications" help="Notifications"
domain="[('type', '=', 'notification')]"/>
<filter string="Emails"
name="emails" help="Emails"
domain="[('type', '=', 'email')]"/>
+ <separator/>
+ <filter string="Has attachments"
+ name="attachments"
+ domain="[('attachment_ids', '!=', False)]"/>
</search>
</field>
</record>
@@ -84,7 +89,6 @@
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="view_message_search"/>
- <field name="context">{'search_default_to_read_message':True}</field>
</record>
<!-- Add menu entry in Settings/Email -->
diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py
index f3203336615..ee1a015396b 100644
--- a/addons/mail/mail_thread.py
+++ b/addons/mail/mail_thread.py
@@ -74,17 +74,17 @@ class mail_thread(osv.AbstractModel):
- message_unread: has uid unread message for the document
- message_summary: html snippet summarizing the Chatter for kanban views """
res = dict((id, dict(message_unread=False, message_summary='')) for id in ids)
+ user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
- # search for unread messages, by reading directly mail.notification, as SUPERUSER
- notif_obj = self.pool.get('mail.notification')
- notif_ids = notif_obj.search(cr, SUPERUSER_ID, [
- ('partner_id.user_ids', 'in', [uid]),
- ('message_id.res_id', 'in', ids),
- ('message_id.model', '=', self._name),
- ('read', '=', False)
- ], context=context)
- for notif in notif_obj.browse(cr, SUPERUSER_ID, notif_ids, context=context):
- res[notif.message_id.res_id]['message_unread'] = True
+ # search for unread messages, directly in SQL to improve performances
+ cr.execute(""" SELECT m.res_id FROM mail_message m
+ RIGHT JOIN mail_notification n
+ ON (n.message_id = m.id AND n.partner_id = %s AND n.read = False)
+ WHERE m.model = %s AND m.res_id in %s""",
+ (user_pid, self._name, tuple(ids),))
+ msg_ids = [result[0] for result in cr.fetchall()]
+ for msg_id in msg_ids:
+ res[msg_id]['message_unread'] = True
for thread in self.browse(cr, uid, ids, context=context):
cls = res[thread.id]['message_unread'] and ' class="oe_kanban_mail_new"' or ''
@@ -319,10 +319,12 @@ class mail_thread(osv.AbstractModel):
"""
assert isinstance(message, Message), 'message must be an email.message.Message at this point'
message_id = message.get('Message-Id')
+ references = decode_header(message, 'References')
+ in_reply_to = decode_header(message, 'In-Reply-To')
# 1. Verify if this is a reply to an existing thread
- references = decode_header(message, 'References') or decode_header(message, 'In-Reply-To')
- ref_match = references and tools.reference_re.search(references)
+ thread_references = references or in_reply_to
+ ref_match = thread_references and tools.reference_re.search(thread_references)
if ref_match:
thread_id = int(ref_match.group(1))
model = ref_match.group(2) or model
@@ -333,6 +335,14 @@ class mail_thread(osv.AbstractModel):
message_id, model, thread_id, custom_values, uid)
return [(model, thread_id, custom_values, uid)]
+ # Verify this is a reply to a private message
+ message_ids = self.pool.get('mail.message').search(cr, uid, [('message_id', '=', in_reply_to)], limit=1, context=context)
+ if message_ids:
+ message = self.pool.get('mail.message').browse(cr, uid, message_ids[0], context=context)
+ _logger.debug('Routing mail with Message-Id %s: direct reply to a private message: %s, custom_values: %s, uid: %s',
+ message_id, message.id, custom_values, uid)
+ return [(False, 0, custom_values, uid)]
+
# 2. Look for a matching mail.alias entry
# Delivered-To is a safe bet in most modern MTAs, but we have to fallback on To + Cc values
# for all the odd MTAs out there, as there is no standard header for the envelope's `rcpt_to` value.
@@ -376,14 +386,19 @@ class mail_thread(osv.AbstractModel):
def message_process(self, cr, uid, model, message, custom_values=None,
save_original=False, strip_attachments=False,
thread_id=None, context=None):
- """Process an incoming RFC2822 email message, relying on
- ``mail.message.parse()`` for the parsing operation,
- and ``message_route()`` to figure out the target model.
+ """ Process an incoming RFC2822 email message, relying on
+ ``mail.message.parse()`` for the parsing operation,
+ and ``message_route()`` to figure out the target model.
- Once the target model is known, its ``message_new`` method
- is called with the new message (if the thread record did not exist)
+ Once the target model is known, its ``message_new`` method
+ is called with the new message (if the thread record did not exist)
or its ``message_update`` method (if it did).
+ There is a special case where the target model is False: a reply
+ to a private message. In this case, we skip the message_new /
+ message_update step, to just post a new message using mail_thread
+ message_post.
+
:param string model: the fallback model to use if the message
does not match any of the currently configured mail aliases
(may be None if a matching alias is supposed to be present)
@@ -425,15 +440,19 @@ class mail_thread(osv.AbstractModel):
for model, thread_id, custom_values, user_id in routes:
if self._name != model:
context.update({'thread_model': model})
- model_pool = self.pool.get(model)
- assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \
- "Undeliverable mail with Message-Id %s, model %s does not accept incoming emails" % \
- (msg['message_id'], model)
- if thread_id and hasattr(model_pool, 'message_update'):
- model_pool.message_update(cr, user_id, [thread_id], msg, context=context)
+ if model:
+ model_pool = self.pool.get(model)
+ assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \
+ "Undeliverable mail with Message-Id %s, model %s does not accept incoming emails" % \
+ (msg['message_id'], model)
+ if thread_id and hasattr(model_pool, 'message_update'):
+ model_pool.message_update(cr, user_id, [thread_id], msg, context=context)
+ else:
+ thread_id = model_pool.message_new(cr, user_id, msg, custom_values, context=context)
else:
- thread_id = model_pool.message_new(cr, user_id, msg, custom_values, context=context)
- model_pool.message_post(cr, uid, [thread_id], context=context, **msg)
+ assert thread_id == 0, "Posting a message without model should be with a null res_id, to create a private message."
+ model_pool = self.pool.get('mail.thread')
+ model_pool.message_post_user_api(cr, uid, [thread_id], context=context, content_subtype='html', **msg)
return thread_id
def message_new(self, cr, uid, msg_dict, custom_values=None, context=None):
@@ -501,7 +520,7 @@ class mail_thread(osv.AbstractModel):
body = tools.ustr(body, encoding, errors='replace')
if message.get_content_type() == 'text/plain':
# text/plain -> <pre/>
- body = tools.append_content_to_html(u'', body)
+ body = tools.append_content_to_html(u'', body, preserve=True)
else:
alternative = (message.get_content_type() == 'multipart/alternative')
for part in message.walk():
@@ -516,7 +535,7 @@ class mail_thread(osv.AbstractModel):
# 2) text/plain -> <pre/>
if part.get_content_type() == 'text/plain' and (not alternative or not body):
body = tools.append_content_to_html(body, tools.ustr(part.get_payload(decode=True),
- encoding, errors='replace'))
+ encoding, errors='replace'), preserve=True)
# 3) text/html -> raw
elif part.get_content_type() == 'text/html':
html = tools.ustr(part.get_payload(decode=True), encoding, errors='replace')
@@ -556,7 +575,6 @@ class mail_thread(osv.AbstractModel):
"""
msg_dict = {
'type': 'email',
- 'subtype': 'mail.mt_comment',
'author_id': False,
}
if not isinstance(message, Message):
@@ -588,7 +606,7 @@ class mail_thread(osv.AbstractModel):
else:
msg_dict['email_from'] = message.get('from')
partner_ids = self._message_find_partners(cr, uid, message, ['From', 'To', 'Cc'], context=context)
- msg_dict['partner_ids'] = partner_ids
+ msg_dict['partner_ids'] = [(4, partner_id) for partner_id in partner_ids]
if 'Date' in message:
date_hdr = decode(message.get('Date'))
@@ -629,7 +647,8 @@ class mail_thread(osv.AbstractModel):
mail.message ID. Extra keyword arguments will be used as default
column values for the new mail.message record.
Auto link messages for same id and object
- :param int thread_id: thread ID to post into, or list with one ID
+ :param int thread_id: thread ID to post into, or list with one ID;
+ if False/0, mail.message model will also be set as False
:param str body: body of the message, usually raw HTML that will
be sanitized
:param str subject: optional subject
@@ -639,10 +658,13 @@ class mail_thread(osv.AbstractModel):
``(name,content)``, where content is NOT base64 encoded
:return: ID of newly created mail.message
"""
- context = context or {}
- attachments = attachments or []
+ if context is None:
+ context = {}
+ if attachments is None:
+ attachments = {}
+
assert (not thread_id) or isinstance(thread_id, (int, long)) or \
- (isinstance(thread_id, (list, tuple)) and len(thread_id) == 1), "Invalid thread_id"
+ (isinstance(thread_id, (list, tuple)) and len(thread_id) == 1), "Invalid thread_id; should be 0, False, an ID or a list with one ID"
if isinstance(thread_id, (list, tuple)):
thread_id = thread_id and thread_id[0]
mail_message = self.pool.get('mail.message')
@@ -682,7 +704,6 @@ class mail_thread(osv.AbstractModel):
# avoid loops when finding ancestors
processed_list = []
if message_ids:
- _counter, _counter_max = 0, 200
message = mail_message.browse(cr, SUPERUSER_ID, message_ids[0], context=context)
while (message.parent_id and message.parent_id.id not in processed_list):
processed_list.append(message.parent_id.id)
@@ -707,18 +728,45 @@ class mail_thread(osv.AbstractModel):
return mail_message.create(cr, uid, values, context=context)
- def message_post_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False, attachment_ids=None, context=None):
- """ Wrapper on message_post, used only in Chatter (JS). The purpose is
- to handle attachments.
- # TDE FIXME: body is plaintext: convert it into html
+ def message_post_user_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False,
+ attachment_ids=None, context=None, content_subtype='plaintext', **kwargs):
+ """ Wrapper on message_post, used for user input :
+ - mail gateway
+ - quick reply in Chatter (refer to mail.js), not
+ the mail.compose.message wizard
+ The purpose is to perform some pre- and post-processing:
+ - if body is plaintext: convert it into html
+ - if parent_id: handle reply to a previous message by adding the
+ parent partners to the message
+ - type and subtype: comment and mail.mt_comment by default
+ - attachment_ids: supposed not attached to any document; attach them
+ to the related document. Should only be set by Chatter.
"""
- new_message_id = self.message_post(cr, uid, thread_id=thread_id, body=body, subject=subject, type='comment',
- subtype='mail.mt_comment', parent_id=parent_id, context=context)
+ ir_attachment = self.pool.get('ir.attachment')
+ mail_message = self.pool.get('mail.message')
+
+ # 1. Pre-processing: body, partner_ids, type and subtype
+ if content_subtype == 'plaintext':
+ body = tools.plaintext2html(body)
+
+ partner_ids = kwargs.pop('partner_ids', [])
+ if parent_id:
+ parent_message = self.pool.get('mail.message').browse(cr, uid, parent_id, context=context)
+ partner_ids += [(4, partner.id) for partner in parent_message.partner_ids]
+ # TDE FIXME HACK: mail.thread -> private message
+ if self._name == 'mail.thread' and parent_message.author_id.id:
+ partner_ids.append((4, parent_message.author_id.id))
+
+ message_type = kwargs.pop('type', 'comment')
+ message_subtype = kwargs.pop('subtype', 'mail.mt_comment')
+
+ # 2. Post message
+ new_message_id = self.message_post(cr, uid, thread_id=thread_id, body=body, subject=subject, type=message_type,
+ subtype=message_subtype, parent_id=parent_id, context=context, partner_ids=partner_ids, **kwargs)
- # HACK FIXME: Chatter: attachments linked to the document (not done JS-side), load the message
+ # 3. Post-processing
+ # HACK TDE FIXME: Chatter: attachments linked to the document (not done JS-side), load the message
if attachment_ids:
- ir_attachment = self.pool.get('ir.attachment')
- mail_message = self.pool.get('mail.message')
filtered_attachment_ids = ir_attachment.search(cr, SUPERUSER_ID, [
('res_model', '=', 'mail.compose.message'),
('res_id', '=', 0),
diff --git a/addons/mail/mail_thread_view.xml b/addons/mail/mail_thread_view.xml
index 07b24725b05..3a37218c813 100644
--- a/addons/mail/mail_thread_view.xml
+++ b/addons/mail/mail_thread_view.xml
@@ -4,48 +4,126 @@
<record id="action_mail_inbox_feeds" model="ir.actions.client">
<field name="name">Inbox</field>
<field name="tag">mail.wall</field>
- <field name="params" eval="&quot;{'domain': [('notification_ids.partner_id.user_ids', 'in', [uid]), ('to_read', '=', True)],
- 'context': {'default_model': 'res.users', 'default_res_id': uid, 'typeof_thread': 'inbox'} }&quot;"/>
+ <field name="res_model">mail.message</field>
+ <field name="context">{
+ 'default_model': 'res.users',
+ 'default_res_id': uid,
+ }</field>
+ <field name="params" eval="&quot;{
+ 'domain': [
+ ('notification_ids.partner_id.user_ids', 'in', [uid]),
+ ('to_read', '=', True),
+ ('favorite_user_ids', 'not in', [uid])
+ ],
+ 'view_mailbox': True,
+ 'view_inbox': True,
+ 'read_action': 'read'
+ }&quot;"/>
+ <field name="help" type="html">
+ <p>
+ <b>Good Job!</b> Your inbox is empty.
+ </p><p>
+ Your inbox contains private messages or emails sent to you
+ as well as information related to documents or people you
+ follow.
+ </p>
+ </field>
</record>
<record id="action_mail_to_me_feeds" model="ir.actions.client">
<field name="name">To: me</field>
<field name="tag">mail.wall</field>
- <field name="params" eval="&quot;{'domain': [('partner_ids.user_ids', 'in', [uid]), ('to_read', '=', True), ('author_id.user_ids', 'in', [uid])],
- 'context': {'default_model': 'res.users', 'default_res_id': uid, 'typeof_thread': 'inbox'} }&quot;"/>
+ <field name="res_model">mail.message</field>
+ <field name="context">{
+ 'default_model': 'res.users',
+ 'default_res_id': uid,
+ 'search_default_message_unread': True
+ }</field>
+ <field name="params" eval="&quot;{
+ 'domain': [('partner_ids.user_ids', 'in', [uid])],
+ 'view_mailbox': True,
+ 'read_action': 'read', }&quot;"/>
+ <field name="help" type="html">
+ <p>
+ <b>No private message.</b>
+ </p><p>
+ This list contains messages sent to you.
+ </p>
+ </field>
</record>
<record id="action_mail_star_feeds" model="ir.actions.client">
- <field name="name">Favorites</field>
+ <field name="name">Todo</field>
<field name="tag">mail.wall</field>
- <field name="params" eval="&quot;{'domain': [('favorite_user_ids.user_ids', 'in', [uid])],
- 'context': {'default_model': 'res.users', 'default_res_id': uid, 'typeof_thread': 'stared'} }&quot;"/>
+ <field name="res_model">mail.message</field>
+ <field name="context">{
+ 'default_model': 'res.users',
+ 'default_res_id': uid,
+ 'search_default_message_unread': True
+ }</field>
+ <field name="params" eval="&quot;{
+ 'domain': [('favorite_user_ids', 'in', [uid])],
+ 'view_mailbox': True,
+ 'read_action': 'read', }&quot;"/>
+ <field name="help" type="html">
+ <p>
+ <b>No todo!</b>
+ </p><p>
+ When you process messages in your inbox, you can mark some
+ as <i>todo</i>. From this menu, you can process all your todo.
+ </p>
+ </field>
</record>
<record id="action_mail_archives_feeds" model="ir.actions.client">
<field name="name">Archives</field>
<field name="tag">mail.wall</field>
- <field name="params" eval="&quot;{'domain': [('notification_ids.partner_id.user_ids', 'in', [uid]), ('to_read', '=', False)],
- 'context': {'default_model': 'res.users', 'default_res_id': uid, 'typeof_thread': 'archives'} }&quot;"/>
+ <field name="context">{
+ 'default_model': 'res.users',
+ 'default_res_id': uid,
+ 'search_default_message_read': True
+ }</field>
+ <field name="params" eval="&quot;{
+ 'domain': [('notification_ids.partner_id.user_ids', 'in', [uid])],
+ 'view_mailbox': True,
+ 'read_action': 'unread', }&quot;"/>
+ <field name="help" type="html">
+ <p>
+ No message found.
+ </p>
+ </field>
</record>
<record id="action_mail_sent_feeds" model="ir.actions.client">
<field name="name">Sent</field>
<field name="tag">mail.wall</field>
- <field name="params" eval="&quot;{'domain': [('author_id.user_ids', 'in', [uid])],
- 'context': {'default_model': 'res.users', 'default_res_id': uid, 'typeof_thread': 'send'} }&quot;"/>
+ <field name="context">{
+ 'default_model': 'res.users',
+ 'default_res_id': uid
+ }</field>
+ <field name="params" eval="&quot;{
+ 'domain': [('author_id.user_ids', 'in', [uid])],
+ 'view_mailbox': True, }&quot;"/>
+ <field name="help" type="html">
+ <p>
+ <b>No message sent yet.</b>
+ </p><p>
+ Click on the top-right icon to compose a message. This
+ message will be sent by email if it's an internal contact.
+ </p>
+ </field>
</record>
<!-- MENU -->
<!-- Top menu item -->
- <menuitem name="Emails"
+ <menuitem name="Messaging"
id="mail.mail_feeds_main"
groups="base.group_user"
sequence="10"/>
<!-- Left-side menu: Feeds -->
- <menuitem id="mail.mail_feeds" name="Messages" parent="mail.mail_feeds_main" groups="base.group_user" sequence="10"/>
+ <menuitem id="mail.mail_feeds" name="Messaging" parent="mail.mail_feeds_main" groups="base.group_user" sequence="10"/>
<menuitem id="mail_my_stuff" name="Organizer" parent="mail.mail_feeds_main"/>
<record id="mail_inboxfeeds" model="ir.ui.menu">
@@ -61,7 +139,7 @@
<field name="parent_id" ref="mail.mail_feeds"/>
</record>
<record id="mail_starfeeds" model="ir.ui.menu">
- <field name="name">Favorites</field>
+ <field name="name">Todo</field>
<field name="sequence" eval="14"/>
<field name="action" ref="action_mail_star_feeds"/>
<field name="parent_id" ref="mail.mail_feeds"/>
diff --git a/addons/mail/res_partner.py b/addons/mail/res_partner.py
index 6b13fe6ad20..060adc291de 100644
--- a/addons/mail/res_partner.py
+++ b/addons/mail/res_partner.py
@@ -42,4 +42,23 @@ class res_partner_mail(osv.Model):
'notification_email_send': lambda *args: 'comment'
}
+ def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification',
+ subtype=None, parent_id=False, attachments=None, context=None, **kwargs):
+ """ Override related to res.partner. In case of email message, set it as
+ private:
+ - add the target partner in the message partner_ids
+ - set thread_id as None, because this will trigger the 'private'
+ aspect of the message (model=False, res_id=False)
+ """
+ if isinstance(thread_id, (list, tuple)):
+ thread_id = thread_id[0]
+ if type == 'email':
+ partner_ids = kwargs.get('partner_ids', [])
+ if thread_id not in partner_ids:
+ partner_ids.append((4, thread_id))
+ kwargs['partner_ids'] = partner_ids
+ thread_id = False
+ return super(res_partner_mail, self).message_post(cr, uid, thread_id, body=body, subject=subject,
+ type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, **kwargs)
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/mail/res_users.py b/addons/mail/res_users.py
index 1b6388111ba..20c0715c148 100644
--- a/addons/mail/res_users.py
+++ b/addons/mail/res_users.py
@@ -91,8 +91,10 @@ class res_users(osv.Model):
return user_id
def _create_welcome_message(self, cr, uid, user, context=None):
- company_name = user.company_id.name if user.company_id else _('the company')
- body = _('%s has joined %s.') % (user.name, company_name)
+ if not self.has_group(cr, uid, 'base.group_user'):
+ return False
+ company_name = user.company_id.name if user.company_id else ''
+ body = _('%s has joined the %s network.') % (user.name, company_name)
# TODO change SUPERUSER_ID into user.id but catch errors
return self.pool.get('res.partner').message_post(cr, SUPERUSER_ID, [user.partner_id.id],
body=body, context=context)
@@ -111,7 +113,8 @@ class res_users(osv.Model):
alias_pool.unlink(cr, uid, alias_ids, context=context)
return res
- def message_post_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False, attachment_ids=None, context=None):
+ def message_post_user_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False,
+ attachment_ids=None, context=None, content_subtype='plaintext', **kwargs):
""" Redirect the posting of message on res.users to the related partner.
This is done because when giving the context of Chatter on the
various mailboxes, we do not have access to the current partner_id.
@@ -122,8 +125,8 @@ class res_users(osv.Model):
if isinstance(thread_id, (list, tuple)):
thread_id = thread_id[0]
partner_id = self.pool.get('res.users').read(cr, uid, thread_id, ['partner_id'], context=context)['partner_id'][0]
- return self.pool.get('res.partner').message_post_api(cr, uid, partner_id, body=body, subject=subject,
- parent_id=parent_id, attachment_ids=attachment_ids, context=context)
+ return self.pool.get('res.partner').message_post_user_api(cr, uid, partner_id, body=body, subject=subject,
+ parent_id=parent_id, attachment_ids=attachment_ids, context=context, content_subtype=content_subtype, **kwargs)
def message_post(self, cr, uid, thread_id, context=None, **kwargs):
""" Redirect the posting of message on res.users to the related partner.
@@ -143,6 +146,7 @@ class res_users(osv.Model):
return self.pool.get('res.partner').message_update(cr, uid, [partner_id], msg_dict,
update_vals=update_vals, context=context)
+
class res_users_mail_group(osv.Model):
""" Update of res.users class
- if adding groups to an user, check mail.groups linked to this user
diff --git a/addons/mail/security/ir.model.access.csv b/addons/mail/security/ir.model.access.csv
index 4d68b7e3aef..37c6952717c 100644
--- a/addons/mail/security/ir.model.access.csv
+++ b/addons/mail/security/ir.model.access.csv
@@ -7,12 +7,15 @@ access_mail_mail_system,mail.mail.system,model_mail_mail,base.group_system,1,1,1
access_mail_followers_all,mail.followers.all,model_mail_followers,,1,0,0,0
access_mail_followers_system,mail.followers.system,model_mail_followers,base.group_system,1,1,1,1
access_mail_notification_all,mail.notification.all,model_mail_notification,,1,0,0,0
-access_mail_notification_aystem,mail.notification.system,model_mail_notification,base.group_system,1,1,1,1
+access_mail_notification_group_user,mail.notification.user,model_mail_notification,base.group_user,1,1,1,0
+access_mail_notification_system,mail.notification.system,model_mail_notification,base.group_system,1,1,1,1
access_mail_group_all,mail.group.all,model_mail_group,,1,0,0,0
access_mail_group_user,mail.group.user,model_mail_group,base.group_user,1,1,1,1
access_mail_alias_all,mail.alias.all,model_mail_alias,,1,0,0,0
-access_mail_alias_user,mail.alias,model_mail_alias,base.group_user,1,1,1,0
-access_mail_alias_system,mail.alias,model_mail_alias,base.group_system,1,1,1,1
+access_mail_alias_user,mail.alias.user,model_mail_alias,base.group_user,1,1,1,0
+access_mail_alias_system,mail.alias.system,model_mail_alias,base.group_system,1,1,1,1
access_mail_message_subtype_all,mail.message.subtype.all,model_mail_message_subtype,,1,0,0,0
access_mail_vote_all,mail.vote.all,model_mail_vote,,1,1,1,1
access_mail_favorite_all,mail.favorite.all,model_mail_favorite,,1,1,1,1
+access_mail_thread_all,mail.thread.all,model_mail_thread,,1,1,1,1
+access_publisher_warranty_contract_all,publisher.warranty.contract.all,model_publisher_warranty_contract,,1,1,1,1
diff --git a/addons/mail/security/mail_security.xml b/addons/mail/security/mail_security.xml
index 3f2b7bf3e9a..525425c2aa0 100644
--- a/addons/mail/security/mail_security.xml
+++ b/addons/mail/security/mail_security.xml
@@ -10,7 +10,7 @@
<field name="domain_force">['|', '|', ('public', '=', 'public'), ('message_follower_ids', 'in', [user.partner_id.id]), '&amp;', ('public','=','groups'), ('group_public_id','in', [g.id for g in user.groups_id])]</field>
</record>
- <record id="mail_followers_read_own" model="ir.rule">
+ <record id="mail_followers_read_write_own" model="ir.rule">
<field name="name">mail.followers: read and write its own entries</field>
<field name="model_id" ref="model_mail_followers"/>
<field name="domain_force">[('partner_id', '=', user.partner_id.id)]</field>
@@ -18,6 +18,14 @@
<field name="perm_unlink" eval="False"/>
</record>
+ <record id="mail_notification_read_write_own" model="ir.rule">
+ <field name="name">mail.notification: read and write its own entries</field>
+ <field name="model_id" ref="model_mail_notification"/>
+ <field name="domain_force">[('partner_id', '=', user.partner_id.id)]</field>
+ <field name="perm_create" eval="False"/>
+ <field name="perm_unlink" eval="False"/>
+ </record>
+
<!--
This rule can not be uncommented, because we have a more wide method in mail.message. When we implement a many2one_variable field, we will be able to uncomment this.
<record id="mail_message_read_partner_or_author" model="ir.rule">
diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css
index af3cc3ed359..b0ce6d499b5 100644
--- a/addons/mail/static/src/css/mail.css
+++ b/addons/mail/static/src/css/mail.css
@@ -1,7 +1,36 @@
+/* ------------ TOPBAR MAIL BUTTON --------------- */
+
+/* FIXME this css is not very pretty because it uses a
+ * 'button' element wich comes with a lot of inappropriate
+ * styling. Entypo is also a headache to center properly
+ * */
+
+.openerp .oe_topbar_item.oe_topbar_compose_full_email{
+ padding: 0px;
+ width: 32px;
+ height: 32px;
+}
+.openerp .oe_topbar_item.oe_topbar_compose_full_email button{
+ position: relative;
+ top: -3px; /* centering entypo ... urgh */
+ box-sizing: border-box;
+ border: none;
+ box-shadow: none;
+ color: white;
+ background: none;
+ text-shadow: 0px 1px 2px black;
+ width: 32px;
+ height: 32px;
+ padding: 0px;
+ margin: 0px
+ border-radius: 0px;
+}
/* ------------ MAIL WIDGET --------------- */
.openerp .oe_mail, .openerp .oe_mail *{
- box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
}
.openerp .oe_mail {
display: block;
@@ -42,9 +71,10 @@
}
.openerp .oe_mail .oe_msg .oe_msg_footer{
padding-left: 4px;
+ padding-top: 3px;
overflow: hidden;
- opacity:0.8;
- -webkit-transition: opacity 0.2s linear;
+ margin-bottom: 4px;
+ font-size: 11px;
}
.openerp .oe_mail .oe_msg .oe_msg_content{
display: block;
@@ -57,6 +87,13 @@
margin-bottom: 0px;
margin-top: 2px;
}
+.openerp .oe_mail .oe_msg .oe_msg_content .oe_msg_body p:first-of-type {
+ margin-top: 0px;
+}
+
+.openerp .oe_mail .oe_msg .oe_msg_content .oe_msg_body p {
+ margin-bottom: 0px;
+}
/* a) Indented Messages */
@@ -80,18 +117,24 @@
.openerp .oe_mail .oe_msg.oe_msg_indented .oe_msg_content{
padding-top:2px;
}
+.openerp .oe_mail .oe_msg.oe_msg_indented .oe_msg_footer{
+ margin-bottom: 5px;
+}
+
/* b) Votes (likes) */
+
.openerp .oe_mail .oe_mail_vote_count{
display: inline;
position: relative;
- background: #7C7BAD;
- color: white;
+ background: white;
+ box-shadow: 0px 0px 0px 1px rgba(124, 123, 173, 0.36) inset;
+ color: #7c7bad;
text-shadow: none;
border-radius: 3px;
margin: 0px;
padding-left: 3px;
- padding-right: 18px;
- margin-right: 3px;
+ padding-right: 15px;
+ margin-right: 5px;
}
.openerp .oe_mail .oe_mail_vote_count .oe_e{
position: absolute;
@@ -102,12 +145,6 @@
/* c) Message action icons */
-.openerp .oe_mail .oe_msg.oe_msg_unread .oe_unread{
- display:none;
-}
-.openerp .oe_mail .oe_msg.oe_msg_read .oe_read{
- display:none;
-}
.openerp .oe_mail .oe_msg .oe_msg_icons{
float: right;
margin-top: 4px;
@@ -115,6 +152,9 @@
margin-left: 8px;
height: 24px;
-webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
}
.openerp .oe_mail .oe_msg .oe_msg_icons span{
float:right;
@@ -128,10 +168,16 @@
color: #FFF;
text-shadow: 0px 1px #AAA,0px -1px #AAA, -1px 0px #AAA, 1px 0px #AAA, 0px 3px 3px rgba(0,0,0,0.1);
-webkit-transition: all 0.2s linear;
+ -moz-transition: all 0.2s linear;
+ -o-transition: all 0.2s linear;
+ transition: all 0.2s linear;
}
.openerp .oe_mail .oe_msg:hover .oe_msg_icons a{
opacity: 1;
-webkit-transition: all 0.1s linear;
+ -moz-transition: all 0.1s linear;
+ -o-transition: all 0.1s linear;
+ transition: all 0.1s linear;
}
.openerp .oe_mail .oe_msg .oe_msg_icons .oe_star:hover a{
color: #FFF6C0;
@@ -155,7 +201,7 @@
}
.openerp .oe_mail .oe_msg .oe_msg_content textarea{
width: 100%;
- height: 32px;
+ height: 64px;
margin: 0px;
padding: 0px;
resize: vertical;
@@ -171,43 +217,156 @@
width: 100%;
}
-/* ---------------- MESSAGE QUICK COMPOSER --------------- */
+/* --------------------- ATTACHMENTS --------------------- */
-.openerp .oe_mail .oe_msg_composer .oe_msg_footer{
- padding-right:4px;
- padding-top: 2px;
- padding-bottom:6px;
+.openerp .oe_mail .oe_msg_attachment_list{
+ display: none;
+ margin-top: 12px;
+ margin-bottom: 12px;
}
-.openerp .oe_mail .oe_msg_attachments.oe_hidden,
-.openerp .oe_mail .oe_msg_images.oe_hidden{
- margin:0px;
- border: none;
+.openerp .oe_mail .oe_msg_composer .oe_msg_attachment_list{
+ display: block;
+}
+.openerp .oe_mail .oe_attachment{
+ display: inline-block;
+ width: 100px;
+ margin: 2px;
+ min-height: 80px;
+ position: relative;
+ border-radius: 3px;
+ text-align: center;
+ vertical-align: top;
+}
+.openerp .oe_mail .oe_attachment .oe_name{
+ display: inline-block;
+ max-width: 100%;
+ padding: 1px 3px;
+ margin-top: 50px;
+ margin-bottom: 5px;
+ background: rgba(124, 123, 173, 0.13);
+ overflow: hidden;
+ color: #4c4c4c;
+ text-shadow: none;
+ border-radius: 3px;
+}
+
+.openerp .oe_mail .oe_attachment.oe_preview{
+ background: url( data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAJ0lEQVQYV2MsLS39z4AGLCws0IUYGIeCwrVr12J45sSJE5ieGQIKAbuZKf/EMCs7AAAAAElFTkSuQmCC );
+}
+.openerp .oe_mail .oe_attachment .oe_progress_bar{
display: none;
+ position: absolute;
+ top: 18px;
+ left: 16px;
+ right: 16px;
+ height: 17px;
+ line-height: 13px;
+ padding: 0px;
+ background: #4BBD00;
+ color: white;
+ text-align: center;
+ border-radius: 3px;
+ border: solid 1px rgba(0,0,0,0.2);
+ box-shadow: 0px 3px 10px rgba(0, 0, 0, 0.34);
+ -webkit-animation: oe_mail_attach_loading_anim 0.75s infinite linear;
+ -moz-animation: oe_mail_attach_loading_anim 0.75s infinite linear;
+ -o-animation: oe_mail_attach_loading_anim 0.75s infinite linear;
+ animation: oe_mail_attach_loading_anim 0.75s infinite linear;
+}
+.openerp .oe_mail .oe_attachment.oe_uploading .oe_progress_bar{
+ display: block;
}
-.openerp .oe_mail .oe_msg_attachments{
- margin-bottom: 4px;
- margin-right: 0px;
- font-size: 12px;
- border-radius: 2px;
- border: solid 1px rgba(124,123,173,0.14);
+@-webkit-keyframes oe_mail_attach_loading_anim{
+ 0% { background: #4BBD00 }
+ 50% { background: #009123 }
+ 100% { background: #4BBD00 }
}
-.openerp .oe_mail .oe_msg_attachments .oe_attachment{
- padding: 2px;
- padding-left: 4px;
- padding-right: 4px;
+@-moz-keyframes oe_mail_attach_loading_anim{
+ 0% { background: #4BBD00 }
+ 50% { background: #009123 }
+ 100% { background: #4BBD00 }
}
-.openerp .oe_mail .oe_msg_attachments .oe_attachment .oe_e{
- font-size: 23px;
- margin-top: -5px;
+@-o-keyframes oe_mail_attach_loading_anim{
+ 0% { background: #4BBD00 }
+ 50% { background: #009123 }
+ 100% { background: #4BBD00 }
}
-.openerp .oe_mail .oe_msg_attachments .oe_attachment .oe_e:hover{
- text-decoration: none;
+@keyframes oe_mail_attach_loading_anim{
+ 0% { background: #4BBD00 }
+ 50% { background: #009123 }
+ 100% { background: #4BBD00 }
}
-.openerp .oe_mail .oe_msg_attachments .oe_attachment:nth-child(odd){
- background:white;
+.openerp .oe_mail .oe_attachment.oe_preview .oe_name{
+ position: absolute;
+ bottom: 0px;
+ margin: 0px;
+ left: 0px;
+ right: 0px;
+ max-height: 64px;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ border-top-left-radius: 0px;
+ border-top-right-radius: 0px;
+ opacity: 0;
+ -webkit-transition: opacity 0.2s linear;
+ -moz-transition: opacity 0.2s linear;
+ -o-transition: opacity 0.2s linear;
+ transition: opacity 0.2s linear;
+}
+.openerp .oe_mail .oe_attachment.oe_preview:hover .oe_name{
+ opacity: 1;
+ -webkit-transition: opacity 0.2s linear;
+ -moz-transition: opacity 0.2s linear;
+ -o-transition: opacity 0.2s linear;
+ transition: opacity 0.2s linear;
}
-.openerp .oe_mail .oe_msg_attachments .oe_attachment:nth-child(even){
- background: #F4F5FA;
+.openerp .oe_mail .oe_attachment img{
+ position: absolute;
+ width: 48px;
+ height: 48px;
+ top: 0px;
+ left: 50%;
+ margin-left: -24px;
+}
+.openerp .oe_mail .oe_attachment.oe_preview img{
+ display: block;
+ position: relative;
+ margin:0px;
+ width: 100px;
+ height: 100px;
+ border-radius: 3px;
+ margin-left: -50px;
+}
+.openerp .oe_mail .oe_attachment .oe_delete{
+ display: none;
+}
+.openerp .oe_mail .oe_msg_composer .oe_attachment .oe_delete{
+ display: block;
+ position: absolute;
+ top: -7px;
+ right: 0px;
+ color: black;
+ text-shadow: 1px 0px white, -1px 0px white, 0px 1px white, 0px -1px white;
+ cursor: pointer;
+ opacity: 0;
+ -webkit-transition: opacity 0.2s linear;
+ -moz-transition: opacity 0.2s linear;
+ -o-transition: opacity 0.2s linear;
+ transition: opacity 0.2s linear;
+}
+.openerp .oe_mail .oe_msg_composer .oe_attachment:hover .oe_delete{
+ opacity: 1;
+ -webkit-transition: opacity 0.2s linear;
+ -moz-transition: opacity 0.2s linear;
+ -o-transition: opacity 0.2s linear;
+ transition: opacity 0.2s linear;
+}
+/* ---------------- MESSAGE QUICK COMPOSER --------------- */
+
+.openerp .oe_mail .oe_msg_composer .oe_msg_footer{
+ padding-right:4px;
+ padding-top: 2px;
+ padding-bottom:6px;
}
.openerp .oe_mail .oe_msg_images {
display: block;
@@ -222,11 +381,13 @@
.openerp .oe_mail .oe_msg_footer button.oe_attach{
width: 24px;
overflow: hidden;
+ filter:none;
}
.openerp .oe_mail .oe_msg_footer button.oe_attach .oe_e{
position: relative;
top: -1px;
left: -9px;
+ filter:none;
}
.openerp .oe_mail .oe_hidden_input_file, .openerp .oe_mail .oe_hidden_input_file form{
display:inline;
@@ -235,11 +396,13 @@
width:24px;
overflow:hidden;
float: right;
+ filter:none;
}
.openerp .oe_mail .oe_msg_footer button.oe_full .oe_e{
position: relative;
top: -1px;
left: -9px;
+ filter:none;
}
.openerp .oe_mail button.oe_attach, .openerp .oe_mail button.oe_full{
background: transparent;
@@ -247,6 +410,7 @@
box-shadow: none;
border: none;
text-shadow: none;
+ filter:none;
}
.openerp .oe_mail .oe_attach_label{
color: #7C7BAD;
@@ -258,6 +422,7 @@
height: 28px;
width: 52px;
margin-top: -6px;
+ filter:none;
}
.openerp .oe_mail .oe_mail_list_recipients{
font-size: 12px;
@@ -269,6 +434,7 @@
.openerp .oe_mail .oe_msg_content.oe_msg_more_message{
text-align: right;
+ cursor: pointer;
}
.openerp .oe_mail .oe_msg_content.oe_msg_more_message .oe_separator{
height: 0;
@@ -280,7 +446,7 @@
}
.openerp .oe_mail .oe_msg_more_message .oe_msg_fetch_more {
background: white;
- margin-right: 280px;
+ margin-right: 210px;
padding-left: 8px;
padding-right: 8px;
text-decoration: none;
@@ -298,6 +464,7 @@
padding-top: 5px;
width: 160px;
float: right;
+ margin-right: 16px;
}
/* a) THE FOLLOW BUTTON */
@@ -308,9 +475,23 @@
width:100%;
}
.openerp .oe_followers button.oe_follower.oe_following{
+ color: white;
background-color: #3465A4;
background-image: -webkit-linear-gradient(top, #729FCF, #3465A4);
+ background-image: -moz-linear-gradient(top, #729FCF, #3465A4);
+ background-image: -ms-linear-gradient(top, #729FCF, #3465A4);
+ background-image: -o-linear-gradient(top, #729FCF, #3465A4);
+ background-image: linear-gradient(to bottom, #729FCF, #3465A4);
+}
+.openerp .oe_followers button.oe_follower.oe_following:hover{
color: white;
+ filter:none;
+ background-color: #A21A1A;
+ background-image: -webkit-linear-gradient(top, #DF3F3F, #A21A1A);
+ background-image: -moz-linear-gradient(top, #DF3F3F, #A21A1A);
+ background-image: -ms-linear-gradient(top, #DF3F3F, #A21A1A);
+ background-image: -o-linear-gradient(top, #DF3F3F, #A21A1A);
+ background-image: linear-gradient(to bottom, #DF3F3F, #A21A1A);
}
.openerp .oe_followers button.oe_follower .oe_follow,
@@ -371,12 +552,17 @@
.openerp .oe_record_thread{
display: block;
- margin-right: 180px;
+ margin-left: 16px;
+ margin-right: 212px;
}
/* ----------- INBOX INTEGRATION ----------- */
.openerp .oe_mail_wall .oe_mail{
margin: 16px;
- width: 720px;
+ width: 600px;
+}
+
+.openerp .oe_mail .oe_view_nocontent > p {
+ padding-left: 15px;
}
diff --git a/addons/mail/static/src/css/mail_group.css b/addons/mail/static/src/css/mail_group.css
index b700cb8c80f..c1cefee9070 100644
--- a/addons/mail/static/src/css/mail_group.css
+++ b/addons/mail/static/src/css/mail_group.css
@@ -44,20 +44,23 @@
text-align: center;
overflow: hidden;
-moz-border-radius: 3px;
+ border-collapse: separate;
-webkit-border-radius: 3px;
-o-border-radius: 3px;
-ms-border-radius: 3px;
border-radius: 3px;
+ border-collapse: separate;
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
-o-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
- -box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
}
.oe_group_photo {
width: 100px;
height: 100px;
clip: rect(0px, 100px, 100px, 0px);
+ border:none;
}
.oe_group_details {
@@ -68,30 +71,31 @@
min-height: 120px;
}
-.oe_group_details a, .oe_group_details a:hover {
- font-weight: bold;
- color: #4c4c4c;
-}
-
.oe_group_details h4 {
margin: 0;
font-size: 13px;
}
-.oe_group_details h4 a {
- color: #4c4c4c;
-}
-
-.oe_group_details h4 a:hover {
- text-decoration: underline;
-}
-
.oe_group_details ul {
margin: 3px 0 5px;
padding: 0;
list-style: none;
}
-.oe_group_details li {
+.openerp .oe_group_details li {
margin: 2px 0;
}
+
+.openerp .oe_group_button {
+ padding-top: 7px;
+}
+
+.openerp .oe_group_button .oe_group_join {
+ color: white;
+ background-color: #3465A4;
+ background-image: -webkit-linear-gradient(top, #729FCF, #3465A4);
+ background-image: -moz-linear-gradient(top, #729FCF, #3465A4);
+ background-image: -ms-linear-gradient(top, #729FCF, #3465A4);
+ background-image: -o-linear-gradient(top, #729FCF, #3465A4);
+ background-image: linear-gradient(to bottom, #729FCF, #3465A4);
+}
diff --git a/addons/mail/static/src/img/mimetypes/addresses.png b/addons/mail/static/src/img/mimetypes/addresses.png
new file mode 100644
index 00000000000..586f1257196
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/addresses.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/archive.png b/addons/mail/static/src/img/mimetypes/archive.png
new file mode 100644
index 00000000000..704d962d426
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/archive.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/audio.png b/addons/mail/static/src/img/mimetypes/audio.png
new file mode 100644
index 00000000000..6dd4c635fe7
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/audio.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/binary.png b/addons/mail/static/src/img/mimetypes/binary.png
new file mode 100644
index 00000000000..5708c9fc2a5
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/binary.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/calendar.png b/addons/mail/static/src/img/mimetypes/calendar.png
new file mode 100644
index 00000000000..81791af05e0
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/calendar.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/certificate.png b/addons/mail/static/src/img/mimetypes/certificate.png
new file mode 100644
index 00000000000..e48cb1de432
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/certificate.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/disk.png b/addons/mail/static/src/img/mimetypes/disk.png
new file mode 100644
index 00000000000..9c241cdf896
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/disk.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/document.png b/addons/mail/static/src/img/mimetypes/document.png
new file mode 100644
index 00000000000..fee2f1619b6
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/document.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/font.png b/addons/mail/static/src/img/mimetypes/font.png
new file mode 100644
index 00000000000..3b04787b9f9
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/font.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/html.png b/addons/mail/static/src/img/mimetypes/html.png
new file mode 100644
index 00000000000..440c5bc9972
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/html.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/image.png b/addons/mail/static/src/img/mimetypes/image.png
new file mode 100644
index 00000000000..ab2f84a1a54
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/image.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/presentation.png b/addons/mail/static/src/img/mimetypes/presentation.png
new file mode 100644
index 00000000000..8642a8e9298
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/presentation.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/print.png b/addons/mail/static/src/img/mimetypes/print.png
new file mode 100644
index 00000000000..fee2f1619b6
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/print.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/script.png b/addons/mail/static/src/img/mimetypes/script.png
new file mode 100644
index 00000000000..10c58c0bcc3
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/script.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/spreadsheet.png b/addons/mail/static/src/img/mimetypes/spreadsheet.png
new file mode 100644
index 00000000000..77a834697f1
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/spreadsheet.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/text.png b/addons/mail/static/src/img/mimetypes/text.png
new file mode 100644
index 00000000000..e65d2ec5a67
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/text.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/unknown.png b/addons/mail/static/src/img/mimetypes/unknown.png
new file mode 100644
index 00000000000..e65d2ec5a67
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/unknown.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/vector.png b/addons/mail/static/src/img/mimetypes/vector.png
new file mode 100644
index 00000000000..c4595ec1b24
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/vector.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/video.png b/addons/mail/static/src/img/mimetypes/video.png
new file mode 100644
index 00000000000..e3a87b5bde6
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/video.png
Binary files differ
diff --git a/addons/mail/static/src/img/mimetypes/webimage.png b/addons/mail/static/src/img/mimetypes/webimage.png
new file mode 100644
index 00000000000..ab2f84a1a54
--- /dev/null
+++ b/addons/mail/static/src/img/mimetypes/webimage.png
Binary files differ
diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js
index 7acebe9b1df..dc265a343d5 100644
--- a/addons/mail/static/src/js/mail.js
+++ b/addons/mail/static/src/js/mail.js
@@ -24,9 +24,10 @@ openerp.mail = function (session) {
*/
var context_keys = ['default_template_id', 'default_composition_mode',
'default_use_template', 'default_partner_ids', 'default_model',
- 'default_res_id', 'default_content_subtype', , 'default_subject',
+ 'default_res_id', 'default_content_subtype', 'default_subject',
'default_body', 'active_id', 'lang', 'bin_raw', 'tz',
- 'active_model', 'edi_web_url_view', 'active_ids']
+ 'active_model', 'edi_web_url_view', 'active_ids',
+ 'default_attachment_ids']
for (var key in action.context) {
if (_.indexOf(context_keys, key) == -1) {
action.context[key] = null;
@@ -54,13 +55,15 @@ openerp.mail = function (session) {
mail.ChatterUtils = {
/* Get an image in /web/binary/image?... */
- get_image: function (session, model, field, id) {
- return session.prefix + '/web/binary/image?session_id=' + session.session_id + '&model=' + model + '&field=' + field + '&id=' + (id || '');
+ get_image: function (session, model, field, id, resize) {
+ var r = resize ? encodeURIComponent(resize) : '';
+ id = id || '';
+ return session.url('/web/binary/image', {model: model, field: field, id: id, resize: r});
},
/* Get the url of an attachment {'id': id} */
get_attachment_url: function (session, attachment) {
- return session.origin + '/web/binary/saveas?session_id=' + session.session_id + '&model=ir.attachment&field=datas&filename_field=datas_fname&id=' + attachment['id'];
+ return session.url('/web/binary/saveas', {model: 'ir.attachment', field: 'datas', filename_field: 'datas_fname', id: attachment['id']});
},
/**
@@ -111,12 +114,267 @@ openerp.mail = function (session) {
}
return domain;
- }
+ },
+
+ // inserts zero width space between each letter of a string so that
+ // the word will correctly wrap in html boxes smaller than the text
+ breakword: function(str){
+ var out = '';
+ if (!str) {
+ return str;
+ }
+ for(var i = 0, len = str.length; i < len; i++){
+ out += _.str.escapeHTML(str[i]) + '&#8203;';
+ }
+ return out;
+ },
+
+ // returns the file type of a file based on its extension
+ // As it only looks at the extension it is quite approximative.
+ filetype: function(url){
+ url = url.filename || url;
+ var tokens = url.split('.');
+ if(tokens.length <= 1){
+ return 'unknown';
+ }
+ var extension = tokens[tokens.length -1];
+ if(extension.length === 0){
+ return 'unknown';
+ }else{
+ extension = extension.toLowerCase();
+ }
+ var filetypes = {
+ 'webimage': ['png','jpg','jpeg','jpe','gif'], // those have browser preview
+ 'image': ['tif','tiff','tga',
+ 'bmp','xcf','psd','ppm','pbm','pgm','pnm','mng',
+ 'xbm','ico','icon','exr','webp','psp','pgf','xcf',
+ 'jp2','jpx','dng','djvu','dds'],
+ 'vector': ['ai','svg','eps','vml','cdr','xar','cgm','odg','sxd'],
+ 'print': ['dvi','pdf','ps'],
+ 'document': ['doc','docx','odm','odt'],
+ 'presentation': ['key','keynote','odp','pps','ppt'],
+ 'font': ['otf','ttf','woff','eot'],
+ 'archive': ['zip','7z','ace','apk','bzip2','cab','deb','dmg','gzip','jar',
+ 'rar','tar','gz','pak','pk3','pk4','lzip','lz','rpm'],
+ 'certificate': ['cer','key','pfx','p12','pem','crl','der','crt','csr'],
+ 'audio': ['aiff','wav','mp3','ogg','flac','wma','mp2','aac',
+ 'm4a','ra','mid','midi'],
+ 'video': ['asf','avi','flv','mkv','m4v','mpeg','mpg','mpe','wmv','mp4','ogm'],
+ 'text': ['txt','rtf','ass'],
+ 'html': ['html','xhtml','xml','htm','css'],
+ 'disk': ['iso','nrg','img','ccd','sub','cdi','cue','mds','mdx'],
+ 'script': ['py','js','c','cc','cpp','cs','h','java','bat','sh',
+ 'd','rb','pl','as','cmd','coffee','m','r','vbs','lisp'],
+ 'spreadsheet': ['123','csv','ods','numbers','sxc','xls','vc','xlsx'],
+ 'binary': ['exe','com','bin','app'],
+ };
+ for(filetype in filetypes){
+ var ext_list = filetypes[filetype];
+ for(var i = 0, len = ext_list.length; i < len; i++){
+ if(extension === ext_list[i]){
+ return filetype;
+ }
+ }
+ }
+ return 'unknown';
+ },
+
};
/**
* ------------------------------------------------------------
+ * MessageCommon
+ * ------------------------------------------------------------
+ *
+ * Common base for expandables, chatter messages and composer. It manages
+ * the various variables common to those models.
+ */
+
+ mail.MessageCommon = session.web.Widget.extend({
+
+ /**
+ * ------------------------------------------------------------
+ * FIXME: this comment was moved as is from the ThreadMessage Init as
+ * part of a refactoring. Check that it is still correct
+ * ------------------------------------------------------------
+ * This widget handles the display of a messages in a thread.
+ * Displays a record and performs some formatting on the record :
+ * - record.date: formatting according to the user timezone
+ * - record.timerelative: relative time givein by timeago lib
+ * - record.avatar: image url
+ * - record.attachment_ids[].url: url of each attachmentThe
+ * thread view :
+ * - root thread
+ * - - sub message (parent_id = root message)
+ * - - - sub thread
+ * - - - - sub sub message (parent id = sub thread)
+ * - - sub message (parent_id = root message)
+ * - - - sub thread
+ */
+
+ init: function (parent, datasets, options) {
+ this._super(parent, options);
+
+ // record options
+ this.options = datasets.options || options || {};
+ // record domain and context
+ this.domain = datasets.domain || options.domain || [];
+ this.context = _.extend({
+ default_model: false,
+ default_res_id: 0,
+ default_parent_id: false }, options.context || {});
+
+ // data of this message
+ this.id = datasets.id || false,
+ this.last_id = this.id,
+ this.model = datasets.model || this.context.default_model || false,
+ this.res_id = datasets.res_id || this.context.default_res_id || false,
+ this.parent_id = datasets.parent_id || false,
+ this.type = datasets.type || false,
+ this.is_author = datasets.is_author || false,
+ this.is_private = datasets.is_private || false,
+ this.subject = datasets.subject || false,
+ this.name = datasets.name || false,
+ this.record_name = datasets.record_name || false,
+ this.body = datasets.body || false,
+ this.vote_nb = datasets.vote_nb || 0,
+ this.has_voted = datasets.has_voted || false,
+ this.is_favorite = datasets.is_favorite || false,
+ this.thread_level = datasets.thread_level || 0,
+ this.to_read = datasets.to_read || false,
+ this.author_id = datasets.author_id || false,
+ this.attachment_ids = datasets.attachment_ids || [],
+ this.partner_ids = datasets.partner_ids || [];
+ this._date = datasets.date;
+
+ this.format_data();
+
+ // record options and data
+ this.show_record_name = this.record_name && !this.thread_level && this.model != 'res.partner';
+ this.options.show_read = false;
+ this.options.show_unread = false;
+ if (this.options.show_read_unread_button) {
+ if (this.options.read_action == 'read') this.options.show_read = true;
+ else if (this.options.read_action == 'unread') this.options.show_unread = true;
+ else {
+ this.options.show_read = this.to_read;
+ this.options.show_unread = !this.to_read;
+ this.options.rerender = true;
+ this.options.toggle_read = true;
+ }
+ }
+ this.parent_thread = parent.messages != undefined ? parent : this.options.root_thread;
+ this.thread = false;
+ },
+
+ /* Convert date, timerelative and avatar in displayable data. */
+ format_data: function () {
+
+ //formating and add some fields for render
+ if (this._date) {
+ this.date = session.web.format_value(this._date, {type:"datetime"});
+ this.timerelative = $.timeago(this.date);
+ }
+ if (this.type == 'email' && (!this.author_id || !this.author_id[0])) {
+ this.avatar = ('/mail/static/src/img/email_icon.png');
+ } else if (this.author_id && this.template != 'mail.compose_message') {
+ this.avatar = mail.ChatterUtils.get_image(this.session, 'res.partner', 'image_small', this.author_id[0]);
+ } else {
+ this.avatar = mail.ChatterUtils.get_image(this.session, 'res.users', 'image_small', this.session.uid);
+ }
+
+ },
+
+
+ /* upload the file on the server, add in the attachments list and reload display
+ */
+ display_attachments: function () {
+ for (var l in this.attachment_ids) {
+ var attach = this.attachment_ids[l];
+ if (!attach.formating) {
+ attach.url = mail.ChatterUtils.get_attachment_url(this.session, attach);
+ attach.filetype = mail.ChatterUtils.filetype(attach.filename);
+ attach.name = mail.ChatterUtils.breakword(attach.name || attach.filename);
+ attach.formating = true;
+ }
+ }
+ this.$(".oe_msg_attachment_list").html( session.web.qweb.render('mail.thread.message.attachments', {'widget': this}) );
+ },
+
+ /* return the link to resized image
+ */
+ attachments_resize_image: function (id, resize) {
+ return mail.ChatterUtils.get_image(this.session, 'ir.attachment', 'datas', id, resize);
+ },
+
+ /* get all child message id linked.
+ * @return array of id
+ */
+ get_child_ids: function () {
+ return _.map(this.get_childs(), function (val) { return val.id; });
+ },
+
+ /* get all child message linked.
+ * @return array of message object
+ */
+ get_childs: function (nb_thread_level) {
+ var res=[];
+ if (arguments[1] && this.id) res.push(this);
+ if ((isNaN(nb_thread_level) || nb_thread_level>0) && this.thread) {
+ _(this.thread.messages).each(function (val, key) {
+ res = res.concat( val.get_childs((isNaN(nb_thread_level) ? undefined : nb_thread_level-1), true) );
+ });
+ }
+ return res;
+ },
+
+ /**
+ * search a message in all thread and child thread.
+ * This method return an object message.
+ * @param {object}{int} option.id
+ * @param {object}{string} option.model
+ * @param {object}{boolean} option._go_thread_wall
+ * private for check the top thread
+ * @return thread object
+ */
+ browse_message: function (options) {
+ // goto the wall thread for launch browse
+ if (!options._go_thread_wall) {
+ options._go_thread_wall = true;
+ for (var i in this.options.root_thread.messages) {
+ var res=this.options.root_thread.messages[i].browse_message(options);
+ if (res) return res;
+ }
+ }
+
+ if (this.id==options.id)
+ return this;
+
+ for (var i in this.thread.messages) {
+ if (this.thread.messages[i].thread) {
+ var res=this.thread.messages[i].browse_message(options);
+ if (res) return res;
+ }
+ }
+
+ return false;
+ },
+
+ /**
+ * call on_message_delete on his parent thread
+ */
+ destroy: function () {
+
+ this._super();
+ this.parent_thread.on_message_detroy(this);
+
+ }
+
+ });
+
+ /**
+ * ------------------------------------------------------------
* ComposeMessage widget
* ------------------------------------------------------------
*
@@ -126,7 +384,7 @@ openerp.mail = function (session) {
* When the user focuses the textarea, the compose message is instantiated.
*/
- mail.ThreadComposeMessage = session.web.Widget.extend({
+ mail.ThreadComposeMessage = mail.MessageCommon.extend({
template: 'mail.compose_message',
/**
@@ -138,45 +396,22 @@ openerp.mail = function (session) {
*/
init: function (parent, datasets, options) {
- var self = this;
- this._super(parent);
- this.context = options.context || {};
- this.options = options.options;
-
+ this._super(parent, datasets, options);
this.show_compact_message = false;
+ this.show_delete_attachment = true;
+ },
- // data of this compose message
- this.attachment_ids = [];
- this.id = datasets.id;
- this.model = datasets.model;
- this.res_model = datasets.res_model;
- this.is_private = datasets.is_private || false;
- this.partner_ids = datasets.partner_ids || [];
- this.avatar = mail.ChatterUtils.get_image(this.session, 'res.users', 'image_small', this.session.uid);
- this.thread_level = datasets.thread_level;
- this.parent_thread= parent.messages!= undefined ? parent : false;
+ start: function () {
+ this._super.apply(this, arguments);
this.ds_attachment = new session.web.DataSetSearch(this, 'ir.attachment');
- this.show_delete_attachment = true;
-
this.fileupload_id = _.uniqueId('oe_fileupload_temp');
- $(window).on(self.fileupload_id, self.on_attachment_loaded);
- },
+ $(window).on(this.fileupload_id, this.on_attachment_loaded);
- start: function () {
this.display_attachments();
this.bind_events();
},
- /* upload the file on the server, add in the attachments list and reload display
- */
- display_attachments: function () {
- this.$(".oe_msg_attachment_list").html(
- session.web.qweb.render('mail.thread.message.attachments', {'widget': this}) );
- // event: delete an attachment
- this.$(".oe_msg_attachment_list").on('click', '.oe_mail_attachment_delete', this.on_attachment_delete);
- },
-
/* when a user click on the upload button, send file read on_attachment_loaded
*/
on_attachment_change: function (event) {
@@ -263,19 +498,24 @@ openerp.mail = function (session) {
this.$('textarea.oe_compact').on('focus', _.bind( this.on_compose_expandable, this));
// set the function called when attachments are added
- this.$el.on('change', 'input.oe_form_binary_file', _.bind( this.on_attachment_change, this) );
+ this.$('input.oe_form_binary_file').on('change', _.bind( this.on_attachment_change, this) );
- this.$el.on('click', '.oe_cancel', _.bind( this.on_cancel, this) );
- this.$el.on('click', '.oe_post', _.bind( this.on_message_post, this) );
- this.$el.on('click', '.oe_full', _.bind( this.on_compose_fullmail, this, 'reply') );
+ this.$('.oe_cancel').on('click', _.bind( this.on_cancel, this) );
+ this.$('.oe_post').on('click', _.bind( this.on_message_post, this) );
+ this.$('.oe_full').on('click', _.bind( this.on_compose_fullmail, this, this.id ? 'reply' : 'comment') );
/* stack for don't close the compose form if the user click on a button */
- this.$el.on('mousedown', '.oe_msg_footer', _.bind( function () { this.stay_open = true; }, this));
- this.$('textarea:not(.oe_compact):first').on('focus, mouseup, keydown', _.bind( function () { this.stay_open = false; }, this));
- this.$('textarea:not(.oe_compact):first').autosize();
+ this.$('.oe_msg_footer').on('mousedown', _.bind( function () { this.stay_open = true; }, this));
+ var ev_stay = {};
+ ev_stay.mouseup = ev_stay.keydown = ev_stay.focus = function () { self.stay_open = false; };
+ this.$('textarea:not(.oe_compact)').on(ev_stay);
+ this.$('textarea:not(.oe_compact)').autosize();
// auto close
- this.$el.on('blur', 'textarea:not(.oe_compact):first', _.bind( this.on_compose_expandable, this));
+ this.$('textarea:not(.oe_compact)').on('blur', _.bind( this.on_compose_expandable, this));
+
+ // event: delete child attachments off the oe_msg_attachment_list box
+ this.$(".oe_msg_attachment_list").on('click', '.oe_delete', this.on_attachment_delete);
},
on_compose_fullmail: function (default_composition_mode) {
@@ -290,7 +530,6 @@ openerp.mail = function (session) {
var context = {
'default_model': this.context.default_model,
'default_res_id': this.context.default_res_id,
- 'default_content_subtype': 'html',
'default_composition_mode': default_composition_mode,
'default_parent_id': this.id,
'default_body': mail.ChatterUtils.get_text2html(this.$el ? (this.$el.find('textarea:not(.oe_compact)').val() || '') : ''),
@@ -350,7 +589,7 @@ openerp.mail = function (session) {
if (body.match(/\S+/)) {
//session.web.blockUI();
- this.parent_thread.ds_thread.call('message_post_api', [
+ this.parent_thread.ds_thread.call('message_post_user_api', [
this.context.default_res_id,
mail.ChatterUtils.get_text2html(body),
false,
@@ -359,11 +598,15 @@ openerp.mail = function (session) {
this.parent_thread.context
]).done(function (record) {
var thread = self.parent_thread;
+ if (self.options.display_indented_thread < self.thread_level && thread.parent_message) {
+ var thread = thread.parent_message.parent_thread;
+ }
+ var root = thread == self.options.root_thread;
// create object and attach to the thread object
- thread.message_fetch(false, false, [record], function (arg, data) {
+ thread.message_fetch([['id', 'child_of', [self.id]]], false, [record], function (arg, data) {
var message = thread.create_message_object( data[0] );
// insert the message on dom
- thread.insert_message( message, self.$el );
+ thread.insert_message( message, root ? undefined : self.$el, root );
if (thread.parent_message) {
self.$el.remove();
self.parent_thread.compose_message = null;
@@ -419,30 +662,16 @@ openerp.mail = function (session) {
* - - visible message
* - - expandable
*/
- mail.ThreadExpandable = session.web.Widget.extend({
+ mail.ThreadExpandable = mail.MessageCommon.extend({
template: 'mail.thread.expandable',
- init: function (parent, datasets, context) {
- this._super(parent);
- this.domain = datasets.domain || [];
- this.options = datasets.options;
- this.context = _.extend({
- default_model: 'mail.thread',
- default_res_id: 0,
- default_parent_id: false }, context || {});
-
- // data of this expandable message
- this.id = datasets.id || -1,
- this.model = datasets.model || false,
- this.parent_id = datasets.parent_id || false,
- this.nb_messages = datasets.nb_messages || 0,
- this.thread_level = datasets.thread_level || 0,
- this.type = 'expandable',
- this.max_limit = this.id < 0 || false,
- this.flag_used = false,
- this.parent_thread= parent.messages!= undefined ? parent : this.options._parents[0];
+ init: function (parent, datasets, options) {
+ this._super(parent, datasets, options);
+ this.type = 'expandable';
+ this.max_limit = datasets.max_limit;
+ this.nb_messages = datasets.nb_messages;
+ this.flag_used = false;
},
-
start: function () {
this._super.apply(this, arguments);
@@ -460,7 +689,7 @@ openerp.mail = function (session) {
* Bind events in the widget. Each event is slightly described
* in the function. */
bind_events: function () {
- this.$el.on('click', 'a.oe_msg_fetch_more', this.on_expandable);
+ this.$('.oe_msg_more_message').on('click', this.on_expandable);
},
animated_destroy: function (fadeTime) {
@@ -480,154 +709,35 @@ openerp.mail = function (session) {
}
this.flag_used = true;
- this.animated_destroy(200);
- this.parent_thread.message_fetch(this.domain, this.context);
- return false;
- },
+ var self = this;
- /**
- * call on_message_delete on his parent thread
- */
- destroy: function () {
+ // read messages
+ self.parent_thread.message_fetch(this.domain, this.context, false, function (arg, data) {
+ // insert the message on dom after this message
+ self.id = false;
+ self.parent_thread.switch_new_message( data, self.$el );
+ self.animated_destroy(200);
+ });
- this._super();
- this.parent_thread.on_message_detroy(this);
+ return false;
+ },
- }
});
- /**
- * ------------------------------------------------------------
- * Thread Message Widget
- * ------------------------------------------------------------
- * This widget handles the display of a messages in a thread.
- * Displays a record and performs some formatting on the record :
- * - record.date: formatting according to the user timezone
- * - record.timerelative: relative time givein by timeago lib
- * - record.avatar: image url
- * - record.attachment_ids[].url: url of each attachmentThe
- * thread view :
- * - root thread
- * - - sub message (parent_id = root message)
- * - - - sub thread
- * - - - - sub sub message (parent id = sub thread)
- * - - sub message (parent_id = root message)
- * - - - sub thread
- */
- mail.ThreadMessage = session.web.Widget.extend({
+ mail.ThreadMessage = mail.MessageCommon.extend({
template: 'mail.thread.message',
-
- /**
- * @param {Object} parent parent
- * @param {Array} [domain]
- * @param {Object} [context] context of the thread. It should
- contain at least default_model, default_res_id. Please refer to
- the ComposeMessage widget for more information about it.
- * @param {Object} [options]
- * @param {Object} [thread] read obout mail.Thread object
- * @param {Object} [message]
- * @param {Number} [truncate_limit=250] number of character to
- * display before having a "show more" link; note that the text
- * will not be truncated if it does not have 110% of the parameter
- * @param {Boolean} [show_record_name]
- *... @param {int} [show_reply_button] number thread level to display the reply button
- *... @param {int} [show_read_unread_button] number thread level to display the read/unread button
- */
- init: function (parent, datasets, context) {
- this._super(parent);
-
- // record domain and context
- this.domain = datasets.domain || [];
- this.context = _.extend({
- default_model: 'mail.thread',
- default_res_id: 0,
- default_parent_id: false }, context || {});
-
- // record options
- this.options = datasets.options;
-
- // data of this message
- this.id = datasets.id || -1,
- this.model = datasets.model || false,
- this.parent_id = datasets.parent_id || false,
- this.res_id = datasets.res_id || false,
- this.type = datasets.type || false,
- this.is_author = datasets.is_author || false,
- this.is_private = datasets.is_private || false,
- this.subject = datasets.subject || false,
- this.name = datasets.name || false,
- this.record_name = datasets.record_name || false,
- this.body = datasets.body || false,
- this.vote_nb = datasets.vote_nb || 0,
- this.has_voted = datasets.has_voted || false,
- this.is_favorite = datasets.is_favorite || false,
- this.thread_level = datasets.thread_level || 0,
- this.to_read = datasets.to_read || false,
- this.author_id = datasets.author_id || [],
- this.attachment_ids = datasets.attachment_ids || [],
- this._date = datasets.date;
-
-
- this.show_reply_button = this.options.show_compose_message && this.options.show_reply_button > this.thread_level;
- this.show_read_unread_button = this.options.show_read_unread_button > this.thread_level;
-
- // record options and data
- this.parent_thread= parent.messages!= undefined ? parent : this.options._parents[0];
- this.thread = false;
-
- if ( this.id > 0 ) {
- this.formating_data();
- }
-
- this.ds_notification = new session.web.DataSetSearch(this, 'mail.notification');
- this.ds_message = new session.web.DataSetSearch(this, 'mail.message');
- this.ds_follow = new session.web.DataSetSearch(this, 'mail.followers');
- },
-
- /* Convert date, timerelative and avatar in displayable data. */
- formating_data: function () {
-
- //formating and add some fields for render
- this.date = session.web.format_value(this._date, {type:"datetime"});
- this.timerelative = $.timeago(this.date);
- if (this.type == 'email') {
- this.avatar = ('/mail/static/src/img/email_icon.png');
- } else {
- this.avatar = mail.ChatterUtils.get_image(this.session, 'res.partner', 'image_small', this.author_id[0]);
- }
- for (var l in this.attachment_ids) {
- var attach = this.attachment_ids[l];
- attach['url'] = mail.ChatterUtils.get_attachment_url(this.session, attach);
-
- if ((attach.filename || attach.name).match(/[.](jpg|jpg|gif|png|tif|svg)$/i)) {
- attach.is_image = true;
- attach['url'] = mail.ChatterUtils.get_image(this.session, 'ir.attachment', 'datas', attach.id);
- }
- }
- },
start: function () {
this._super.apply(this, arguments);
this.expender();
- this.$el.hide().fadeIn(750, function () {$(this).css('display', '');});
- this.resize_img();
this.bind_events();
if(this.thread_level < this.options.display_indented_thread) {
this.create_thread();
}
this.$('.oe_msg_attachments, .oe_msg_images').addClass("oe_hidden");
- },
- resize_img: function () {
- var resize = function () {
- var h = $(this).height();
- var w = $(this).width();
- if ( h > 100 || w >100 ) {
- var ratio = 100 / (h > w ? h : w);
- $(this).attr("width", parseInt( w*ratio )).attr("height", parseInt( h*ratio ));
- }
- };
- this.$("img").load(resize).each(resize);
+ this.ds_notification = new session.web.DataSetSearch(this, 'mail.notification');
+ this.ds_message = new session.web.DataSetSearch(this, 'mail.message');
},
/**
@@ -635,30 +745,15 @@ openerp.mail = function (session) {
* in the function. */
bind_events: function () {
var self = this;
+ // header icons bindings
+ this.$('.oe_read').on('click', this.on_message_read);
+ this.$('.oe_unread').on('click', this.on_message_unread);
+ this.$('.oe_msg_delete').on('click', this.on_message_delete);
+ this.$('.oe_reply').on('click', this.on_message_reply);
+ this.$('.oe_star').on('click', this.on_star);
+ this.$('.oe_msg_vote').on('click', this.on_vote);
+ this.$('.oe_view_attachments').on('click', this.on_view_attachments);
- // event: click on 'Attachment(s)' in msg
- this.$('.oe_mail_msg_view_attachments').on('click', function (event) {
- var attach = self.$('.oe_msg_attachments:first, .oe_msg_images:first');
- if ( self.$('.oe_msg_attachments:first').hasClass("oe_hidden") ) {
- attach.removeClass("oe_hidden");
- } else {
- attach.addClass("oe_hidden");
- }
- self.resize_img();
- });
- // event: click on icone 'Read' in header
- this.$el.on('click', '.oe_read', this.on_message_read_unread);
- // event: click on icone 'UnRead' in header
- this.$el.on('click', '.oe_unread', this.on_message_read_unread);
- // event: click on 'Delete' in msg side menu
- this.$el.on('click', '.oe_msg_delete', this.on_message_delete);
-
- // event: click on 'Reply' in msg
- this.$el.on('click', '.oe_reply', this.on_message_reply);
- // event: click on 'Vote' button
- this.$el.on('click', '.oe_msg_vote', this.on_vote);
- // event: click on 'starred/favorite' button
- this.$el.on('click', '.oe_star', this.on_star);
},
/* Call the on_compose_message on the thread of this message. */
@@ -673,7 +768,7 @@ openerp.mail = function (session) {
this.$('.oe_msg_body:first').expander({
slicePoint: this.options.truncate_limit,
expandText: 'read more',
- userCollapseText: '[^]',
+ userCollapseText: 'read less',
detailClass: 'oe_msg_tail',
moreClass: 'oe_mail_expand',
lessClass: 'oe_mail_reduce',
@@ -717,6 +812,17 @@ openerp.mail = function (session) {
}
},
+ /* Call the on_compose_message on the thread of this message. */
+ on_view_attachments:function (event) {
+ event.stopPropagation();
+ var self = this;
+ if (!this.toggle_attachment) {
+ self.display_attachments();
+ this.toggle_attachment = true;
+ }
+ this.$('.oe_msg_attachment_list').toggle(200);
+ },
+
/**
* Wait a confirmation for delete the message on the DB.
* Make an animate destroy
@@ -732,68 +838,76 @@ openerp.mail = function (session) {
return false;
},
- /*The selected thread and all childs (messages/thread) became read
- * @param {object} mouse envent
+ /* Check if the message must be destroy and detroy it or check for re render widget
+ * @param {callback} apply function
*/
- on_message_read_unread: function (event) {
- event.stopPropagation();
- var self=this;
+ check_for_rerender: function () {
+ var self = this;
- if ( (this.to_read && this.options.typeof_thread == 'inbox') ||
- (!this.to_read && this.options.typeof_thread == 'archives')) {
- this.animated_destroy(150);
- }
+ var messages = [this].concat(this.get_childs());
+ var message_ids = _.map(messages, function (msg) { return msg.id;});
+ var domain = mail.ChatterUtils.expand_domain( this.options.root_thread.domain )
+ .concat([["id", "in", message_ids ]]);
+
+ return this.parent_thread.ds_message.call('message_read', [undefined, domain, [], !!this.parent_thread.options.display_indented_thread, this.context, this.parent_thread.id])
+ .then( function (records) {
+ // remove message not loaded
+ _.map(messages, function (msg) {
+ if(!_.find(records, function (record) { return record.id == msg.id; })) {
+ msg.animated_destroy(150);
+ } else {
+ msg.renderElement();
+ msg.start()
+ }
+ });
- // if this message is read, all childs message display is read
- this.ds_notification.call('set_message_read', [ [this.id].concat( this.get_child_ids() ) , this.to_read, this.context]).then(function () {
- self.$el.removeClass(self.to_read ? 'oe_msg_unread':'oe_msg_read').addClass(self.to_read ? 'oe_msg_read':'oe_msg_unread');
- self.to_read = !self.to_read;
- });
- return false;
+ });
},
- /**
- * search a message in all thread and child thread.
- * This method return an object message.
- * @param {object}{int} option.id
- * @param {object}{string} option.model
- * @param {object}{boolean} option._go_thread_wall
- * private for check the top thread
- * @return thread object
- */
- browse_message: function (options) {
- // goto the wall thread for launch browse
- if (!options._go_thread_wall) {
- options._go_thread_wall = true;
- for (var i in this.options._parents[0].messages) {
- var res=this.options._parents[0].messages[i].browse_message(options);
- if (res) return res;
- }
- }
-
- if (this.id==options.id)
- return this;
-
- for (var i in this.thread.messages) {
- if (this.thread.messages[i].thread) {
- var res=this.thread.messages[i].browse_message(options);
- if (res) return res;
- }
- }
+ on_message_read: function (event) {
+ event.stopPropagation();
+ this.on_message_read_unread(true);
+ return false;
+ },
+ on_message_unread: function (event) {
+ event.stopPropagation();
+ this.on_message_read_unread(false);
return false;
},
- /* get all child message id linked.
- * @return array of id
+ /*The selected thread and all childs (messages/thread) became read
+ * @param {object} mouse envent
*/
- get_child_ids: function () {
- var res=[]
- if (arguments[0]) res.push(this.id);
- if (this.thread) {
- res = res.concat( this.thread.get_child_ids(true) );
+ on_message_read_unread: function (read_value) {
+ var self = this;
+ var messages = [this].concat(this.get_childs());
+
+ // inside the inbox, when the user mark a message as read/done, don't apply this value
+ // for the stared/favorite message
+ if (this.options.view_inbox && read_value) {
+ var messages = _.filter(messages, function (val) { return !val.is_favorite && val.id; });
+ if (!messages.length) {
+ this.check_for_rerender();
+ return false;
+ }
}
- return res;
+ var message_ids = _.map(messages, function (val) { return val.id; });
+
+ this.ds_notification.call('set_message_read', [message_ids, read_value, this.context])
+ .then(function () {
+ // apply modification
+ _.each(messages, function (msg) {
+ msg.to_read = !read_value;
+ if (msg.options.toggle_read) {
+ msg.options.show_read = msg.to_read;
+ msg.options.show_unread = !msg.to_read;
+ }
+ });
+ // check if the message must be display, destroy or rerender
+ self.check_for_rerender();
+ });
+ return false;
},
/**
@@ -801,12 +915,13 @@ openerp.mail = function (session) {
*/
on_vote: function (event) {
event.stopPropagation();
- var self=this;
- return this.ds_message.call('vote_toggle', [[self.id]]).then(function (vote) {
- self.has_voted = vote;
- self.vote_nb += self.has_voted ? 1 : -1;
- self.display_vote();
- });
+ this.ds_message.call('vote_toggle', [[this.id]])
+ .then(
+ _.bind(function (vote) {
+ this.has_voted = vote;
+ this.vote_nb += this.has_voted ? 1 : -1;
+ this.display_vote();
+ }, this));
return false;
},
@@ -814,10 +929,10 @@ openerp.mail = function (session) {
* Display the render of this message's vote
*/
display_vote: function () {
- var self = this;
- var vote_element = session.web.qweb.render('mail.thread.message.vote', {'widget': self});
- self.$(".oe_msg_vote:first").remove();
- self.$(".oe_mail_vote_count:first").replaceWith(vote_element);
+ var vote_element = session.web.qweb.render('mail.thread.message.vote', {'widget': this});
+ this.$(".oe_msg_footer:first .oe_mail_vote_count").remove();
+ this.$(".oe_msg_footer:first .oe_msg_vote").replaceWith(vote_element);
+ this.$('.oe_msg_vote').on('click', this.on_vote);
},
/**
@@ -827,34 +942,29 @@ openerp.mail = function (session) {
event.stopPropagation();
var self=this;
var button = self.$('.oe_star:first');
- return this.ds_message.call('favorite_toggle', [[self.id]]).then(function (star) {
- self.is_favorite=star;
- if (self.is_favorite) {
- button.addClass('oe_starred');
- } else {
- button.removeClass('oe_starred');
- if ( self.options.typeof_thread == 'stared' ) {
- self.animated_destroy(150);
+
+ this.ds_message.call('favorite_toggle', [[self.id]])
+ .then(function (star) {
+ self.is_favorite=star;
+ if (self.is_favorite) {
+ button.addClass('oe_starred');
+ } else {
+ button.removeClass('oe_starred');
}
- }
- });
+
+ if (self.options.view_inbox && self.is_favorite) {
+ self.on_message_read_unread(true);
+ } else {
+ self.check_for_rerender();
+ }
+ });
return false;
},
- /**
- * call on_message_delete on his parent thread
- */
- destroy: function () {
-
- this._super();
- this.parent_thread.on_message_detroy(this);
-
- }
-
});
/**
- * ------------------------------------------------------------
+ * ------------------------------------------------------------
* Thread Widget
* ------------------------------------------------------------
*
@@ -881,14 +991,11 @@ openerp.mail = function (session) {
* @param {Object} [thread]
* @param {int} [display_indented_thread] number thread level to indented threads.
* other are on flat mode
- * @param {Select} [typeof_thread] inbox/archives/stared/sent
- * type of thread and option for user application like animate
- * destroy for read/unread
* @param {Array} [parents] liked with the parents thread
* use with browse, fetch... [O]= top parent
*/
init: function (parent, datasets, options) {
- this._super(parent);
+ this._super(parent, options);
this.domain = options.domain || [];
this.context = _.extend({
default_model: 'mail.thread',
@@ -896,21 +1003,24 @@ openerp.mail = function (session) {
default_parent_id: false }, options.context || {});
this.options = options.options;
- this.options._parents = (options.options._parents != undefined ? options.options._parents : []).concat( [this] );
-
+ this.options.root_thread = (options.options.root_thread != undefined ? options.options.root_thread : this);
+ this.options.show_compose_message = this.options.show_compose_message && (this.options.display_indented_thread >= this.thread_level || !this.thread_level);
+
// record options and data
this.parent_message= parent.thread!= undefined ? parent : false ;
// data of this thread
this.id = datasets.id || false,
- this.model = datasets.model || false,
+ this.last_id = datasets.last_id || false,
this.parent_id = datasets.parent_id || false,
+
this.is_private = datasets.is_private || false,
this.author_id = datasets.author_id || false,
this.thread_level = (datasets.thread_level+1) || 0,
this.partner_ids = _.filter(datasets.partner_ids, function (partner) { return partner[0]!=datasets.author_id[0]; } )
this.messages = [];
- this.show_compose_message = this.options.show_compose_message && (this.options.show_reply_button > this.thread_level || !this.thread_level);
+
+ this.options.flat_mode = !!(this.options.display_indented_thread > this.thread_level ? this.options.display_indented_thread - this.thread_level : 0);
// object compose message
this.compose_message = false;
@@ -934,13 +1044,10 @@ openerp.mail = function (session) {
'context': this.context,
'options': this.options,
});
- if (!this.thread_level) {
- // root view
+ if (!this.thread_level || this.thread_level > this.options.display_indented_thread) {
this.compose_message.insertBefore(this.$el);
- } else if (this.thread_level > this.options.display_indented_thread) {
- this.compose_message.insertAfter(this.$el);
} else {
- this.compose_message.appendTo(this.$el);
+ this.compose_message.prependTo(this.$el);
}
}
},
@@ -948,21 +1055,20 @@ openerp.mail = function (session) {
/* When the expandable object is visible on screen (with scrolling)
* then the on_expandable function is launch
*/
- on_scroll: function (event) {
- if (event)event.stopPropagation();
- this.$('.oe_msg_expandable:last');
-
- var message = this.messages[this.messages.length-1];
- if (message && message.type=="expandable" && message.max_limit) {
- var pos = message.$el.position();
+ on_scroll: function () {
+ var expandables =
+ _.each( _.filter(this.messages, function (val) {return val.max_limit && !val.parent_id;}), function (val) {
+ var pos = val.$el.position();
if (pos.top) {
/* bottom of the screen */
var bottom = $(window).scrollTop()+$(window).height()+200;
if (bottom > pos.top) {
- message.on_expandable();
+ val.on_expandable();
+ // load only one time
+ val.loading = true;
}
}
- }
+ });
},
/**
@@ -970,8 +1076,8 @@ openerp.mail = function (session) {
* in the function. */
bind_events: function () {
var self = this;
- self.$el.on('click', '.oe_mail_list_recipients .oe_more', self.on_show_recipients);
- self.$el.on('click', '.oe_mail_compose_textarea .oe_more_hidden', self.on_hide_recipients);
+ self.$('.oe_mail_list_recipients .oe_more').on('click', self.on_show_recipients);
+ self.$('.oe_mail_compose_textarea .oe_more_hidden').on('click', self.on_hide_recipients);
},
/**
@@ -981,6 +1087,7 @@ openerp.mail = function (session) {
var p=$(this).parent();
p.find('.oe_more_hidden, .oe_hidden').show();
p.find('.oe_more').hide();
+ return false;
},
/**
@@ -990,15 +1097,14 @@ openerp.mail = function (session) {
var p=$(this).parent();
p.find('.oe_more_hidden, .oe_hidden').hide();
p.find('.oe_more').show();
+ return false;
},
/* get all child message/thread id linked.
* @return array of id
*/
get_child_ids: function () {
- var res=[];
- _(this.get_childs()).each(function (val, key) { res.push(val.id); });
- return res;
+ return _.map(this.get_childs(), function (val) { return val.id; });
},
/* get all child message/thread linked.
@@ -1033,17 +1139,17 @@ openerp.mail = function (session) {
// goto the wall thread for launch browse
if (!options._go_thread_wall) {
options._go_thread_wall = true;
- return this.options._parents[0].browse_thread(options);
+ return this.options.root_thread.browse_thread(options);
}
- if (this.id==options.id) {
+ if (this.id == options.id) {
return this;
}
if (options.id) {
for (var i in this.messages) {
if (this.messages[i].thread) {
- var res=this.messages[i].thread.browse_thread({'id':options.id, '_go_thread_wall':true});
+ var res = this.messages[i].thread.browse_thread({'id':options.id, '_go_thread_wall':true});
if (res) return res;
}
}
@@ -1067,8 +1173,8 @@ openerp.mail = function (session) {
* @return message object
*/
browse_message: function (options) {
- if (this.options._parents[0].messages[0])
- return this.options._parents[0].messages[0].browse_message(options);
+ if (this.options.root_thread.messages[0])
+ return this.options.root_thread.messages[0].browse_message(options);
},
/**
@@ -1079,6 +1185,7 @@ openerp.mail = function (session) {
on_compose_message: function () {
this.instantiate_compose_message();
this.compose_message.on_compose_expandable();
+ return false;
},
/**
@@ -1086,8 +1193,8 @@ openerp.mail = function (session) {
*/
no_message: function () {
var no_message = $(session.web.qweb.render('mail.wall_no_message', {}));
- if (this.options.no_message) {
- no_message.html(this.options.no_message);
+ if (this.options.help) {
+ no_message.html(this.options.help);
}
no_message.appendTo(this.$el);
},
@@ -1101,18 +1208,20 @@ openerp.mail = function (session) {
* @param {Array} ids read (if the are some ids, the method don't use the domain)
*/
message_fetch: function (replace_domain, replace_context, ids, callback) {
- var self = this;
-
- // domain and context: options + additional
- fetch_domain = replace_domain ? replace_domain : this.domain;
- fetch_context = replace_context ? replace_context : this.context;
- var message_loaded_ids = this.id ? [this.id].concat( self.get_child_ids() ) : self.get_child_ids();
-
- // CHM note : option for sending in flat mode by server
- var thread_level = this.options.display_indented_thread > this.thread_level ? this.options.display_indented_thread - this.thread_level : 0;
-
- return this.ds_message.call('message_read', [ids, fetch_domain, message_loaded_ids, thread_level, fetch_context, this.context.default_parent_id || undefined])
- .done(callback ? _.bind(callback, this, arguments) : this.proxy('switch_new_message'));
+ return this.ds_message.call('message_read', [
+ // ids force to read
+ ids == false ? undefined : ids,
+ // domain + additional
+ (replace_domain ? replace_domain : this.domain),
+ // ids allready loaded
+ (this.id ? [this.id].concat( this.get_child_ids() ) : this.get_child_ids()),
+ // option for sending in flat mode by server
+ this.options.flat_mode,
+ // context + additional
+ (replace_context ? replace_context : this.context),
+ // parent_id
+ this.context.default_parent_id || undefined
+ ]).done(callback ? _.bind(callback, this, arguments) : this.proxy('switch_new_message'));
},
/**
@@ -1128,22 +1237,23 @@ openerp.mail = function (session) {
data.options = _.extend(self.options, data.options);
if (data.type=='expandable') {
- var message = new mail.ThreadExpandable(self, data, {
+ var message = new mail.ThreadExpandable(self, data, {'context':{
'default_model': data.model || self.context.default_model,
'default_res_id': data.res_id || self.context.default_res_id,
'default_parent_id': self.id,
- });
+ }});
} else {
- var message = new mail.ThreadMessage(self, data, {
+ var message = new mail.ThreadMessage(self, data, {'context':{
'default_model': data.model,
'default_res_id': data.res_id,
'default_parent_id': data.id,
- });
+ }});
}
// check if the message is already create
for (var i in self.messages) {
if (self.messages[i] && self.messages[i].id == message.id) {
+ console.log('Reload message', message.id);
self.messages[i].destroy();
}
}
@@ -1161,76 +1271,22 @@ openerp.mail = function (session) {
* The sort is define by the thread_level (O for newer on top).
* @param : {object} ThreadMessage object
*/
- insert_message: function (message, dom_insert_after) {
+ insert_message: function (message, dom_insert_after, prepend) {
var self=this;
-
- if (this.show_compose_message && this.options.show_compact_message) {
+ if (this.options.show_compact_message > this.thread_level) {
this.instantiate_compose_message();
this.compose_message.do_show_compact();
}
- this.$('.oe_wall_no_message').remove();
+ this.$('.oe_view_nocontent').remove();
if (dom_insert_after) {
message.insertAfter(dom_insert_after);
- return message
- }
-
- // check older and newer message for insertion
- var message_newer = false;
- var message_older = false;
- if (message.id > 0) {
- for (var i in self.messages) {
- if (self.messages[i].id > message.id) {
- if (!message_newer || message_newer.id > self.messages[i].id) {
- message_newer = self.messages[i];
- }
- } else if (self.messages[i].id > 0 && self.messages[i].id < message.id) {
- if (!message_older || message_older.id < self.messages[i].id) {
- message_older = self.messages[i];
- }
- }
- }
- }
-
- var sort = (!!self.thread_level || message.id<0);
-
- if (sort) {
- if (message_older) {
-
- message.insertAfter(message_older.thread ? (message_older.thread.compose_message ? message_older.thread.compose_message.$el : message_older.thread.$el) : message_older.$el);
-
- } else if (message_newer) {
-
- message.insertBefore(message_newer.$el);
-
- } else if (message.id < 0) {
-
- message.appendTo(self.$el);
-
- } else {
-
- message.prependTo(self.$el);
- }
+ }if (prepend) {
+ message.prependTo(self.$el);
} else {
- if (message_older) {
-
- message.insertBefore(message_older.$el);
-
- } else if (message_newer) {
-
- message.insertAfter(message_newer.thread ? (message_newer.thread.compose_message ? message_newer.thread.compose_message.$el : message_newer.thread.$el) : message_newer.$el );
-
- } else if (message.id < 0) {
-
- message.prependTo(self.$el);
-
- } else {
-
- message.appendTo(self.$el);
-
- }
+ message.appendTo(self.$el);
}
return message
@@ -1241,7 +1297,7 @@ openerp.mail = function (session) {
* Each message is send to his parent object (or parent thread flat mode) for creating the object message.
* @param : {Array} datas from calling RPC to "message_read"
*/
- switch_new_message: function (records) {
+ switch_new_message: function (records, dom_insert_after) {
var self=this;
_(records).each(function (record) {
var thread = self.browse_thread({
@@ -1251,7 +1307,7 @@ openerp.mail = function (session) {
// create object and attach to the thread object
var message = thread.create_message_object( record );
// insert the message on dom
- thread.insert_message( message );
+ thread.insert_message( message, typeof dom_insert_after == 'object' ? dom_insert_after : false);
});
},
@@ -1262,6 +1318,10 @@ openerp.mail = function (session) {
on_message_detroy: function (message) {
this.messages = _.filter(this.messages, function (val) { return !val.isDestroyed(); });
+ if (this.options.root_thread == this && !this.messages.length) {
+ this.no_message();
+ }
+ return false;
},
@@ -1323,7 +1383,6 @@ openerp.mail = function (session) {
} else {
// create a expandable message
var expandable = new mail.ThreadExpandable(this, {
- 'id': message.id,
'model': message.model,
'parent_id': message.parent_id,
'nb_messages': 1,
@@ -1332,9 +1391,11 @@ openerp.mail = function (session) {
'domain': message_dom,
'options': message.options,
}, {
- 'default_model': message.model || this.context.default_model,
- 'default_res_id': message.res_id || this.context.default_res_id,
- 'default_parent_id': this.id,
+ 'context':{
+ 'default_model': message.model || this.context.default_model,
+ 'default_res_id': message.res_id || this.context.default_res_id,
+ 'default_parent_id': this.id,
+ }
});
// add object on array and DOM
@@ -1350,7 +1411,7 @@ openerp.mail = function (session) {
});
/**
- * ------------------------------------------------------------
+ * ------------------------------------------------------------
* mail : root Widget
* ------------------------------------------------------------
*
@@ -1360,7 +1421,7 @@ openerp.mail = function (session) {
*/
session.web.client_actions.add('mail.Widget', 'session.mail.Widget');
mail.Widget = session.web.Widget.extend({
- template: 'mail.Widget',
+ template: 'mail.Root',
/**
* @param {Object} parent parent
@@ -1368,15 +1429,13 @@ openerp.mail = function (session) {
* @param {Object} [context] context of the thread. It should
* contain at least default_model, default_res_id. Please refer to
* the compose_message widget for more information about it.
- * ... @param {Select} [typeof_thread=(mail|stared|archives|send|other)]
- * options for destroy message when the user click on a button
* @param {Object} [options]
*... @param {Number} [truncate_limit=250] number of character to
* display before having a "show more" link; note that the text
* will not be truncated if it does not have 110% of the parameter
*... @param {Boolean} [show_record_name] display the name and link for do action
- *... @param {int} [show_reply_button] number thread level to display the reply button
- *... @param {int} [show_read_unread_button] number thread level to display the read/unread button
+ *... @param {boolean} [show_reply_button] display the reply button
+ *... @param {boolean} [show_read_unread_button] display the read/unread button
*... @param {int} [display_indented_thread] number thread level to indented threads.
* other are on flat mode
*... @param {Boolean} [show_compose_message] allow to display the composer
@@ -1387,35 +1446,25 @@ openerp.mail = function (session) {
* @param {String} [no_message] Message to display when there are no message
*/
init: function (parent, action) {
- var options = action.params || {};
- this._super(parent);
- this.domain = options.domain || [];
- this.context = options.context || {};
- this.search_results = {'domain': [], 'context': {}, 'groupby': {}};
+ this._super(parent, action);
+ var self = this;
+ this.action = _.clone(action);
+ this.domain = this.action.domain || this.action.params.domain || [];
+ this.context = this.action.context || this.action.params.context || {};
- this.options = _.extend({
- 'typeof_thread' : 'inbox',
+ this.action.params = _.extend({
'display_indented_thread' : -1,
- 'show_reply_button' : -1,
- 'show_read_unread_button' : -1,
+ 'show_reply_button' : false,
+ 'show_read_unread_button' : false,
'truncate_limit' : 250,
'show_record_name' : false,
'show_compose_message' : false,
'show_compact_message' : false,
+ 'view_inbox': false,
'message_ids': undefined,
- 'no_message': false
- }, options);
+ }, this.action.params);
- if (this.display_indented_thread === false) {
- this.display_indented_thread = -1;
- }
- if (this.show_reply_button === false) {
- this.show_reply_button = -1;
- }
- if (this.show_read_unread_button === false) {
- this.show_read_unread_button = -1;
- }
-
+ this.action.params.help = this.action.help || false;
},
start: function (options) {
@@ -1423,7 +1472,6 @@ openerp.mail = function (session) {
this.message_render();
this.bind_events();
},
-
/**
*Create the root thread and display this object in the DOM.
@@ -1435,35 +1483,32 @@ openerp.mail = function (session) {
this.thread = new mail.Thread(this, {}, {
'domain' : this.domain,
'context' : this.context,
- 'options': this.options,
+ 'options': this.action.params,
});
this.thread.appendTo( this.$el );
this.thread.no_message();
- this.thread.message_fetch(null, null, this.options.message_ids);
- if (this.options.show_compose_message) {
+ if (this.action.params.show_compose_message) {
this.thread.instantiate_compose_message();
- if (this.options.show_compact_message) {
- this.thread.compose_message.do_show_compact();
- } else {
- this.thread.compose_message.do_hide_compact();
- }
+ this.thread.compose_message.do_show_compact();
}
+
+ this.thread.message_fetch(null, null, this.action.params.message_ids);
+
},
bind_events: function () {
- if (this.context['typeof_thread']!='other') {
- $(document).scroll( this.thread.on_scroll );
- $(window).resize( this.thread.on_scroll );
- window.setTimeout( this.thread.on_scroll, 500 );
- }
+ $(document).scroll( _.bind(this.thread.on_scroll, this.thread) );
+ $(window).resize( _.bind(this.thread.on_scroll, this.thread) );
+ this.$el.resize( _.bind(this.thread.on_scroll, this.thread) );
+ window.setTimeout( _.bind(this.thread.on_scroll, this.thread), 500 );
}
});
/**
- * ------------------------------------------------------------
+ * ------------------------------------------------------------
* mail_thread Widget
* ------------------------------------------------------------
*
@@ -1476,10 +1521,18 @@ openerp.mail = function (session) {
mail.RecordThread = session.web.form.AbstractField.extend({
template: 'mail.record_thread',
- init: function () {
+ init: function (parent, node) {
this._super.apply(this, arguments);
- this.options.domain = this.options.domain || [];
- this.options.context = {'default_model': 'mail.thread', 'default_res_id': false};
+ this.node = _.clone(node);
+
+ this.node.params = _.extend({
+ 'display_indented_thread': -1,
+ 'show_reply_button': false,
+ 'show_read_unread_button': false,
+ 'show_compact_message': 1,
+ }, this.node.params);
+
+ this.domain = this.node.params && this.node.params.domain || [];
},
start: function () {
@@ -1492,42 +1545,32 @@ openerp.mail = function (session) {
_check_visibility: function () {
this.$el.toggle(this.view.get("actual_mode") !== "create");
},
+
render_value: function () {
var self = this;
+
if (! this.view.datarecord.id || session.web.BufferedDataSet.virtual_id_regex.test(this.view.datarecord.id)) {
this.$('oe_mail_thread').hide();
return;
}
- // update context
- _.extend(this.options.context, {
- default_res_id: this.view.datarecord.id,
- default_model: this.view.model,
- default_is_private: false });
- // update domain
- var domain = this.options.domain.concat([['model', '=', this.view.model], ['res_id', '=', this.view.datarecord.id]]);
-
- var show_compose_message = this.view.is_action_enabled('edit') ||
- (this.getParent().fields.message_is_follower && this.getParent().fields.message_is_follower.get_value());
- var message_ids = this.getParent().fields.message_ids && this.getParent().fields.message_ids.get_value();
+ this.node.params = _.extend(this.node.params, {
+ 'message_ids': this.get_value(),
+ 'show_compose_message': this.view.is_action_enabled('edit'),
+ });
+ this.node.context = {
+ 'default_res_id': this.view.datarecord.id || false,
+ 'default_model': this.view.model || false,
+ };
if (this.root) {
+ $('<span class="oe_mail-placeholder"/>').insertAfter(this.root.$el);
this.root.destroy();
}
// create and render Thread widget
- this.root = new mail.Widget(this, { params: {
- 'domain' : domain,
- 'context' : this.options.context,
- 'typeof_thread': this.options.context['typeof_thread'] || 'other',
- 'display_indented_thread': -1,
- 'show_reply_button': 0,
- 'show_read_unread_button': -1,
- 'show_compose_message': show_compose_message,
- 'message_ids': message_ids,
- 'show_compact_message': true,
- 'no_message': this.node.attrs.help
- }}
- );
+ this.root = new mail.Widget(this, _.extend(this.node, {
+ 'domain' : (this.domain || []).concat([['model', '=', this.view.model], ['res_id', '=', this.view.datarecord.id]]),
+ }));
return this.root.replace(this.$('.oe_mail-placeholder'));
},
@@ -1535,7 +1578,7 @@ openerp.mail = function (session) {
/**
- * ------------------------------------------------------------
+ * ------------------------------------------------------------
* Wall Widget
* ------------------------------------------------------------
*
@@ -1543,6 +1586,7 @@ openerp.mail = function (session) {
* use is to receive a context and a domain, and to delegate the message
* fetching and displaying to the Thread widget.
*/
+
session.web.client_actions.add('mail.wall', 'session.mail.Wall');
mail.Wall = session.web.Widget.extend({
template: 'mail.wall',
@@ -1555,35 +1599,53 @@ openerp.mail = function (session) {
* contain default_model, default_res_id, to give it to the threads.
*/
init: function (parent, action) {
- this._super(parent);
- var options = action.params || {};
- this.options = options;
- this.options.domain = options.domain || [];
- this.options.context = options.context || {};
- this.search_results = {'domain': [], 'context': {}, 'groupby': {}}
- this.ds_msg = new session.web.DataSetSearch(this, 'mail.message');
+ this._super(parent, action);
+
+ this.action = _.clone(action);
+ this.domain = this.action.params.domain || this.action.domain || [];
+ this.context = this.action.params.context || this.action.context || {};
+
+ this.defaults = {};
+ for (var key in this.context) {
+ if (key.match(/^search_default_/)) {
+ this.defaults[key.replace(/^search_default_/, '')] = this.context[key];
+ }
+ }
+
+ this.action.params = _.extend({
+ 'display_indented_thread': 1,
+ 'show_reply_button': true,
+ 'show_read_unread_button': true,
+ 'show_compose_message': true,
+ 'show_compact_message': this.action.params.view_mailbox ? false : 1,
+ 'view_inbox': false,
+ }, this.action.params);
},
start: function () {
- this._super.apply(this, arguments);
- var searchview_ready = this.load_searchview({}, false);
- var thread_displayed = this.message_render();
- this.options.domain = this.options.domain.concat(this.search_results['domain']);
+ this._super.apply(this);
this.bind_events();
- return $.when(searchview_ready, thread_displayed);
+ var searchview_loaded = this.load_searchview(this.defaults);
+ if (! this.searchview.has_defaults) {
+ this.message_render();
+ }
+
},
/**
* Load the mail.message search view
* @param {Object} defaults ??
- * @param {Boolean} hidden some kind of trick we do not care here
*/
- load_searchview: function (defaults, hidden) {
+ load_searchview: function (defaults) {
var self = this;
- this.searchview = new session.web.SearchView(this, this.ds_msg, false, defaults || {}, hidden || false);
- return this.searchview.appendTo(this.$('.oe_view_manager_view_search')).done(function () {
- self.searchview.on('search_data', self, self.do_searchview_search);
- });
+ var ds_msg = new session.web.DataSetSearch(this, 'mail.message');
+ this.searchview = new session.web.SearchView(this, ds_msg, false, defaults || {}, false);
+ this.searchview.appendTo(this.$('.oe_view_manager_view_search'))
+ .then(function () { self.searchview.on('search_data', self, self.do_searchview_search); });
+ if (this.searchview.has_defaults) {
+ this.searchview.ready.then(this.searchview.do_search);
+ }
+ return this.searchview
},
/**
@@ -1599,33 +1661,26 @@ openerp.mail = function (session) {
domains: domains || [],
contexts: contexts || [],
group_by_seq: groupbys || []
- }).done(function (results) {
- self.search_results['context'] = results.context;
- self.search_results['domain'] = results.domain;
- self.root.destroy();
- return self.message_render();
+ }).then(function (results) {
+ if(self.root) {
+ $('<span class="oe_mail-placeholder"/>').insertAfter(self.root.$el);
+ self.root.destroy();
+ }
+ return self.message_render(results);
});
},
-
/**
- *Create the root thread widget and display this object in the DOM
- */
+ * Create the root thread widget and display this object in the DOM
+ */
message_render: function (search) {
- var domain = this.options.domain.concat(this.search_results['domain']);
- var context = _.extend(this.options.context, search&&search.search_results['context'] ? search.search_results['context'] : {});
- this.root = new mail.Widget(this, { params: {
+ var domain = this.domain.concat(search && search['domain'] ? search['domain'] : []);
+ var context = _.extend(this.context, search && search['context'] ? search['context'] : {});
+
+ this.root = new mail.Widget(this, _.extend(this.action, {
'domain' : domain,
'context' : context,
- 'typeof_thread': context['typeof_thread'] || 'other',
- 'display_indented_thread': 1,
- 'show_reply_button': 10,
- 'show_read_unread_button': 11,
- 'show_compose_message': true,
- 'show_compact_message': false,
- }}
- );
-
+ }));
return this.root.replace(this.$('.oe_mail-placeholder'));
},
@@ -1642,7 +1697,6 @@ openerp.mail = function (session) {
views: [[false, 'form']],
target: 'new',
context: {
- 'default_content_subtype': 'html',
},
};
session.client.action_manager.do_action(action);
@@ -1653,19 +1707,18 @@ openerp.mail = function (session) {
/**
- * ------------------------------------------------------------
+ * ------------------------------------------------------------
* UserMenu
* ------------------------------------------------------------
*
* Add a link on the top user bar for write a full mail
*/
session.web.ComposeMessageTopButton = session.web.Widget.extend({
- template:'mail.compose_message.button_top_bar',
+ template:'mail.ComposeMessageTopButton',
- start: function (parent, params) {
- var self = this;
- this.$el.on('click', 'button', self.on_compose_message );
- this._super(parent, params);
+ start: function () {
+ this.$('button').on('click', this.on_compose_message );
+ this._super();
},
on_compose_message: function (event) {
@@ -1675,26 +1728,22 @@ openerp.mail = function (session) {
res_model: 'mail.compose.message',
view_mode: 'form',
view_type: 'form',
- action_from: 'mail.ThreadComposeMessage',
views: [[false, 'form']],
target: 'new',
- context: {
- 'default_model': '',
- 'default_res_id': false,
- 'default_content_subtype': 'html',
- },
+ context: {},
};
session.client.action_manager.do_action(action);
},
-
});
- session.web.UserMenu = session.web.UserMenu.extend({
- start: function (parent, params) {
- var render = new session.web.ComposeMessageTopButton();
- render.insertAfter(this.$el);
- this._super(parent, params);
- }
+ session.web.UserMenu.include({
+ do_update: function(){
+ var self = this;
+ this._super.apply(this, arguments);
+ this.update_promise.then(function() {
+ var mail_button = new session.web.ComposeMessageTopButton();
+ mail_button.appendTo(session.webclient.$el.find('.oe_systray'));
+ });
+ },
});
-
};
diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js
index a5a97f48d26..7bb019cde4f 100644
--- a/addons/mail/static/src/js/mail_followers.js
+++ b/addons/mail/static/src/js/mail_followers.js
@@ -30,6 +30,8 @@ openerp_mail_followers = function(session, mail) {
this.ds_model = new session.web.DataSetSearch(this, this.view.model);
this.ds_follow = new session.web.DataSetSearch(this, this.field.relation);
this.ds_users = new session.web.DataSetSearch(this, 'res.users');
+
+ this.value = [];
},
start: function() {
@@ -41,6 +43,11 @@ openerp_mail_followers = function(session, mail) {
this._super();
},
+ set_value: function(_value) {
+ this.value = _value;
+ this._super(_value);
+ },
+
_check_visibility: function() {
this.$el.toggle(this.view.get("actual_mode") !== "create");
},
@@ -86,13 +93,14 @@ openerp_mail_followers = function(session, mail) {
read_value: function () {
var self = this;
return this.ds_model.read_ids([this.view.datarecord.id], ['message_follower_ids']).then(function (results) {
- self.set_value(results[0].message_follower_ids);
+ self.value = results[0].message_follower_ids;
+ self.render_value();
});
},
render_value: function () {
this.reinit();
- return this.fetch_followers(this.get("value"));
+ return this.fetch_followers(this.value);
},
fetch_followers: function (value_) {
@@ -111,7 +119,7 @@ openerp_mail_followers = function(session, mail) {
event.preventDefault();
return this.ds_users.call('read', [this.session.uid, ['partner_id']]).then(function (results) {
var pid = results['partner_id'][0];
- self.message_is_follower = (_.indexOf(self.get('value'), pid) != -1);
+ self.message_is_follower = (_.indexOf(self.value, pid) != -1);
}).then(self.proxy('display_generic'));
},
_format_followers: function(count){
@@ -131,7 +139,7 @@ openerp_mail_followers = function(session, mail) {
display_generic: function () {
var self = this;
var node_user_list = this.$('.oe_follower_list').empty();
- this.$('.oe_follower_title').html(this._format_followers(this.get('value').length));
+ this.$('.oe_follower_title').html(this._format_followers(this.value.length));
},
/** Display the followers */
@@ -206,7 +214,8 @@ openerp_mail_followers = function(session, mail) {
$(record).attr('checked',false);
});
var context = new session.web.CompoundContext(this.build_context(), {});
- return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id], [this.session.uid], context]).then(this.proxy('read_value'));
+ return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id], [this.session.uid], context])
+ .then(this.proxy('read_value'));
},
do_update_subscription: function (event) {
@@ -220,7 +229,7 @@ openerp_mail_followers = function(session, mail) {
});
var context = new session.web.CompoundContext(this.build_context(), {});
- return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], this.message_is_follower ? checklist:undefined, context])
+ return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], this.message_is_follower ? checklist : undefined, context])
.then(this.proxy('read_value'));
},
});
diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml
index bfd0e4cd10f..89fbe45dc36 100644
--- a/addons/mail/static/src/xml/mail.xml
+++ b/addons/mail/static/src/xml/mail.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<template>
- <!-- this template contains the mail widget and is used to namespace the css -->
- <t t-name="mail.Widget">
+ <!--
+ mail.Widget template used to namespace the css -->
+ <t t-name="mail.Root">
<div class="oe_mail">
</div>
</t>
@@ -38,7 +39,8 @@
</div>
</div>
<div t-if="widget.show_compact_message and !widget.show_composer" t-attf-class="oe_msg oe_msg_composer_compact #{widget.thread_level and widget.options.display_indented_thread > -1 ? 'oe_msg_indented' : ''}">
- <textarea class="field_text oe_compact" placeholder="Write a reply..."/>
+ <textarea t-if="!widget.options.view_mailbox" class="field_text oe_compact" placeholder="Write to the followers of this docmuent..."/>
+ <textarea t-if="widget.options.view_mailbox" class="field_text oe_compact" placeholder="Write to my followers..."/>
</div>
<span t-if="!(widget.show_compact_message and !widget.show_composer) and !widget.show_composer" class="oe_placeholder_compose"></span>
</t>
@@ -69,41 +71,28 @@
Template used to display attachments in a mail.message
-->
<t t-name="mail.thread.message.attachments">
- <span class="oe_msg_attachments">
- <t t-foreach="widget.attachment_ids" t-as="attachment" t-if="!attachment.is_image">
- <div class="oe_attachment">
- <span t-if="(attachment.upload and attachment.percent_loaded&lt;100)" t-attf-title="{(attachment.name || attachment.filename) + (attachment.date?' \n('+attachment.date+')':'' )}" t-attf-name="{attachment.name || attachment.filename}">
- <div class="oe_upload_in_process">
- <span>...Upload in progress...</span>
- </div>
- <t t-raw="attachment.name || attachment.filename"/>
- </span>
- <t t-if="(!attachment.upload or attachment.percent_loaded&gt;=100)">
- <a t-att-href="attachment.url" t-attf-title="{(attachment.name || attachment.filename) + (attachment.date?' \n('+attachment.date+')':'' )}">
- <t t-raw="attachment.name || attachment.filename"/>
- </a>
- </t>
- <t t-if="(widget.show_delete_attachment and (!attachment.upload or attachment.percent_loaded&gt;=100))">
- <a class="oe_right oe_mail_attachment_delete oe_e" title="Delete this attachment" t-attf-data-id="{attachment.id}">[</a>
- </t>
+ <t t-foreach='widget.attachment_ids' t-as='attachment'>
+ <t t-if="attachment.filetype !== 'webimage'">
+ <div t-attf-class="oe_attachment #{attachment.upload ? 'oe_uploading' : ''}">
+ <a t-att-href='attachment.url'><img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.filetype + '.png'"></img></a>
+ <div class='oe_delete oe_e' title="Delete this attachment" t-attf-data-id="{attachment.id}">[</div>
+ <div class='oe_name'><t t-raw='attachment.name' /></div>
+ <div class='oe_progress_bar'>
+ uploading
+ </div>
</div>
</t>
- </span>
- <span class="oe_msg_images">
- <t t-foreach="widget.attachment_ids" t-as="attachment" t-if="attachment.is_image">
- <a t-att-href="attachment.url" t-attf-title="{(attachment.name || attachment.filename) + (attachment.date?' \n('+attachment.date+')':'' )}">
- <img t-if="attachment.is_image" t-attf-title="{(attachment.name || attachment.filename) + (attachment.date?' \n('+attachment.date+')':'' )}" t-att-src="attachment.url"/>
- </a>
+ <t t-if="attachment.filetype === 'webimage'">
+ <div t-attf-class="oe_attachment oe_preview #{attachment.upload ? 'oe_uploading' : ''}">
+ <a t-att-href='attachment.url'><img t-att-src="widget.attachments_resize_image(attachment.id, [100,100])"></img></a>
+ <div class='oe_delete oe_e'>[</div>
+ <div class='oe_name'><t t-raw='attachment.name' /></div>
+ <div class='oe_progress_bar'>
+ uploading
+ </div>
+ </div>
</t>
- </span>
- </t>
-
- <t t-name="mail.thread.message.private">
- <div>
- <span class="oe_placeholder_checkbox_private"/>
- <span class="oe_send_private">This email is private.</span>
- <span class="oe_send_public">I wrote for contacts and all my followers.</span>
- </div>
+ </t>
</t>
<!--
@@ -112,7 +101,7 @@
<t t-name="mail.thread.list_recipients">
<div class="oe_mail_list_recipients">
To:
- <span t-if="!widget.is_private" class="oe_all_follower">Everyone</span>
+ <span t-if="!widget.is_private" class="oe_all_follower">Followers <t t-raw="' of ' + (widget.parent_thread.parent_message.record_name ? '&quot;' + widget.parent_thread.parent_message.record_name + '&quot;' : 'this document')"/></span>
<t t-if="!widget.is_private and widget.partner_ids.length"> and </t>
<t t-set="inc" t-value="0"/>
<t t-if="widget.partner_ids.length" t-foreach="widget.partner_ids" t-as="partner"><span t-attf-class="oe_partner_follower #{inc>=3?'oe_hidden':''}"><t t-if="inc" t-raw="', '"/><a t-attf-href="#model=res.partner&amp;id=#{partner[0]}"><t t-raw="partner[1]"/></a></span><t t-set="inc" t-value="inc+1"/>
@@ -140,22 +129,20 @@
<td colspan="2">
<h2 class="oe_view_title">
<span class="oe_view_title_text">
- News Feed
- <t t-if="widget.options.res_model"> / </t>
- <t t-if="widget.options.res_model" t-esc="widget.options.res_model"/>
+ Email box
</span>
</h2>
</td>
<td><div class="oe_view_manager_view_search" t-opentag="true"/></td>
</tr>
- <tr class="oe_header_row">
+ <tr class="oe_header_row" t-if="widget.action.params.view_inbox" >
<td colspan="2">
<button type="button" class="oe_write_full oe_highlight">
Compose a new message
</button>
<span class='oe_alternative'>
or
- <a href='#' class='oe_write_onwall oe_bold' help='Your followers can read this message'>Write to your followers</a>
+ <a href='#' class='oe_write_onwall oe_bold' help='Your followers can read this message'>Write to my followers</a>
</span>
</td>
</tr>
@@ -168,7 +155,7 @@
display message on the wall when there are no message
-->
<t t-name="mail.wall_no_message">
- <div class="oe_wall_no_message">You have no messages</div>
+ <div class="oe_view_nocontent">No messages.</div>
</t>
<!--
@@ -187,7 +174,7 @@
<!-- default layout -->
<t t-name="mail.thread.message">
- <div t-attf-class="oe_msg #{widget.thread_level and widget.options.display_indented_thread > -1 ? 'oe_msg_indented' : ''} oe_msg_#{widget.type} oe_msg_#{widget.to_read?'unread':'read'}">
+ <div t-attf-class="oe_msg #{widget.thread_level and widget.options.display_indented_thread > -1 ? 'oe_msg_indented' : ''} oe_msg_#{widget.type}">
<div class='oe_msg_left'>
<a t-attf-href="#model=res.partner&amp;id=#{widget.author_id[0]}" t-att-title="widget.author_id[1]">
@@ -197,10 +184,11 @@
<div class="oe_msg_center">
<div class='oe_msg_icons'>
- <span class='oe_read' t-if="widget.show_read_unread_button"><a title="Mark as read" class="oe_e">X</a></span>
- <span class='oe_unread' t-if="widget.show_read_unread_button"><a title="Mark as unread" class="oe_e">v</a></span>
- <span class='oe_reply' t-if="widget.show_reply_button"><a title="Reply" class="oe_e">(</a></span>
- <span t-attf-class="oe_star #{widget.is_favorite?'oe_starred':''}"><a title="Add To Favorites" class="oe_e">7</a></span>
+ <span class='oe_read' t-if="widget.options.show_read"><a title="Done" class="oe_e">X</a></span>
+ <span class='oe_unread' t-if="widget.is_favorite and widget.options.show_unread"><a title="Set back to Todo" class="oe_e">v</a></span>
+ <span class='oe_unread' t-if="!widget.is_favorite and widget.options.show_unread"><a title="Set back to Inbox" class="oe_e">v</a></span>
+ <span class='oe_reply' t-if="widget.options.show_reply_button"><a title="Reply" class="oe_e">(</a></span>
+ <span t-attf-class="oe_star #{widget.is_favorite?'oe_starred':''}"><a title="Mark as Todo" class="oe_e">7</a></span>
</div>
<!-- message itself -->
<div class="oe_msg_content">
@@ -208,23 +196,26 @@
<t t-raw="widget.subject"/>
</h1>
<div class="oe_msg_body">
- <t t-if="widget.options.show_record_name and widget.record_name and (!widget.subject) and !widget.options.thread_level and !widget.options.display_on_thread[0] and widget.model!='res.partner'">
+ <t t-if="widget.show_record_name">
<a class="oe_mail_action_model" t-attf-href="#model=#{widget.model}&amp;id=#{widget.res_id}"><t t-raw="widget.record_name"/></a>
</t>
<t t-raw="widget.body"/>
</div>
- <t t-if="widget.attachment_ids.length > 0">
- <t t-call="mail.thread.message.attachments"/>
- </t>
</div>
<div class="oe_msg_footer">
+ <t t-if="widget.attachment_ids.length > 0">
+ <div class="oe_msg_attachment_list"></div>
+ </t>
<a t-if="widget.author_id" t-attf-href="#model=res.partner&amp;id=#{widget.author_id[0]}"><t t-raw="widget.author_id[1]"/></a>
<span class='oe_subtle'>•</span>
<span t-att-title="widget.date"><t t-raw="widget.timerelative"/></span>
- <a t-if="widget.attachment_ids.length > 0" class="oe_mail_msg_view_attachments">
+ <t t-if='widget.attachment_ids.length > 0'>
+ <span class='oe_subtle'>•</span>
+ <a class="oe_view_attachments">
<t t-if="widget.attachment_ids.length == 1">1 Attachment</t>
<t t-if="widget.attachment_ids.length > 1"><t t-raw="widget.attachment_ids.length"/> Attachments</t>
</a>
+ </t>
<span class='oe_subtle'>•</span>
<t t-call="mail.thread.message.vote"/>
</div>
@@ -234,11 +225,12 @@
<!-- expandable message layout -->
<t t-name="mail.thread.expandable">
- <div t-attf-class="oe_msg oe_msg_#{widget.type} #{widget.thread_level and widget.options.display_indented_thread > -1 ? 'oe_msg_indented' : ''} oe_msg_unread">
+ <div t-attf-class="oe_msg oe_msg_#{widget.type} #{widget.max_limit ? 'oe_max_limit' : ''} #{widget.thread_level and widget.options.display_indented_thread > -1 ? 'oe_msg_indented' : ''}">
<div class="oe_msg_content oe_msg_more_message">
<div class='oe_separator'></div>
+ <a t-if="widget.nb_messages &lt;= 0" class="oe_msg_fetch_more">show more message</a>
<a t-if="widget.nb_messages === 1" class="oe_msg_fetch_more">show one more message</a>
- <a t-if="widget.nb_messages !== 1" class="oe_msg_fetch_more">show <t t-raw="widget.nb_messages" /> more messages</a>
+ <a t-if="widget.nb_messages &gt; 1" class="oe_msg_fetch_more">show <t t-raw="widget.nb_messages" /> more messages</a>
</div>
</div>
</t>
@@ -247,9 +239,9 @@
mail.compose_message.button_top_bar
render of the button on the user bar for open wizard compose message
-->
- <t t-name="mail.compose_message.button_top_bar">
- <div class="oe_topbar_compose_full_email">
- <!-- <button class="oe_button oe_highlight">Write an email</button> -->
+ <t t-name="mail.ComposeMessageTopButton">
+ <div title='Compose new Message' class="oe_topbar_item oe_topbar_compose_full_email">
+ <button class="oe_e">%</button>
</div>
</t>
@@ -257,12 +249,11 @@
Template used to display Like/Unlike in a mail.message
-->
<span t-name="mail.thread.message.vote">
-
<span class="oe_mail_vote_count" t-if='widget.vote_nb > 0'>
<t t-raw='widget.vote_nb' />
<span class='oe_e'>8</span>
</span>
- <a href='#' t-attf-class="oe_msg_vote">
+ <a href='#' class="oe_msg_vote">
<t t-if="!widget.has_voted">like</t>
<t t-if="widget.has_voted">unlike</t>
</a>
diff --git a/addons/mail/tests/__init__.py b/addons/mail/tests/__init__.py
index 2d48fa233c4..3dcddf769e8 100644
--- a/addons/mail/tests/__init__.py
+++ b/addons/mail/tests/__init__.py
@@ -18,6 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
+
from . import test_mail, test_mail_access_rights
checks = [
diff --git a/addons/mail/tests/test_mail.py b/addons/mail/tests/test_mail.py
index 8e880a611a7..99ccd41e1f7 100644
--- a/addons/mail/tests/test_mail.py
+++ b/addons/mail/tests/test_mail.py
@@ -21,8 +21,8 @@
import tools
-from openerp.tests import common
-from openerp.tools.html_sanitize import html_sanitize
+from openerp.addons.mail.tests import test_mail_mockup
+from openerp.tools.mail import html_sanitize
MAIL_TEMPLATE = """Return-Path: <whatever-2a840@postmaster.twitter.com>
To: {to}
@@ -84,43 +84,11 @@ Sylvie
"""
-class TestMailMockups(common.TransactionCase):
-
- def _mock_smtp_gateway(self, *args, **kwargs):
- return True
-
- def _init_mock_build_email(self):
- self._build_email_args_list = []
- self._build_email_kwargs_list = []
-
- def _mock_build_email(self, *args, **kwargs):
- """ Mock build_email to be able to test its values. Store them into
- some internal variable for latter processing. """
- self._build_email_args_list.append(args)
- self._build_email_kwargs_list.append(kwargs)
- return self._build_email(*args, **kwargs)
-
- def setUp(self):
- super(TestMailMockups, self).setUp()
- # Install mock SMTP gateway
- self._init_mock_build_email()
- self._build_email = self.registry('ir.mail_server').build_email
- self.registry('ir.mail_server').build_email = self._mock_build_email
- self._send_email = self.registry('ir.mail_server').send_email
- self.registry('ir.mail_server').send_email = self._mock_smtp_gateway
-
- def tearDown(self):
- # Remove mocks
- self.registry('ir.mail_server').build_email = self._build_email
- self.registry('ir.mail_server').send_email = self._send_email
- super(TestMailMockups, self).tearDown()
-
-
-class test_mail(TestMailMockups):
+class test_mail(test_mail_mockup.TestMailMockups):
def _mock_send_get_mail_body(self, *args, **kwargs):
# def _send_get_mail_body(self, cr, uid, mail, partner=None, context=None)
- body = tools.append_content_to_html(args[2].body_html, kwargs.get('partner').name if kwargs.get('partner') else 'No specific partner')
+ body = tools.append_content_to_html(args[2].body_html, kwargs.get('partner').name if kwargs.get('partner') else 'No specific partner', plaintext=False)
return body
def setUp(self):
@@ -375,10 +343,10 @@ class test_mail(TestMailMockups):
_subject = 'Pigs'
_mail_subject = '%s posted on %s' % (user_admin.name, group_pigs.name)
_body1 = 'Pigs rules'
- _mail_body1 = 'Pigs rules\n<pre>Admin</pre>\n'
- _mail_bodyalt1 = 'Pigs rules\nAdmin'
+ _mail_body1 = 'Pigs rules\n<div><p>Admin</p></div>\n'
+ _mail_bodyalt1 = 'Pigs rules\nAdmin\n'
_body2 = '<html>Pigs rules</html>'
- _mail_body2 = html_sanitize('<html>Pigs rules\n<pre>Admin</pre>\n</html>')
+ _mail_body2 = html_sanitize('<html>Pigs rules\n<div><p>Admin</p></div>\n</html>')
_mail_bodyalt2 = 'Pigs rules\nAdmin'
_attachments = [('First', 'My first attachment'), ('Second', 'My second attachment')]
@@ -399,7 +367,7 @@ class test_mail(TestMailMockups):
# Test: sent_email: email send by server: correct subject, body, body_alternative
for sent_email in sent_emails:
self.assertEqual(sent_email['subject'], _subject, 'sent_email subject incorrect')
- self.assertEqual(sent_email['body'], _mail_body1 + '\n<pre>Bert Tartopoils</pre>\n', 'sent_email body incorrect')
+ self.assertEqual(sent_email['body'], _mail_body1 + '\nBert Tartopoils\n', 'sent_email body incorrect')
# the html2plaintext uses etree or beautiful soup, so the result may be slighly different
# depending if you have installed beautiful soup.
self.assertIn(sent_email['body_alternative'], _mail_bodyalt1 + '\nBert Tartopoils\n', 'sent_email body_alternative is incorrect')
@@ -495,7 +463,8 @@ class test_mail(TestMailMockups):
# 1. Comment group_pigs with body_text and subject
compose_id = mail_compose.create(cr, uid,
{'subject': _subject, 'body_text': _body_text, 'partner_ids': [(4, p_c_id), (4, p_d_id)]},
- {'default_composition_mode': 'comment', 'default_model': 'mail.group', 'default_res_id': self.group_pigs_id})
+ {'default_composition_mode': 'comment', 'default_model': 'mail.group', 'default_res_id': self.group_pigs_id,
+ 'default_content_subtype': 'plaintext'})
compose = mail_compose.browse(cr, uid, compose_id)
# Test: mail.compose.message: composition_mode, model, res_id
self.assertEqual(compose.composition_mode, 'comment', 'mail.compose.message incorrect composition_mode')
@@ -537,10 +506,8 @@ class test_mail(TestMailMockups):
self.assertEqual(compose.parent_id and compose.parent_id.id, message.id, 'mail.message parent_id incorrect')
# Test: mail.message: attachments
for attach in compose.attachment_ids:
- self.assertEqual(attach.res_model, 'mail.group', 'mail.message attachment res_model incorrect')
- self.assertEqual(attach.res_id, self.group_pigs_id, 'mail.message attachment res_id incorrect')
self.assertIn((attach.datas_fname, attach.datas.decode('base64')), _attachments_test, 'mail.message attachment name / data incorrect')
-
+
# ----------------------------------------
# CASE3: mass_mail on Pigs and Bird
# ----------------------------------------
@@ -576,7 +543,7 @@ class test_mail(TestMailMockups):
cr, uid, user_admin, group_pigs = self.cr, self.uid, self.user_admin, self.group_pigs
pigs_domain = [('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)]
- # Data: create a discussion in Pigs (2 messages, one with 2 and one with 3 answers)
+ # Data: create a discussion in Pigs (3 threads, with respectively 0, 4 and 4 answers)
msg_id0 = self.group_pigs.message_post(body='0', subtype='mt_comment')
msg_id1 = self.group_pigs.message_post(body='1', subtype='mt_comment')
msg_id2 = self.group_pigs.message_post(body='2', subtype='mt_comment')
@@ -588,7 +555,8 @@ class test_mail(TestMailMockups):
msg_id8 = self.group_pigs.message_post(body='2-1-1', subtype='mt_comment', parent_id=msg_id4)
msg_id9 = self.group_pigs.message_post(body='1-1-1', subtype='mt_comment', parent_id=msg_id3)
msg_id10 = self.group_pigs.message_post(body='2-1-1', subtype='mt_comment', parent_id=msg_id4)
- msg_ids = [msg_id0, msg_id1, msg_id2, msg_id3, msg_id4, msg_id5, msg_id6, msg_id7, msg_id8, msg_id9, msg_id10]
+ msg_ids = [msg_id10, msg_id9, msg_id8, msg_id7, msg_id6, msg_id5, msg_id4, msg_id3, msg_id2, msg_id1, msg_id0]
+ ordered_msg_ids = [msg_id2, msg_id4, msg_id6, msg_id8, msg_id10, msg_id1, msg_id3, msg_id5, msg_id7, msg_id9, msg_id0]
# Test: read some specific ids
read_msg_list = self.mail_message.message_read(cr, uid, ids=msg_ids[2:4], domain=[('body', 'like', 'dummy')])
@@ -601,7 +569,8 @@ class test_mail(TestMailMockups):
self.assertEqual(msg_ids, read_msg_ids, 'message_read flat with domain on Pigs should equal all messages of Pigs')
read_msg_list = self.mail_message.message_read(cr, uid, domain=pigs_domain, limit=200, thread_level=1)
read_msg_ids = [msg.get('id') for msg in read_msg_list]
- self.assertEqual(msg_ids, read_msg_ids, 'message_read threaded with domain on Pigs should equal all messages of Pigs')
+ self.assertEqual(ordered_msg_ids, read_msg_ids,
+ 'message_read threaded with domain on Pigs should equal all messages of Pigs, and sort them with newer thread first, last message last in thread')
# ----------------------------------------
# CASE1: message_read with domain, threaded
@@ -611,6 +580,8 @@ class test_mail(TestMailMockups):
# Do: read last message, threaded
read_msg_list = self.mail_message.message_read(cr, uid, domain=pigs_domain, limit=1, thread_level=1)
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
+ # TDE TODO: test expandables order
+ type_list = map(lambda item: item.get('type'), read_msg_list)
# Test: structure content, ancestor is added to the read messages, ordered by id, ancestor is set, 2 expandables
self.assertEqual(len(read_msg_list), 4, 'message_read on last Pigs message should return 2 messages and 2 expandables')
self.assertEqual(set([msg_id2, msg_id10]), set(read_msg_ids), 'message_read on the last Pigs message should also get its parent')
@@ -618,7 +589,7 @@ class test_mail(TestMailMockups):
# Data: get expandables
new_threads_exp, new_msg_exp = None, None
for msg in read_msg_list:
- if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('id') == -1:
+ if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('max_limit'):
new_threads_exp = msg
elif msg.get('type') == 'expandable':
new_msg_exp = msg
@@ -630,12 +601,20 @@ class test_mail(TestMailMockups):
self.assertIn(('id', 'child_of', msg_id2), domain, 'new messages expandable domain should contain a child_of condition')
self.assertIn(('id', '>=', msg_id4), domain, 'new messages expandable domain should contain an id greater than condition')
self.assertIn(('id', '<=', msg_id8), domain, 'new messages expandable domain should contain an id less than condition')
- self.assertEqual(new_msg_exp.get('parent_id'), msg_id2, 'new messages expandable should have ancestor_id set to the thread header')
- # Do: message_read with domain, thread_level=0, parent_id=msg_id2 (should be imposed by JS)
- read_msg_list = self.mail_message.message_read(cr, uid, domain=domain, limit=200, thread_level=0, parent_id=msg_id2)
+ self.assertEqual(new_msg_exp.get('parent_id'), msg_id2, 'new messages expandable should have parent_id set to the thread header')
+ # Do: message_read with domain, thread_level=0, parent_id=msg_id2 (should be imposed by JS), 2 messages
+ read_msg_list = self.mail_message.message_read(cr, uid, domain=domain, limit=2, thread_level=0, parent_id=msg_id2)
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
- # Test: other message in thread have been fetch
- self.assertEqual(set([msg_id4, msg_id6, msg_id8]), set(read_msg_ids), 'message_read in Pigs thread should return all the previous messages')
+ new_msg_exp = [msg for msg in read_msg_list if msg.get('type') == 'expandable'][0]
+ # Test: structure content, 2 messages and 1 thread expandable
+ self.assertEqual(len(read_msg_list), 3, 'message_read in Pigs thread should return 2 messages and 1 expandables')
+ self.assertEqual(set([msg_id6, msg_id8]), set(read_msg_ids), 'message_read in Pigs thread should return 2 more previous messages in thread')
+ # Do: read the last message
+ read_msg_list = self.mail_message.message_read(cr, uid, domain=new_msg_exp.get('domain'), limit=2, thread_level=0, parent_id=msg_id2)
+ read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
+ # Test: structure content, 1 message
+ self.assertEqual(len(read_msg_list), 1, 'message_read in Pigs thread should return 1 message')
+ self.assertEqual(set([msg_id4]), set(read_msg_ids), 'message_read in Pigs thread should return the last message in thread')
# Do: fetch a new thread, domain from expandable
self.assertIsNotNone(new_threads_exp, 'message_read on last Pigs message should have returned a new threads expandable')
@@ -643,7 +622,7 @@ class test_mail(TestMailMockups):
# Test: expandable, conditions in domain
for condition in pigs_domain:
self.assertIn(condition, domain, 'new threads expandable domain should contain the message_read domain parameter')
- self.assertFalse(new_threads_exp.get('parent_id'), 'new threads expandable should not have an ancestor_id')
+ self.assertFalse(new_threads_exp.get('parent_id'), 'new threads expandable should not have an parent_id')
# Do: message_read with domain, thread_level=1 (should be imposed by JS)
read_msg_list = self.mail_message.message_read(cr, uid, domain=domain, limit=1, thread_level=1)
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
@@ -654,7 +633,7 @@ class test_mail(TestMailMockups):
# Data: get expandables
new_threads_exp, new_msg_exp = None, None
for msg in read_msg_list:
- if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('id') == -1:
+ if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('max_limit'):
new_threads_exp = msg
elif msg.get('type') == 'expandable':
new_msg_exp = msg
@@ -701,7 +680,7 @@ class test_mail(TestMailMockups):
# Data: get expandables
new_threads_exp, new_msg_exp = None, None
for msg in read_msg_list:
- if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('id') == -1:
+ if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('max_limit'):
new_threads_exp = msg
# Do: fetch new messages, domain from expandable
@@ -715,7 +694,7 @@ class test_mail(TestMailMockups):
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
# Test: structure content, ancestor is added to the read messages, ordered by id, ancestor is set, 2 expandables
self.assertEqual(len(read_msg_list), 9, 'message_read on Pigs should return 9 messages and 0 expandable')
- self.assertEqual([msg_id0, msg_id1, msg_id2, msg_id3, msg_id4, msg_id5, msg_id6, msg_id7, msg_id8], read_msg_ids,
+ self.assertEqual([msg_id8, msg_id7, msg_id6, msg_id5, msg_id4, msg_id3, msg_id2, msg_id1, msg_id0], read_msg_ids,
'message_read, More on flat, should return all remaning messages')
def test_40_needaction(self):
diff --git a/addons/mail/tests/test_mail_access_rights.py b/addons/mail/tests/test_mail_access_rights.py
index 7b90e07b9b5..7594de87faf 100644
--- a/addons/mail/tests/test_mail_access_rights.py
+++ b/addons/mail/tests/test_mail_access_rights.py
@@ -19,11 +19,12 @@
#
##############################################################################
-from openerp.addons.mail.tests import test_mail
-from osv.orm import except_orm
+from openerp.addons.mail.tests import test_mail_mockup
+from openerp.osv.orm import except_orm
+from openerp.tools.misc import mute_logger
-class test_mail_access_rights(test_mail.TestMailMockups):
+class test_mail_access_rights(test_mail_mockup.TestMailMockups):
def setUp(self):
super(test_mail_access_rights, self).setUp()
@@ -84,6 +85,7 @@ class test_mail_access_rights(test_mail.TestMailMockups):
msg_ids = self.mail_message.search(cr, uid, [('subject', 'like', '_Test')])
self.assertEqual(set([msg_id1, msg_id2, msg_id3, msg_id4, msg_id5, msg_id6, msg_id7, msg_id8]), set(msg_ids), 'mail_message search failed')
+ @mute_logger('openerp.osv.orm')
def test_05_mail_message_read_access_rights(self):
""" Test basic mail_message read access rights. """
cr, uid = self.cr, self.uid
@@ -131,6 +133,8 @@ class test_mail_access_rights(test_mail.TestMailMockups):
self.assertRaises(except_orm, self.mail_message.read,
cr, user_bert_id, message_id)
+ @mute_logger('openerp.addons.base.ir.ir_model')
+ @mute_logger('openerp.osv.orm')
def test_10_mail_flow_access_rights(self):
""" Test a Chatter-looks alike flow. """
cr, uid = self.cr, self.uid
diff --git a/addons/mail/tests/test_mail_mockup.py b/addons/mail/tests/test_mail_mockup.py
new file mode 100644
index 00000000000..cba04a0c6b3
--- /dev/null
+++ b/addons/mail/tests/test_mail_mockup.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Business Applications
+# Copyright (c) 2012-TODAY OpenERP S.A. <http://openerp.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# 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/>.
+#
+##############################################################################
+
+from openerp.tests import common
+
+
+class TestMailMockups(common.TransactionCase):
+
+ def _mock_smtp_gateway(self, *args, **kwargs):
+ return True
+
+ def _init_mock_build_email(self):
+ self._build_email_args_list = []
+ self._build_email_kwargs_list = []
+
+ def _mock_build_email(self, *args, **kwargs):
+ """ Mock build_email to be able to test its values. Store them into
+ some internal variable for latter processing. """
+ self._build_email_args_list.append(args)
+ self._build_email_kwargs_list.append(kwargs)
+ return self._build_email(*args, **kwargs)
+
+ def setUp(self):
+ super(TestMailMockups, self).setUp()
+ # Install mock SMTP gateway
+ self._init_mock_build_email()
+ self._build_email = self.registry('ir.mail_server').build_email
+ self.registry('ir.mail_server').build_email = self._mock_build_email
+ self._send_email = self.registry('ir.mail_server').send_email
+ self.registry('ir.mail_server').send_email = self._mock_smtp_gateway
+
+ def tearDown(self):
+ # Remove mocks
+ self.registry('ir.mail_server').build_email = self._build_email
+ self.registry('ir.mail_server').send_email = self._send_email
+ super(TestMailMockups, self).tearDown()
diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py
index 33712847534..c409d4ab076 100644
--- a/addons/mail/wizard/mail_compose_message.py
+++ b/addons/mail/wizard/mail_compose_message.py
@@ -102,9 +102,9 @@ class mail_compose_message(osv.TransientModel):
'partner_ids': fields.many2many('res.partner',
'mail_compose_message_res_partner_rel',
'wizard_id', 'partner_id', 'Additional contacts'),
- 'attachment_ids': fields.one2many('ir.attachment', 'res_id',
- domain=lambda self: [('res_model', '=', self._name)],
- string='Attachments'),
+ 'attachment_ids': fields.many2many('ir.attachment',
+ 'mail_compose_message_ir_attachments_rel',
+ 'wizard_id', 'attachment_id', 'Attachments'),
'filter_id': fields.many2one('ir.filters', 'Filters'),
'body_text': fields.text('Plain-text Contents'),
'content_subtype': fields.char('Message content subtype', size=32, readonly=1,
@@ -114,7 +114,7 @@ class mail_compose_message(osv.TransientModel):
_defaults = {
'composition_mode': 'comment',
- 'content_subtype': lambda self, cr, uid, ctx={}: 'plain',
+ 'content_subtype': lambda self, cr, uid, ctx={}: 'html',
'body_text': lambda self, cr, uid, ctx={}: False,
'body': lambda self, cr, uid, ctx={}: '',
'subject': lambda self, cr, uid, ctx={}: False,
@@ -135,7 +135,12 @@ class mail_compose_message(osv.TransientModel):
related to.
:param int res_id: id of the document record this mail is related to
"""
- return {'model': model, 'res_id': res_id}
+ doc_name_get = self.pool.get(model).name_get(cr, uid, [res_id], context=context)
+ if doc_name_get:
+ record_name = doc_name_get[0][1]
+ else:
+ record_name = False
+ return {'model': model, 'res_id': res_id, 'record_name': record_name}
def get_message_data(self, cr, uid, message_id, context=None):
""" Returns a defaults-like dict with initial values for the composition
@@ -161,6 +166,7 @@ class mail_compose_message(osv.TransientModel):
# update the result
result = {
+ 'record_name': message_data.record_name,
'model': message_data.model,
'res_id': message_data.res_id,
'parent_id': message_data.id,
diff --git a/addons/mail/wizard/mail_compose_message_view.xml b/addons/mail/wizard/mail_compose_message_view.xml
index b9c3d237e78..01ceb770f49 100644
--- a/addons/mail/wizard/mail_compose_message_view.xml
+++ b/addons/mail/wizard/mail_compose_message_view.xml
@@ -14,13 +14,22 @@
<field name="parent_id" invisible="1"/>
<field name="content_subtype" invisible="1"/>
<!-- visible wizard -->
- <field name="partner_ids" widget="many2many_tags_email" placeholder="Add contacts to notify..."
+ <label for="partner_ids" string="Recipients"/>
+ <div>
+ <span attrs="{'invisible':[('model', '=', False)]}">
+ Followers of
+ <field name="record_name" readonly="1" class="oe_inline"
+ attrs="{'invisible':[('model', '=', False)]}"/>
+ and
+ </span>
+ <field name="partner_ids" widget="many2many_tags_email" placeholder="Add contacts to notify..."
context="{'force_email':True}" required="1"/>
+ </div>
<field name="subject" placeholder="Subject..."
- attrs="{'invisible':[('content_subtype', '=', 'plain')]}"/>
+ attrs="{'invisible':[('content_subtype', '=', 'plain')]}"/>
</group>
<field name="body"/>
- <field name="attachment_ids" widget="one2many_binary" blockui="0"/>
+ <field name="attachment_ids" widget="many2many_binary"/>
<footer>
<button string="Send" name="send_mail" type="object" class="oe_highlight"/>
or
diff --git a/addons/marketing/i18n/lt.po b/addons/marketing/i18n/lt.po
new file mode 100644
index 00000000000..70b6c1645b3
--- /dev/null
+++ b/addons/marketing/i18n/lt.po
@@ -0,0 +1,28 @@
+# Lithuanian translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2012-02-08 00:36+0000\n"
+"PO-Revision-Date: 2012-11-15 13:26+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Lithuanian <lt@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-11-16 04:36+0000\n"
+"X-Generator: Launchpad (build 16272)\n"
+
+#. module: marketing
+#: model:res.groups,name:marketing.group_marketing_manager
+msgid "Manager"
+msgstr ""
+
+#. module: marketing
+#: model:res.groups,name:marketing.group_marketing_user
+msgid "User"
+msgstr ""
diff --git a/addons/mrp/mrp_data.xml b/addons/mrp/mrp_data.xml
index 3310bc98899..a6b65b7c475 100644
--- a/addons/mrp/mrp_data.xml
+++ b/addons/mrp/mrp_data.xml
@@ -6,11 +6,11 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">MRP application installed!</field>
- <field name="body">Manage your manufacturing process with OpenERP by defining your bills of materials (BoM), routings and work centers.
-This application supports complete integration and production scheduling for stockable goods, consumables, and services.
-
-From the Manufacturing Settings, you can choose to compute production schedules periodically or just-in-time.</field>
+ <field name="body"><![CDATA[<p>Manage your manufacturing process with OpenERP by defining your bills of materials (BoM), routings and work centers.</p><p>
+This application supports complete integration and production scheduling for stockable goods, consumables, and services.</p>
+<p>From the Manufacturing Settings, you can choose to compute production schedules periodically or just-in-time.</p>]]></field>
</record>
<record id="sequence_mrp_prod_type" model="ir.sequence.type">
diff --git a/addons/mrp/report/price.py b/addons/mrp/report/price.py
index 527505d8ea5..b1e04749ab2 100644
--- a/addons/mrp/report/price.py
+++ b/addons/mrp/report/price.py
@@ -111,7 +111,7 @@ class report_custom(report_rml):
<PageWidth>595.27</PageWidth>
<PageHeight>841.88</PageHeight>
<tableSize>55.00mm,58.00mm,29.00mm,29.00mm,29.00mm</tableSize>
- """ % (user_pool.browse(cr, uid, uid).company_id.name)
+ """ % to_xml(user_pool.browse(cr, uid, uid).company_id.name)
config_stop = """
<report-footer>Generated by OpenERP</report-footer>
</config>
diff --git a/addons/mrp/res_config.py b/addons/mrp/res_config.py
index c1712b81a26..ec3deb524a3 100644
--- a/addons/mrp/res_config.py
+++ b/addons/mrp/res_config.py
@@ -28,10 +28,6 @@ class mrp_config_settings(osv.osv_memory):
_inherit = 'res.config.settings'
_columns = {
- 'module_stock_planning': fields.boolean('Manage master production shedule',
- help ="""This allows to create a manual procurement plan apart of the normal MRP scheduling,
- which works automatically based on minimum stock rules.
- This installs the module stock_planning."""),
'module_mrp_repair': fields.boolean("Manage repairs of products ",
help="""Allows to manage all product repairs.
* Add/remove products in the reparation
diff --git a/addons/mrp/res_config_view.xml b/addons/mrp/res_config_view.xml
index 6b4058fb7b4..2c7047380a8 100644
--- a/addons/mrp/res_config_view.xml
+++ b/addons/mrp/res_config_view.xml
@@ -56,10 +56,6 @@
<field name="module_mrp_operations" class="oe_inline"/>
<label for="module_mrp_operations" />
</div>
- <div>
- <field name="module_stock_planning" class="oe_inline"/>
- <label for="module_stock_planning"/>
- </div>
</div>
</group>
<separator string="Master Data"/>
diff --git a/addons/mrp_jit/i18n/sl.po b/addons/mrp_jit/i18n/sl.po
index dfdea2fbcd0..8527b96e315 100644
--- a/addons/mrp_jit/i18n/sl.po
+++ b/addons/mrp_jit/i18n/sl.po
@@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2011-01-11 11:15+0000\n"
-"PO-Revision-Date: 2010-11-27 05:28+0000\n"
-"Last-Translator: OpenERP Administrators <Unknown>\n"
+"PO-Revision-Date: 2012-11-18 21:54+0000\n"
+"Last-Translator: Dusan Laznik <laznik@mentis.si>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-10-30 05:22+0000\n"
-"X-Generator: Launchpad (build 16206)\n"
+"X-Launchpad-Export-Date: 2012-11-19 04:37+0000\n"
+"X-Generator: Launchpad (build 16278)\n"
#. module: mrp_jit
#: model:ir.module.module,shortdesc:mrp_jit.module_meta_information
@@ -46,3 +46,24 @@ msgid ""
" \n"
" "
msgstr ""
+"\n"
+" This module allows Just In Time computation of procurement orders.\n"
+"\n"
+" If you install this module, you will not have to run the regular "
+"procurement \n"
+" scheduler anymore (but you still need to run the minimum order point "
+"rule \n"
+" scheduler, or for example let it run daily.)\n"
+" All procurement orders will be processed immediately, which could in "
+"some\n"
+" cases entail a small performance impact.\n"
+"\n"
+" It may also increase your stock size because products are reserved as "
+"soon\n"
+" as possible and the scheduler time range is not taken into account "
+"anymore. \n"
+" In that case, you can not use priorities any more on the different "
+"picking.\n"
+" \n"
+" \n"
+" "
diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py
index bc9b9413c65..d79620ce93c 100644
--- a/addons/mrp_repair/mrp_repair.py
+++ b/addons/mrp_repair/mrp_repair.py
@@ -690,7 +690,7 @@ class mrp_repair_line(osv.osv, ProductChangeMixin):
'repair_id': fields.many2one('mrp.repair', 'Repair Order Reference',ondelete='cascade', select=True),
'type': fields.selection([('add','Add'),('remove','Remove')],'Type', required=True),
'to_invoice': fields.boolean('To Invoice'),
- 'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok','=',True)], required=True),
+ 'product_id': fields.many2one('product.product', 'Product', required=True),
'invoiced': fields.boolean('Invoiced',readonly=True),
'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price')),
'price_subtotal': fields.function(_amount_line, string='Subtotal',digits_compute= dp.get_precision('Account')),
diff --git a/addons/note/__openerp__.py b/addons/note/__openerp__.py
index d87ee70086d..797270637e2 100644
--- a/addons/note/__openerp__.py
+++ b/addons/note/__openerp__.py
@@ -38,6 +38,7 @@ Notes can be found in the 'Home' menu.
'author': 'OpenERP SA',
'website': 'http://openerp.com',
'summary': 'Sticky notes, Collaborative, Memos',
+ 'sequence': 9,
'depends': [
'mail',
],
diff --git a/addons/note/i18n/pt_BR.po b/addons/note/i18n/pt_BR.po
new file mode 100644
index 00000000000..eea43f2275f
--- /dev/null
+++ b/addons/note/i18n/pt_BR.po
@@ -0,0 +1,334 @@
+# Brazilian Portuguese translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2012-11-02 12:54+0000\n"
+"PO-Revision-Date: 2012-11-14 04:29+0000\n"
+"Last-Translator: Guilherme R. Santos <Unknown>\n"
+"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-11-15 04:42+0000\n"
+"X-Generator: Launchpad (build 16265)\n"
+
+#. module: note
+#: sql_constraint:res.users:0
+msgid "You can not have two users with the same login !"
+msgstr "Você não pode ter dois usuários com o mesmo login!"
+
+#. module: note
+#: field:note.note,memo:0
+msgid "Note Content"
+msgstr "Conteúdo da Nota"
+
+#. module: note
+#: view:note.stage:0
+msgid "Stages of Notes"
+msgstr "Estágio das Notas"
+
+#. module: note
+#: model:ir.model,name:note.model_base_config_settings
+msgid "base.config.settings"
+msgstr "base.config.settings"
+
+#. module: note
+#: model:ir.model,name:note.model_note_tag
+msgid "Note Tag"
+msgstr "Tag da Nota"
+
+#. module: note
+#: model:res.groups,name:note.group_note_fancy
+msgid "Notes / Fancy mode"
+msgstr "Notas / Modo fantasia"
+
+#. module: note
+#: model:ir.model,name:note.model_note_note
+#: view:note.note:0
+msgid "Note"
+msgstr "Nota"
+
+#. module: note
+#: view:note.note:0
+msgid "Group By..."
+msgstr "Agrupar Por..."
+
+#. module: note
+#: field:note.note,message_summary:0
+msgid "Summary"
+msgstr "Resumo"
+
+#. module: note
+#: field:note.note,message_follower_ids:0
+msgid "Followers"
+msgstr "Seguidores"
+
+#. module: note
+#: model:ir.actions.act_window,help:note.action_note_note
+msgid ""
+"<p class=\"oe_view_nocontent_create\">\n"
+" Click to add a personal note.\n"
+" </p><p>\n"
+" Use notes to organize personal tasks or notes. All\n"
+" notes are private; no one else will be able to see them. "
+"However\n"
+" you can share some notes with other people by inviting "
+"followers\n"
+" on the note. (Useful for meeting minutes, especially if\n"
+" you activate the pad feature for collaborative writings).\n"
+" </p><p>\n"
+" You can customize how you process your notes/tasks by adding,\n"
+" removing or modifying columns.\n"
+" </p>\n"
+" "
+msgstr ""
+"<p class=\"oe_view_nocontent_create\">\n"
+" Clique para adicionar nota pessoal.\n"
+" </p><p>\n"
+" Use notas para organizar tarefas ou notas pessoais. Todas\n"
+" notas são privadas; ninguém mais é capaz de vê-las. Contudo\n"
+" você pode compartilhar algumas notas com outras pessoas "
+"convidando seguidores\n"
+" na nota. (Útil para atas de reunião, especialmente se\n"
+" você ativar o recurso \"PAD\" para textos colaborativos).\n"
+" </p><p>\n"
+" Você pode customizar a forma como você processa suas "
+"notas/tarefas adicionando,\n"
+" removendo ou modificando colunas.\n"
+" </p>\n"
+" "
+
+#. module: note
+#: view:note.note:0
+msgid "kanban note"
+msgstr "nota kanban"
+
+#. module: note
+#: model:note.stage,name:note.demo_note_stage_01
+#: model:note.stage,name:note.note_stage_01
+msgid "Today"
+msgstr "Hoje"
+
+#. module: note
+#: model:ir.model,name:note.model_res_users
+msgid "Users"
+msgstr "Usuários"
+
+#. module: note
+#: view:note.note:0
+msgid "í"
+msgstr "í"
+
+#. module: note
+#: view:note.stage:0
+msgid "Stage of Notes"
+msgstr "Estágios das Notas"
+
+#. module: note
+#: field:note.note,message_unread:0
+msgid "Unread Messages"
+msgstr "Mensagens não lidas"
+
+#. module: note
+#: field:note.note,current_partner_id:0
+msgid "unknown"
+msgstr "desconhecido"
+
+#. module: note
+#: view:note.note:0
+msgid "By sticky note Category"
+msgstr ""
+
+#. module: note
+#: help:note.note,message_unread:0
+msgid "If checked new messages require your attention."
+msgstr "Se marcado novas mensagens requerem sua atenção"
+
+#. module: note
+#: field:note.stage,name:0
+msgid "Stage Name"
+msgstr "Nome do Estágio"
+
+#. module: note
+#: field:note.note,message_is_follower:0
+msgid "Is a Follower"
+msgstr "É um seguidor"
+
+#. module: note
+#: view:note.note:0
+msgid "title"
+msgstr "título"
+
+#. module: note
+#: model:note.stage,name:note.demo_note_stage_02
+#: model:note.stage,name:note.note_stage_02
+msgid "Tomorrow"
+msgstr "Amanhã"
+
+#. module: note
+#: view:note.note:0
+#: field:note.note,open:0
+msgid "Active"
+msgstr "Ativo"
+
+#. module: note
+#: help:note.stage,user_id:0
+msgid "Owner of the note stage."
+msgstr "Proprietário do estágio da nota."
+
+#. module: note
+#: model:ir.ui.menu,name:note.menu_notes_stage
+msgid "Categories"
+msgstr "Categorias"
+
+#. module: note
+#: field:note.note,message_comment_ids:0
+#: help:note.note,message_comment_ids:0
+msgid "Comments and emails"
+msgstr "Comentários e emails"
+
+#. module: note
+#: field:note.tag,name:0
+msgid "Tag Name"
+msgstr "Nome da Tag"
+
+#. module: note
+#: field:note.note,message_ids:0
+msgid "Messages"
+msgstr "Mensagens"
+
+#. module: note
+#: view:base.config.settings:0
+#: model:ir.actions.act_window,name:note.action_note_note
+#: model:ir.ui.menu,name:note.menu_note_notes
+#: view:note.note:0
+#: model:note.stage,name:note.note_stage_04
+msgid "Notes"
+msgstr "Notas"
+
+#. module: note
+#: model:note.stage,name:note.demo_note_stage_03
+#: model:note.stage,name:note.note_stage_03
+msgid "Later"
+msgstr "Mais tarde"
+
+#. module: note
+#: model:ir.model,name:note.model_note_stage
+msgid "Note Stage"
+msgstr "Estágio da Nota"
+
+#. module: note
+#: view:note.note:0
+msgid "dropdown menu"
+msgstr "dropdown menu"
+
+#. module: note
+#: model:note.stage,name:note.demo_note_stage_04
+msgid "Morning"
+msgstr "Manhã"
+
+#. module: note
+#: help:note.stage,sequence:0
+msgid "Used to order the note stages"
+msgstr "Usado para ordenar os estágios das notas"
+
+#. module: note
+#: view:note.note:0
+msgid "W"
+msgstr "W"
+
+#. module: note
+#: field:note.note,stage_ids:0
+msgid "Stages of Users"
+msgstr "Estágios de Usuários"
+
+#. module: note
+#: field:note.note,name:0
+msgid "Note Summary"
+msgstr "Resumo da Nota"
+
+#. module: note
+#: model:ir.actions.act_window,name:note.action_note_stage
+#: view:note.note:0
+msgid "Stages"
+msgstr "Estágios"
+
+#. module: note
+#: help:note.note,message_ids:0
+msgid "Messages and communication history"
+msgstr "Histórico de mensagens e comunicação"
+
+#. module: note
+#: view:note.note:0
+msgid "Delete"
+msgstr "Excluir"
+
+#. module: note
+#: field:note.note,color:0
+msgid "Color Index"
+msgstr "Índice de Cores"
+
+#. module: note
+#: field:note.note,sequence:0
+#: field:note.stage,sequence:0
+msgid "Sequence"
+msgstr "Sequencia"
+
+#. module: note
+#: field:note.note,tag_ids:0
+msgid "Tags"
+msgstr "Tags"
+
+#. module: note
+#: view:note.note:0
+msgid "Archive"
+msgstr "Arquivo"
+
+#. module: note
+#: field:base.config.settings,module_note_pad:0
+msgid "Use collaborative pads (etherpad)"
+msgstr "Usar pads colaborativos (etherpad)"
+
+#. module: note
+#: help:note.note,message_summary:0
+msgid ""
+"Holds the Chatter summary (number of messages, ...). This summary is "
+"directly in html format in order to be inserted in kanban views."
+msgstr ""
+
+#. module: note
+#: field:base.config.settings,group_note_fancy:0
+msgid "Use fancy layouts for notes"
+msgstr "Usar leiautes fantasia para notas"
+
+#. module: note
+#: field:note.stage,user_id:0
+msgid "Owner"
+msgstr "Proprietário"
+
+#. module: note
+#: constraint:res.users:0
+msgid "The chosen company is not in the allowed companies for this user"
+msgstr ""
+"A empresa escolhida não está entre as empresas habilitadas para este usuário"
+
+#. module: note
+#: view:note.note:0
+#: field:note.note,stage_id:0
+msgid "Stage"
+msgstr "Estágio"
+
+#. module: note
+#: field:note.note,date_done:0
+msgid "Date done"
+msgstr "Data de conclusão"
+
+#. module: note
+#: field:note.stage,fold:0
+msgid "Folded by Default"
+msgstr "Dobrado por Padrão"
diff --git a/addons/note/note.py b/addons/note/note.py
index fe5eca5efd7..9e1a9187095 100644
--- a/addons/note/note.py
+++ b/addons/note/note.py
@@ -20,9 +20,7 @@
##############################################################################
from openerp.osv import osv, fields
-from tools.translate import _
-import re
-from openerp.tools.misc import html2plaintext
+from openerp.tools import html2plaintext
class note_stage(osv.osv):
""" Category of Note """
diff --git a/addons/note/note_view.xml b/addons/note/note_view.xml
index 18a3ec840a9..5aae6204d86 100644
--- a/addons/note/note_view.xml
+++ b/addons/note/note_view.xml
@@ -120,7 +120,7 @@
<field name="memo" widget="html" class="oe_memo" editor_height="450px" />
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
- <field class="oe_chatter" name="message_ids" widget="mail_thread"/>
+ <field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
diff --git a/addons/note/security/ir.rule.xml b/addons/note/security/ir.rule.xml
index 1195314cc9e..b0c79561355 100644
--- a/addons/note/security/ir.rule.xml
+++ b/addons/note/security/ir.rule.xml
@@ -6,6 +6,10 @@
<field model="ir.model" ref="model_note_note" name="model_id"/>
<field name="domain_force">[('message_follower_ids','=',user.partner_id.id)]</field>
<field eval="True" name="global"/>
+ <field eval="1" name="perm_unlink"/>
+ <field eval="0" name="perm_write"/>
+ <field eval="1" name="perm_read"/>
+ <field eval="0" name="perm_create"/>
</record>
<record id="note_stage_rule_global" model="ir.rule">
diff --git a/addons/note/static/src/css/note.css b/addons/note/static/src/css/note.css
index 1b7e9315e74..16d71e28aa5 100644
--- a/addons/note/static/src/css/note.css
+++ b/addons/note/static/src/css/note.css
@@ -49,8 +49,8 @@
padding: 8px;
margin-left: 3px;
margin-right: 3px;
- padding-bottom: 16px;
- margin-bottom: 16px;
+ padding-bottom: 8px;
+ margin-bottom: 10px;
-webkit-transform: rotate(-2deg);
-o-transform: rotate(-2deg);
-moz-transform: rotate(-2deg);
diff --git a/addons/note/static/src/css/note.sass b/addons/note/static/src/css/note.sass
index b5bc28a2593..6f0c0883ae7 100644
--- a/addons/note/static/src/css/note.sass
+++ b/addons/note/static/src/css/note.sass
@@ -53,8 +53,8 @@
padding: 8px
margin-left: 3px
margin-right: 3px
- padding-bottom: 16px
- margin-bottom: 16px
+ padding-bottom: 8px
+ margin-bottom: 10px
@include rotate(-2deg)
@include transition(all, 300ms)
.oe_kanban_record:nth-of-type(even)
diff --git a/addons/pad/pad.py b/addons/pad/pad.py
index e5b36e5f64c..8f9f79a78e0 100644
--- a/addons/pad/pad.py
+++ b/addons/pad/pad.py
@@ -6,7 +6,7 @@ import string
import urllib2
import logging
from tools.translate import _
-from openerp.tools.misc import html2plaintext
+from openerp.tools import html2plaintext
from py_etherpad import EtherpadLiteClient
_logger = logging.getLogger(__name__)
@@ -19,7 +19,7 @@ class pad_common(osv.osv_memory):
pad = {
"server" : company.pad_server,
- "key" : company.pad_key or "4DxmsNIbnQUVQMW9S9tx2oLOSjFdrx1l",
+ "key" : company.pad_key,
}
# make sure pad server in the form of http://hostname
diff --git a/addons/pad/pad_demo.xml b/addons/pad/pad_demo.xml
index 407f90e8242..99c4b38481c 100644
--- a/addons/pad/pad_demo.xml
+++ b/addons/pad/pad_demo.xml
@@ -1,9 +1,13 @@
<openerp>
- <data noupdate="1">
+ <data>
<record id="base.main_company" model="res.company">
<field name="pad_server">pad.openerp.com</field>
</record>
+
+ <record id="base.main_company" model="res.company">
+ <field name="pad_key">4DxmsNIbnQUVQMW9S9tx2oLOSjFdrx1l</field>
+ </record>
</data>
</openerp>
diff --git a/addons/pad/static/src/js/pad.js b/addons/pad/static/src/js/pad.js
index 7c6b2a639c1..929d62681c8 100644
--- a/addons/pad/static/src/js/pad.js
+++ b/addons/pad/static/src/js/pad.js
@@ -14,6 +14,7 @@ openerp.pad = function(instance) {
object_id: self.view.datarecord.id
}}).done(function(data) {
if(data&&data.url){
+ self.set({value: data.url});
_super(data.url);
self.renderElement();
}
diff --git a/addons/point_of_sale/point_of_sale_data.xml b/addons/point_of_sale/point_of_sale_data.xml
index 634d2606aa8..01d8dd9ff60 100644
--- a/addons/point_of_sale/point_of_sale_data.xml
+++ b/addons/point_of_sale/point_of_sale_data.xml
@@ -20,10 +20,10 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Point of Sale application installed!</field>
- <field name="body">Record sale orders, register payments, compute change to return, create invoices, and manage refunds through a specific web touch-screen interface.
-
-If you install the PoS proxy you will be able to interface OpenERP with retail hardware: barcode scanners, printers, cash registers, weighing machines, credit card payment terminals.</field>
+ <field name="body"><![CDATA[<p>Record sale orders, register payments, compute change to return, create invoices, and manage refunds through a specific web touch-screen interface.</p>
+<p>If you install the PoS proxy you will be able to interface OpenERP with retail hardware: barcode scanners, printers, cash registers, weighing machines, credit card payment terminals.</p>]]></field>
</record>
<record id="unreferenced_product" model="product.product">
diff --git a/addons/point_of_sale/report/pos_receipt.py b/addons/point_of_sale/report/pos_receipt.py
index 2ee6b2e3360..58044c28c77 100644
--- a/addons/point_of_sale/report/pos_receipt.py
+++ b/addons/point_of_sale/report/pos_receipt.py
@@ -34,7 +34,7 @@ class order(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
super(order, self).__init__(cr, uid, name, context=context)
- user = pooler.get_pool(cr.dbname).get('res.users').browse(cr, uid, uid)
+ user = pooler.get_pool(cr.dbname).get('res.users').browse(cr, uid, uid, context=context)
partner = user.company_id.partner_id
self.localcontext.update({
diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js
index 7301a85eb2d..f1462424f1e 100644
--- a/addons/point_of_sale/static/src/js/models.js
+++ b/addons/point_of_sale/static/src/js/models.js
@@ -320,7 +320,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
module.Product = Backbone.Model.extend({
get_image_url: function(){
- return '/web/binary/image?session_id='+instance.session.session_id+'&model=product.product&field=image&id='+this.get('id');
+ return instance.session.url('/web/binary/image', {model: 'product.product', field: 'image', id: this.get('id')});
},
});
diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js
index c823350cdfd..0b8ab70a9c0 100644
--- a/addons/point_of_sale/static/src/js/screens.js
+++ b/addons/point_of_sale/static/src/js/screens.js
@@ -941,8 +941,10 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
var self = this;
var x = new module.PaymentlineWidget(null, {
payment_line: newPaymentLine
- });
- x.on('delete_payment_line', self, self.deleteLine);
+ });
+ x.on('delete_payment_line', self, function(r) {
+ self.deleteLine(r);
+ });
x.appendTo(this.$('#paymentlines'));
},
renderElement: function() {
diff --git a/addons/point_of_sale/static/src/js/widgets.js b/addons/point_of_sale/static/src/js/widgets.js
index fe86c9dc163..4728c584b21 100644
--- a/addons/point_of_sale/static/src/js/widgets.js
+++ b/addons/point_of_sale/static/src/js/widgets.js
@@ -315,7 +315,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
this._super();
this.$('input').keyup(_.bind(this.changeAmount, this));
this.$('.delete-payment-line').click(function() {
- self.trigger('delete_payment_line');
+ self.trigger('delete_payment_line', self);
});
},
});
@@ -474,7 +474,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
},
get_image_url: function(category){
- return '/web/binary/image?session_id='+instance.session.session_id+'&model=pos.category&field=image&id='+category.id;
+ return instance.session.url('/web/binary/image', {model: 'pos.category', field: 'image', id: category.id});
},
renderElement: function(){
@@ -1051,7 +1051,8 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
this.pos.barcode_reader.disconnect();
return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_client_pos_menu']], ['res_id']).pipe(
_.bind(function(res) {
- return this.rpc('/web/action/load', {'action_id': res[0]['res_id']}).pipe(_.bind(function(action) {
+ return this.rpc('/web/action/load', {'action_id': res[0]['res_id']}).pipe(_.bind(function(result) {
+ var action = result;
action.context = _.extend(action.context || {}, {'cancel_action': {type: 'ir.actions.client', tag: 'reload'}});
//self.destroy();
this.do_action(action);
diff --git a/addons/point_of_sale/wizard/pos_payment.py b/addons/point_of_sale/wizard/pos_payment.py
index 9511aed6331..70b88f35e33 100644
--- a/addons/point_of_sale/wizard/pos_payment.py
+++ b/addons/point_of_sale/wizard/pos_payment.py
@@ -75,7 +75,7 @@ class pos_make_payment(osv.osv_memory):
def launch_payment(self, cr, uid, ids, context=None):
return {
- 'name': _('Paiement'),
+ 'name': _('Payment'),
'view_type': 'form',
'view_mode': 'form',
'res_model': 'pos.make.payment',
@@ -83,6 +83,7 @@ class pos_make_payment(osv.osv_memory):
'target': 'new',
'views': False,
'type': 'ir.actions.act_window',
+ 'context': context,
}
def print_report(self, cr, uid, ids, context=None):
diff --git a/addons/portal/mail_mail.py b/addons/portal/mail_mail.py
index f57170ed67b..0dc7348f2c8 100644
--- a/addons/portal/mail_mail.py
+++ b/addons/portal/mail_mail.py
@@ -36,5 +36,5 @@ class mail_mail(osv.Model):
if partner:
context = dict(context or {}, signup_valid=True)
partner = self.pool.get('res.partner').browse(cr, uid, partner.id, context)
- body = tools.append_content_to_html(body, "Log in our portal at: %s" % partner.signup_url)
+ body = tools.append_content_to_html(body, ("<div><p>Log in our portal at: %s</p></div>" % partner.signup_url), plaintext=False)
return body
diff --git a/addons/portal/portal_demo.xml b/addons/portal/portal_demo.xml
index e8d0fb4159b..fc20bbccae7 100644
--- a/addons/portal/portal_demo.xml
+++ b/addons/portal/portal_demo.xml
@@ -1,17 +1,22 @@
<?xml version="1.0"?>
<openerp>
- <data>
+ <data noupdate="1">
- <!-- Create a portal member attached to a partner -->
- <record id="demo_user0" model="res.users">
+ <!-- Create a partner, that is also a portal user -->
+ <record id="partner_demo_portal" model="res.partner">
<field name="name">Demo Portal User</field>
+ <field name="email">demo@portal.example.com</field>
+ <field name="supplier" eval="False"/>
+ <field name="customer" eval="True"/>
+ </record>
+ <record id="demo_user0" model="res.users">
+ <field name="partner_id" ref="partner_demo_portal"/>
<field name="login">portal</field>
<field name="password">portal</field>
+ <field name="signature">--
+Mr Demo Portal</field>
<!-- Avoid auto-including this user in any default group -->
<field name="groups_id" eval="[(5,)]"/>
- <field name="supplier" eval="False"/>
- <field name="customer" eval="True"/>
- <field name="email">demo@portal.wrong.address</field>
</record>
<!-- Add the demo user to the portal (and therefore to the portal member group) -->
@@ -24,33 +29,41 @@
<field name="subject">Our company's first blog-post !</field>
<field name="model">mail.group</field>
<field name="res_id" ref="company_news_feed"/>
- <field name="body"><![CDATA[Hello, and welcome to our company's portal !
-
-Lorem ipsum <b>sit amet</b>, consectetur <em>adipiscing elit</em>. Pellentesque et quam sapien, in sagittis tellus.
-Praesent vel massa sed massa consequat egestas in tristique orci. Praesent iaculis libero et neque vehicula iaculis. Vivamus placerat tincidunt orci ac ornare. Proin ut dolor fringilla velit ultricies consequat. Maecenas sit amet ipsum non leo interdum imperdiet. Donec sapien mi.
-
-Fusce tempus elit volutpat mi auctor adipiscing. Nam congue luctus suscipit. Sed tellus libero, venenatis ut mollis ut, luctus quis dui. Sed rhoncus pulvinar orci in consectetur.
-
-Nulla turpis leo, rhoncus ut egestas sit amet, consectetur vitae urna. Mauris in dolor in sapien tempus vehicula.]]></field>
+ <field name="body"><![CDATA[<p>Hello, and welcome to our company's portal !</p>
+<p>It is a great pleasure to announce you the creation of our portal by writing this first news! As you may have seen, a new discussion group is now present under your 'My groups' menu: <b>Company's News</b>. We will post news about the company and its employees in this discussion group. Moreover, we will be able to communicate with our partners that are given the opportunity to join us in our portal.</p>
+<p>A new era of communication has begun! <b>Feel free to post your feelings about our portal by replying on this message!</b></p>]]></field>
<field name="type">comment</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="author_id" ref="base.partner_root"/>
</record>
<record id="message_company_news0_comment0" model="mail.message">
<field name="model">mail.group</field>
<field name="res_id" ref="company_news_feed"/>
- <field name="body"><![CDATA[Great first blogpost ! (first comment)]]></field>
+ <field name="body"><![CDATA[<p>As your first portal member, I am very pleased to be able to be able to communicate directly with you. Be sure I'll read all news carefully!</p>]]></field>
<field name="parent_id" ref="message_company_news0"/>
<field name="type">comment</field>
- <field name="author_id" ref="base.res_partner_1"/>
+ <field name="subtype_id" ref="mail.mt_comment"/>
+ <field name="author_id" ref="partner_demo_portal"/>
</record>
<record id="message_company_news0_comment1" model="mail.message">
<field name="model">mail.group</field>
<field name="res_id" ref="company_news_feed"/>
- <field name="body"><![CDATA[Thanks ! (second comment)]]></field>
+ <field name="body"><![CDATA[<p>That's good news! As said by <i>Demo Portal User</i> in the previous post, I'm looking forward to hearing from you!</p>]]></field>
+ <field name="parent_id" ref="message_company_news0"/>
+ <field name="type">comment</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
+ <field name="author_id" ref="base.res_partner_1"/>
+ </record>
+
+ <record id="message_company_news0_comment2" model="mail.message">
+ <field name="model">mail.group</field>
+ <field name="res_id" ref="company_news_feed"/>
+ <field name="body"><![CDATA[<p>This feature is realy great! We will be able to communicate directly to our partners!</p>]]></field>
<field name="parent_id" ref="message_company_news0"/>
<field name="type">comment</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="author_id" ref="base.partner_demo"/>
</record>
diff --git a/addons/portal/tests/test_portal.py b/addons/portal/tests/test_portal.py
index 83b10b39c28..0a2772c9cfe 100644
--- a/addons/portal/tests/test_portal.py
+++ b/addons/portal/tests/test_portal.py
@@ -19,12 +19,12 @@
#
##############################################################################
-from openerp.addons.mail.tests import test_mail
-from openerp.tools import append_content_to_html
-from osv.orm import except_orm
+from openerp.addons.mail.tests import test_mail_mockup
+from openerp.osv.orm import except_orm
+from openerp.tools.misc import mute_logger
-class test_portal(test_mail.TestMailMockups):
+class test_portal(test_mail_mockup.TestMailMockups):
def setUp(self):
super(test_portal, self).setUp()
@@ -53,6 +53,7 @@ class test_portal(test_mail.TestMailMockups):
# Set an email address for the user running the tests, used as Sender for outgoing mails
self.res_users.write(cr, uid, uid, {'email': 'test@localhost'})
+ @mute_logger('openerp.addons.base.ir.ir_model')
def test_00_access_rights(self):
""" Test basic mail_message and mail_group access rights for portal users. """
cr, uid = self.cr, self.uid
diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py
index c94d6509f63..bf8353c92c1 100644
--- a/addons/portal/wizard/portal_wizard.py
+++ b/addons/portal/wizard/portal_wizard.py
@@ -24,10 +24,9 @@ import random
from osv import osv, fields
from tools.translate import _
-from tools.misc import email_re
+from tools import email_re
from openerp import SUPERUSER_ID
-from base.res.res_partner import _lang_get
_logger = logging.getLogger(__name__)
# welcome email sent to portal users
diff --git a/addons/portal/wizard/share_wizard.py b/addons/portal/wizard/share_wizard.py
index b1b6e980dec..51e5e59eb0e 100644
--- a/addons/portal/wizard/share_wizard.py
+++ b/addons/portal/wizard/share_wizard.py
@@ -35,8 +35,8 @@ class share_wizard_portal(osv.TransientModel):
def _user_type_selection(self, cr, uid, context=None):
selection = super(share_wizard_portal, self)._user_type_selection(cr, uid, context=context)
- selection.extend([('existing','Users you already shared with'),
- ('groups','Existing Groups (e.g Portal Groups)')])
+ selection.extend([('existing',_('Users you already shared with')),
+ ('groups',_('Existing Groups (e.g Portal Groups)'))])
return selection
_columns = {
diff --git a/addons/portal_claim/security/portal_security.xml b/addons/portal_claim/security/portal_security.xml
index e177b07eab9..3742765f795 100644
--- a/addons/portal_claim/security/portal_security.xml
+++ b/addons/portal_claim/security/portal_security.xml
@@ -7,6 +7,10 @@
<field ref="crm_claim.model_crm_claim" name="model_id"/>
<field name="domain_force">[('message_follower_ids','in', [user.partner_id.id])]</field>
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
+ <field eval="1" name="perm_unlink"/>
+ <field eval="1" name="perm_write"/>
+ <field eval="1" name="perm_read"/>
+ <field eval="0" name="perm_create"/>
</record>
</data>
diff --git a/addons/portal_project/security/portal_security.xml b/addons/portal_project/security/portal_security.xml
index 1247d25365a..ba686f72db4 100644
--- a/addons/portal_project/security/portal_security.xml
+++ b/addons/portal_project/security/portal_security.xml
@@ -7,6 +7,10 @@
<field ref="project.model_project_task" name="model_id"/>
<field name="domain_force">[('message_follower_ids','in', [user.partner_id.id])]</field>
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
+ <field eval="1" name="perm_unlink"/>
+ <field eval="1" name="perm_write"/>
+ <field eval="1" name="perm_read"/>
+ <field eval="0" name="perm_create"/>
</record>
</data>
diff --git a/addons/portal_project_issue/security/portal_security.xml b/addons/portal_project_issue/security/portal_security.xml
index 9527f1f9628..a121eeb593e 100644
--- a/addons/portal_project_issue/security/portal_security.xml
+++ b/addons/portal_project_issue/security/portal_security.xml
@@ -7,6 +7,10 @@
<field ref="project_issue.model_project_issue" name="model_id"/>
<field name="domain_force">[('message_follower_ids','in', [user.partner_id.id])]</field>
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
+ <field eval="1" name="perm_unlink"/>
+ <field eval="1" name="perm_write"/>
+ <field eval="1" name="perm_read"/>
+ <field eval="0" name="perm_create"/>
</record>
</data>
diff --git a/addons/portal_sale/security/portal_security.xml b/addons/portal_sale/security/portal_security.xml
index 39dabf754fe..19d44947f03 100644
--- a/addons/portal_sale/security/portal_security.xml
+++ b/addons/portal_sale/security/portal_security.xml
@@ -8,6 +8,10 @@
<field name="model_id" ref="sale.model_sale_order"/>
<field name="domain_force">[('message_follower_ids','in',[user.partner_id.id])]</field>
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
+ <field eval="1" name="perm_unlink"/>
+ <field eval="1" name="perm_write"/>
+ <field eval="1" name="perm_read"/>
+ <field eval="0" name="perm_create"/>
</record>
<record id="portal_stock_picking_user_rule" model="ir.rule">
diff --git a/addons/process/__openerp__.py b/addons/process/__openerp__.py
index fcae18c5490..c998288a614 100644
--- a/addons/process/__openerp__.py
+++ b/addons/process/__openerp__.py
@@ -35,7 +35,7 @@ This module shows the basic processes involved in the selected modules and in th
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
- 'depends': ['base'],
+ 'depends': ['web'],
'data': [
'security/ir.model.access.csv',
'process_view.xml'
diff --git a/addons/product/product.py b/addons/product/product.py
index b6a58fcd1e8..27cd4249a60 100644
--- a/addons/product/product.py
+++ b/addons/product/product.py
@@ -657,9 +657,9 @@ class product_product(osv.osv):
# Performing a quick memory merge of ids in Python will give much better performance
ids = set()
ids.update(self.search(cr, user, args + [('default_code',operator,name)], limit=limit, context=context))
- if len(ids) < limit:
+ if not limit or len(ids) < limit:
# we may underrun the limit because of dupes in the results, that's fine
- ids.update(self.search(cr, user, args + [('name',operator,name)], limit=(limit-len(ids)), context=context))
+ ids.update(self.search(cr, user, args + [('name',operator,name)], limit=(limit and (limit-len(ids)) or False) , context=context))
ids = list(ids)
if not ids:
ptrn = re.compile('(\[(.*?)\])')
diff --git a/addons/product_expiry/product_expiry.py b/addons/product_expiry/product_expiry.py
index c16ccc2b1ee..e4ed28db4e6 100644
--- a/addons/product_expiry/product_expiry.py
+++ b/addons/product_expiry/product_expiry.py
@@ -45,12 +45,13 @@ class stock_production_lot(osv.osv):
_columns = {
'life_date': fields.datetime('End of Life Date',
- help='The date on which the lot may become dangerous and should not be consumed.'),
+ help='This is the date on which the goods with this Serial Number may become dangerous and must not be consumed.'),
'use_date': fields.datetime('Best before Date',
- help='The date on which the lot starts deteriorating without becoming dangerous.'),
+ help='This is the date on which the goods with this Serial Number start deteriorating, without being dangerous yet.'),
'removal_date': fields.datetime('Removal Date',
- help='The date on which the lot should be removed.'),
- 'alert_date': fields.datetime('Alert Date', help="The date on which an alert should be notified about the serial number."),
+ help='This is the date on which the goods with this Serial Number should be removed from the stock.'),
+ 'alert_date': fields.datetime('Alert Date',
+ help="This is the date on which an alert should be notified about the goods with this Serial Number."),
}
# Assign dates according to products data
def create(self, cr, uid, vals, context=None):
@@ -78,12 +79,13 @@ class product_product(osv.osv):
_inherit = 'product.product'
_columns = {
'life_time': fields.integer('Product Life Time',
- help='The number of days before a serial number may become dangerous and should not be consumed.'),
+ help='When a new a Serial Number is issued, this is the number of days before the goods may become dangerous and must not be consumed.'),
'use_time': fields.integer('Product Use Time',
- help='The number of days before a serial number starts deteriorating without becoming dangerous.'),
+ help='When a new a Serial Number is issued, this is the number of days before the goods starts deteriorating, without being dangerous yet.'),
'removal_time': fields.integer('Product Removal Time',
- help='The number of days before a serial number should be removed.'),
- 'alert_time': fields.integer('Product Alert Time', help="The number of days after which an alert should be notified about the serial number."),
+ help='When a new a Serial Number is issued, this is the number of days before the goods should be removed from the stock.'),
+ 'alert_time': fields.integer('Product Alert Time',
+ help='When a new a Serial Number is issued, this is the number of days before an alert should be notified.'),
}
product_product()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/product_margin/product_margin.py b/addons/product_margin/product_margin.py
index 4c033a4a6ca..c06c4971474 100644
--- a/addons/product_margin/product_margin.py
+++ b/addons/product_margin/product_margin.py
@@ -56,11 +56,12 @@ class product_product(osv.osv):
sum(l.price_unit * l.quantity)/sum(l.quantity) as avg_unit_price,
sum(l.quantity) as num_qty,
sum(l.quantity * (l.price_subtotal/l.quantity)) as total,
- sum(l.quantity * product.list_price) as sale_expected,
- sum(l.quantity * product.standard_price) as normal_cost
+ sum(l.quantity * pt.list_price) as sale_expected,
+ sum(l.quantity * pt.standard_price) as normal_cost
from account_invoice_line l
left join account_invoice i on (l.invoice_id = i.id)
- left join product_template product on (product.id=l.product_id)
+ left join product_product product on (product.id=l.product_id)
+ left join product_template pt on (pt.id=product.product_tmpl_id)
where l.product_id = %s and i.state in %s and i.type IN %s and (i.date_invoice IS NULL or (i.date_invoice>=%s and i.date_invoice<=%s))
"""
invoice_types = ('out_invoice', 'in_refund')
diff --git a/addons/product_visible_discount/i18n/lt.po b/addons/product_visible_discount/i18n/lt.po
new file mode 100644
index 00000000000..da70b62c1dd
--- /dev/null
+++ b/addons/product_visible_discount/i18n/lt.po
@@ -0,0 +1,62 @@
+# Lithuanian translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2012-02-08 00:37+0000\n"
+"PO-Revision-Date: 2012-11-15 13:54+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Lithuanian <lt@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-11-16 04:36+0000\n"
+"X-Generator: Launchpad (build 16272)\n"
+
+#. module: product_visible_discount
+#: code:addons/product_visible_discount/product_visible_discount.py:153
+#, python-format
+msgid "No Sale Pricelist Found!"
+msgstr ""
+
+#. module: product_visible_discount
+#: field:product.pricelist,visible_discount:0
+msgid "Visible Discount"
+msgstr "Matoma Nuolaida"
+
+#. module: product_visible_discount
+#: code:addons/product_visible_discount/product_visible_discount.py:145
+#, python-format
+msgid "No Purchase Pricelist Found!"
+msgstr "Nerastas pirkimo kainoraštis !"
+
+#. module: product_visible_discount
+#: model:ir.model,name:product_visible_discount.model_account_invoice_line
+msgid "Invoice Line"
+msgstr "Sąskaitos eilutė"
+
+#. module: product_visible_discount
+#: model:ir.model,name:product_visible_discount.model_product_pricelist
+msgid "Pricelist"
+msgstr "Kainoraštis"
+
+#. module: product_visible_discount
+#: code:addons/product_visible_discount/product_visible_discount.py:145
+#, python-format
+msgid "You must first define a pricelist on the supplier form!"
+msgstr "Pirma turite aprašyti kainoraštį tiekėjo formoje !"
+
+#. module: product_visible_discount
+#: model:ir.model,name:product_visible_discount.model_sale_order_line
+msgid "Sales Order Line"
+msgstr "Pardavimo užsakymo eilutė"
+
+#. module: product_visible_discount
+#: code:addons/product_visible_discount/product_visible_discount.py:153
+#, python-format
+msgid "You must first define a pricelist on the customer form!"
+msgstr "Pirma turite aprašyti kainoraštį pirkėjo formoje !"
diff --git a/addons/project/project.py b/addons/project/project.py
index 741cae4b91b..9c28fadeab9 100644
--- a/addons/project/project.py
+++ b/addons/project/project.py
@@ -166,17 +166,17 @@ class project(osv.osv):
res[id]['progress_rate'] = 0.0
return res
- def unlink(self, cr, uid, ids, *args, **kwargs):
+ def unlink(self, cr, uid, ids, context=None):
alias_ids = []
mail_alias = self.pool.get('mail.alias')
- for proj in self.browse(cr, uid, ids):
+ for proj in self.browse(cr, uid, ids, context=context):
if proj.tasks:
raise osv.except_osv(_('Invalid Action!'),
_('You cannot delete a project containing tasks. You can either delete all the project\'s tasks and then delete the project or simply deactivate the project.'))
elif proj.alias_id:
alias_ids.append(proj.alias_id.id)
- res = super(project, self).unlink(cr, uid, ids, *args, **kwargs)
- mail_alias.unlink(cr, uid, alias_ids, *args, **kwargs)
+ res = super(project, self).unlink(cr, uid, ids, context=context)
+ mail_alias.unlink(cr, uid, alias_ids, context=context)
return res
def _get_attached_docs(self, cr, uid, ids, field_name, arg, context):
@@ -204,8 +204,8 @@ class project(osv.osv):
def attachment_tree_view(self, cr, uid, ids, context):
task_ids = self.pool.get('project.task').search(cr, uid, [('project_id', 'in', ids)])
domain = [
- ('|',
- '&', 'res_model', '=', 'project.project'), ('res_id', 'in', ids),
+ '|',
+ '&', ('res_model', '=', 'project.project'), ('res_id', 'in', ids),
'&', ('res_model', '=', 'project.task'), ('res_id', 'in', task_ids)
]
res_id = ids and ids[0] or False
@@ -474,7 +474,7 @@ def Project():
resource = %s
""" % (
project.id,
- project.date_start, working_days,
+ project.date_start or time.strftime('%Y-%m-%d'), working_days,
'|'.join(['User_'+str(x) for x in puids])
)
vacation = calendar_id and tuple(resource_pool.compute_vacation(cr, uid, calendar_id, context=context)) or False
diff --git a/addons/project/project_data.xml b/addons/project/project_data.xml
index 4f467c89a29..08981bd126a 100644
--- a/addons/project/project_data.xml
+++ b/addons/project/project_data.xml
@@ -125,11 +125,11 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Project Management application installed!</field>
- <field name="body">Manage multi-level projects and tasks. You can delegate tasks, track task work, and review your planning.
-
-You can manage todo lists on tasks by installing the "Todo Lists" application, supporting the Getting Things Done (GTD) methodology.
-You can also manage issues/bugs in projects by installing the "Issue Tracker" application.</field>
+ <field name="body"><![CDATA[<p>Manage multi-level projects and tasks. You can delegate tasks, track task work, and review your planning.</p>
+<p>You can manage todo lists on tasks by installing the <i>Todo Lists</i> application, supporting the Getting Things Done (GTD) methodology.</p>
+<p>You can also manage issues/bugs in projects by installing the "Issue Tracker" application.</p>]]></field>
</record>
</data>
</openerp>
diff --git a/addons/project/project_demo.xml b/addons/project/project_demo.xml
index cd22bad67d4..698a1a99627 100644
--- a/addons/project/project_demo.xml
+++ b/addons/project/project_demo.xml
@@ -21,31 +21,15 @@
<field name="name">Usability</field>
</record>
- <!-- Projects -->
- <record id="project_project_internal" model="project.project">
- <field name="name">Internal Projects</field>
- <field name="parent_id" ref="all_projects_account"/>
- <field name="user_id" ref="base.user_root"/>
- <field name="alias_model">project.task</field>
- <field name="type_ids" eval="[(6, 0, [ref('project_tt_specification'),ref('project_tt_development'),ref('project_tt_testing'),ref('project_tt_merge'),ref('project_tt_deployment')])]"/>
- </record>
-
- <record id="project_project_customer" model="project.project">
- <field name="name">Customer Projects</field>
- <field name="parent_id" ref="all_projects_account"/>
- <field name="user_id" ref="base.user_root"/>
- <field name="alias_model">project.task</field>
- <field name="type_ids" eval="[(6, 0, [ref('project_tt_analysis'),ref('project_tt_specification'),ref('project_tt_negotiation'),ref('project_tt_development'),ref('project_tt_testing'),ref('project_tt_deployment')])]"/>
- </record>
-
<record id="project_project_1" model="project.project">
<field name="date_start" eval="time.strftime('%Y-%m-01 10:00:00')"/>
<field name="state">open</field>
<field name="type">normal</field>
<field name="name">The Jackson Group's Project</field>
+ <field name="color">3</field>
<field name="partner_id" ref="base.res_partner_10"/>
<field name="parent_id" ref="all_projects_account"/>
- <field name="privacy_visibility">followers</field>
+ <field name="privacy_visibility">public</field>
<field name="members" eval="[(6, 0, [
ref('base.user_root'),
ref('base.user_demo')])]"/>
@@ -58,6 +42,7 @@
<record id="project_project_2" model="project.project">
<field name="name">Research &amp; Development</field>
<field name="parent_id" ref="all_projects_account"/>
+ <field name="privacy_visibility">public</field>
<field name="user_id" ref="base.user_demo"/>
<field name="alias_model">project.task</field>
<field name="type_ids" eval="[(6, 0, [ref('project_tt_specification'),ref('project_tt_development'),ref('project_tt_testing'),ref('project_tt_merge'),ref('project_tt_deployment')])]"/>
@@ -69,6 +54,7 @@
<field name="name">E-Learning Integration</field>
<field name="user_id" ref="base.user_demo"/>
<field name="alias_model">project.task</field>
+ <field name="privacy_visibility">public</field>
<field name="members" eval="[(6, 0, [
ref('base.user_root'),
ref('base.user_demo')])]"/>
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml
index 58f0ae17962..e7f12ff3797 100644
--- a/addons/project/project_view.xml
+++ b/addons/project/project_view.xml
@@ -164,7 +164,7 @@
<field name="model">project.project</field>
<field name="arch" type="xml">
<search string="Search Project">
- <field name="complete_name" string="Project Name"/>
+ <field name="name" string="Project Name"/>
<filter icon="terp-mail-message-new" string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]"/>
<separator/>
<filter icon="terp-check" string="Open" name="Current" domain="[('state', '=','open')]" help="Open Projects"/>
diff --git a/addons/project_gtd/__openerp__.py b/addons/project_gtd/__openerp__.py
index 441f8859dc6..c99535f63fd 100644
--- a/addons/project_gtd/__openerp__.py
+++ b/addons/project_gtd/__openerp__.py
@@ -24,7 +24,7 @@
'name': 'Todo Lists',
'version': '1.0',
'category': 'Project Management',
- 'sequence': 9,
+ 'sequence': 100,
'summary': 'Personal Tasks, Contexts, Timeboxes',
'description': """
Implement concepts of the "Getting Things Done" methodology
diff --git a/addons/project_gtd/project_gtd_data.xml b/addons/project_gtd/project_gtd_data.xml
index 61b2468329c..9d8c99f23ff 100644
--- a/addons/project_gtd/project_gtd_data.xml
+++ b/addons/project_gtd/project_gtd_data.xml
@@ -30,9 +30,10 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Todo Lists application installed!</field>
- <field name="body">Add todo items on project tasks, to help you organize your work.
-This application supports the Getting Things Done (GTD) methodology, based on David Allen's book.</field>
+ <field name="body"><![CDATA[<p>Add todo items on project tasks, to help you organize your work.</p><p>
+This application supports the Getting Things Done (GTD) methodology, based on David Allen's book.</p>]]></field>
</record>
</data>
diff --git a/addons/project_issue/project_issue_data.xml b/addons/project_issue/project_issue_data.xml
index 72f824715a8..c1460167097 100644
--- a/addons/project_issue/project_issue_data.xml
+++ b/addons/project_issue/project_issue_data.xml
@@ -36,10 +36,11 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Issue Tracker application installed!</field>
- <field name="body">Manage the issues you might face in a project, such as bugs in a system, client complaints or material breakdowns.
-You can record issues, assign them to a responsible person, and keep track of their status as they evolve over time.
-Access all issues from the top Project menu, and access the issues of a specific project via the projects gallery view.</field>
+ <field name="body"><![CDATA[<p>Manage the issues you might face in a project, such as bugs in a system, client complaints or material breakdowns.</p><p>
+You can record issues, assign them to a responsible person, and keep track of their status as they evolve over time.</p><p>
+Access all issues from the top Project menu, and access the issues of a specific project via the projects gallery view.</p>]]></field>
</record>
<!-- Mail subtypes -->
diff --git a/addons/project_issue/project_issue_demo.xml b/addons/project_issue/project_issue_demo.xml
index 9759d15dabb..63fa37c84c3 100644
--- a/addons/project_issue/project_issue_demo.xml
+++ b/addons/project_issue/project_issue_demo.xml
@@ -1,5 +1,24 @@
<?xml version="1.0"?>
<openerp>
+ <data>
+
+ <record id="project.project_project_1" model="project.project">
+ <field name="use_issues" eval="True"/>
+ </record>
+ <record id="project.project_project_2" model="project.project">
+ <field name="use_issues" eval="True"/>
+ </record>
+ <record id="project.project_project_3" model="project.project">
+ <field name="use_issues" eval="True"/>
+ </record>
+ <record id="project.project_project_4" model="project.project">
+ <field name="use_issues" eval="True"/>
+ </record>
+ <record id="project.project_project_5" model="project.project">
+ <field name="use_issues" eval="True"/>
+ </record>
+
+ </data>
<data noupdate="1">
<!-- Categories -->
diff --git a/addons/project_long_term/project_long_term_view.xml b/addons/project_long_term/project_long_term_view.xml
index 52eb5d80a3a..18e471ddd40 100644
--- a/addons/project_long_term/project_long_term_view.xml
+++ b/addons/project_long_term/project_long_term_view.xml
@@ -121,8 +121,8 @@
<xpath expr="//div[contains(@class, 'oe_kanban_project_list')]" position="inside">
<a t-if="record.use_phases.raw_value"
name="%(act_project_phases)d" type="action">
- <span t-if="record.phase_count.raw_value gt 1">Phases(<field name="phase_count"/>)</span>
- <span t-if="record.phase_count.raw_value lt 2">Phase(<field name="phase_count"/>)</span>
+ <span t-if="record.phase_count.raw_value gt 1"><field name="phase_count"/> Phases</span>
+ <span t-if="record.phase_count.raw_value lt 2"><field name="phase_count"/> Phase</span>
</a>
</xpath>
</field>
diff --git a/addons/purchase/edi/purchase_order_action_data.xml b/addons/purchase/edi/purchase_order_action_data.xml
index daad4467929..fab7eeacf6c 100644
--- a/addons/purchase/edi/purchase_order_action_data.xml
+++ b/addons/purchase/edi/purchase_order_action_data.xml
@@ -40,7 +40,7 @@
<field name="name">Automated Purchase Order Notification Mail</field>
<field name="email_from">${object.validator.email or ''}</field>
<field name="subject">${object.company_id.name} Order (Ref ${object.name or 'n/a' })</field>
- <field name="email_to">${object.partner_id.email}</field>
+ <field name="email_recipients">${object.partner_id.id}</field>
<field name="model_id" ref="purchase.model_purchase_order"/>
<field name="auto_delete" eval="True"/>
<field name="body_html"><![CDATA[
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 2801df1a2b6..9557c2299e5 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -46,7 +46,7 @@ class purchase_order(osv.osv):
cur = order.pricelist_id.currency_id
for line in order.order_line:
val1 += line.price_subtotal
- for c in self.pool.get('account.tax').compute_all(cr, uid, line.taxes_id, line.price_unit, line.product_qty, line.product_id.id, order.partner_id)['taxes']:
+ for c in self.pool.get('account.tax').compute_all(cr, uid, line.taxes_id, line.price_unit, line.product_qty, line.product_id, order.partner_id)['taxes']:
val += c.get('amount', 0.0)
res[order.id]['amount_tax']=cur_obj.round(cr, uid, cur, val)
res[order.id]['amount_untaxed']=cur_obj.round(cr, uid, cur, val1)
@@ -296,6 +296,27 @@ class purchase_order(osv.osv):
fiscal_position = supplier.property_account_position and supplier.property_account_position.id or False
return {'value':{'pricelist_id': pricelist, 'fiscal_position': fiscal_position}}
+ def invoice_open(self, cr, uid, ids, context=None):
+ mod_obj = self.pool.get('ir.model.data')
+ act_obj = self.pool.get('ir.actions.act_window')
+
+ result = mod_obj.get_object_reference(cr, uid, 'account', 'action_invoice_tree2')
+ id = result and result[1] or False
+ result = act_obj.read(cr, uid, [id], context=context)[0]
+ inv_ids = []
+ for po in self.browse(cr, uid, ids, context=context):
+ inv_ids+= [invoice.id for invoice in po.invoice_ids]
+ if not inv_ids:
+ raise osv.except_osv(_('Error!'), _('Please create Invoices.'))
+ #choose the view_mode accordingly
+ if len(inv_ids)>1:
+ result['domain'] = "[('id','in',["+','.join(map(str, inv_ids))+"])]"
+ else:
+ res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_supplier_form')
+ result['views'] = [(res and res[1] or False, 'form')]
+ result['res_id'] = inv_ids and inv_ids[0] or False
+ return result
+
def view_invoice(self, cr, uid, ids, context=None):
'''
This function returns an action that display existing invoices of given sale order ids. It can either be a in a list or in a form view, if there is only one invoice to show.
@@ -377,6 +398,7 @@ class purchase_order(osv.osv):
'default_res_id': ids[0],
'default_use_template': True,
'default_template_id': template_id,
+ 'default_composition_mode': 'comment',
})
return {
'view_type': 'form',
@@ -571,7 +593,6 @@ class purchase_order(osv.osv):
'invoice_state': '2binvoiced' if order.invoice_method == 'picking' else 'none',
'type': 'in',
'partner_id': order.dest_address_id.id or order.partner_id.id,
- 'invoice_state': '2binvoiced' if order.invoice_method == 'picking' else 'none',
'purchase_id': order.id,
'company_id': order.company_id.id,
'move_lines' : [],
@@ -827,7 +848,7 @@ class purchase_order_line(osv.osv):
cur_obj=self.pool.get('res.currency')
tax_obj = self.pool.get('account.tax')
for line in self.browse(cr, uid, ids, context=context):
- taxes = tax_obj.compute_all(cr, uid, line.taxes_id, line.price_unit, line.product_qty)
+ taxes = tax_obj.compute_all(cr, uid, line.taxes_id, line.price_unit, line.product_qty, line.product_id, line.order_id.partner_id)
cur = line.order_id.pricelist_id.currency_id
res[line.id] = cur_obj.round(cr, uid, cur, taxes['total'])
return res
diff --git a/addons/purchase/purchase_data.xml b/addons/purchase/purchase_data.xml
index 693d18eb1ba..fa701c1f179 100644
--- a/addons/purchase/purchase_data.xml
+++ b/addons/purchase/purchase_data.xml
@@ -7,10 +7,10 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Purchase Management application installed!</field>
- <field name="body">From the top menu Purchases, create purchase orders to buy products from your suppliers, enter supplier invoices and manage payments.
-
-You can also manage purchase requisitions, see also the Purchase Settings.</field>
+ <field name="body"><![CDATA[<p>From the top menu Purchases, create purchase orders to buy products from your suppliers, enter supplier invoices and manage payments.</p>
+<p>You can also manage purchase requisitions, see also the Purchase Settings.</p>]]></field>
</record>
<record id="req_link_purchase_order" model="res.request.link">
diff --git a/addons/purchase/stock_view.xml b/addons/purchase/stock_view.xml
index 9e5aa2e074e..188baeccd69 100644
--- a/addons/purchase/stock_view.xml
+++ b/addons/purchase/stock_view.xml
@@ -48,6 +48,8 @@
<button type="object"
name="view_picking"
string="Incoming Shipments" states="approved"/>
+ <button type="object" name="invoice_open"
+ string="Invoices" attrs="{'invisible': [('state', '=', 'draft')]}"/>
</div>
</xpath>
</field>
diff --git a/addons/sale/edi/sale_order_action_data.xml b/addons/sale/edi/sale_order_action_data.xml
index 9796d0bda16..da1a1ceb393 100644
--- a/addons/sale/edi/sale_order_action_data.xml
+++ b/addons/sale/edi/sale_order_action_data.xml
@@ -25,7 +25,7 @@
<field name="name">Automated Sale Order Notification Mail</field>
<field name="email_from">${object.user_id.email or ''}</field>
<field name="subject">${object.company_id.name} Order (Ref ${object.name or 'n/a' })</field>
- <field name="email_to">${object.partner_invoice_id.email}</field>
+ <field name="email_recipients">${object.partner_invoice_id.id}</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="auto_delete" eval="True"/>
<field name="body_html"><![CDATA[
diff --git a/addons/sale/i18n/lv.po b/addons/sale/i18n/lv.po
index 65d1f92d71c..a1b6b6a37c9 100644
--- a/addons/sale/i18n/lv.po
+++ b/addons/sale/i18n/lv.po
@@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-09-20 07:29+0000\n"
-"PO-Revision-Date: 2009-09-08 12:39+0000\n"
-"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
+"PO-Revision-Date: 2012-11-16 12:35+0000\n"
+"Last-Translator: Normunds (Alistek) <Unknown>\n"
"Language-Team: Latvian <lv@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-10-30 05:08+0000\n"
-"X-Generator: Launchpad (build 16206)\n"
+"X-Launchpad-Export-Date: 2012-11-17 04:36+0000\n"
+"X-Generator: Launchpad (build 16278)\n"
#. module: sale
#: code:addons/sale/wizard/sale_make_invoice_advance.py:215
@@ -161,14 +161,14 @@ msgstr ""
#. module: sale
#: field:sale.order,date_confirm:0
msgid "Confirmation Date"
-msgstr ""
+msgstr "Apstiprināšanas Datums"
#. module: sale
#: view:sale.order:0
#: view:sale.order.line:0
#: view:sale.report:0
msgid "Group By..."
-msgstr ""
+msgstr "Grupēt Pēc..."
#. module: sale
#: view:sale.order.line:0
@@ -209,7 +209,7 @@ msgstr ""
#. module: sale
#: field:sale.report,state:0
msgid "Order State"
-msgstr "Pasūtījuma statuss"
+msgstr "Pasūtījuma Statuss"
#. module: sale
#: help:sale.config.settings,module_account_analytic_analysis:0
@@ -228,7 +228,7 @@ msgstr ""
#: view:sale.order:0
#: view:sale.order.line:0
msgid "To Invoice"
-msgstr ""
+msgstr "Piestādīt Rēķinu"
#. module: sale
#: view:sale.order.line:0
@@ -239,7 +239,7 @@ msgstr ""
#. module: sale
#: help:sale.order,date_confirm:0
msgid "Date on which sales order is confirmed."
-msgstr ""
+msgstr "Datums, kurā pasūtījums tika apstiprināts."
#. module: sale
#: model:ir.actions.act_window,name:sale.action_order_tree5
@@ -247,12 +247,12 @@ msgstr ""
#: view:sale.order:0
#: view:sale.report:0
msgid "Quotations"
-msgstr ""
+msgstr "Tāmējumi"
#. module: sale
#: selection:sale.report,month:0
msgid "March"
-msgstr ""
+msgstr "Marts"
#. module: sale
#: code:addons/sale/sale.py:558
@@ -277,12 +277,12 @@ msgstr ""
#: field:sale.report,company_id:0
#: field:sale.shop,company_id:0
msgid "Company"
-msgstr ""
+msgstr "Uzņēmums"
#. module: sale
#: field:sale.make.invoice,invoice_date:0
msgid "Invoice Date"
-msgstr ""
+msgstr "Rēķina Datums"
#. module: sale
#: model:ir.actions.act_window,name:sale.action_order_line_tree3
@@ -292,7 +292,7 @@ msgstr ""
#. module: sale
#: help:sale.advance.payment.inv,amount:0
msgid "The amount to be invoiced in advance."
-msgstr ""
+msgstr "Priekšapmaksas rēķina summa."
#. module: sale
#: selection:sale.order,state:0
@@ -321,7 +321,7 @@ msgstr ""
#. module: sale
#: help:sale.order,amount_total:0
msgid "The total amount."
-msgstr ""
+msgstr "Summa"
#. module: sale
#: view:sale.report:0
@@ -405,7 +405,7 @@ msgstr ""
#. module: sale
#: selection:sale.report,month:0
msgid "September"
-msgstr ""
+msgstr "Septembris"
#. module: sale
#: field:sale.order,amount_tax:0
@@ -437,7 +437,7 @@ msgstr ""
#. module: sale
#: report:sale.order:0
msgid "Net Total :"
-msgstr "Tīrais kopā:"
+msgstr "Neto Summa:"
#. module: sale
#: help:sale.config.settings,module_analytic_user_function:0
@@ -456,7 +456,7 @@ msgstr ""
#: selection:sale.order.line,state:0
#: selection:sale.report,state:0
msgid "Cancelled"
-msgstr ""
+msgstr "Atcelts"
#. module: sale
#: view:sale.order.line:0
@@ -490,7 +490,7 @@ msgstr "Veikals"
#. module: sale
#: model:ir.actions.act_window,name:sale.action_order_tree2
msgid "Sales in Exception"
-msgstr ""
+msgstr "Veiktas Izmaiņas"
#. module: sale
#: field:sale.order,partner_invoice_id:0
@@ -500,7 +500,7 @@ msgstr "Rēķina Adrese"
#. module: sale
#: help:sale.order,create_date:0
msgid "Date on which sales order is created."
-msgstr ""
+msgstr "Datums, kurā izveidots pasūtījums."
#. module: sale
#: view:res.partner:0
@@ -516,7 +516,7 @@ msgstr "Veidot Rēķinu"
#: view:sale.make.invoice:0
#: view:sale.order.line.make.invoice:0
msgid "Create Invoices"
-msgstr ""
+msgstr "Veidot Rēķinus"
#. module: sale
#: report:sale.order:0
@@ -537,13 +537,13 @@ msgstr ""
#. module: sale
#: field:sale.report,date_confirm:0
msgid "Date Confirm"
-msgstr ""
+msgstr "Apstiprināšanas Datums"
#. module: sale
#: view:sale.report:0
#: field:sale.report,nbr:0
msgid "# of Lines"
-msgstr ""
+msgstr "Rindu skaits"
#. module: sale
#: help:sale.order,message_summary:0
@@ -561,7 +561,7 @@ msgstr ""
#: view:sale.report:0
#: field:sale.report,product_uom_qty:0
msgid "# of Qty"
-msgstr ""
+msgstr "Daudz."
#. module: sale
#: report:sale.order:0
@@ -588,12 +588,12 @@ msgstr ""
#: view:sale.order:0
#, python-format
msgid "Sales Order"
-msgstr ""
+msgstr "Pasūtījums"
#. module: sale
#: field:sale.order.line,product_uos_qty:0
msgid "Quantity (UoS)"
-msgstr ""
+msgstr "Daudzums (Pārdošanas mērvienība)"
#. module: sale
#: view:sale.order.line:0
@@ -603,7 +603,7 @@ msgstr ""
#. module: sale
#: field:sale.advance.payment.inv,amount:0
msgid "Advance Amount"
-msgstr ""
+msgstr "Priekšapmaksas Summa"
#. module: sale
#: selection:sale.order.line,state:0
@@ -657,7 +657,7 @@ msgstr ""
#: view:sale.report:0
#: field:sale.report,year:0
msgid "Year"
-msgstr ""
+msgstr "Gads"
#. module: sale
#: field:sale.config.settings,group_uom:0
@@ -710,12 +710,12 @@ msgstr "Rēķina pozīcijas"
#: view:sale.report:0
#: field:sale.report,price_total:0
msgid "Total Price"
-msgstr ""
+msgstr "Cena Kopā"
#. module: sale
#: model:ir.actions.act_window,name:sale.action_order_tree
msgid "Old Quotations"
-msgstr ""
+msgstr "Vecie Tāmējumi"
#. module: sale
#: help:sale.config.settings,module_sale_journal:0
@@ -735,7 +735,7 @@ msgstr ""
#: model:ir.actions.act_window,name:sale.action_sale_order_make_invoice
#: model:ir.actions.act_window,name:sale.action_view_sale_order_line_make_invoice
msgid "Make Invoices"
-msgstr ""
+msgstr "Veidot Rēķinus"
#. module: sale
#: model:ir.actions.server,name:sale.actions_server_sale_order_read
@@ -766,7 +766,7 @@ msgstr ""
#. module: sale
#: field:sale.order,create_date:0
msgid "Creation Date"
-msgstr ""
+msgstr "Izveides Datums"
#. module: sale
#: selection:sale.order,state:0
@@ -777,7 +777,7 @@ msgstr ""
#. module: sale
#: help:sale.order,partner_invoice_id:0
msgid "Invoice address for current sales order."
-msgstr ""
+msgstr "Pasūtījuma rēķina adrese"
#. module: sale
#: selection:sale.order,invoice_quantity:0
@@ -814,24 +814,24 @@ msgstr "Kopā:"
#. module: sale
#: view:sale.report:0
msgid "My Sales"
-msgstr ""
+msgstr "Mana Pārdošana"
#. module: sale
#: code:addons/sale/sale.py:253
#: code:addons/sale/sale.py:822
#, python-format
msgid "Invalid action !"
-msgstr "Nepareiza darbība!"
+msgstr "Nederīga darbība!"
#. module: sale
#: field:sale.order,fiscal_position:0
msgid "Fiscal Position"
-msgstr "Fiskālā Pozīcija"
+msgstr "Nodokļu Profils"
#. module: sale
#: selection:sale.report,month:0
msgid "July"
-msgstr ""
+msgstr "Jūlijs"
#. module: sale
#: field:account.config.settings,module_sale_analytic_plans:0
@@ -903,12 +903,12 @@ msgstr ""
#. module: sale
#: report:sale.order:0
msgid "Quotation Date"
-msgstr ""
+msgstr "Tāmējuma Datums"
#. module: sale
#: view:sale.order:0
msgid "Order Date"
-msgstr ""
+msgstr "Pasūtījuma datums"
#. module: sale
#: help:sale.order,order_policy:0
@@ -946,7 +946,7 @@ msgstr ""
#: view:sale.report:0
#: field:sale.report,partner_id:0
msgid "Partner"
-msgstr ""
+msgstr "Partneris"
#. module: sale
#: view:sale.advance.payment.inv:0
@@ -976,7 +976,7 @@ msgstr ""
#. module: sale
#: model:ir.model,name:sale.model_sale_make_invoice
msgid "Sales Make Invoice"
-msgstr ""
+msgstr "Izrakstīt Rēķinu"
#. module: sale
#: model:ir.actions.act_window,help:sale.action_order_tree5
@@ -1040,7 +1040,7 @@ msgstr ""
#. module: sale
#: selection:sale.report,month:0
msgid "December"
-msgstr ""
+msgstr "Decembris"
#. module: sale
#: view:sale.config.settings:0
@@ -1050,13 +1050,13 @@ msgstr ""
#. module: sale
#: view:sale.order.line:0
msgid "Shipped"
-msgstr ""
+msgstr "Piegādāts"
#. module: sale
#: view:sale.report:0
#: field:sale.report,month:0
msgid "Month"
-msgstr ""
+msgstr "Mēnesis"
#. module: sale
#: model:email.template,subject:sale.email_template_edi_sale
@@ -1077,13 +1077,13 @@ msgstr ""
#. module: sale
#: view:sale.order.line:0
msgid "Uninvoiced"
-msgstr ""
+msgstr "Nav piestādīts rēķins"
#. module: sale
#: view:sale.report:0
#: field:sale.report,categ_id:0
msgid "Category of Product"
-msgstr ""
+msgstr "Produkta Kategorija"
#. module: sale
#: code:addons/sale/sale.py:557
@@ -1109,7 +1109,7 @@ msgstr ""
#. module: sale
#: field:sale.shop,name:0
msgid "Shop Name"
-msgstr ""
+msgstr "Tirdzniecības Punkta Nosaukums"
#. module: sale
#: code:addons/sale/sale.py:253
@@ -1121,7 +1121,7 @@ msgstr ""
#. module: sale
#: report:sale.order:0
msgid "Taxes :"
-msgstr "Nodokļi"
+msgstr "Nodokļi:"
#. module: sale
#: code:addons/sale/sale.py:658
@@ -1137,7 +1137,7 @@ msgstr ""
#. module: sale
#: model:ir.model,name:sale.model_sale_advance_payment_inv
msgid "Sales Advance Payment Invoice"
-msgstr ""
+msgstr "Priekšapmaksas Rēķins"
#. module: sale
#: model:ir.actions.client,name:sale.action_client_sale_menu
@@ -1147,13 +1147,13 @@ msgstr ""
#. module: sale
#: selection:sale.report,state:0
msgid "In Progress"
-msgstr ""
+msgstr "Apstrādē"
#. module: sale
#: code:addons/sale/sale.py:867
#, python-format
msgid "No Customer Defined !"
-msgstr ""
+msgstr "Klients nav Definēts!"
#. module: sale
#: view:sale.make.invoice:0
@@ -1226,7 +1226,7 @@ msgstr "Grupēt rēķinus"
#. module: sale
#: help:sale.order,amount_tax:0
msgid "The tax amount."
-msgstr ""
+msgstr "Nodokļa summa."
#. module: sale
#: view:sale.order:0
@@ -1245,7 +1245,7 @@ msgstr ""
#. module: sale
#: selection:sale.report,month:0
msgid "August"
-msgstr ""
+msgstr "Augusts"
#. module: sale
#: view:sale.order:0
@@ -1255,7 +1255,7 @@ msgstr ""
#. module: sale
#: model:process.node,note:sale.process_node_saleorder0
msgid "Drives procurement and invoicing"
-msgstr ""
+msgstr "Nodrošina iepirkumu un rēķinu piestādīšanas procesu"
#. module: sale
#: model:ir.actions.act_window,help:sale.action_order_form
@@ -1275,7 +1275,7 @@ msgstr ""
#. module: sale
#: selection:sale.report,month:0
msgid "June"
-msgstr ""
+msgstr "Jūnijs"
#. module: sale
#: model:ir.actions.act_window,name:sale.action_email_templates
@@ -1313,12 +1313,12 @@ msgstr ""
#: model:ir.model,name:sale.model_sale_shop
#: view:sale.shop:0
msgid "Sales Shop"
-msgstr ""
+msgstr "Tirdzniecības Kanāls"
#. module: sale
#: model:ir.model,name:sale.model_sale_report
msgid "Sales Orders Statistics"
-msgstr ""
+msgstr "Pasūtījumu Statistika"
#. module: sale
#: field:sale.order,date_order:0
@@ -1328,17 +1328,17 @@ msgstr ""
#. module: sale
#: model:ir.model,name:sale.model_sale_order_line
msgid "Sales Order Line"
-msgstr ""
+msgstr "Pasūtījuma Rinda"
#. module: sale
#: selection:sale.report,month:0
msgid "November"
-msgstr ""
+msgstr "Novembris"
#. module: sale
#: view:sale.report:0
msgid "Extended Filters..."
-msgstr ""
+msgstr "Paplašinātie filtri..."
#. module: sale
#: code:addons/sale/wizard/sale_line_invoice.py:111
@@ -1356,7 +1356,7 @@ msgstr ""
#. module: sale
#: field:sale.advance.payment.inv,product_id:0
msgid "Advance Product"
-msgstr ""
+msgstr "Priekšapmaksas Prece"
#. module: sale
#: selection:sale.order.line,state:0
@@ -1366,7 +1366,7 @@ msgstr "Kļūda"
#. module: sale
#: selection:sale.report,month:0
msgid "October"
-msgstr ""
+msgstr "Oktobris"
#. module: sale
#: model:process.transition,note:sale.process_transition_invoice0
@@ -1395,7 +1395,7 @@ msgstr ""
#. module: sale
#: selection:sale.report,month:0
msgid "January"
-msgstr ""
+msgstr "Janvāris"
#. module: sale
#: model:ir.actions.act_window,name:sale.action_order_tree4
@@ -1521,7 +1521,7 @@ msgstr ""
#. module: sale
#: model:process.node,note:sale.process_node_order0
msgid "Confirmed sales order to invoice."
-msgstr ""
+msgstr "Apstiprinātie pasūtījumi rēķina piestādīšanai."
#. module: sale
#: model:ir.actions.act_window,name:sale.action_order_line_product_tree
@@ -1552,7 +1552,7 @@ msgstr ""
#: view:sale.report:0
#: field:sale.report,day:0
msgid "Day"
-msgstr ""
+msgstr "Diena"
#. module: sale
#: view:sale.order:0
@@ -1616,12 +1616,12 @@ msgstr ""
#: model:process.node,name:sale.process_node_quotation0
#: selection:sale.report,state:0
msgid "Quotation"
-msgstr ""
+msgstr "Tāme"
#. module: sale
#: view:sale.order.line:0
msgid "Search Uninvoiced Lines"
-msgstr ""
+msgstr "Meklēt Rindas, par kurām nav piestādīti Rēķini"
#. module: sale
#: model:ir.model,name:sale.model_account_config_settings
@@ -1656,7 +1656,7 @@ msgstr ""
#. module: sale
#: view:sale.order.line:0
msgid "To Do"
-msgstr ""
+msgstr "Veicamais"
#. module: sale
#: report:sale.order:0
@@ -1694,7 +1694,7 @@ msgstr ""
#: model:ir.ui.menu,name:sale.menu_report_product_all
#: view:sale.report:0
msgid "Sales Analysis"
-msgstr ""
+msgstr "Pārdošanu Analīze"
#. module: sale
#: help:sale.order,pricelist_id:0
@@ -1714,7 +1714,7 @@ msgstr "Izveidot Rēķinu"
#. module: sale
#: help:sale.order,amount_untaxed:0
msgid "The amount without tax."
-msgstr ""
+msgstr "Summa bez nodokļiem."
#. module: sale
#: view:sale.order.line:0
@@ -1724,7 +1724,7 @@ msgstr ""
#. module: sale
#: help:sale.order,invoiced:0
msgid "It indicates that an invoice has been paid."
-msgstr ""
+msgstr "Norāda, ka rēķins ir apmaksāts."
#. module: sale
#: code:addons/sale/sale.py:822
@@ -1776,7 +1776,7 @@ msgstr ""
#. module: sale
#: selection:sale.report,month:0
msgid "May"
-msgstr ""
+msgstr "Maijs"
#. module: sale
#: code:addons/sale/sale.py:766
@@ -1823,7 +1823,7 @@ msgstr ""
#. module: sale
#: view:sale.order:0
msgid "Other Information"
-msgstr ""
+msgstr "Cita Informācija"
#. module: sale
#: view:res.partner:0
@@ -1838,7 +1838,7 @@ msgstr "Sk."
#. module: sale
#: model:process.node,note:sale.process_node_invoice0
msgid "To be reviewed by the accountant."
-msgstr ""
+msgstr "Pārbaudīt Grāmatvedim."
#. module: sale
#: view:sale.order:0
@@ -1853,7 +1853,7 @@ msgstr ""
#. module: sale
#: help:sale.order,partner_shipping_id:0
msgid "Shipping address for current sales order."
-msgstr ""
+msgstr "Piegādes adrese pasūtījumam."
#. module: sale
#: selection:sale.order,state:0
@@ -1880,17 +1880,17 @@ msgstr "Klients"
#. module: sale
#: model:product.template,name:sale.advance_product_0_product_template
msgid "Advance"
-msgstr ""
+msgstr "Priekšapmaksa"
#. module: sale
#: selection:sale.report,month:0
msgid "February"
-msgstr ""
+msgstr "Februāris"
#. module: sale
#: field:sale.order,invoice_quantity:0
msgid "Invoice on"
-msgstr ""
+msgstr "Rēķins pēc"
#. module: sale
#: selection:sale.advance.payment.inv,advance_payment_method:0
@@ -1911,7 +1911,7 @@ msgstr "Datums, kad tika pasūtīts"
#. module: sale
#: field:sale.order.line,product_uos:0
msgid "Product UoS"
-msgstr ""
+msgstr "Produkta pārdošanas mērvienība"
#. module: sale
#: help:account.config.settings,group_analytic_account_for_sales:0
@@ -1921,22 +1921,22 @@ msgstr ""
#. module: sale
#: model:process.node,note:sale.process_node_quotation0
msgid "Draft state of sales order"
-msgstr ""
+msgstr "Pasūtījuma melnraksta statuss"
#. module: sale
#: field:sale.order,origin:0
msgid "Source Document"
-msgstr ""
+msgstr "Pamatojuma Dokuments"
#. module: sale
#: selection:sale.report,month:0
msgid "April"
-msgstr ""
+msgstr "Aprīlis"
#. module: sale
#: selection:sale.report,state:0
msgid "Manual In Progress"
-msgstr ""
+msgstr "Manuāls Progresā"
#. module: sale
#: model:ir.actions.server,name:sale.actions_server_sale_order_unread
@@ -1978,7 +1978,7 @@ msgstr ""
#: view:sale.order:0
#: view:sale.order.line:0
msgid "Search Sales Order"
-msgstr ""
+msgstr "Meklēt Pasūtījumu"
#. module: sale
#: view:sale.config.settings:0
@@ -2005,12 +2005,12 @@ msgstr ""
#. module: sale
#: model:process.transition,name:sale.process_transition_saleinvoice0
msgid "From a sales order"
-msgstr ""
+msgstr "No pasūtījuma"
#. module: sale
#: view:sale.order:0
msgid "Ignore Exception"
-msgstr ""
+msgstr "Ignorēt Brīdinājumu"
#. module: sale
#: model:process.transition,note:sale.process_transition_saleinvoice0
@@ -2035,7 +2035,7 @@ msgstr ""
#. module: sale
#: help:sale.order,project_id:0
msgid "The analytic account related to a sales order."
-msgstr ""
+msgstr "Ar pasūtījumu saistītais analītiskais konts."
#. module: sale
#: report:sale.order:0
@@ -2086,7 +2086,7 @@ msgstr ""
#. module: sale
#: field:sale.order,client_order_ref:0
msgid "Customer Reference"
-msgstr ""
+msgstr "Klienta Kods"
#. module: sale
#: view:sale.report:0
@@ -2113,7 +2113,7 @@ msgstr ""
#. module: sale
#: view:sale.order:0
msgid "Total Tax Included"
-msgstr ""
+msgstr "Iekļauto Nodokļu Summa"
#. module: sale
#: field:sale.order,invoice_exists:0
@@ -2360,9 +2360,6 @@ msgstr ""
#~ msgid "Assign"
#~ msgstr "Piešķirt"
-#~ msgid "Delivery Order Only"
-#~ msgstr "Piegādes Pasūtījums Tikai"
-
#~ msgid "Sales order lines"
#~ msgstr "Tirdzniecības pasūtījuma pozīcijas"
@@ -2381,9 +2378,6 @@ msgstr ""
#~ msgid "Shipping & Manual Invoice"
#~ msgstr "Piegāde un Manuāls Rēķins"
-#~ msgid "UoM"
-#~ msgstr "mērv."
-
#~ msgid "Sale Invoice"
#~ msgstr "Rēķins"
@@ -2484,3 +2478,279 @@ msgstr ""
#~ msgid "Invoice Based on Deliveries"
#~ msgstr "Rēķins pēc Piegādes"
+
+#~ msgid "Sales by Salesman in last 90 days"
+#~ msgstr "Pārdošana pa Pārdevējiem pēdējās 90 dienās"
+
+#~ msgid "Configure Sales Order Logistics"
+#~ msgstr "Konfigurēt Pasūtījuma Loģistiku"
+
+#~ msgid "Allows you to compute delivery costs on your quotations."
+#~ msgstr "Ļauj aprēķināt piegādes izmaksas."
+
+#~ msgid ""
+#~ "If you don't have enough stock available to deliver all at once, do you "
+#~ "accept partial shipments or not?"
+#~ msgstr ""
+#~ "Vai piegādāt pasūtījumu pa daļām, ja noliktavā nav iespējams piegādāt visu "
+#~ "pasūtījumu vienlaicīgi?"
+
+#, python-format
+#~ msgid "The quotation '%s' has been converted to a sales order."
+#~ msgstr "Tāmējums \"%s\" tika pārveidots par pasūtījumu."
+
+#~ msgid "Dates"
+#~ msgstr "Datumi"
+
+#~ msgid "Sales by Salesman"
+#~ msgstr "Pārdošana pēc Pārdevējiem"
+
+#~ msgid "Conditions"
+#~ msgstr "Nosacījumi"
+
+#~ msgid "Sales Manager Dashboard"
+#~ msgstr "Pārdevēja Instrumentu Panelis"
+
+#~ msgid "Configure"
+#~ msgstr "Konfigurēt"
+
+#, python-format
+#~ msgid "Could not cancel this sales order !"
+#~ msgstr "Nevar atcelt pasūtījumu!"
+
+#~ msgid "Number Packages"
+#~ msgstr "Iepakojumu Skaits"
+
+#, python-format
+#~ msgid "(n/a)"
+#~ msgstr "(nav pieejams)"
+
+#~ msgid "Order Reference must be unique !"
+#~ msgstr "Pasūtījuma kodam ir jābūt unikālam!"
+
+#~ msgid "Lines to Invoice"
+#~ msgstr "Rindas, par kurām piestādīt Rēķinu."
+
+#~ msgid "Do you really want to create the invoice(s) ?"
+#~ msgstr "Vai tiešām vēlaties piestādīt rēķinu(-s)?"
+
+#~ msgid "All Quotations"
+#~ msgstr "Visi Tāmējumi"
+
+#, python-format
+#~ msgid "Could not cancel sales order line!"
+#~ msgstr "Nevar atcelt pasūtījuma rindu!"
+
+#~ msgid "Sales By Month"
+#~ msgstr "Pārdošana Pa Mēnešiem"
+
+#~ msgid "Procurement of sold material"
+#~ msgstr "Pārdoto preču piegāde"
+
+#~ msgid " Year "
+#~ msgstr " Gads "
+
+#~ msgid "Companies"
+#~ msgstr "Uzņēmumi"
+
+#~ msgid ""
+#~ "The name and address of the contact who requested the order or quotation."
+#~ msgstr "Pasūtītāja vārds un adrese."
+
+#~ msgid "Create Final Invoice"
+#~ msgstr "Veidot Gala Rēķinu"
+
+#~ msgid "Sales by Partner"
+#~ msgstr "Pārdošana pa Partneriem"
+
+#~ msgid "Sales Order Dates"
+#~ msgstr "Pasūtījumu Datumi"
+
+#~ msgid "Open Invoice"
+#~ msgstr "Atvērt Rēķinu"
+
+#~ msgid "on order"
+#~ msgstr "pie pasūtījuma"
+
+#~ msgid "Delivery Costs"
+#~ msgstr "Piegādes Izmaksas"
+
+#~ msgid "Deliveries to Invoice"
+#~ msgstr "Piegādes, par kurām piestādīt rēķinus"
+
+#~ msgid "Order date"
+#~ msgstr "Pasūtījuma datums"
+
+#~ msgid "Invoicing"
+#~ msgstr "Rēķinu izrakstīšana"
+
+#, python-format
+#~ msgid "The sales order '%s' has been cancelled."
+#~ msgstr "Pasūtījums \"%s\" ir atcelts."
+
+#~ msgid "Configuration Progress"
+#~ msgstr "Konfigurācijas Progress"
+
+#~ msgid "You invoice has been successfully created!"
+#~ msgstr "Rēķins ir veiksmīgi izveidots!"
+
+#~ msgid "Shipped Qty"
+#~ msgstr "Piegādātais Daudz."
+
+#~ msgid "Delivered"
+#~ msgstr "Piegādāts"
+
+#, python-format
+#~ msgid "The sales order '%s' has been set in draft state."
+#~ msgstr "Pasūtījums \"%s\" ir atzīmēts kā melnraksts."
+
+#, python-format
+#~ msgid "Warning !"
+#~ msgstr "Uzmanību!"
+
+#~ msgid "Procurement Order"
+#~ msgstr "Iepirkuma Pasūtījums"
+
+#~ msgid "UoM"
+#~ msgstr "Mērv."
+
+#, python-format
+#~ msgid "You must first cancel stock moves attached to this sales order line."
+#~ msgstr "Vispirms jāatceļ saistītie noliktavas grāmatojumi."
+
+#~ msgid "Sales Open Invoice"
+#~ msgstr "Atvērt Rēķinu"
+
+#~ msgid "Security Days"
+#~ msgstr "Rezerves Dienas"
+
+#, python-format
+#~ msgid "You cannot cancel a sales order line that has already been invoiced !"
+#~ msgstr "Nevar atcelt pasūtījuma rindu, par kuru jau ir piestādīts rēķins!"
+
+#~ msgid "Margins in Sales Orders"
+#~ msgstr "Uzcenojumi Pasūtījumiem"
+
+#~ msgid "Total Tax Excluded"
+#~ msgstr "Nodokļa Summa, kas nav Iekļauta"
+
+#~ msgid "Sales by Product Category"
+#~ msgstr "Pārdošana pa Produktu Kategorijām"
+
+#~ msgid "Procurement Method"
+#~ msgstr "Sagādes Veids"
+
+#~ msgid "Pick List"
+#~ msgstr "Komplektācijas Saraksts"
+
+#~ msgid "Sales per Customer in last 90 days"
+#~ msgstr "Pārdošana pa Klientiem pēdējās 90 dienās"
+
+#~ msgid "Invoice From The Picking"
+#~ msgstr "Veidot Rēķinu Pēc Komplektācijas"
+
+#, python-format
+#~ msgid "Picking Information !"
+#~ msgstr "Informācija par Komplektāciju"
+
+#, python-format
+#~ msgid "Could not cancel sales order !"
+#~ msgstr "Nevar atcelt pasūtījumu!"
+
+#~ msgid "Properties"
+#~ msgstr "Parametri"
+
+#~ msgid "Logistic"
+#~ msgstr "Loģistika"
+
+#~ msgid " Month "
+#~ msgstr " Mēnesis "
+
+#, python-format
+#~ msgid "Warning"
+#~ msgstr "Brīdinājums"
+
+#~ msgid "Sales by Month"
+#~ msgstr "Pārdošana pa Mēnešiem"
+
+#~ msgid "Delivery Lead Time"
+#~ msgstr "Piegādes laiks"
+
+#~ msgid "Image"
+#~ msgstr "Attēls"
+
+#~ msgid "Error! You can not create recursive companies."
+#~ msgstr "Kļūda! Jums nav tiesību veidot rekursīvus uzņēmumus."
+
+#~ msgid "Invoicing journals"
+#~ msgstr "Rēķinu žurnāli"
+
+#~ msgid "Ordered Date"
+#~ msgstr "Pasūtījuma Veikšanas Datums"
+
+#~ msgid "Configure Your Sales Management Application"
+#~ msgstr "Konfigurēt Tirdzniecības Vadības Moduli"
+
+#~ msgid "Sales Order Layout Improvement"
+#~ msgstr "Pasūtījuma Izkārtojuma Uzlabojums"
+
+#, python-format
+#~ msgid "You must first cancel all invoices attached to this sales order."
+#~ msgstr "Vispirms jāatceļ visi rēķini, kas saistīti ar pasūtījumu."
+
+#, python-format
+#~ msgid "Not enough stock !"
+#~ msgstr "Nav pietiekošs skaits noliktavā!"
+
+#~ msgid "Layout Sequence"
+#~ msgstr "Izkārtojuma Secība"
+
+#, python-format
+#~ msgid "Cannot delete Sales Order(s) which are already confirmed !"
+#~ msgstr "Nevar izdzēst jau apstiprināto(-s) Pasūtījumu(-s)!"
+
+#~ msgid "Accounting"
+#~ msgstr "Grāmatvedība"
+
+#~ msgid "You must assign a production lot for this product"
+#~ msgstr "Šim produktam ir jāpiesaista produkcijas lots"
+
+#~ msgid "State"
+#~ msgstr "Statuss"
+
+#~ msgid "Delivery Order Only"
+#~ msgstr "Veikt Tikai Piegādi"
+
+#~ msgid "Picking Default Policy"
+#~ msgstr "Komplektācijas Noteikumi"
+
+#~ msgid "References"
+#~ msgstr "Kodi"
+
+#~ msgid "Based on the shipped or on the ordered quantities."
+#~ msgstr "Balstīts uz piegādāto vai pasūtīto skaitu."
+
+#~ msgid "Related Picking"
+#~ msgstr "Saistītā Komplektēšana Noliktavā"
+
+#~ msgid "Create Pick List"
+#~ msgstr "Veidot Komplektēšanas Sarakstu"
+
+#~ msgid "Create Delivery Order"
+#~ msgstr "Veidot Piegādes Rīkojumu"
+
+#~ msgid "Create Procurement Order"
+#~ msgstr "Veidot Piegādes Pasūtījumu"
+
+#~ msgid "Picking List"
+#~ msgstr "Komplektēšanas Saraksts"
+
+#, python-format
+#~ msgid "You must first cancel all picking attached to this sales order."
+#~ msgstr "Vispirms jāatceļ visa komplektācija, kas saistīta ar pasūtījumu."
+
+#~ msgid "Picking Policy"
+#~ msgstr "Komplektācijas Noteikumi"
+
+#~ msgid "Picking List & Delivery Order"
+#~ msgstr "Komplektācijas Saraksts un Piegādes Pasūtījums"
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index 033dd778f1f..c1af024ad9c 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -264,7 +264,24 @@ class sale_order(osv.osv):
return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
+ def copy_quotation(self, cr, uid, ids, context=None):
+ id = self.copy(cr, uid, ids[0], context=None)
+ view_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sale', 'view_order_form')
+ view_id = view_ref and view_ref[1] or False,
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': _('Sales Order'),
+ 'res_model': 'sale.order',
+ 'res_id': id,
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'view_id': view_id,
+ 'target': 'current',
+ 'nodestroy': True,
+ }
+
def onchange_pricelist_id(self, cr, uid, ids, pricelist_id, order_lines, context=None):
+ context = context or {}
if not pricelist_id:
return {}
value = {
@@ -601,6 +618,7 @@ class sale_order(osv.osv):
}
def action_wait(self, cr, uid, ids, context=None):
+ context = context or {}
for o in self.browse(cr, uid, ids):
if not o.order_line:
raise osv.except_osv(_('Error!'),_('You cannot confirm a sale order which has no line.'))
@@ -629,6 +647,7 @@ class sale_order(osv.osv):
'default_res_id': ids[0],
'default_use_template': True,
'default_template_id': template_id,
+ 'default_composition_mode': 'comment',
'mark_so_as_sent': True
})
return {
@@ -903,7 +922,7 @@ class sale_order_line(osv.osv):
result = {}
warning_msgs = {}
- product_obj = product_obj.browse(cr, uid, product, context=context)
+ product_obj = product_obj.browse(cr, uid, product, context=context_partner)
uom2 = False
if uom:
diff --git a/addons/sale/sale_data.xml b/addons/sale/sale_data.xml
index 6f4ed76614e..3fe03966da2 100644
--- a/addons/sale/sale_data.xml
+++ b/addons/sale/sale_data.xml
@@ -38,10 +38,10 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Sales Management application installed!</field>
- <field name="body">This application lets you create and send quotations and process your sales orders; from delivery to invoicing.
-
-If you need to manage your sales pipeline (leads, opportunities, phonecalls), the &lt;i&gt;CRM&lt;/i&gt; application may be useful. Use the Settings menu to install it.</field>
+ <field name="body"><![CDATA[<p>This application lets you create and send quotations and process your sales orders; from delivery to invoicing.</p>
+<p>If you need to manage your sales pipeline (leads, opportunities, phonecalls), the <i>CRM</i> application may be useful. Use the Settings menu to install it.</p>]]></field>
</record>
</data>
</openerp>
diff --git a/addons/sale/sale_demo.xml b/addons/sale/sale_demo.xml
index ba75b1571cb..428b586ffa8 100644
--- a/addons/sale/sale_demo.xml
+++ b/addons/sale/sale_demo.xml
@@ -329,7 +329,7 @@ Thanks!</field>
<field name="type">service</field>
<field name="list_price">150.0</field>
<field name="standard_price">100.0</field>
- <field name="supply_method">produce</field>
+ <field name="supply_method">produce</field> <!-- TODO this is a procurement field, which is not a sale dependency -->
<field name="uom_id" ref="product.product_uom_day"/>
<field name="uom_po_id" ref="product.product_uom_day"/>
<field name="company_id" eval="[]"/>
diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml
index 838c63f34a1..9f385339173 100644
--- a/addons/sale/sale_view.xml
+++ b/addons/sale/sale_view.xml
@@ -176,6 +176,7 @@
attrs="{'invisible': [('invoice_exists', '=', False)]}" groups="base.group_user"/>
<button name="%(action_view_sale_advance_payment_inv)d" string="Create Invoice"
type="action" states="manual" class="oe_highlight" groups="base.group_user"/>
+ <button name="copy_quotation" states="cancel" string="New Copy of Quotation" type="object"/>
<button name="cancel" states="draft,sent" string="Cancel" groups="base.group_user"/>
<button name="action_cancel" states="manual,progress" string="Cancel" type="object" groups="base.group_user"/>
<button name="invoice_cancel" states="invoice_except" string="Cancel" groups="base.group_user"/>
@@ -310,7 +311,7 @@
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
- <field name="message_ids" widget="mail_thread"/>
+ <field name="message_ids" widget="mail_thread" placeholder="Share a message..."/>
</div>
</form>
</field>
diff --git a/addons/sale_crm/wizard/crm_make_sale.py b/addons/sale_crm/wizard/crm_make_sale.py
index 2597c1db56c..10225990229 100644
--- a/addons/sale_crm/wizard/crm_make_sale.py
+++ b/addons/sale_crm/wizard/crm_make_sale.py
@@ -64,7 +64,9 @@ class crm_make_sale(osv.osv_memory):
"""
if context is None:
context = {}
-
+ # update context: if come from phonecall, default state values can make the quote crash lp:1017353
+ context.pop('default_state', False)
+
case_obj = self.pool.get('crm.lead')
sale_obj = self.pool.get('sale.order')
partner_obj = self.pool.get('res.partner')
diff --git a/addons/share/wizard/share_wizard.py b/addons/share/wizard/share_wizard.py
index 360b1eff159..6a1f5681f4f 100644
--- a/addons/share/wizard/share_wizard.py
+++ b/addons/share/wizard/share_wizard.py
@@ -74,7 +74,7 @@ class share_wizard(osv.TransientModel):
def _user_type_selection(self, cr, uid, context=None):
"""Selection values may be easily overridden/extended via inheritance"""
- return [('embedded', 'Direct link or embed code'), ('emails','Emails'), ]
+ return [('embedded', _('Direct link or embed code')), ('emails',_('Emails')), ]
"""Override of create() to auto-compute the action name"""
def create(self, cr, uid, values, context=None):
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 606cb9247d5..859cda8ce94 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -1351,14 +1351,14 @@ class stock_picking(osv.osv):
wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_confirm', cr)
# Then we finish the good picking
self.write(cr, uid, [pick.id], {'backorder_id': new_picking})
- self.action_move(cr, uid, [new_picking])
+ self.action_move(cr, uid, [new_picking], context=context)
wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_done', cr)
wf_service.trg_write(uid, 'stock.picking', pick.id, cr)
delivered_pack_id = new_picking
back_order_name = self.browse(cr, uid, delivered_pack_id, context=context).name
self.back_order_send_note(cr, uid, ids, back_order_name, context)
else:
- self.action_move(cr, uid, [pick.id])
+ self.action_move(cr, uid, [pick.id], context=context)
wf_service.trg_validate(uid, 'stock.picking', pick.id, 'button_done', cr)
delivered_pack_id = pick.id
self.ship_done_send_note(cr, uid, ids, context)
@@ -1553,7 +1553,7 @@ class stock_production_lot(osv.osv):
'product_id': lambda x, y, z, c: c.get('product_id', False),
}
_sql_constraints = [
- ('name_ref_uniq', 'unique (name, ref)', 'The combination of serial number and internal reference must be unique !'),
+ ('name_ref_uniq', 'unique (name, ref)', 'The combination of Serial Number and internal reference must be unique !'),
]
def action_traceability(self, cr, uid, ids, context=None):
""" It traces the information of a product
@@ -2123,7 +2123,7 @@ class stock_move(osv.osv):
old_ptype = location_obj.picking_type_get(cr, uid, picking.move_lines[0].location_id, picking.move_lines[0].location_dest_id)
if old_ptype != picking.type:
old_pick_name = seq_obj.get(cr, uid, 'stock.picking.' + old_ptype)
- self.pool.get('stock.picking').write(cr, uid, [picking.id], {'name': old_pick_name}, context=context)
+ self.pool.get('stock.picking').write(cr, uid, [picking.id], {'name': old_pick_name, 'type': old_ptype}, context=context)
else:
pickid = False
for move, (loc, dummy, delay, dummy, company_id, ptype) in todo:
@@ -2433,14 +2433,17 @@ class stock_move(osv.osv):
if move.picking_id:
picking_ids.append(move.picking_id.id)
if move.move_dest_id.id and (move.state != 'done'):
- self.write(cr, uid, [move.id], {'move_history_ids': [(4, move.move_dest_id.id)]})
- #cr.execute('insert into stock_move_history_ids (parent_id,child_id) values (%s,%s)', (move.id, move.move_dest_id.id))
- if move.move_dest_id.state in ('waiting', 'confirmed'):
- self.force_assign(cr, uid, [move.move_dest_id.id], context=context)
- if move.move_dest_id.picking_id:
- wf_service.trg_write(uid, 'stock.picking', move.move_dest_id.picking_id.id, cr)
- if move.move_dest_id.auto_validate:
- self.action_done(cr, uid, [move.move_dest_id.id], context=context)
+ # Downstream move should only be triggered if this move is the last pending upstream move
+ other_upstream_move_ids = self.search(cr, uid, [('id','!=',move.id),('state','not in',['done','cancel']),
+ ('move_dest_id','=',move.move_dest_id.id)], context=context)
+ if not other_upstream_move_ids:
+ self.write(cr, uid, [move.id], {'move_history_ids': [(4, move.move_dest_id.id)]})
+ if move.move_dest_id.state in ('waiting', 'confirmed'):
+ self.force_assign(cr, uid, [move.move_dest_id.id], context=context)
+ if move.move_dest_id.picking_id:
+ wf_service.trg_write(uid, 'stock.picking', move.move_dest_id.picking_id.id, cr)
+ if move.move_dest_id.auto_validate:
+ self.action_done(cr, uid, [move.move_dest_id.id], context=context)
self._create_product_valuation_moves(cr, uid, move, context=context)
if move.state not in ('confirmed','done','assigned'):
@@ -2875,7 +2878,7 @@ class stock_inventory(osv.osv):
if change:
location_id = line.product_id.product_tmpl_id.property_stock_inventory.id
value = {
- 'name': 'INV:' + str(line.inventory_id.id) + ':' + line.inventory_id.name,
+ 'name': _('INV:') + (line.inventory_id.name or ''),
'product_id': line.product_id.id,
'product_uom': line.product_uom.id,
'prodlot_id': lot_id,
diff --git a/addons/stock/stock_data.xml b/addons/stock/stock_data.xml
index 77c82989a21..a1ce136e304 100644
--- a/addons/stock/stock_data.xml
+++ b/addons/stock/stock_data.xml
@@ -6,9 +6,10 @@
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
+ <field name="subtype_id" ref="mail.mt_comment"/>
<field name="subject">Warehouse Management application installed!</field>
- <field name="body">Manage your product inventoy and stock locations: you can control stock moves history and planning,
-watch your stock valuation, and track production lots upstream and downstream (based on serial numbers).</field>
+ <field name="body"><![CDATA[<p>Manage your product inventoy and stock locations: you can control stock moves history and planning,
+watch your stock valuation, and track production lots upstream and downstream (based on serial numbers).</p>]]></field>
</record>
<record id="stock_journal_sequence" model="ir.sequence">
diff --git a/addons/stock/stock_sequence.xml b/addons/stock/stock_sequence.xml
index 6c0b3e84cf2..c3569c48c3e 100644
--- a/addons/stock/stock_sequence.xml
+++ b/addons/stock/stock_sequence.xml
@@ -17,7 +17,7 @@
<record id="seq_type_picking_internal" model="ir.sequence.type">
<field name="name">Picking INT</field>
- <field name="code">stock.picking.internal</field>
+ <field name="code">stock.picking</field>
</record>
<!--
@@ -42,7 +42,7 @@
<record id="seq_picking_internal" model="ir.sequence">
<field name="name">Picking INT</field>
- <field name="code">stock.picking.internal</field>
+ <field name="code">stock.picking</field>
<field name="prefix">INT/</field>
<field name="padding">5</field>
<field name="company_id" eval="False"/>
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index 9c2a672caf7..a08597df60b 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -283,10 +283,11 @@
<field name="model">stock.tracking</field>
<field name="field_parent">child_ids</field>
<field name="arch" type="xml">
- <tree colors="grey:not active" string="Packs">
+ <tree colors="grey:active == False" string="Packs">
<field name="name"/>
<field name="serial"/>
<field name="date"/>
+ <field name="active" invisible="1"/>
</tree>
</field>
</record>
@@ -913,7 +914,7 @@
<xpath expr="/form/sheet" position="after">
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
- <field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
+ <field name="message_ids" widget="mail_thread"/>
</div>
</xpath>
</data>
@@ -1039,7 +1040,7 @@
<xpath expr="/form/sheet" position="after">
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
- <field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
+ <field name="message_ids" widget="mail_thread"/>
</div>
</xpath>
</data>
diff --git a/addons/stock/wizard/stock_change_product_qty_view.xml b/addons/stock/wizard/stock_change_product_qty_view.xml
index 20114301ab2..807a0a15df5 100644
--- a/addons/stock/wizard/stock_change_product_qty_view.xml
+++ b/addons/stock/wizard/stock_change_product_qty_view.xml
@@ -10,7 +10,7 @@
<field name="new_quantity" />
<field name="product_id" invisible="1"/>
<field name="location_id" groups="stock.group_locations"/>
- <field name="prodlot_id" groups="stock.group_tracking_lot"/>
+ <field name="prodlot_id" context="{'search_default_product_id':product_id,'default_product_id':product_id}" groups="stock.group_tracking_lot"/>
</group>
<footer>
<button name="change_product_qty" string="_Apply" type="object" class="oe_highlight"/>
diff --git a/addons/stock/wizard/stock_fill_inventory.py b/addons/stock/wizard/stock_fill_inventory.py
index 11907b674a1..8422412a254 100644
--- a/addons/stock/wizard/stock_fill_inventory.py
+++ b/addons/stock/wizard/stock_fill_inventory.py
@@ -79,8 +79,6 @@ class stock_fill_inventory(osv.osv_memory):
inventory_line_obj = self.pool.get('stock.inventory.line')
location_obj = self.pool.get('stock.location')
- product_obj = self.pool.get('product.product')
- stock_location_obj = self.pool.get('stock.location')
move_obj = self.pool.get('stock.move')
uom_obj = self.pool.get('product.uom')
if ids and len(ids):
diff --git a/addons/web_linkedin/static/src/js/linkedin.js b/addons/web_linkedin/static/src/js/linkedin.js
index ec58c3736f4..d6237e48d51 100644
--- a/addons/web_linkedin/static/src/js/linkedin.js
+++ b/addons/web_linkedin/static/src/js/linkedin.js
@@ -20,7 +20,7 @@ openerp.web_linkedin = function(instance) {
var tag = document.createElement('script');
tag.type = 'text/javascript';
tag.src = "http://platform.linkedin.com/in.js";
- tag.innerHTML = 'api_key : ' + self.api_key + '\nauthorize : true';
+ tag.innerHTML = 'api_key : ' + self.api_key + '\nauthorize : true\nscope: r_network r_contactinfo';
document.getElementsByTagName('head')[0].appendChild(tag);
self.linkedin_added = true;
$(tag).load(function() {
@@ -107,7 +107,7 @@ openerp.web_linkedin = function(instance) {
}
to_change.website = entity.websiteUrl;
to_change.phone = false;
- _.each(entity.locations.values || [], function(el) {
+ _.each((entity.locations || {}).values || [], function(el) {
to_change.phone = el.contactInfo.phone1;
});
var children_def = $.Deferred();
diff --git a/addons/web_shortcuts/static/src/js/web_shortcuts.js b/addons/web_shortcuts/static/src/js/web_shortcuts.js
index e7cbbaccef6..918feb4634d 100644
--- a/addons/web_shortcuts/static/src/js/web_shortcuts.js
+++ b/addons/web_shortcuts/static/src/js/web_shortcuts.js
@@ -54,12 +54,8 @@ instance.web_shortcuts.Shortcuts = instance.web.Widget.extend({
},
add: function (sc) {
var self = this;
- this.dataset.create(sc, function (out) {
- self.trigger('display', {
- name : sc.name,
- id : out.result,
- res_id : sc.res_id
- });
+ this.dataset.create(sc).then(function(out){
+ self.trigger('load');
});
},
display: function(sc) {