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') diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index aef88b59e87..020f1d42efd 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) @@ -1125,7 +1125,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 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 4dad6b15e5f..4b88cb511ed 100644 --- a/addons/payment_stripe/models/payment_acquirer.py +++ b/addons/payment_stripe/models/payment_acquirer.py @@ -29,8 +29,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 df49240f7fc..5d0fa66ff23 100644 --- a/addons/payment_stripe/static/src/js/stripe.js +++ b/addons/payment_stripe/static/src/js/stripe.js @@ -13,11 +13,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, @@ -26,8 +21,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; @@ -42,27 +36,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 978f1ffea42..b92182b852d 100644 --- a/addons/payment_stripe/views/stripe.xml +++ b/addons/payment_stripe/views/stripe.xml @@ -11,6 +11,7 @@ + diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py index 40931e54006..4b41e10361b 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 @@ -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): @@ -646,6 +647,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 @@ - + diff --git a/addons/website_sale/static/src/js/website_sale.js b/addons/website_sale/static/src/js/website_sale.js index c6ab7952701..305b5840325 100644 --- a/addons/website_sale/static/src/js/website_sale.js +++ b/addons/website_sale/static/src/js/website_sale.js @@ -121,7 +121,7 @@ odoo.define('website_sale.website_sale', function (require) { 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)'); @@ -140,7 +140,7 @@ odoo.define('website_sale.website_sale', function (require) { '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; } @@ -186,7 +186,7 @@ odoo.define('website_sale.website_sale', function (require) { 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"])'); diff --git a/openerp/tools/mail.py b/openerp/tools/mail.py index 3714df9c56f..934d9c15b15 100644 --- a/openerp/tools/mail.py +++ b/openerp/tools/mail.py @@ -52,14 +52,14 @@ class _Cleaner(clean.Cleaner): def __call__(self, doc): # perform quote detection before cleaning and class removal - for el in doc.iter(): + for el in doc.iter(tag=etree.Element): self.tag_quote(el) super(_Cleaner, self).__call__(doc) # if we keep style attribute, sanitize them if not self.style: - for el in doc.iter(): + for el in doc.iter(tag=etree.Element): self.parse_style(el) def tag_quote(self, el):