From aad8079c73aa35ea70c7add456c3798e4eeff12c Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Tue, 22 Nov 2016 16:37:37 +0100 Subject: [PATCH 1/7] [FIX] website_sale: Empty quantity in website cart Empty quantity on a line in the website cart didn't delete the line. opw:694361 --- addons/website_sale/static/src/js/website_sale.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/website_sale/static/src/js/website_sale.js b/addons/website_sale/static/src/js/website_sale.js index a48483b5349..cc6a57e2796 100644 --- a/addons/website_sale/static/src/js/website_sale.js +++ b/addons/website_sale/static/src/js/website_sale.js @@ -143,7 +143,7 @@ $('.oe_website_sale').each(function () { if ($input.data('update_change')) { return; } - var value = parseInt($input.val(), 10); + var value = parseInt($input.val() || 0, 10); var $dom = $(this).closest('tr'); var default_price = parseFloat($dom.find('.text-danger > span.oe_currency_value').text()); var $dom_optional = $dom.nextUntil(':not(.optional_product.info)'); @@ -164,7 +164,7 @@ $('.oe_website_sale').each(function () { 'set_qty': value}) .then(function (data) { $input.data('update_change', false); - if (value !== parseInt($input.val(), 10)) { + if (value !== parseInt($input.val() || 0, 10)) { $input.trigger('change'); return; } @@ -211,7 +211,7 @@ $('.oe_website_sale').each(function () { var product_id = +$input.closest('*:has(input[name="product_id"])').find('input[name="product_id"]').val(); var min = parseFloat($input.data("min") || 0); var max = parseFloat($input.data("max") || Infinity); - var quantity = ($link.has(".fa-minus").length ? -1 : 1) + parseFloat($input.val(),10); + var quantity = ($link.has(".fa-minus").length ? -1 : 1) + parseFloat($input.val() || 0, 10); // if they are more of one input for this product (eg: option modal) $('input[name="'+$input.attr("name")+'"]').add($input).filter(function () { var $prod = $(this).closest('*:has(input[name="product_id"])'); From 1c58ff30bd5e61c644242292acec86ba1d5242a1 Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Wed, 23 Nov 2016 09:44:55 +0100 Subject: [PATCH 2/7] [FIX] account: _get_analytic_amount_currency When creating a timesheet with several lines, it creates several analytic lines and it raised an error: "Expected singleton" opw:694722 --- addons/account/models/account_analytic_line.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/account/models/account_analytic_line.py b/addons/account/models/account_analytic_line.py index c5c0d5ed746..94a7cdb28eb 100644 --- a/addons/account/models/account_analytic_line.py +++ b/addons/account/models/account_analytic_line.py @@ -25,7 +25,8 @@ class AccountAnalyticLine(models.Model): partner_id = fields.Many2one('res.partner', related='account_id.partner_id', string='Partner', store=True, readonly=True) def _get_analytic_amount_currency(self): - self.analytic_amount_currency = abs(self.amount_currency) * copysign(1, self.amount) + for line in self: + line.analytic_amount_currency = abs(line.amount_currency) * copysign(1, line.amount) @api.v8 @api.onchange('product_id', 'product_uom_id', 'unit_amount', 'currency_id') From ba1602ee77c5fa5b297548bb17e6697058af955b Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Fri, 4 Nov 2016 16:31:16 +0100 Subject: [PATCH 3/7] [FIX] stock: fix search and domain on location_id, company_id, owner_id of stock.quant.package Those fields were stored computed fields before. However store has been removed while migrating to the new API. We need a search function if we want to be able to search on those fields and to use domains. Domains are necessary to take packages from the right source locations. The computation is done by searching the packages with the "location/owner/..." domain and by returning a parent-of domain in order to include all parent packages too. --- addons/stock/models/stock_quant.py | 36 +++++++++++++++++-- .../views/stock_pack_operation_views.xml | 2 +- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py index 62ade53bc68..ee78249bcab 100644 --- a/addons/stock/models/stock_quant.py +++ b/addons/stock/models/stock_quant.py @@ -598,13 +598,13 @@ class QuantPackage(models.Model): 'product.packaging', 'Package Type', index=True, help="This field should be completed only if everything inside the package share the same product, otherwise it doesn't really makes sense.") location_id = fields.Many2one( - 'stock.location', 'Location', compute='_compute_package_info', + 'stock.location', 'Location', compute='_compute_package_info', search='_search_location', index=True, readonly=True) company_id = fields.Many2one( - 'res.company', 'Company', compute='_compute_package_info', + 'res.company', 'Company', compute='_compute_package_info', search='_search_company', index=True, readonly=True) owner_id = fields.Many2one( - 'res.partner', 'Owner', compute='_compute_package_info', + 'res.partner', 'Owner', compute='_compute_package_info', search='_search_owner', index=True, readonly=True) @api.one @@ -646,6 +646,36 @@ class QuantPackage(models.Model): res[package.id] = name return res + def _search_location(self, operator, value): + if value: + packs = self.search([('quant_ids.location_id', operator, value)]) + else: + packs = self.search([('quant_ids', operator, value)]) + if packs: + return [('id', 'parent_of', packs.ids)] + else: + return [('id', '=', False)] + + def _search_company(self, operator, value): + if value: + packs = self.search([('quant_ids.company_id', operator, value)]) + else: + packs = self.search([('quant_ids', operator, value)]) + if packs: + return [('id', 'parent_of', packs.ids)] + else: + return [('id', '=', False)] + + def _search_owner(self, operator, value): + if value: + packs = self.search([('quant_ids.owner_id', operator, value)]) + else: + packs = self.search([('quant_ids', operator, value)]) + if packs: + return [('id', 'parent_of', packs.ids)] + else: + return [('id', '=', False)] + def _check_location_constraint(self): '''checks that all quants in a package are stored in the same location. This function cannot be used as a constraint because it needs to be checked on pack operations (they may not call write on the diff --git a/addons/stock/views/stock_pack_operation_views.xml b/addons/stock/views/stock_pack_operation_views.xml index 80f8b492423..1f79f6fd758 100644 --- a/addons/stock/views/stock_pack_operation_views.xml +++ b/addons/stock/views/stock_pack_operation_views.xml @@ -26,7 +26,7 @@ - + From a6b41186ca88e26be4244e5ecfd606cfc0407b42 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Tue, 22 Nov 2016 17:28:50 +0100 Subject: [PATCH 4/7] [FIX] stock: fix issue when creating package and computing children quants children_quant_ids is a computed field that does a search based on current record id. However this causes a traceback when creating a record as there is no id. This commit fixes this issue. --- addons/stock/models/stock_quant.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py index ee78249bcab..7492911801f 100644 --- a/addons/stock/models/stock_quant.py +++ b/addons/stock/models/stock_quant.py @@ -612,11 +612,12 @@ class QuantPackage(models.Model): def _compute_ancestor_ids(self): self.ancestor_ids = self.env['stock.quant.package'].search(['id', 'parent_of', self.id]).ids - @api.one + @api.multi @api.depends('parent_id', 'children_ids', 'quant_ids.package_id') def _compute_children_quant_ids(self): for package in self: - package.children_quant_ids = self.env['stock.quant'].search([('package_id', 'child_of', package.id)]).ids + if package.id: + package.children_quant_ids = self.env['stock.quant'].search([('package_id', 'child_of', package.id)]).ids @api.depends('quant_ids.package_id', 'quant_ids.location_id', 'quant_ids.company_id', 'quant_ids.owner_id', 'ancestor_ids') def _compute_package_info(self): From aa7d1ab9d1b14a68e421ee254d31d3eb6ef04207 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Wed, 23 Nov 2016 15:47:14 +0100 Subject: [PATCH 5/7] [FIX] account: invoice tracebacks When the company field is empty on an invoice, tracebacks occur. Fixes #14410 opw-694476 --- addons/account/models/account_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index 8a2b74b0083..3841f66e16d 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -49,7 +49,7 @@ class AccountInvoice(models.Model): self.amount_total = self.amount_untaxed + self.amount_tax amount_total_company_signed = self.amount_total amount_untaxed_signed = self.amount_untaxed - if self.currency_id and self.currency_id != self.company_id.currency_id: + if self.currency_id and self.company_id and self.currency_id != self.company_id.currency_id: currency_id = self.currency_id.with_context(date=self.date_invoice) amount_total_company_signed = currency_id.compute(self.amount_total, self.company_id.currency_id) amount_untaxed_signed = currency_id.compute(self.amount_untaxed, self.company_id.currency_id) @@ -1103,7 +1103,7 @@ class AccountInvoiceLine(models.Model): if self.invoice_line_tax_ids: taxes = self.invoice_line_tax_ids.compute_all(price, currency, self.quantity, product=self.product_id, partner=self.invoice_id.partner_id) self.price_subtotal = price_subtotal_signed = taxes['total_excluded'] if taxes else self.quantity * price - if self.invoice_id.currency_id and self.invoice_id.currency_id != self.invoice_id.company_id.currency_id: + if self.invoice_id.currency_id and self.invoice_id.company_id and self.invoice_id.currency_id != self.invoice_id.company_id.currency_id: price_subtotal_signed = self.invoice_id.currency_id.compute(price_subtotal_signed, self.invoice_id.company_id.currency_id) sign = self.invoice_id.type in ['in_refund', 'out_refund'] and -1 or 1 self.price_subtotal_signed = price_subtotal_signed * sign From 7e7205a7bfd5543f05808d71ae7ec8513d910079 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Wed, 23 Nov 2016 14:03:50 +0100 Subject: [PATCH 6/7] [FIX] payment_stripe: make it work The module `payment_stripe` was apparently not designed to work with module `website_payment`, althought the payment method is available. For example: - Go to '/my/home', select "Pay Now" on an invoice - Try to pay with Stripe ==> nothing happens This commit brings the necessary modifications to make it compatible with `website_payment`. Moreover, it prevents the creation of 2 `payment.transactions`, which was not necessary. opw-693421 --- addons/payment_stripe/controllers/main.py | 21 ++------ .../payment_stripe/models/payment_acquirer.py | 2 + addons/payment_stripe/static/src/js/stripe.js | 49 ++++++++++++------- addons/payment_stripe/views/stripe.xml | 2 + 4 files changed, 38 insertions(+), 36 deletions(-) diff --git a/addons/payment_stripe/controllers/main.py b/addons/payment_stripe/controllers/main.py index f2f2d60b8f5..ceebb17e500 100644 --- a/addons/payment_stripe/controllers/main.py +++ b/addons/payment_stripe/controllers/main.py @@ -29,24 +29,9 @@ class StripeController(http.Controller): """ Create a payment transaction Expects the result from the user input from checkout.js popup""" - acquirer = request.env['payment.acquirer'].browse(int(post.get('acquirer_id'))) - - sale_order_id = int(request.session.get('sale_order_id') or post.get('sale_order_id')) - - order = request.env['sale.order'].sudo().browse(sale_order_id) - tx = request.env['payment.transaction'].sudo().create({ - 'acquirer_id': acquirer.id, - 'reference': 'STRIPE-%s' % order.id, - 'amount': float(post.get('amount')), - 'currency_id': request.env['res.currency'].search([('name', '=', post.get('currency'))], limit=1).id, - 'partner_id': request.env.user.partner_id.id, - 'sale_order_id': order.id - }) - order.write({ - 'payment_acquirer_id': acquirer.id, - 'payment_tx_id': tx.id - }) - request.session['sale_transaction_id'] = tx.id + tx = request.env['payment.transaction'].sudo().browse( + int(request.session.get('sale_transaction_id') or request.session.get('website_payment_tx_id', False)) + ) response = tx._create_stripe_charge(tokenid=post['tokenid']) _logger.info('Stripe: entering form_feedback with post data %s', pprint.pformat(response)) if response: diff --git a/addons/payment_stripe/models/payment_acquirer.py b/addons/payment_stripe/models/payment_acquirer.py index 1a0f6f3ed6e..7b103fac645 100644 --- a/addons/payment_stripe/models/payment_acquirer.py +++ b/addons/payment_stripe/models/payment_acquirer.py @@ -25,8 +25,10 @@ class PaymentAcquirerStripe(models.Model): self.ensure_one() stripe_tx_values = dict(tx_values) temp_stripe_tx_values = { + 'company': self.company_id.name, 'amount': tx_values.get('amount'), 'currency': tx_values.get('currency') and tx_values.get('currency').name or '', + 'currency_id': tx_values.get('currency') and tx_values.get('currency').id or '', 'address_line1': tx_values['partner_address'], 'address_city': tx_values['partner_city'], 'address_country': tx_values['partner_country'] and tx_values['partner_country'].name or '', diff --git a/addons/payment_stripe/static/src/js/stripe.js b/addons/payment_stripe/static/src/js/stripe.js index a6cc6ad5637..73d6fbe2dd6 100644 --- a/addons/payment_stripe/static/src/js/stripe.js +++ b/addons/payment_stripe/static/src/js/stripe.js @@ -12,11 +12,6 @@ odoo.define('payment_stripe.stripe', function(require) { } }, token: function(token, args) { - var sale_order_id = $("input[name='return_url']").val().match(/quote\/([0-9]+)/); - if (sale_order_id) { - sale_order_id = parseInt(sale_order_id[1]); - } - handler.isTokenGenerate = true; ajax.jsonRpc("/payment/stripe/create_charge", 'call', { tokenid: token.id, @@ -25,8 +20,7 @@ odoo.define('payment_stripe.stripe', function(require) { acquirer_id: $("#acquirer_stripe").val(), currency: $("input[name='currency']").val(), invoice_num: $("input[name='invoice_num']").val(), - return_url: $("input[name='return_url']").val(), - sale_order_id: sale_order_id, + return_url: $("input[name='return_url']").val() }).done(function(data){ handler.isTokenGenerate = false; window.location.href = data; @@ -41,27 +35,46 @@ odoo.define('payment_stripe.stripe', function(require) { $(this).attr('disabled','disabled'); var $form = $(e.currentTarget).parents('form'); - var acquirer_id = $(e.currentTarget).closest('div.oe_sale_acquirer_button,div.oe_quote_acquirer_button').data('id'); + var acquirer_id = $(e.currentTarget).closest('div.oe_sale_acquirer_button,div.oe_quote_acquirer_button,div.o_website_payment_new_payment'); + acquirer_id = acquirer_id.data('id') || acquirer_id.data('acquirer_id'); if (! acquirer_id) { return false; } var so_token = $("input[name='token']").val(); - var so_id = $("input[name='return_url']").val().match(/quote\/([0-9]+)/); + var so_id = $("input[name='return_url']").val().match(/quote\/([0-9]+)/) || undefined; if (so_id) { so_id = parseInt(so_id[1]); } e.preventDefault(); - ajax.jsonRpc('/shop/payment/transaction/' + acquirer_id, 'call', {'so_id': so_id, 'so_token': so_token}).then(function (data) { - $form.html(data); - handler.open({ - name: $("input[name='merchant']").val(), - description: $("input[name='invoice_num']").val(), - currency: $("input[name='currency']").val(), - amount: $("input[name='amount']").val()*100 + if ($('.o_website_payment').length !== 0) { + ajax.jsonRpc('/website_payment/transaction', 'call', { + reference: $("input[name='invoice_num']").val(), + amount: $("input[name='amount']").val(), + currency_id: $("input[name='currency_id']").val(), + acquirer_id: acquirer_id + }).then(function (data) { + handler.open({ + name: $("input[name='merchant']").val(), + description: $("input[name='invoice_num']").val(), + currency: $("input[name='currency']").val(), + amount: $("input[name='amount']").val()*100 + }); }); - }); - + } else { + ajax.jsonRpc('/shop/payment/transaction/' + acquirer_id, 'call', { + so_id: so_id, + so_token: so_token + }).then(function (data) { + $form.html(data); + handler.open({ + name: $("input[name='merchant']").val(), + description: $("input[name='invoice_num']").val(), + currency: $("input[name='currency']").val(), + amount: $("input[name='amount']").val()*100 + }); + }); + } }); }); diff --git a/addons/payment_stripe/views/stripe.xml b/addons/payment_stripe/views/stripe.xml index ea089287b22..75271d509f0 100644 --- a/addons/payment_stripe/views/stripe.xml +++ b/addons/payment_stripe/views/stripe.xml @@ -4,11 +4,13 @@