[MERGE] forward port branch 10.0 up to 0ac49ee1e4

This commit is contained in:
Christophe Simonis
2017-07-11 11:05:19 +02:00
14 changed files with 70 additions and 29 deletions
+1 -1
View File
@@ -133,7 +133,7 @@ class EventEvent(models.Model):
'event.registration', 'event_id', string='Attendees', 'event.registration', 'event_id', string='Attendees',
readonly=False, states={'done': [('readonly', True)]}) readonly=False, states={'done': [('readonly', True)]})
# Date fields # Date fields
date_tz = fields.Selection('_tz_get', string='Timezone', required=True, default=lambda self: self.env.user.tz) date_tz = fields.Selection('_tz_get', string='Timezone', required=True, default=lambda self: self.env.user.tz or 'UTC')
date_begin = fields.Datetime( date_begin = fields.Datetime(
string='Start Date', required=True, string='Start Date', required=True,
track_visibility='onchange', states={'done': [('readonly', True)]}) track_visibility='onchange', states={'done': [('readonly', True)]})
+1
View File
@@ -2065,6 +2065,7 @@ class MailThread(models.AbstractModel):
partner_ids=[(4, pid) for pid in partner_ids], partner_ids=[(4, pid) for pid in partner_ids],
auto_delete=True, auto_delete=True,
auto_delete_message=True, auto_delete_message=True,
parent_id=False, # override accidental context defaults
subtype_id=self.env.ref('mail.mt_note').id) subtype_id=self.env.ref('mail.mt_note').id)
@api.multi @api.multi
+1 -1
View File
@@ -209,7 +209,7 @@ class PosOrder(models.Model):
have_to_group_by = session and session.config_id.group_by or False have_to_group_by = session and session.config_id.group_by or False
rounding_method = session and session.config_id.company_id.tax_calculation_rounding_method rounding_method = session and session.config_id.company_id.tax_calculation_rounding_method
for order in self.filtered(lambda o: not o.account_move or order.state == 'paid'): for order in self.filtered(lambda o: not o.account_move or o.state == 'paid'):
current_company = order.sale_journal.company_id current_company = order.sale_journal.company_id
account_def = IrProperty.get( account_def = IrProperty.get(
'property_account_receivable_id', 'res.partner') 'property_account_receivable_id', 'res.partner')
@@ -1109,6 +1109,7 @@ exports.Orderline = Backbone.Model.extend({
orderline.quantity = this.quantity; orderline.quantity = this.quantity;
orderline.quantityStr = this.quantityStr; orderline.quantityStr = this.quantityStr;
orderline.discount = this.discount; orderline.discount = this.discount;
orderline.price = this.price;
orderline.type = this.type; orderline.type = this.type;
orderline.selected = false; orderline.selected = false;
return orderline; return orderline;
+6 -2
View File
@@ -1405,8 +1405,12 @@
<div class="pos-center-align"><t t-esc="moment().format('L LT')"/> <t t-esc="order.name"/></div> <div class="pos-center-align"><t t-esc="moment().format('L LT')"/> <t t-esc="order.name"/></div>
<br /> <br />
<t t-esc="widget.pos.company.name"/><br /> <t t-esc="widget.pos.company.name"/><br />
Phone: <t t-esc="widget.pos.company.phone || ''"/><br /> <div class="receipt-phone">
User: <t t-esc="widget.pos.cashier ? widget.pos.cashier.name : widget.pos.user.name"/><br /> Phone: <t t-esc="widget.pos.company.phone || ''"/><br />
</div>
<div class="receipt-user">
User: <t t-esc="widget.pos.cashier ? widget.pos.cashier.name : widget.pos.user.name"/><br />
</div>
<br /> <br />
<t t-if="receipt.header"> <t t-if="receipt.header">
<div style='text-align:center'> <div style='text-align:center'>
+1 -1
View File
@@ -20,7 +20,7 @@ class ProductTemplate(models.Model):
if self._context.get('categ_id') or self._context.get('default_categ_id'): if self._context.get('categ_id') or self._context.get('default_categ_id'):
return self._context.get('categ_id') or self._context.get('default_categ_id') return self._context.get('categ_id') or self._context.get('default_categ_id')
category = self.env.ref('product.product_category_all', raise_if_not_found=False) category = self.env.ref('product.product_category_all', raise_if_not_found=False)
return category.id if category.type == 'normal' else False return category and category.type == 'normal' and category.id or False
def _get_default_uom_id(self): def _get_default_uom_id(self):
return self.env["product.uom"].search([], limit=1, order='id').id return self.env["product.uom"].search([], limit=1, order='id').id
+6 -1
View File
@@ -59,7 +59,12 @@ class SaleOrderLine(models.Model):
def _product_margin(self): def _product_margin(self):
for line in self: for line in self:
currency = line.order_id.pricelist_id.currency_id currency = line.order_id.pricelist_id.currency_id
line.margin = currency.round(line.price_subtotal - ((line.purchase_price or line.product_id.standard_price) * line.product_uom_qty)) price = line.purchase_price
if not price:
from_cur = line.env.user.company_id.currency_id.with_context(date=line.order_id.date_order)
price = from_cur.compute(line.product_id.standard_price, currency, round=False)
line.margin = currency.round(line.price_subtotal - (price * line.product_uom_qty))
class SaleOrder(models.Model): class SaleOrder(models.Model):
+4 -3
View File
@@ -128,16 +128,17 @@ class WebsiteSale(http.Controller):
(variant id, [visible attribute ids], variant price, variant sale price) (variant id, [visible attribute ids], variant price, variant sale price)
""" """
# product attributes with at least two choices # product attributes with at least two choices
product = product.with_context(quantity=1) quantity = product._context.get('quantity') or 1
product = product.with_context(quantity=quantity)
visible_attrs_ids = product.attribute_line_ids.filtered(lambda l: len(l.value_ids) > 1).mapped('attribute_id').ids visible_attrs_ids = product.attribute_line_ids.filtered(lambda l: len(l.value_ids) > 1).mapped('attribute_id').ids
to_currency = request.website.get_current_pricelist().currency_id to_currency = request.website.get_current_pricelist().currency_id
attribute_value_ids = [] attribute_value_ids = []
for variant in product.product_variant_ids: for variant in product.product_variant_ids:
if to_currency != product.currency_id: if to_currency != product.currency_id:
price = variant.currency_id.compute(variant.website_public_price, to_currency) price = variant.currency_id.compute(variant.website_public_price, to_currency) / quantity
else: else:
price = variant.website_public_price price = variant.website_public_price / quantity
visible_attribute_ids = [v.id for v in variant.attribute_value_ids if v.attribute_id.id in visible_attrs_ids] visible_attribute_ids = [v.id for v in variant.attribute_value_ids if v.attribute_id.id in visible_attrs_ids]
attribute_value_ids.append([variant.id, visible_attribute_ids, variant.website_price, price]) attribute_value_ids.append([variant.id, visible_attribute_ids, variant.website_price, price])
return attribute_value_ids return attribute_value_ids
@@ -86,23 +86,30 @@ odoo.define('website_sale.website_sale', function (require) {
$(oe_website_sale).on("change", 'input[name="add_qty"]', function (event) { $(oe_website_sale).on("change", 'input[name="add_qty"]', function (event) {
var product_ids = []; var product_ids = [];
var product_dom = $(".js_product .js_add_cart_variants[data-attribute_value_ids]").last(); var product_dom = $(".js_product .js_add_cart_variants[data-attribute_value_ids]");
var qty = $(event.target).closest('form').find('input[name="add_qty"]').val();
if (!product_dom.length) { if (!product_dom.length) {
return; return;
} }
_.each(product_dom.data("attribute_value_ids"), function(entry) { _.each(product_dom, function (prod) {
product_ids.push(entry[0]);}); _.each($(prod).data("attribute_value_ids"), function(entry) {
var qty = $(event.target).closest('form').find('input[name="add_qty"]').val(); if (product_ids.indexOf(entry[0]) === -1) {
product_ids.push(entry[0]);
}
});
});
if ($("#product_detail").length) { if ($("#product_detail").length) {
// display the reduction from the pricelist in function of the quantity // display the reduction from the pricelist in function of the quantity
ajax.jsonRpc("/shop/get_unit_price", 'call', {'product_ids': product_ids,'add_qty': parseInt(qty)}) ajax.jsonRpc("/shop/get_unit_price", 'call', {'product_ids': product_ids,'add_qty': parseInt(qty)})
.then(function (data) { .then(function (data) {
var current = product_dom.data("attribute_value_ids"); _.each(product_dom, function (prod) {
for(var j=0; j < current.length; j++){ var current = $(prod).data("attribute_value_ids");
current[j][2] = data[current[j][0]]; for(var j=0; j < current.length; j++){
} current[j][2] = data[current[j][0]];
product_dom.attr("data-attribute_value_ids", JSON.stringify(current)).trigger("change"); }
$(prod).trigger("change");
});
}); });
} }
}); });
@@ -296,17 +303,18 @@ odoo.define('website_sale.website_sale', function (require) {
$(oe_website_sale).on('change', 'input.js_variant_change, select.js_variant_change, ul[data-attribute_value_ids]', function (ev) { $(oe_website_sale).on('change', 'input.js_variant_change, select.js_variant_change, ul[data-attribute_value_ids]', function (ev) {
var $ul = $(ev.target).closest('.js_add_cart_variants'); var $ul = $(ev.target).closest('.js_add_cart_variants');
var $parent = $ul.closest('.js_product'); var $parent = $ul.closest('.js_product');
var $product_id = $parent.find('input.product_id').first(); var $product_id = $parent.find('.product_id').first();
var $price = $parent.find(".oe_price:first .oe_currency_value") var $price = $parent.find(".oe_price:first .oe_currency_value");
.add($('#product_confirmation').find(".oe_price")); var $default_price = $parent.find(".oe_default_price:first .oe_currency_value");
var $default_price = $parent.find(".oe_default_price:first .oe_currency_value")
.add($('#product_confirmation').find(".oe_default_price:first .oe_currency_value"));
var $optional_price = $parent.find(".oe_optional:first .oe_currency_value"); var $optional_price = $parent.find(".oe_optional:first .oe_currency_value");
var variant_ids = $ul.data("attribute_value_ids"); var variant_ids = $ul.data("attribute_value_ids");
var values = []; var values = [];
var unchanged_values = $parent.find('div.oe_unchanged_value_ids').data('unchanged_value_ids') || [];
$parent.find('input.js_variant_change:checked, select.js_variant_change').each(function () { $parent.find('input.js_variant_change:checked, select.js_variant_change').each(function () {
values.push(+$(this).val()); values.push(+$(this).val());
}); });
values = values.concat(unchanged_values);
$parent.find("label").removeClass("text-muted css_not_available"); $parent.find("label").removeClass("text-muted css_not_available");
@@ -320,8 +328,10 @@ odoo.define('website_sale.website_sale', function (require) {
if (variant_ids[k][3]-variant_ids[k][2]>0.01) { if (variant_ids[k][3]-variant_ids[k][2]>0.01) {
$default_price.closest('.oe_website_sale').addClass("discount"); $default_price.closest('.oe_website_sale').addClass("discount");
$optional_price.closest('.oe_optional').show().css('text-decoration', 'line-through'); $optional_price.closest('.oe_optional').show().css('text-decoration', 'line-through');
$default_price.parent().removeClass('hidden');
} else { } else {
$optional_price.closest('.oe_optional').hide(); $optional_price.closest('.oe_optional').hide();
$default_price.parent().addClass('hidden');
} }
product_id = variant_ids[k][0]; product_id = variant_ids[k][0];
update_product_image(this, product_id); update_product_image(this, product_id);
+2 -1
View File
@@ -449,7 +449,8 @@
<div class="col-sm-5 col-lg-4 col-lg-offset-1" id="product_details"> <div class="col-sm-5 col-lg-4 col-lg-offset-1" id="product_details">
<h1 itemprop="name" t-field="product.name">Product Name</h1> <h1 itemprop="name" t-field="product.name">Product Name</h1>
<span itemprop="url" style="display:none;" t-esc="'/shop/product/%s' % slug(product)" /> <span itemprop="url" style="display:none;" t-esc="'/shop/product/%s' % slug(product)" />
<form action="/shop/cart/update" class="js_add_cart_variants" t-att-data-attribute_value_ids="product.product_variant_ids.ids" method="POST"> <t t-set="attribute_value_ids" t-value="get_attribute_value_ids(product)"/>
<form action="/shop/cart/update" class="js_add_cart_variants" t-att-data-attribute_value_ids="attribute_value_ids" method="POST">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" /> <input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
<div class="js_product" t-if="product.product_variant_ids"> <div class="js_product" t-if="product.product_variant_ids">
<t t-placeholder="select"> <t t-placeholder="select">
@@ -54,6 +54,7 @@ class WebsiteSaleOptions(WebsiteSale):
def modal(self, product_id, **kw): def modal(self, product_id, **kw):
pricelist = request.website.get_current_pricelist() pricelist = request.website.get_current_pricelist()
product_context = dict(request.context) product_context = dict(request.context)
quantity = kw['kwargs']['context']['quantity']
if not product_context.get('pricelist'): if not product_context.get('pricelist'):
product_context['pricelist'] = pricelist.id product_context['pricelist'] = pricelist.id
# fetch quantity from custom context # fetch quantity from custom context
@@ -63,8 +64,18 @@ class WebsiteSaleOptions(WebsiteSale):
to_currency = pricelist.currency_id to_currency = pricelist.currency_id
compute_currency = lambda price: request.env['res.currency']._compute(from_currency, to_currency, price) compute_currency = lambda price: request.env['res.currency']._compute(from_currency, to_currency, price)
product = request.env['product.product'].with_context(product_context).browse(int(product_id)) product = request.env['product.product'].with_context(product_context).browse(int(product_id))
main_product_attr_ids = self.get_attribute_value_ids(product)
for variant in main_product_attr_ids:
if variant[0] == product.id:
# We indeed need a list of lists (even with only 1 element)
main_product_attr_ids = [variant]
break
return request.env['ir.ui.view'].render_template("website_sale_options.modal", { return request.env['ir.ui.view'].render_template("website_sale_options.modal", {
'product': product, 'product': product,
'quantity': quantity,
'compute_currency': compute_currency, 'compute_currency': compute_currency,
'get_attribute_value_ids': self.get_attribute_value_ids, 'get_attribute_value_ids': self.get_attribute_value_ids,
'main_product_attr_ids': main_product_attr_ids,
}) })
@@ -15,3 +15,8 @@ div#modal_optional_products table tr td {
display: none; display: none;
} }
} }
.oe_striked_price {
text-decoration: line-through;
white-space: nowrap;
}
@@ -85,7 +85,7 @@ $('.oe_website_sale #add_to_cart, .oe_website_sale #products_grid .a-submit')
var product_id = $($modal.find('span.oe_price[data-product-id]')).first().data('product-id'); var product_id = $($modal.find('span.oe_price[data-product-id]')).first().data('product-id');
var product_ids = [product_id]; var product_ids = [product_id];
var $products_dom = []; var $products_dom = [];
$modal.find(".js_add_cart_variants[data-attribute_value_ids]").each(function(){ $("ul.js_add_cart_variants[data-attribute_value_ids]").each(function(){
var $el = $(this); var $el = $(this);
$products_dom.push($el); $products_dom.push($el);
_.each($el.data("attribute_value_ids"), function (values) { _.each($el.data("attribute_value_ids"), function (values) {
@@ -42,7 +42,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr id="product_confirmation"> <tr id="product_confirmation" class="js_product">
<td class='td-img'> <td class='td-img'>
<span t-field="product.image_medium" t-options='{"widget": "image" }'/> <span t-field="product.image_medium" t-options='{"widget": "image" }'/>
</td> </td>
@@ -65,16 +65,18 @@
</div> </div>
</td> </td>
<td class="text-center td-price" name="price"> <td class="text-center td-price" name="price">
<span t-attf-class="text-danger oe_default_price" style="text-decoration: line-through; white-space: nowrap;" <ul class="hidden js_add_cart_variants" t-att-data-attribute_value_ids="main_product_attr_ids"></ul>
<div class="hidden oe_unchanged_value_ids" t-att-data-unchanged_value_ids="main_product_attr_ids[0][1]" ></div>
<span t-attf-class="text-danger oe_default_price oe_striked_price {{ (compute_currency(product.lst_price) - product.website_price) &lt; 0.01 and 'hidden' }}"
t-field="product.lst_price" t-field="product.lst_price"
t-options='{ t-options='{
"widget": "monetary", "widget": "monetary",
"from_currency": product.currency_id, "from_currency": product.currency_id,
"display_currency": website.currency_id "display_currency": website.currency_id
}'/> }'/>
<span class="oe_price" style="white-space: nowrap;" <span class="oe_price product_id" style="white-space: nowrap;"
t-att-data-product-id="product.id" t-att-data-product-id="product.id"
t-field="product.with_context(quantity=1).website_price" t-esc="product.website_price / quantity"
t-options='{ t-options='{
"widget": "monetary", "widget": "monetary",
"display_currency": website.currency_id "display_currency": website.currency_id