diff --git a/addons/account/models/account.py b/addons/account/models/account.py index 0096d755b10..b81fd23cdda 100644 --- a/addons/account/models/account.py +++ b/addons/account/models/account.py @@ -797,6 +797,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/account/models/account_invoice.py b/addons/account/models/account_invoice.py index c7d889238c5..130ec854493 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -525,6 +525,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'): @@ -1138,7 +1139,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), @@ -1150,7 +1151,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/account/views/report_journal.xml b/addons/account/views/report_journal.xml index f94e20fa3b0..41abc050cd0 100644 --- a/addons/account/views/report_journal.xml +++ b/addons/account/views/report_journal.xml @@ -49,7 +49,7 @@ - + diff --git a/addons/bus/models/bus.py b/addons/bus/models/bus.py index 8795a6047c8..0af875cecbb 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: @@ -127,8 +128,17 @@ 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: + # Lazy start of events listener + self.start() + event = self.Event() for channel in channels: self.channels.setdefault(hashable(channel), []).append(event) @@ -178,15 +188,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() diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index af45e150871..4f5e3d8257e 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -882,7 +882,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 b264254491b..456d999a123 100644 --- a/addons/purchase/models/purchase.py +++ b/addons/purchase/models/purchase.py @@ -820,7 +820,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) @@ -893,7 +893,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) @@ -958,7 +958,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) @@ -1083,7 +1083,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 b49182a23e0..6e91fc130fa 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -914,7 +914,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 @@ -934,7 +934,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): @@ -1010,7 +1010,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/stock/models/procurement.py b/addons/stock/models/procurement.py index d75014fd331..6322149c854 100644 --- a/addons/stock/models/procurement.py +++ b/addons/stock/models/procurement.py @@ -289,6 +289,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) diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py index 0a6e36c7bde..d6616d38cbe 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -567,8 +567,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) diff --git a/addons/website_portal_sale/models/payment.py b/addons/website_portal_sale/models/payment.py index a5095502fb6..3302ac87967 100644 --- a/addons/website_portal_sale/models/payment.py +++ b/addons/website_portal_sale/models/payment.py @@ -30,7 +30,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: diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py index 11ba7389fee..22f4f47e9db 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) diff --git a/doc/reference/testing.rst b/doc/reference/testing.rst index 7b5bb666988..ab32a9d3e0a 100644 --- a/doc/reference/testing.rst +++ b/doc/reference/testing.rst @@ -48,6 +48,11 @@ related to testing Odoo content (modules, mainly): .. autoclass:: odoo.tests.common.SingleTransactionCase :members: browse_ref, ref +.. autoclass:: odoo.tests.common.SavepointCase + +.. autoclass:: odoo.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: diff --git a/odoo/addons/base/res/res_partner_view.xml b/odoo/addons/base/res/res_partner_view.xml index a0b762adadb..fbfbf8823fa 100644 --- a/odoo/addons/base/res/res_partner_view.xml +++ b/odoo/addons/base/res/res_partner_view.xml @@ -220,6 +220,11 @@ + + + + +