diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index 69a7443f3da..0f8d901c4f4 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -992,6 +992,7 @@ class AccountInvoice(models.Model): @api.multi def get_taxes_values(self): tax_grouped = {} + round_curr = self.currency_id.round for line in self.invoice_line_ids: if not line.account_id: continue @@ -1003,9 +1004,10 @@ class AccountInvoice(models.Model): if key not in tax_grouped: tax_grouped[key] = val + tax_grouped[key]['base'] = round_curr(val['base']) else: tax_grouped[key]['amount'] += val['amount'] - tax_grouped[key]['base'] += val['base'] + tax_grouped[key]['base'] += round_curr(val['base']) return tax_grouped @api.multi diff --git a/addons/account/tests/test_account_customer_invoice.py b/addons/account/tests/test_account_customer_invoice.py index a6b3459c9b9..83822ef8ffb 100644 --- a/addons/account/tests/test_account_customer_invoice.py +++ b/addons/account/tests/test_account_customer_invoice.py @@ -103,3 +103,66 @@ class TestAccountCustomerInvoice(AccountTestUsers): # I clicked on Add Credit Note button. self.account_invoice_refund_0.invoice_refund() + + def test_customer_invoice_tax(self): + + self.env.user.company_id.tax_calculation_rounding_method = 'round_globally' + + payment_term = self.env.ref('account.account_payment_term_advance') + journalrec = self.env['account.journal'].search([('type', '=', 'sale')])[0] + partner3 = self.env.ref('base.res_partner_3') + account_id = self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)], limit=1).id + + tax = self.env['account.tax'].create({ + 'name': 'Tax 15.0', + 'amount': 15.0, + 'amount_type': 'percent', + 'type_tax_use': 'sale', + }) + + invoice_line_data = [ + (0, 0, + { + 'product_id': self.env.ref('product.product_product_1').id, + 'quantity': 40.0, + 'account_id': account_id, + 'name': 'product test 1', + 'discount' : 10.00, + 'price_unit': 2.27, + 'invoice_line_tax_ids': [(6, 0, [tax.id])], + } + ), + (0, 0, + { + 'product_id': self.env.ref('product.product_product_2').id, + 'quantity': 21.0, + 'account_id': self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)], limit=1).id, + 'name': 'product test 2', + 'discount' : 10.00, + 'price_unit': 2.77, + 'invoice_line_tax_ids': [(6, 0, [tax.id])], + } + ), + (0, 0, + { + 'product_id': self.env.ref('product.product_product_3').id, + 'quantity': 21.0, + 'account_id': self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)], limit=1).id, + 'name': 'product test 3', + 'discount' : 10.00, + 'price_unit': 2.77, + 'invoice_line_tax_ids': [(6, 0, [tax.id])], + } + ) + ] + + invoice = self.env['account.invoice'].create(dict( + name="Test Customer Invoice", + reference_type="none", + payment_term_id=payment_term.id, + journal_id=journalrec.id, + partner_id=partner3.id, + invoice_line_ids=invoice_line_data + )) + + self.assertEquals(invoice.amount_untaxed, sum([x.base for x in invoice.tax_line_ids])) diff --git a/addons/payment_authorize/models/authorize_request.py b/addons/payment_authorize/models/authorize_request.py index e4bd3382caa..bca2164dac1 100644 --- a/addons/payment_authorize/models/authorize_request.py +++ b/addons/payment_authorize/models/authorize_request.py @@ -149,7 +149,7 @@ class AuthorizeAPI(): root = self._base_tree('createCustomerProfileRequest') profile = etree.SubElement(root, "profile") etree.SubElement(profile, "merchantCustomerId").text = 'ODOO-%s-%s' % (partner.id, uuid4().hex[:8]) - etree.SubElement(profile, "email").text = partner.email + etree.SubElement(profile, "email").text = partner.email or '' payment_profile = etree.SubElement(profile, "paymentProfiles") etree.SubElement(payment_profile, "customerType").text = 'business' if partner.is_company else 'individual' billTo = etree.SubElement(payment_profile, "billTo") diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index 9321d224ea7..af93a311658 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -839,21 +839,18 @@ class PosOrder(models.Model): lots_necessary = True if picking_type: lots_necessary = picking_type and picking_type.use_existing_lots - qty = 0 qty_done = 0 pack_lots = [] pos_pack_lots = PosPackOperationLot.search([('order_id', '=', order.id), ('product_id', '=', move.product_id.id)]) - pack_lot_names = [pos_pack.lot_name for pos_pack in pos_pack_lots] - if pack_lot_names and lots_necessary: - for lot_name in list(set(pack_lot_names)): - stock_production_lot = StockProductionLot.search([('name', '=', lot_name), ('product_id', '=', move.product_id.id)]) + if pos_pack_lots and lots_necessary: + for pos_pack_lot in pos_pack_lots: + stock_production_lot = StockProductionLot.search([('name', '=', pos_pack_lot.lot_name), ('product_id', '=', move.product_id.id)]) if stock_production_lot: + # a serialnumber always has a quantity of 1 product, a lot number takes the full quantity of the order line + qty = 1.0 if stock_production_lot.product_id.tracking == 'lot': - # if a lot nr is set through the frontend it will refer to the full quantity - qty = move.product_uom_qty - else: # serial numbers - qty = 1.0 + qty = pos_pack_lot.pos_order_line_id.qty qty_done += qty pack_lots.append({'lot_id': stock_production_lot.id, 'qty': qty}) else: diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index 7b80a8c98fd..6939aff72f2 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -1970,16 +1970,11 @@ var PaymentScreenWidget = ScreenWidget.extend({ $('body').keypress(this.keyboard_handler); // that one comes from the pos, but we prefer to cover all the basis $('body').keydown(this.keyboard_keydown_handler); - // legacy vanilla JS listeners - window.document.body.addEventListener('keypress',this.keyboard_handler); - window.document.body.addEventListener('keydown',this.keyboard_keydown_handler); this._super(); }, hide: function(){ $('body').off('keypress', this.keyboard_handler); $('body').off('keydown', this.keyboard_keydown_handler); - window.document.body.removeEventListener('keypress',this.keyboard_handler); - window.document.body.removeEventListener('keydown',this.keyboard_keydown_handler); this._super(); }, // sets up listeners to watch for order changes diff --git a/addons/sale_timesheet/static/src/js/timesheet_plan.js b/addons/sale_timesheet/static/src/js/timesheet_plan.js index 90cbcd98379..e2c199ad545 100644 --- a/addons/sale_timesheet/static/src/js/timesheet_plan.js +++ b/addons/sale_timesheet/static/src/js/timesheet_plan.js @@ -107,7 +107,13 @@ var ProjectPlan = AbstractAction.extend(ControlPanelMixin, { * @param {string|html} dom */ _refreshPlan: function (dom) { - this.$el.html(dom); + // TODO: Not forward port this fix on master + var $dom = $(dom); + $dom.find('div.o_timesheet_plan_sale_timesheet_dashboard > table.table, ' + + 'div.o_timesheet_plan_sale_timesheet_people_time > table.table, ' + + 'div.o_project_plan_project_timesheet_forecast > table.table') + .wrap('
'); + this.$el.html($dom); }, /** diff --git a/addons/sale_timesheet/static/tests/timesheet_plan_tests.js b/addons/sale_timesheet/static/tests/timesheet_plan_tests.js index d1d71c4face..12ccea8e53b 100644 --- a/addons/sale_timesheet/static/tests/timesheet_plan_tests.js +++ b/addons/sale_timesheet/static/tests/timesheet_plan_tests.js @@ -48,7 +48,7 @@ QUnit.module('Timesheet Plan', { mockRPC: function (route) { assert.step(route); if (route === '/timesheet/plan') { - return $.when({html_content: 'Banach-Tarski'}); + return $.when({html_content: '

Banach-Tarski

'}); } return this._super.apply(this, arguments); }, @@ -81,7 +81,7 @@ QUnit.module('Timesheet Plan', { action: {name: 'Fibonacci'}, mockRPC: function (route) { if (route === '/timesheet/plan') { - return $.when({html_content: 'Banach-Tarski'}); + return $.when({html_content: '

Banach-Tarski

'}); } return this._super.apply(this, arguments); }, diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py index 2b46709335a..0fbdcf7e7d4 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -533,6 +533,10 @@ class Picking(models.Model): def action_assign_owner(self): self.move_line_ids.write({'owner_id': self.owner_id.id}) + def action_assign_partner(self): + for picking in self: + picking.move_lines.write({'partner_id': picking.partner_id.id}) + @api.multi def do_print_picking(self): self.write({'printed': True}) diff --git a/addons/stock/views/stock_picking_views.xml b/addons/stock/views/stock_picking_views.xml index b4f47463482..78bc346495b 100644 --- a/addons/stock/views/stock_picking_views.xml +++ b/addons/stock/views/stock_picking_views.xml @@ -247,6 +247,9 @@ +