diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml
index 80dc098e770..2225ae5ba9b 100644
--- a/addons/account/test/test_edi_invoice.yml
+++ b/addons/account/test/test_edi_invoice.yml
@@ -38,45 +38,46 @@
-
Then I export the customer invoice
-
- !python {model: edi.document}: |
+ !python {model: edi.edi}: |
+ import json
invoice_pool = self.pool.get('account.invoice')
invoice = invoice_pool.browse(cr, uid, ref("invoice_edi_1"))
- token = self.export_edi(cr, uid, [invoice])
- assert token, 'Invalid EDI Token'
+ edi_doc = self.generate_edi(cr, uid, [invoice])
+ assert isinstance(json.loads(edi_doc)[0], dict), 'EDI doc should be a JSON dict'
-
- Then I import a sample EDI document of another customer invoice
+ Then I import a sample EDI document of another customer invoice from OpenERP 7.0
-
!python {model: account.invoice}: |
import time
edi_document = {
- "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.random_invoice_763jsms",
+ "__id": "account:b33adf8a-decd-11f0-a4de-702a04e25700.random_invoice_763jsms",
"__module": "account",
"__model": "account.invoice",
- "__version": [6,1,0],
- "internal_number": time.strftime("SAJ/%Y/002"),
+ "__version": [7,0,0],
+ "internal_number": time.strftime("SAJ/%Y/070"),
"company_address": {
- "__id": "base:b22acf7a-ddcd-11e0-a4db-701a04e25543.main_address",
+ "__id": "base:b33adf8a-decd-11f0-a4de-702a04e25700.main_address",
"__module": "base",
"__model": "res.partner",
"city": "Gerompont",
"name": "Company main address",
"zip": "1367",
- "country_id": ["base:b22acf7a-ddcd-11e0-a4db-701a04e25543.be", "Belgium"],
+ "country_id": ["base:b33adf8a-decd-11f0-a4de-702a04e25700.be", "Belgium"],
"phone": "(+32).81.81.37.00",
"street": "Chaussee de Namur 40",
"bank_ids": [
- ["base:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_partner_bank-ZrTWzesfsdDJzGbp","Sample bank: 123465789-156113"]
+ ["base:b33adf8a-decd-11f0-a4de-702a04e25700.res_partner_bank-ZrTWzesfsdDJzGbp","Sample bank: 70-123465789-156113"]
],
},
- "company_id": ["account:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_company_test11", "Thomson pvt. ltd."],
+ "company_id": ["account:b33adf8a-decd-11f0-a4de-702a04e25700.res_company_test11", "Thomson pvt. ltd."],
"currency": {
- "__id": "base:b22acf7a-ddcd-11e0-a4db-701a04e25543.EUR",
+ "__id": "base:b33adf8a-decd-11f0-a4de-702a04e25700.EUR",
"__module": "base",
"__model": "res.currency",
"code": "EUR",
"symbol": "€",
},
- "partner_id": ["account:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_partner_test20", "Junjun wala"],
+ "partner_id": ["account:b33adf8a-decd-11f0-a4de-702a04e25700.res_partner_test20", "Junjun wala"],
"partner_address": {
"__id": "base:5af1272e-dd26-11e0-b65e-701a04e25543.res_partner_address_7wdsjasdjh",
"__module": "base",
@@ -91,7 +92,7 @@
"date_invoice": time.strftime('%Y-%m-%d'),
"name": "sample invoice",
"tax_line": [{
- "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_tax-4g4EutbiEMVl",
+ "__id": "account:b33adf8a-decd-11f0-a4de-702a04e25700.account_invoice_tax-4g4EutbiEMVl",
"__module": "account",
"__model": "account.invoice.tax",
"amount": 1000.0,
@@ -102,21 +103,21 @@
"invoice_line": [{
"__module": "account",
"__model": "account.invoice.line",
- "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_line-1RP3so",
- "uos_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_uom_unit", "Unit"],
+ "__id": "account:b33adf8a-decd-11f0-a4de-702a04e25700.account_invoice_line-1RP3so",
+ "uos_id": ["product:b33adf8a-decd-11f0-a4de-702a04e25700.product_uom_unit", "Unit"],
"name": "PC Assemble SC234",
"price_unit": 10.0,
- "product_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_product_3", "[PCSC234] PC Assemble SC234"],
+ "product_id": ["product:b33adf8a-decd-11f0-a4de-702a04e25700.product_product_3", "[PCSC234] PC Assemble SC234"],
"quantity": 1.0
},
{
"__module": "account",
"__model": "account.invoice.line",
- "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_line-u2XV5",
- "uos_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_uom_unit", "Unit"],
+ "__id": "account:b33adf8a-decd-11f0-a4de-702a04e25700.account_invoice_line-u2XV5",
+ "uos_id": ["product:b33adf8a-decd-11f0-a4de-702a04e25700.product_uom_unit", "Unit"],
"name": "PC on Demand",
"price_unit": 100.0,
- "product_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_product_5", "[PC-DEM] PC on Demand"],
+ "product_id": ["product:b33adf8a-decd-11f0-a4de-702a04e25700.product_product_5", "[PC-DEM] PC on Demand"],
"quantity": 5.0
}]
}
@@ -125,12 +126,13 @@
invoice_new = self.browse(cr, uid, invoice_id)
# check bank info on partner
+ assert invoice_new.partner_id.supplier, "Imported partner should be a supplier, as we just imported the document as a supplier invoice"
assert len(invoice_new.partner_id.bank_ids) == 1, "Expected 1 bank entry related to partner"
bank_info = invoice_new.partner_id.bank_ids[0]
- assert bank_info.acc_number == "Sample bank: 123465789-156113", 'Expected "Sample bank: 123465789-156113", got %s' % bank_info.acc_number
+ assert bank_info.acc_number == "Sample bank: 70-123465789-156113", 'Expected "Sample bank: 70-123465789-156113", got %s' % bank_info.acc_number
assert invoice_new.partner_id.supplier, 'Imported Partner is not marked as supplier'
- assert invoice_new.reference == time.strftime("SAJ/%Y/002"), "internal number is not stored in reference"
+ assert invoice_new.reference == time.strftime("SAJ/%Y/070"), "internal number is not stored in reference"
assert invoice_new.reference_type == 'none', "reference type is not set to 'none'"
assert invoice_new.internal_number == False, "internal number is not reset"
assert invoice_new.journal_id.id, "journal id is not selected"
@@ -152,3 +154,111 @@
for inv_tax in invoice_new.tax_line:
assert inv_tax.manual, "tax line not set to manual"
assert inv_tax.account_id, "missing tax line account"
+-
+ Then I import a sample EDI document of another customer invoice from OpenERP 6.1 (to test backwards compatibility)
+-
+ !python {model: account.invoice}: |
+ import time
+ edi_document = {
+ "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.random_invoice_763jsms",
+ "__module": "account",
+ "__model": "account.invoice",
+ "__version": [6,1,0],
+ "internal_number": time.strftime("SAJ/%Y/061"),
+ "company_address": {
+ "__id": "base:b22acf7a-ddcd-11e0-a4db-701a04e25543.main_address",
+ "__module": "base",
+ "__model": "res.partner.address",
+ "city": "Gerompont",
+ "zip": "1367",
+ "country_id": ["base:b22acf7a-ddcd-11e0-a4db-701a04e25543.be", "Belgium"],
+ "phone": "(+32).81.81.37.00",
+ "street": "Chaussee de Namur 40",
+ "bank_ids": [
+ ["base:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_partner_bank-ZrTWzesfsdDJzGbp","Sample bank: 123465789-156113"]
+ ],
+ },
+ "company_id": ["account:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_company_test11", "Thomson pvt. ltd."],
+ "currency": {
+ "__id": "base:b22acf7a-ddcd-11e0-a4db-701a04e25543.EUR",
+ "__module": "base",
+ "__model": "res.currency",
+ "code": "EUR",
+ "symbol": "€",
+ },
+ "partner_id": ["account:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_partner_test20", "Junjun wala"],
+ "partner_address": {
+ "__id": "base:5af1272e-dd26-11e0-b65e-701a04e25543.res_partner_address_7wdsjasdjh",
+ "__module": "base",
+ "__model": "res.partner.address",
+ "phone": "(+32).81.81.37.00",
+ "street": "Chaussee de Namur 40",
+ "city": "Gerompont",
+ "zip": "1367",
+ "country_id": ["base:5af1272e-dd26-11e0-b65e-701a04e25543.be", "Belgium"],
+ },
+ "date_invoice": time.strftime('%Y-%m-%d'),
+ "name": "sample invoice",
+ "tax_line": [{
+ "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_tax-4g4EutbiEMVl",
+ "__module": "account",
+ "__model": "account.invoice.tax",
+ "amount": 1000.0,
+ "manual": True,
+ "name": "sale tax",
+ }],
+ "type": "out_invoice",
+ "invoice_line": [{
+ "__module": "account",
+ "__model": "account.invoice.line",
+ "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_line-1RP3so",
+ "uos_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_uom_unit", "PCE"],
+ "name": "Basic PC",
+ "price_unit": 10.0,
+ "product_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_product_pc1", "[PC1] Basic PC"],
+ "quantity": 1.0
+ },
+ {
+ "__module": "account",
+ "__model": "account.invoice.line",
+ "__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_line-u2XV5",
+ "uos_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_uom_unit", "PCE"],
+ "name": "Medium PC",
+ "price_unit": 100.0,
+ "product_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_product_pc3", "[PC3] Medium PC"],
+ "quantity": 5.0
+ }]
+ }
+ invoice_id = self.edi_import(cr, uid, edi_document, context=context)
+ assert invoice_id, 'EDI import failed'
+ invoice_new = self.browse(cr, uid, invoice_id)
+
+ # check bank info on partner
+ assert invoice_new.partner_id.supplier, "Imported partner should be a supplier, as we just imported the document as a supplier invoice"
+ assert len(invoice_new.partner_id.bank_ids) == 1, "Expected 1 bank entry related to partner"
+ bank_info = invoice_new.partner_id.bank_ids[0]
+ assert bank_info.acc_number == "Sample bank: 123465789-156113", 'Expected "Sample bank: 123465789-156113", got %s' % bank_info.acc_number
+
+ assert invoice_new.partner_id.supplier, 'Imported Partner is not marked as supplier'
+ assert invoice_new.reference == time.strftime("SAJ/%Y/061"), "internal number is not stored in reference"
+ assert invoice_new.reference_type == 'none', "reference type is not set to 'none'"
+ assert invoice_new.internal_number == False, "internal number is not reset"
+ assert invoice_new.journal_id.id, "journal id is not selected"
+ assert invoice_new.type == 'in_invoice', "Invoice type was not set properly"
+ assert len(invoice_new.invoice_line) == 2, "invoice lines are not same"
+ for inv_line in invoice_new.invoice_line:
+ if inv_line.name == 'Basic PC':
+ assert inv_line.uos_id.name == "PCE" , "uom is not same"
+ assert inv_line.price_unit == 10 , "price unit is not same"
+ assert inv_line.quantity == 1 , "product qty is not same"
+ assert inv_line.price_subtotal == 10, "price sub total is not same"
+ elif inv_line.name == 'Medium PC':
+ assert inv_line.uos_id.name == "PCE" , "uom is not same"
+ assert inv_line.price_unit == 100 , "price unit is not same"
+ assert inv_line.quantity == 5 , "product qty is not same"
+ assert inv_line.price_subtotal == 500, "price sub total is not same"
+ else:
+ raise AssertionError('unknown invoice line: %s' % inv_line)
+ for inv_tax in invoice_new.tax_line:
+ assert inv_tax.manual, "tax line not set to manual"
+ assert inv_tax.account_id, "missing tax line account"
diff --git a/addons/account_budget/account_budget_view.xml b/addons/account_budget/account_budget_view.xml
index d24124e307d..35194e96b82 100644
--- a/addons/account_budget/account_budget_view.xml
+++ b/addons/account_budget/account_budget_view.xml
@@ -224,7 +224,6 @@
account.budget.line.search
crossovered.budget.lines
- search
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 , 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \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 \n"
+"Language-Team: Lithuanian \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_voucher/account_voucher_view.xml b/addons/account_voucher/account_voucher_view.xml
index 2cb393f4008..4dd9431736b 100644
--- a/addons/account_voucher/account_voucher_view.xml
+++ b/addons/account_voucher/account_voucher_view.xml
@@ -34,7 +34,8 @@
-
+
account.voucher.form
account.voucher
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) \n"
+"PO-Revision-Date: 2012-11-17 09:57+0000\n"
+"Last-Translator: Stefan Rijnhart (Therp) \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/analytic_user_function/i18n/mk.po b/addons/analytic_user_function/i18n/mk.po
new file mode 100644
index 00000000000..520e28e7c06
--- /dev/null
+++ b/addons/analytic_user_function/i18n/mk.po
@@ -0,0 +1,79 @@
+# Macedonian 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 , 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2012-02-08 00:35+0000\n"
+"PO-Revision-Date: 2012-11-20 17:57+0000\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: Macedonian \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-21 04:48+0000\n"
+"X-Generator: Launchpad (build 16293)\n"
+
+#. module: analytic_user_function
+#: field:analytic.user.funct.grid,product_id:0
+msgid "Product"
+msgstr "Производ"
+
+#. module: analytic_user_function
+#: model:ir.model,name:analytic_user_function.model_analytic_user_funct_grid
+msgid "Relation table between users and products on a analytic account"
+msgstr ""
+
+#. module: analytic_user_function
+#: constraint:hr.analytic.timesheet:0
+msgid "You cannot modify an entry in a Confirmed/Done timesheet !."
+msgstr ""
+
+#. module: analytic_user_function
+#: field:analytic.user.funct.grid,account_id:0
+#: model:ir.model,name:analytic_user_function.model_account_analytic_account
+msgid "Analytic Account"
+msgstr "Аналитичко конто"
+
+#. module: analytic_user_function
+#: view:account.analytic.account:0
+#: field:account.analytic.account,user_product_ids:0
+msgid "Users/Products Rel."
+msgstr ""
+
+#. module: analytic_user_function
+#: field:analytic.user.funct.grid,user_id:0
+msgid "User"
+msgstr "Корисник"
+
+#. module: analytic_user_function
+#: code:addons/analytic_user_function/analytic_user_function.py:96
+#: code:addons/analytic_user_function/analytic_user_function.py:131
+#, python-format
+msgid "There is no expense account define for this product: \"%s\" (id:%d)"
+msgstr ""
+
+#. module: analytic_user_function
+#: code:addons/analytic_user_function/analytic_user_function.py:95
+#: code:addons/analytic_user_function/analytic_user_function.py:130
+#, python-format
+msgid "Error !"
+msgstr "Грешка !"
+
+#. module: analytic_user_function
+#: constraint:account.analytic.account:0
+msgid "Error! You can not create recursive analytic accounts."
+msgstr ""
+
+#. module: analytic_user_function
+#: model:ir.model,name:analytic_user_function.model_hr_analytic_timesheet
+msgid "Timesheet Line"
+msgstr ""
+
+#. module: analytic_user_function
+#: view:analytic.user.funct.grid:0
+msgid "User's Product for this Analytic Account"
+msgstr ""
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/association/profile_association.xml b/addons/association/profile_association.xml
index 0627d3dba51..eda0f98fdf3 100644
--- a/addons/association/profile_association.xml
+++ b/addons/association/profile_association.xml
@@ -6,7 +6,7 @@
+ sequence="45"/>
diff --git a/addons/auth_oauth/__openerp__.py b/addons/auth_oauth/__openerp__.py
index 1c29ca8c093..c81f52663c4 100644
--- a/addons/auth_oauth/__openerp__.py
+++ b/addons/auth_oauth/__openerp__.py
@@ -25,10 +25,10 @@
'version': '1.0',
'category': 'Tools',
'description': """
-Allow users to login through Google OAuth2.
-===========================================
+Allow users to login through OAuth2 Provider.
+=============================================
""",
- 'author': 'Victor Tabuenca',
+ 'author': 'OpenERP s.a.',
'maintainer': 'OpenERP s.a.',
'website': 'http://www.openerp.com',
'depends': ['base', 'web', 'base_setup'],
diff --git a/addons/auth_oauth/auth_oauth_view.xml b/addons/auth_oauth/auth_oauth_view.xml
index 35397d72dbd..ffc39752ec6 100644
--- a/addons/auth_oauth/auth_oauth_view.xml
+++ b/addons/auth_oauth/auth_oauth_view.xml
@@ -39,6 +39,8 @@
form
tree,form
-
+
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 """"""
+ 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/controllers/main.py b/addons/auth_signup/controllers/main.py
index 09f9cb23da2..8a2e966e931 100644
--- a/addons/auth_signup/controllers/main.py
+++ b/addons/auth_signup/controllers/main.py
@@ -34,7 +34,6 @@ class Controller(openerp.addons.web.http.Controller):
def retrieve(self, req, dbname, token):
""" retrieve the user info (name, login or email) corresponding to a signup token """
registry = RegistryManager.get(dbname)
- user_info = None
with registry.cursor() as cr:
res_partner = registry.get('res.partner')
user_info = res_partner.signup_retrieve_info(cr, openerp.SUPERUSER_ID, token)
diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py
index 973a8da6588..d936cb0f328 100644
--- a/addons/auth_signup/res_users.py
+++ b/addons/auth_signup/res_users.py
@@ -23,9 +23,7 @@ import time
import urllib
import urlparse
-import openerp
from openerp.osv import osv, fields
-from openerp import SUPERUSER_ID
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools.safe_eval import safe_eval
@@ -35,7 +33,7 @@ class SignupError(Exception):
def random_token():
# the token has an entropy of about 120 bits (6 bits/char * 20 chars)
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
- return ''.join(random.choice(chars) for i in xrange(20))
+ return ''.join(random.choice(chars) for _ in xrange(20))
def now():
return time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
@@ -51,29 +49,44 @@ class res_partner(osv.Model):
(not partner.signup_expiration or dt <= partner.signup_expiration)
return res
- def _get_signup_url(self, cr, uid, ids, name, arg, context=None):
- """ determine a signup url for a given partner """
- base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
-
- # if required, make sure that every partner without user has a valid signup token
- if context and context.get('signup_valid'):
- unsigned_ids = [p.id for p in self.browse(cr, uid, ids, context) if not p.user_ids]
- self.signup_prepare(cr, uid, unsigned_ids, context=context)
-
+ def _get_signup_url_for_action(self, cr, uid, ids, action='login', view_type=None, menu_id=None, res_id=None, context=None):
+ """ generate a signup url for the given partner ids and action, possibly overriding
+ the url state components (menu_id, id, view_type) """
res = dict.fromkeys(ids, False)
+ base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
for partner in self.browse(cr, uid, ids, context):
+ # when required, make sure the partner has a valid signup token
+ if context and context.get('signup_valid') and not partner.user_ids:
+ self.signup_prepare(cr, uid, [partner.id], context=context)
+
+ action_template = None
+ params = {
+ 'action': urllib.quote(action),
+ 'db': urllib.quote(cr.dbname),
+ }
if partner.signup_token:
- params = (urllib.quote(cr.dbname), urllib.quote(partner.signup_token))
- res[partner.id] = urlparse.urljoin(base_url, "#action=login&db=%s&token=%s" % params)
+ action_template = "?db=%(db)s#action=%(action)s&token=%(token)s"
+ params['token'] = urllib.quote(partner.signup_token)
elif partner.user_ids:
- user = partner.user_ids[0]
- params = (urllib.quote(cr.dbname), urllib.quote(user.login))
- res[partner.id] = urlparse.urljoin(base_url, "#action=login&db=%s&login=%s" % params)
+ action_template = "?db=%(db)s#action=%(action)s&db=%(db)s&login=%(login)s"
+ params['login'] = urllib.quote(partner.user_ids[0].login)
+ if action_template:
+ if view_type:
+ action_template += '&view_type=%s' % urllib.quote(view_type)
+ if menu_id:
+ action_template += '&menu_id=%s' % urllib.quote(str(menu_id))
+ if res_id:
+ action_template += '&id=%s' % urllib.quote(str(res_id))
+ res[partner.id] = urlparse.urljoin(base_url, action_template % params)
return res
+ def _get_signup_url(self, cr, uid, ids, name, arg, context=None):
+ """ proxy for function field towards actual implementation """
+ return self._get_signup_url_for_action(cr, uid, ids, context=context)
+
_columns = {
- 'signup_token': fields.char(size=24, string='Signup Token'),
- 'signup_expiration': fields.datetime(string='Signup Expiration'),
+ 'signup_token': fields.char('Signup Token'),
+ 'signup_expiration': fields.datetime('Signup Expiration'),
'signup_valid': fields.function(_get_signup_valid, type='boolean', string='Signup Token is Valid'),
'signup_url': fields.function(_get_signup_url, type='char', string='Signup URL'),
}
diff --git a/addons/base_action_rule/base_action_rule_view.xml b/addons/base_action_rule/base_action_rule_view.xml
index 0e855337d22..bb711be9928 100644
--- a/addons/base_action_rule/base_action_rule_view.xml
+++ b/addons/base_action_rule/base_action_rule_view.xml
@@ -16,7 +16,7 @@
-
+
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,19 +19,24 @@
#
##############################################################################
-from osv import osv, fields
-from tools.translate import _
+import logging
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:
- raise osv.except_osv(_('Gengo ImportError'), _('Please install mygengo lib from http://pypi.python.org/pypi/mygengo'))
-
-import logging
-import tools
-import time
-
-_logger = logging.getLogger(__name__)
+ _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
@@ -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 @@
base.gengo.translations