From be3b0069fb8840cfb11e787e4c59baa0a28f671b Mon Sep 17 00:00:00 2001 From: "Lucas Perais (lpe)" Date: Tue, 12 Sep 2017 09:46:31 +0200 Subject: [PATCH 01/13] [FIX] account_extra_reports: empty partner name in sales/purchase journal Before this commit, since a partner's name can be empty, a traceback was thrown while opening the report in such a case. Now, if the partner's name is falsy we don't try to do operations on it OPW 769835 closes #19400 --- addons/account_extra_reports/views/report_journal.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account_extra_reports/views/report_journal.xml b/addons/account_extra_reports/views/report_journal.xml index b9a22669889..c9481d0c095 100644 --- a/addons/account_extra_reports/views/report_journal.xml +++ b/addons/account_extra_reports/views/report_journal.xml @@ -49,7 +49,7 @@ - + From 4e799fed8ee24fb30f08e9c97d38625aa42d1c7c Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Thu, 14 Sep 2017 14:46:02 +0200 Subject: [PATCH 02/13] [FIX] crm: expected closing Backport of commit abea8d3513e0d6383088c738523425be0cc04dc7 opw-771843 --- addons/crm/crm_lead.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index b8902cb736d..465ab6540eb 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -1158,7 +1158,7 @@ Update your business card, phone book, social media,... Send an email right now res['activity']['today'] += 1 if date_action >= date.today() and date_action <= date.today() + timedelta(days=7): res['activity']['next_7_days'] += 1 - if date_action < date.today(): + if date_action < date.today() and not opp['date_closed']: res['activity']['overdue'] += 1 # Won in Opportunities From c14eb9ae9e29977be27bc0370d7662a6acd6ab9a Mon Sep 17 00:00:00 2001 From: Odoo Translation Bot Date: Sun, 17 Sep 2017 00:29:20 +0200 Subject: [PATCH 03/13] [I18N] Update translation terms from Transifex --- addons/crm/i18n/pl.po | 14 +++++++------- addons/hr_timesheet/i18n/pl.po | 4 ++-- addons/project/i18n/hr.po | 4 ++-- addons/report/i18n/zh_CN.po | 12 ++++++------ addons/sale_stock/i18n/hr.po | 4 ++-- addons/sale_timesheet/i18n/pl.po | 4 ++-- addons/website/i18n/de.po | 4 ++-- openerp/addons/base/i18n/hr.po | 4 ++-- openerp/addons/base/i18n/tr.po | 14 +++++++------- 9 files changed, 32 insertions(+), 32 deletions(-) diff --git a/addons/crm/i18n/pl.po b/addons/crm/i18n/pl.po index 605ba4d065a..9ab266a33db 100644 --- a/addons/crm/i18n/pl.po +++ b/addons/crm/i18n/pl.po @@ -12,7 +12,7 @@ msgstr "" "Project-Id-Version: Odoo 9.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-22 13:15+0000\n" -"PO-Revision-Date: 2017-07-19 08:59+0000\n" +"PO-Revision-Date: 2017-09-15 12:47+0000\n" "Last-Translator: Grzegorz Grzelak \n" "Language-Team: Polish (http://www.transifex.com/odoo/odoo-9/language/pl/)\n" "MIME-Version: 1.0\n" @@ -366,7 +366,7 @@ msgstr "Na przykład: Etapy negocjacji" #. module: crm #: model:ir.ui.view,arch_db:crm.crm_planner msgid "Example: Qualified stage" -msgstr "" +msgstr "Na przykład: Etap kwalifikacji" #. module: crm #: model:ir.ui.view,arch_db:crm.crm_planner @@ -430,7 +430,7 @@ msgstr "Propozycje:" #. module: crm #: model:ir.ui.view,arch_db:crm.crm_planner msgid "Qualified:" -msgstr "" +msgstr "Kwalifikacje:" #. module: crm #: model:ir.ui.view,arch_db:crm.crm_planner @@ -2059,7 +2059,7 @@ msgstr "Sygnał utworzony" #: model:ir.ui.view,arch_db:crm.crm_lead_tag_form #: model:ir.ui.view,arch_db:crm.crm_lead_tag_tree msgid "Lead Tags" -msgstr "" +msgstr "Tagi sygnałów" #. module: crm #: model:ir.model,name:crm.model_crm_lead2opportunity_partner @@ -2225,13 +2225,13 @@ msgstr "Porażka" #: model:ir.ui.view,arch_db:crm.crm_opportunity_report_view_search #: model:ir.ui.view,arch_db:crm.view_crm_case_opportunities_filter msgid "Lost Reason" -msgstr "" +msgstr "Przyczyna utraty" #. module: crm #: model:ir.actions.act_window,name:crm.crm_lost_reason_action #: model:ir.ui.menu,name:crm.menu_crm_lost_reason msgid "Lost Reasons" -msgstr "" +msgstr "Powody utraty" #. module: crm #: selection:crm.lead,priority:0 selection:crm.opportunity.report,priority:0 @@ -3018,7 +3018,7 @@ msgstr "" #: code:addons/crm/sales_team.py:23 #, python-format msgid "Qualified" -msgstr "" +msgstr "Kwalifikacje" #. module: crm #: model:ir.model.fields,field_description:crm.field_crm_lead_priority diff --git a/addons/hr_timesheet/i18n/pl.po b/addons/hr_timesheet/i18n/pl.po index 9163e777e58..4c5e71999b1 100644 --- a/addons/hr_timesheet/i18n/pl.po +++ b/addons/hr_timesheet/i18n/pl.po @@ -10,14 +10,14 @@ msgstr "" "Project-Id-Version: Odoo 9.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-14 10:26+0000\n" -"PO-Revision-Date: 2016-10-13 07:51+0000\n" +"PO-Revision-Date: 2017-09-15 12:43+0000\n" "Last-Translator: Grzegorz Grzelak \n" "Language-Team: Polish (http://www.transifex.com/odoo/odoo-9/language/pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Language: pl\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" #. module: hr_timesheet #: model:ir.ui.view,arch_db:hr_timesheet.hr_timesheet_line_form diff --git a/addons/project/i18n/hr.po b/addons/project/i18n/hr.po index d6a3d5cf0f1..0d4793bf87b 100644 --- a/addons/project/i18n/hr.po +++ b/addons/project/i18n/hr.po @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: Odoo 9.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-10-09 09:17+0000\n" -"PO-Revision-Date: 2017-09-01 09:50+0000\n" +"PO-Revision-Date: 2017-09-11 08:53+0000\n" "Last-Translator: Bole \n" "Language-Team: Croatian (http://www.transifex.com/odoo/odoo-9/language/hr/)\n" "MIME-Version: 1.0\n" @@ -1679,7 +1679,7 @@ msgstr "Predviđanja" #. module: project #: model:ir.model.fields,field_description:project.field_project_config_settings_module_project_forecast msgid "Forecasts, planning and Gantt charts" -msgstr "" +msgstr "Predviđanja, planiranje i Ganttov dijagram" #. module: project #: model:ir.ui.menu,name:project.menu_tasks_config diff --git a/addons/report/i18n/zh_CN.po b/addons/report/i18n/zh_CN.po index 1ccf0ccdfee..9729c22a518 100644 --- a/addons/report/i18n/zh_CN.po +++ b/addons/report/i18n/zh_CN.po @@ -3,19 +3,19 @@ # * report # # Translators: -# Jeffery Chen Fan , 2015 -# Jeffery Chen Fan , 2015-2016 +# Jeffery CHEN , 2015 +# Jeffery CHEN , 2015-2016 # liAnGjiA , 2015 # liyes , 2015 -# zhanghao , 2015 +# 卓忆科技 , 2015 # liAnGjiA , 2015 msgid "" msgstr "" "Project-Id-Version: Odoo 9.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-12-07 10:39+0000\n" -"PO-Revision-Date: 2016-12-08 08:38+0000\n" -"Last-Translator: Martin Trigaux\n" +"PO-Revision-Date: 2017-09-13 05:57+0000\n" +"Last-Translator: liAnGjiA \n" "Language-Team: Chinese (China) (http://www.transifex.com/odoo/odoo-9/language/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -474,7 +474,7 @@ msgstr "在这个系统里没找到Wkhtmltopdf。\n 报表会被显示为html。 #: code:addons/report/models/report.py:164 #, python-format msgid "Unable to find Wkhtmltopdf on this system. The PDF can not be created." -msgstr "" +msgstr "未找到 WKhtmltopdf 系统,无法创建 PDF。" #. module: report #: model:ir.ui.view,arch_db:report.external_layout_footer diff --git a/addons/sale_stock/i18n/hr.po b/addons/sale_stock/i18n/hr.po index cee1c0862f7..a6902408b29 100644 --- a/addons/sale_stock/i18n/hr.po +++ b/addons/sale_stock/i18n/hr.po @@ -11,7 +11,7 @@ msgstr "" "Project-Id-Version: Odoo 9.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-10-01 06:27+0000\n" -"PO-Revision-Date: 2017-03-01 14:27+0000\n" +"PO-Revision-Date: 2017-09-11 13:03+0000\n" "Last-Translator: Bole \n" "Language-Team: Croatian (http://www.transifex.com/odoo/odoo-9/language/hr/)\n" "MIME-Version: 1.0\n" @@ -221,7 +221,7 @@ msgstr "Statistika prodajnih naloga" #. module: sale_stock #: model:ir.model.fields,field_description:sale_stock.field_res_company_security_lead msgid "Sales Safety Days" -msgstr "" +msgstr "Sigurnosni dani prodaje" #. module: sale_stock #: model:ir.model.fields,field_description:sale_stock.field_stock_location_route_sale_selectable diff --git a/addons/sale_timesheet/i18n/pl.po b/addons/sale_timesheet/i18n/pl.po index 49d1fffb14d..6168136ba11 100644 --- a/addons/sale_timesheet/i18n/pl.po +++ b/addons/sale_timesheet/i18n/pl.po @@ -9,14 +9,14 @@ msgstr "" "Project-Id-Version: Odoo 9.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-14 10:28+0000\n" -"PO-Revision-Date: 2016-10-14 15:32+0000\n" +"PO-Revision-Date: 2017-09-15 13:04+0000\n" "Last-Translator: zbik2607 \n" "Language-Team: Polish (http://www.transifex.com/odoo/odoo-9/language/pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Language: pl\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" #. module: sale_timesheet #: model:ir.model,name:sale_timesheet.model_account_analytic_line diff --git a/addons/website/i18n/de.po b/addons/website/i18n/de.po index 3f9139efbad..cfa7ebfb523 100644 --- a/addons/website/i18n/de.po +++ b/addons/website/i18n/de.po @@ -13,7 +13,7 @@ msgstr "" "Project-Id-Version: Odoo 9.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-10-09 09:18+0000\n" -"PO-Revision-Date: 2017-03-29 15:18+0000\n" +"PO-Revision-Date: 2017-09-16 17:49+0000\n" "Last-Translator: Ermin Trevisan \n" "Language-Team: German (http://www.transifex.com/odoo/odoo-9/language/de/)\n" "MIME-Version: 1.0\n" @@ -2737,7 +2737,7 @@ msgstr "Ok" #: code:addons/website/static/src/xml/website.backend.xml:5 #, python-format msgid "On Website" -msgstr "" +msgstr "Auf Website" #. module: website #: model:ir.ui.view,arch_db:website.website_planner diff --git a/openerp/addons/base/i18n/hr.po b/openerp/addons/base/i18n/hr.po index 655c63f2d54..b3bc26e5833 100644 --- a/openerp/addons/base/i18n/hr.po +++ b/openerp/addons/base/i18n/hr.po @@ -16,7 +16,7 @@ msgstr "" "Project-Id-Version: Odoo 9.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-06-22 07:25+0000\n" -"PO-Revision-Date: 2017-09-01 08:36+0000\n" +"PO-Revision-Date: 2017-09-12 09:24+0000\n" "Last-Translator: Martin Trigaux\n" "Language-Team: Croatian (http://www.transifex.com/odoo/odoo-9/language/hr/)\n" "MIME-Version: 1.0\n" @@ -15857,7 +15857,7 @@ msgstr "" msgid "" "The internal user that is in charge of communicating with this contact if " "any." -msgstr "" +msgstr "Korisnik koji je zadužen za komunikaciju za ovim kontaktom, ukoliko postoji." #. module: base #: model:ir.model.fields,help:base.field_ir_model_inherited_model_ids diff --git a/openerp/addons/base/i18n/tr.po b/openerp/addons/base/i18n/tr.po index b7fd96415e6..182ca7bcac2 100644 --- a/openerp/addons/base/i18n/tr.po +++ b/openerp/addons/base/i18n/tr.po @@ -18,7 +18,7 @@ msgstr "" "Project-Id-Version: Odoo 9.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-06-22 07:25+0000\n" -"PO-Revision-Date: 2017-08-17 01:06+0000\n" +"PO-Revision-Date: 2017-09-16 14:30+0000\n" "Last-Translator: Martin Trigaux\n" "Language-Team: Turkish (http://www.transifex.com/odoo/odoo-9/language/tr/)\n" "MIME-Version: 1.0\n" @@ -423,7 +423,7 @@ msgstr "" msgid "" "\n" " Use Plaid.com to retrieve bank statements" -msgstr "" +msgstr "\n Banka hesap özetini almak için Plaid.com servisi kullan." #. module: base #: model:ir.module.module,description:base.module_account_plaid @@ -431,7 +431,7 @@ msgid "" "\n" " Use Plaid.com to retrieve bank statements.\n" " " -msgstr "" +msgstr "\n Banka hesap özetini almak için Plaid.com servisi kullan..\n " #. module: base #: model:ir.module.module,description:base.module_l10n_multilang @@ -4889,7 +4889,7 @@ msgstr "Analitik Varsayılan Hesaplar" #. module: base #: model:ir.module.module,shortdesc:base.module_account_bank_statement_import msgid "Account Bank Statement Import" -msgstr "" +msgstr "Banka Hesap Özeti İçe Aktarımı" #. module: base #: model:ir.module.category,name:base.module_category_localization_account_charts @@ -9324,7 +9324,7 @@ msgstr "Jenerik Modüller" msgid "" "Generic Wizard to Import Bank Statements. Includes the import of files in " ".OFX format" -msgstr "" +msgstr "Banka Hesap Özeti İçe Aktarımı Sihirbazı" #. module: base #: model:ir.module.module,description:base.module_website_form @@ -10185,12 +10185,12 @@ msgstr "İçe Aktar / Dışa Aktar" #. module: base #: model:ir.module.module,shortdesc:base.module_account_bank_statement_import_ofx msgid "Import OFX Bank Statement" -msgstr "" +msgstr "QFX Formatında Banka Hesap Özeti İçe Aktarımı" #. module: base #: model:ir.module.module,shortdesc:base.module_account_bank_statement_import_qif msgid "Import QIF Bank Statement" -msgstr "" +msgstr "QIF Formatında Banka Hesap Özeti İçe Aktarımı" #. module: base #: model:ir.actions.act_window,name:base.action_view_base_import_language From 875dd9221f80ea1b60cd9ee8a005d71246734a2b Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Mon, 18 Sep 2017 17:06:13 +0200 Subject: [PATCH 04/13] [FIX] account, website_portal_sale: _generate_and_pay_invoice in other currency When paying in other currency that the one defined in the company, it generates a payment which has to be in the currency of the transaction. Otherwise it will generate an invoice which won't be completely paid. opw:769278 --- addons/account/models/account_invoice.py | 8 ++++++-- addons/website_portal_sale/models/payment.py | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index 56b95ab8feb..c56ea11333b 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -1113,7 +1113,7 @@ class AccountInvoice(models.Model): if self.origin: communication = '%s (%s)' % (communication, self.origin) - payment = self.env['account.payment'].create({ + payment_vals = { 'invoice_ids': [(6, 0, self.ids)], 'amount': pay_amount or self.residual, 'payment_date': date or fields.Date.context_today(self), @@ -1125,7 +1125,11 @@ class AccountInvoice(models.Model): 'payment_method_id': payment_method.id, 'payment_difference_handling': writeoff_acc and 'reconcile' or 'open', 'writeoff_account_id': writeoff_acc and writeoff_acc.id or False, - }) + } + if self.env.context.get('tx_currency_id'): + payment_vals['currency_id'] = self.env.context.get('tx_currency_id') + + payment = self.env['account.payment'].create(payment_vals) payment.post() return True diff --git a/addons/website_portal_sale/models/payment.py b/addons/website_portal_sale/models/payment.py index 1005250807f..7aa838149bd 100644 --- a/addons/website_portal_sale/models/payment.py +++ b/addons/website_portal_sale/models/payment.py @@ -29,7 +29,7 @@ class PaymentTransaction(models.Model): created_invoice.action_invoice_open() if tx.acquirer_id.journal_id: - created_invoice.pay_and_reconcile(tx.acquirer_id.journal_id, pay_amount=created_invoice.amount_total) + created_invoice.with_context(tx_currency_id=tx.currency_id.id).pay_and_reconcile(tx.acquirer_id.journal_id, pay_amount=created_invoice.amount_total) if created_invoice.payment_ids: created_invoice.payment_ids[0].payment_transaction_id = tx else: From 3678cffcf940f699b29630c3ac3f5427a3cdf9f7 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Mon, 18 Sep 2017 16:07:50 +0530 Subject: [PATCH 05/13] [FIX] account: due date On an invoice: - Select a partner with payment term defined => due date D1 is set - Change to a partner withour payment term defined The due date D1 is kept. opw-772063 --- addons/account/models/account_invoice.py | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index c56ea11333b..8d73a1f5c85 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -505,6 +505,7 @@ class AccountInvoice(models.Model): self.account_id = account_id self.payment_term_id = payment_term_id + self.date_due = False self.fiscal_position_id = fiscal_position if type in ('in_invoice', 'out_refund'): From 4e9b5e8f23edf1a6f137277397a1d612f6ad7251 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 6 Sep 2017 15:26:49 +0200 Subject: [PATCH 06/13] [FIX] bus: compatibility with Odoo's PAAS external long polling handler Only start the bus events dispatcher when needed (lazy starting). On Odoo PAAS it's never started because the platform has its own event dispatcher. Cherry-pick of rev. a2ed3d3d5bdb6025a1ba14ad557a115a86413e65 --- addons/bus/models/bus.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/addons/bus/models/bus.py b/addons/bus/models/bus.py index 466592505a9..645b67d2607 100644 --- a/addons/bus/models/bus.py +++ b/addons/bus/models/bus.py @@ -108,6 +108,7 @@ class ImBus(models.Model): class ImDispatch(object): def __init__(self): self.channels = {} + self.started = False def poll(self, dbname, channels, last, options=None, timeout=TIMEOUT): if options is None: @@ -129,6 +130,10 @@ class ImDispatch(object): notifications = env['bus.bus'].poll(channels, last, options) # or wait for future ones if not notifications: + if not self.started: + # Lazy start of events listener + self.start() + event = self.Event() for channel in channels: self.channels.setdefault(hashable(channel), []).append(event) @@ -178,15 +183,16 @@ class ImDispatch(object): import gevent self.Event = gevent.event.Event gevent.spawn(self.run) - elif odoo.multi_process: - # disabled in prefork mode - return else: # threaded mode self.Event = threading.Event t = threading.Thread(name="%s.Bus" % __name__, target=self.run) t.daemon = True t.start() + self.started = True return self -dispatch = ImDispatch().start() +dispatch = None +if not odoo.multi_process or odoo.evented: + # We only use the event dispatcher in threaded and gevent mode + dispatch = ImDispatch() From f234376034566fb6579306cfe9bb9cd812fd507c Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 6 Sep 2017 17:01:33 +0200 Subject: [PATCH 07/13] [FIX] bus: compatibility with Odoo's PAAS external long polling handler Add a `peek` option in the bus event dispatcher polling in order to let an external event dispatcher fetch the notifications and their corresponding channels. Cherry-pick of rev. f2f99dc091947c0799b17c767a6ad923cd535025 --- addons/bus/models/bus.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addons/bus/models/bus.py b/addons/bus/models/bus.py index 645b67d2607..e58bc8f0276 100644 --- a/addons/bus/models/bus.py +++ b/addons/bus/models/bus.py @@ -128,6 +128,11 @@ class ImDispatch(object): with registry.cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, {}) notifications = env['bus.bus'].poll(channels, last, options) + + # immediatly returns in peek mode + if options.get('peek'): + return dict(notifications=notifications, channels=channels) + # or wait for future ones if not notifications: if not self.started: From 35441cfd62cc1aa7ad5507d5dc8c69218c36bc82 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Thu, 20 Oct 2016 09:10:58 +0200 Subject: [PATCH 08/13] [IMP] doc: add test classes documentation Closes #13902 --- doc/reference/testing.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/reference/testing.rst b/doc/reference/testing.rst index 9523d732e0f..794b6e45b18 100644 --- a/doc/reference/testing.rst +++ b/doc/reference/testing.rst @@ -48,6 +48,11 @@ related to testing Odoo content (modules, mainly): .. autoclass:: openerp.tests.common.SingleTransactionCase :members: browse_ref, ref +.. autoclass:: openerp.tests.common.SavepointCase + +.. autoclass:: openerp.tests.common.HttpCase + :members: browse_ref, ref, url_open, phantom_js + By default, tests are run once right after the corresponding module has been installed. Test cases can also be configured to run after all modules have been installed, and not run right after the module installation: From e34f6aaa26f022762c27ee62666e81e42eb1b8c5 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Thu, 14 Sep 2017 12:16:32 +0200 Subject: [PATCH 09/13] [FIX] stock: procurements must be confirmed with the right company The method _procure_orderpoint_confirm in stock/procurement is calld in sudo() by run_scheduler. Even if this method receives the company as parameter, the company is not enforced for all the processes trigerred into the method. i.e. If a PO is generated by the run of the procurements the sequence used is the one of the admin's company and not the one for the given company. To enforce the company to use, we force the company into the context if it's not the same as the user's company. opw:771851 --- addons/stock/models/procurement.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/stock/models/procurement.py b/addons/stock/models/procurement.py index 836d72875db..aaf5d34474e 100644 --- a/addons/stock/models/procurement.py +++ b/addons/stock/models/procurement.py @@ -295,6 +295,13 @@ class ProcurementOrder(models.Model): 1000 orderpoints. This is appropriate for batch jobs only. """ + if company_id and self.env.user.company_id.id != company_id: + # To ensure that the company_id is taken into account for + # all the processes triggered by this method + # i.e. If a PO is generated by the run of the procurements the + # sequence to use is the one for the specified company not the + # one of the user's company + self = self.with_context(company_id=company_id, force_company=company_id) OrderPoint = self.env['stock.warehouse.orderpoint'] domain = self._get_orderpoint_domain(company_id=company_id) From 6252c21000ad5c4c6d1eb3d5623393d267e8b70d Mon Sep 17 00:00:00 2001 From: Nicolas Lempereur Date: Tue, 5 Sep 2017 10:03:52 +0200 Subject: [PATCH 10/13] [FIX] web: modifiers computed when x2many ready Modifiers (eg. required, readonly, ... on a field) are computed after a record has been changed. When loading a record they could be computed based on x2many in a inconsistent state. eg. on res.partner form, by defaut the email is required depending on: [('user_ids','!=', [])] but when switching from one record to another this was computed wrongly based on the difference between the two records. This change make the x2many when loading a record ready to be used as soon as it is set to solve this issue. forward-port: not needed after saas-15 thanks to framework views rewrite fix #18239 opw-749483 closes #18815 --- addons/web/static/src/js/views/form_common.js | 6 ++++++ addons/web/static/src/js/views/form_relational_widgets.js | 8 +++++++- addons/web/static/src/js/views/form_view.js | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/js/views/form_common.js b/addons/web/static/src/js/views/form_common.js index 638327c8a3a..16e8c088368 100644 --- a/addons/web/static/src/js/views/form_common.js +++ b/addons/web/static/src/js/views/form_common.js @@ -729,6 +729,12 @@ var AbstractField = FormWidget.extend(FieldInterface, { set_value: function(value_) { this.set({'value': value_}); }, + /** + Method to set value of a field when loading a record + */ + set_value_from_record: function(record) { + this.set_value.call(this, record[this.name] || false); + }, get_value: function() { return this.get('value'); }, diff --git a/addons/web/static/src/js/views/form_relational_widgets.js b/addons/web/static/src/js/views/form_relational_widgets.js index e8e9c450c3c..f6e18384c20 100644 --- a/addons/web/static/src/js/views/form_relational_widgets.js +++ b/addons/web/static/src/js/views/form_relational_widgets.js @@ -453,12 +453,18 @@ var AbstractManyField = common.AbstractField.extend({ }); }, - _on_load_record: function (record) { + set_value_from_record: function (record) { + this._super.apply(this, arguments); + // we want to update starting_ids straight away so the value can be used as soon as + // possible without inconsistency this.starting_ids = []; // don't set starting_ids for the new record if (record.id && record[this.name] && (!isNaN(record.id) || record.id.indexOf(this.dataset.virtual_id_prefix) === -1)) { this.starting_ids = this.get('value').slice(); } + }, + + _on_load_record: function (record) { this.trigger("load_record", record); }, diff --git a/addons/web/static/src/js/views/form_view.js b/addons/web/static/src/js/views/form_view.js index 1e93a2954c0..76117111eeb 100644 --- a/addons/web/static/src/js/views/form_view.js +++ b/addons/web/static/src/js/views/form_view.js @@ -308,7 +308,7 @@ var FormView = View.extend(common.FieldManagerMixin, { _(this.fields).each(function (field, f) { field._dirty_flag = false; field._inhibit_on_change_flag = true; - var result = field.set_value(self.datarecord[f] || false); + var result = field.set_value_from_record(self.datarecord); field._inhibit_on_change_flag = false; set_values.push(result); }); From dfe96ff38eff06ecc649c3f779e5163c34266c22 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Tue, 19 Sep 2017 12:09:05 +0200 Subject: [PATCH 11/13] [FIX] stock: UoM on return lot - Create a product with: Product UoM: kg Purchase UoM: lb(s) Tracking: By lot(s) - Purchase 100 lb(s), validate and receive picking (set lot 001) - Return the picking - Set the lot The quantity to do is 45.36 instead of 100. We make sure to convert the quant UoM (=Product UoM) into the appropriate UoM. opw-771930 --- addons/stock/models/stock_picking.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py index 65aa42b69a5..e72ab2acc73 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -572,8 +572,11 @@ class Picking(models.Model): 'location_dest_id': mapping.location_dst_id, 'product_uom_id': uom.id, 'pack_lot_ids': [ - (0, 0, {'lot_id': lot, 'qty': 0.0, 'qty_todo': lots_grouped[mapping][lot]}) - for lot in lots_grouped.get(mapping, {}).keys()], + (0, 0, { + 'lot_id': lot, + 'qty': 0.0, + 'qty_todo': mapping.product.uom_id._compute_quantity(lots_grouped[mapping][lot], uom) + }) for lot in lots_grouped.get(mapping, {}).keys()], } product_id_to_vals.setdefault(mapping.product.id, list()).append(val_dict) From a0fddebe64eaaec9ea362ea2eabdaad7de61e724 Mon Sep 17 00:00:00 2001 From: Nicolas Lempereur Date: Fri, 15 Sep 2017 13:43:21 +0200 Subject: [PATCH 12/13] [FIX] base: prevent bin_size/binary visual defect Changing the address type of a contact in the "Contact & Addresses" tab could in some instance lead to a dead image (just visually, saving it would not change it) because the image is set to something like "data:image/png;base64,5.23 Kb" because of a combination of kanba/form x2many view, onchange, the differences of field present. In 9.0 this did not happen because the image was not a field in the form view corresponding to a contact of the kanban contacts view. In saa-15 thanks to bf26445 the image_small is different than image in the kanban view and this got us out of the issue. In saas-16 it is solved even further because new views only load missing fields. This commit just get out of the issue by preventing an update of the records field (with bin_size which caused the issue of the image) when opening the modal form view of a contact's contact. Ideally we should solve this more deeply but this is dangerous code to change (eg. removing the bin_size would solve it but this was done for a reason and could affect performances) and the effect is just visual in a very particular set of factors (if we save the form after the image is dead, the previous image reappeared). opw-765952 closes #19491 --- odoo/addons/base/res/res_partner_view.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/odoo/addons/base/res/res_partner_view.xml b/odoo/addons/base/res/res_partner_view.xml index 92d4c41db55..216063b6145 100644 --- a/odoo/addons/base/res/res_partner_view.xml +++ b/odoo/addons/base/res/res_partner_view.xml @@ -219,6 +219,11 @@ + + + + + From 776e77b67c2abea9cef8ab7071998d4272c3404f Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Wed, 20 Sep 2017 14:16:12 +0200 Subject: [PATCH 13/13] [FIX] account, point_of_sale, purchase, sale, website_sale: correctly set included tax in multi-company A product can have multiple included taxes (i.e. one by company). When computing the product price with function _fix_tax_included_price, only the taxes of the company should be considered. Otherwise it could remove all the included taxes of all companies. ps: When no company is set on the SO, all the taxes visible from the company of the user are set for the product of the line. Same behavior as in _compute_tax_id. Closes #19566 opw:770464 --- addons/account/models/account.py | 8 ++++++++ addons/point_of_sale/models/pos_order.py | 2 +- addons/purchase/models/purchase.py | 8 ++++---- addons/sale/models/sale.py | 6 +++--- addons/website_sale/models/sale_order.py | 7 ++++--- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/addons/account/models/account.py b/addons/account/models/account.py index 6a2e73160bd..5a7ad534da7 100644 --- a/addons/account/models/account.py +++ b/addons/account/models/account.py @@ -830,6 +830,14 @@ class AccountTax(models.Model): return incl_tax.compute_all(price)['total_excluded'] return price + @api.model + def _fix_tax_included_price_company(self, price, prod_taxes, line_taxes, company_id): + if company_id: + #To keep the same behavior as in _compute_tax_id + prod_taxes = prod_taxes.filtered(lambda tax: tax.company_id == company_id) + line_taxes = line_taxes.filtered(lambda tax: tax.company_id == company_id) + return self._fix_tax_included_price(price, prod_taxes, line_taxes) + class AccountReconcileModel(models.Model): _name = "account.reconcile.model" _description = "Preset to create journal entries during a invoices and payments matching" diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index 1f7e0762e65..840ff6869b9 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -869,7 +869,7 @@ class PosOrderLine(models.Model): self.tax_ids = self.product_id.taxes_id.filtered(lambda r: not self.company_id or r.company_id == self.company_id) fpos = self.order_id.fiscal_position_id tax_ids_after_fiscal_position = fpos.map_tax(self.tax_ids, self.product_id, self.order_id.partner_id) if fpos else self.tax_ids - self.price_unit = self.env['account.tax']._fix_tax_included_price(price, self.product_id.taxes_id, tax_ids_after_fiscal_position) + self.price_unit = self.env['account.tax']._fix_tax_included_price_company(price, self.product_id.taxes_id, tax_ids_after_fiscal_position, self.company_id) @api.onchange('qty', 'discount', 'price_unit', 'tax_ids') def _onchange_qty(self): diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py index 7cd1132d89e..419d184f24e 100644 --- a/addons/purchase/models/purchase.py +++ b/addons/purchase/models/purchase.py @@ -822,7 +822,7 @@ class PurchaseOrderLine(models.Model): if not seller: return - price_unit = self.env['account.tax']._fix_tax_included_price(seller.price, self.product_id.supplier_taxes_id, self.taxes_id) if seller else 0.0 + price_unit = self.env['account.tax']._fix_tax_included_price_company(seller.price, self.product_id.supplier_taxes_id, self.taxes_id, self.company_id) if seller else 0.0 if price_unit and seller and self.order_id.currency_id and seller.currency_id != self.order_id.currency_id: price_unit = seller.currency_id.compute(price_unit, self.order_id.currency_id) @@ -895,7 +895,7 @@ class ProcurementOrder(models.Model): date=procurement.purchase_line_id.order_id.date_order and procurement.purchase_line_id.order_id.date_order[:10], uom_id=procurement.purchase_line_id.product_uom) - price_unit = self.env['account.tax']._fix_tax_included_price(seller.price, procurement.purchase_line_id.product_id.supplier_taxes_id, procurement.purchase_line_id.taxes_id) if seller else 0.0 + price_unit = self.env['account.tax']._fix_tax_included_price_company(seller.price, procurement.purchase_line_id.product_id.supplier_taxes_id, procurement.purchase_line_id.taxes_id, self.company_id) if seller else 0.0 if price_unit and seller and procurement.purchase_line_id.order_id.currency_id and seller.currency_id != procurement.purchase_line_id.order_id.currency_id: price_unit = seller.currency_id.compute(price_unit, procurement.purchase_line_id.order_id.currency_id) @@ -954,7 +954,7 @@ class ProcurementOrder(models.Model): if taxes_id: taxes_id = taxes_id.filtered(lambda x: x.company_id.id == self.company_id.id) - price_unit = self.env['account.tax']._fix_tax_included_price(seller.price, self.product_id.supplier_taxes_id, taxes_id) if seller else 0.0 + price_unit = self.env['account.tax']._fix_tax_included_price_company(seller.price, self.product_id.supplier_taxes_id, taxes_id, self.company_id) if seller else 0.0 if price_unit and seller and po.currency_id and seller.currency_id != po.currency_id: price_unit = seller.currency_id.compute(price_unit, po.currency_id) @@ -1079,7 +1079,7 @@ class ProcurementOrder(models.Model): date=po.date_order and po.date_order[:10], uom_id=procurement.product_id.uom_po_id) - price_unit = self.env['account.tax']._fix_tax_included_price(seller.price, line.product_id.supplier_taxes_id, line.taxes_id) if seller else 0.0 + price_unit = self.env['account.tax']._fix_tax_included_price_company(seller.price, line.product_id.supplier_taxes_id, line.taxes_id, self.company_id) if seller else 0.0 if price_unit and seller and po.currency_id and seller.currency_id != po.currency_id: price_unit = seller.currency_id.compute(price_unit, po.currency_id) diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index 38a4036f609..50d2066fc14 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -903,7 +903,7 @@ class SaleOrderLine(models.Model): self._compute_tax_id() if self.order_id.pricelist_id and self.order_id.partner_id: - vals['price_unit'] = self.env['account.tax']._fix_tax_included_price(self._get_display_price(product), product.taxes_id, self.tax_id) + vals['price_unit'] = self.env['account.tax']._fix_tax_included_price_company(self._get_display_price(product), product.taxes_id, self.tax_id, self.company_id) self.update(vals) return result @@ -923,7 +923,7 @@ class SaleOrderLine(models.Model): uom=self.product_uom.id, fiscal_position=self.env.context.get('fiscal_position') ) - self.price_unit = self.env['account.tax']._fix_tax_included_price(self._get_display_price(product), product.taxes_id, self.tax_id) + self.price_unit = self.env['account.tax']._fix_tax_included_price_company(self._get_display_price(product), product.taxes_id, self.tax_id, self.company_id) @api.multi def unlink(self): @@ -999,7 +999,7 @@ class SaleOrderLine(models.Model): price, rule_id = self.order_id.pricelist_id.with_context(pricelist_context).get_product_price_rule(self.product_id, self.product_uom_qty or 1.0, self.order_id.partner_id) new_list_price, currency_id = self.with_context(context_partner)._get_real_price_currency(self.product_id, rule_id, self.product_uom_qty, self.product_uom, self.order_id.pricelist_id.id) - new_list_price = self.env['account.tax']._fix_tax_included_price(new_list_price, self.product_id.taxes_id, self.tax_id) + new_list_price = self.env['account.tax']._fix_tax_included_price_company(new_list_price, self.product_id.taxes_id, self.tax_id, self.company_id) if new_list_price != 0: if self.product_id.company_id and self.order_id.pricelist_id.currency_id != self.product_id.company_id.currency_id: diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py index 9d1564e06cd..6735d3848f9 100644 --- a/addons/website_sale/models/sale_order.py +++ b/addons/website_sale/models/sale_order.py @@ -71,7 +71,7 @@ class SaleOrder(models.Model): if order.pricelist_id and order.partner_id: order_line = order._cart_find_product_line(product.id) if order_line: - pu = self.env['account.tax']._fix_tax_included_price(pu, product.taxes_id, order_line[0].tax_id) + pu = self.env['account.tax']._fix_tax_included_price_company(pu, product.taxes_id, order_line[0].tax_id, self.company_id) return { 'product_id': product_id, @@ -159,10 +159,11 @@ class SaleOrder(models.Model): 'pricelist': order.pricelist_id.id, }) product = self.env['product.product'].with_context(product_context).browse(product_id) - values['price_unit'] = self.env['account.tax']._fix_tax_included_price( + values['price_unit'] = self.env['account.tax']._fix_tax_included_price_company( order_line._get_display_price(product), order_line.product_id.taxes_id, - order_line.tax_id + order_line.tax_id, + self.company_id ) order_line.write(values)