diff options
| author | Christophe Simonis <chs@odoo.com> | 2019-01-11 18:56:24 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2019-01-11 18:56:24 +0100 |
| commit | 6a0675d36dd888daa4183f3d609ce334ed3cb493 (patch) | |
| tree | 398886eba7df477300b1f433f295caa8c18d8ff1 | |
| parent | 57ccf70a32f677a9076ec2973100c1025f412d85 (diff) | |
| parent | e033114879cfe4a487549c0abbe37ec18bc151c9 (diff) | |
[MERGE] forward port branch saas-11.3 up to e033114879c
| -rw-r--r-- | addons/account/models/account_invoice.py | 4 | ||||
| -rw-r--r-- | addons/account/tests/test_account_customer_invoice.py | 63 | ||||
| -rw-r--r-- | addons/payment_authorize/models/authorize_request.py | 2 | ||||
| -rw-r--r-- | addons/point_of_sale/models/pos_order.py | 15 | ||||
| -rw-r--r-- | addons/point_of_sale/static/src/js/screens.js | 5 | ||||
| -rw-r--r-- | addons/sale_timesheet/static/src/js/timesheet_plan.js | 8 | ||||
| -rw-r--r-- | addons/sale_timesheet/static/tests/timesheet_plan_tests.js | 4 | ||||
| -rw-r--r-- | addons/stock/models/stock_picking.py | 4 | ||||
| -rw-r--r-- | addons/stock/views/stock_picking_views.xml | 3 | ||||
| -rw-r--r-- | addons/web_editor/static/src/js/widgets/widgets.js | 1 | ||||
| -rw-r--r-- | addons/website_sale/static/src/scss/website_sale.scss | 2 | ||||
| -rw-r--r-- | odoo/addons/base/models/res_users.py | 22 |
12 files changed, 111 insertions, 22 deletions
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('<div class="table-responsive"></div>'); + 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: '<p>Banach-Tarski</p>'}); } 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: '<p>Banach-Tarski</p>'}); } 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 @@ <group> <group> <field name="partner_id"/> + <button name="action_assign_partner" string="Assign Partner" type="object" help="Assign the partner to the Operations. Use only if the partner is manually changed!" + attrs="{'invisible': ['|', '|', ('move_line_exist', '=', False), ('state', 'not in', ('draft', 'assigned', 'confirmed')), ('picking_type_code', '=', 'internal')]}" + class="oe_link oe_edit_only"/> <field name="picking_type_id" attrs="{'readonly': [('state', '!=', 'draft')]}"/> <field name="location_id" groups="stock.group_stock_multi_locations" attrs="{'invisible': [('picking_type_code', '=', 'incoming')]}"/> <field name="location_dest_id" groups="stock.group_stock_multi_locations" attrs="{'invisible': [('picking_type_code', '=', 'outgoing')]}"/> diff --git a/addons/web_editor/static/src/js/widgets/widgets.js b/addons/web_editor/static/src/js/widgets/widgets.js index 30de8171e53..34a45f7193d 100644 --- a/addons/web_editor/static/src/js/widgets/widgets.js +++ b/addons/web_editor/static/src/js/widgets/widgets.js @@ -736,6 +736,7 @@ var IconWidget = MediaWidget.extend({ this.$('div.font-icons-icons').html( QWeb.render('web_editor.dialog.font-icons.icons', {iconsParser: iconsParser}) ); + return $.when(); }, //-------------------------------------------------------------------------- diff --git a/addons/website_sale/static/src/scss/website_sale.scss b/addons/website_sale/static/src/scss/website_sale.scss index 29e685b8b4a..6a5d755ad64 100644 --- a/addons/website_sale/static/src/scss/website_sale.scss +++ b/addons/website_sale/static/src/scss/website_sale.scss @@ -690,7 +690,7 @@ a.no-decoration { .o_website_sale_animate { opacity: 0.7; - position: absolute; + position: absolute !important; height: 150px; width: 150px; z-index: 1020; diff --git a/odoo/addons/base/models/res_users.py b/odoo/addons/base/models/res_users.py index 083607f9807..fef68d537d0 100644 --- a/odoo/addons/base/models/res_users.py +++ b/odoo/addons/base/models/res_users.py @@ -868,8 +868,26 @@ class GroupsImplied(models.Model): if values.get('users') or values.get('implied_ids'): # add all implied groups (to all users of each group) for group in self: - vals = {'users': list(pycompat.izip(repeat(4), group.with_context(active_test=False).users.ids))} - super(GroupsImplied, group.trans_implied_ids).write(vals) + self._cr.execute(""" + WITH RECURSIVE group_imply(gid, hid) AS ( + SELECT gid, hid + FROM res_groups_implied_rel + UNION + SELECT i.gid, r.hid + FROM res_groups_implied_rel r + JOIN group_imply i ON (i.hid = r.gid) + ) + INSERT INTO res_groups_users_rel (gid, uid) + SELECT i.hid, r.uid + FROM group_imply i, res_groups_users_rel r + WHERE r.gid = i.gid + AND i.gid = %(gid)s + EXCEPT + SELECT r.gid, r.uid + FROM res_groups_users_rel r + JOIN group_imply i ON (r.gid = i.hid) + WHERE i.gid = %(gid)s + """, dict(gid=group.id)) return res class UsersImplied(models.Model): |
