This commit is contained in:
Christophe Matthieu 2014-06-24 17:37:13 +02:00
parent 204a62499a
commit 7505cce2e9
16 changed files with 328 additions and 292 deletions

View File

@ -216,7 +216,7 @@ class website_sale(http.Controller):
product = template_obj.browse(cr, uid, int(product), context=context)
attribute_value_ids = []
if request.website.company_pricelist_id.id != context['pricelist']:
if request.website.pricelist_id.id != context['pricelist']:
company_currency_id = request.website.company_currency_id.id
currency_id = self.get_pricelist().currency_id.id
for p in product.product_variant_ids:
@ -289,12 +289,11 @@ class website_sale(http.Controller):
@http.route(['/shop/cart/update_json'], type='json', auth="public", methods=['POST'], website=True)
def cart_update_json(self, product_id, line_id, add_qty=None, set_qty=None, display=True):
order = request.website.sale_get_order(force_create=1)
line_id, quantity, option_ids = order._cart_update(product_id=product_id, line_id=line_id, add_qty=add_qty, set_qty=set_qty)
line_id, quantity = order._cart_update(product_id=product_id, line_id=line_id, add_qty=add_qty, set_qty=set_qty)
if not display:
return None
return {
'quantity': quantity,
'option_ids': option_ids,
'cart_quantity': order.cart_quantity,
'website_sale.total': request.website._render("website_sale.total", {
'website_sale_order': request.website.sale_get_order()

View File

@ -132,7 +132,6 @@ class product_template(osv.Model):
'website_sequence': fields.integer('Sequence', help="Determine the display order in the Website E-commerce"),
'website_url': fields.function(_website_url, string="Website url", type="char"),
'public_categ_ids': fields.many2many('product.public.category', string='Public Category', help="Those categories are used to group similar products for e-commerce."),
'optional_product_ids': fields.many2many('product.template','product_optional_rel','src_id','dest_id',string='Optional Products', help="Products to propose when add to cart."),
}
def _defaults_website_sequence(self, cr, uid, *l, **kwargs):

View File

@ -51,18 +51,12 @@ class sale_order(osv.Model):
'order': order
}
def _cart_find_product_line(self, cr, uid, ids, product_id=None, line_id=None, context=None):
def _cart_find_product_line(self, cr, uid, ids, product_id=None, line_id=None, context=None, *args):
for so in self.browse(cr, uid, ids, context=context):
order_line_id = None
domain = [('order_id', '=', so.id), ('product_id', '=', product_id)]
if line_id:
domain += [('id', '=', line_id)]
order_line_ids = self.pool.get('sale.order.line').search(cr, SUPERUSER_ID, domain, context=context)
if order_line_ids:
order_line_id = order_line_ids[0]
return order_line_id
return self.pool.get('sale.order.line').search(cr, SUPERUSER_ID, domain, context=context)
def _website_product_id_change(self, cr, uid, ids, order_id, product_id, line_id=None, context=None):
so = self.pool.get('sale.order').browse(cr, uid, order_id, context=context)
@ -87,13 +81,16 @@ class sale_order(osv.Model):
values['tax_id'] = [(6, 0, values['tax_id'])]
return values
def _cart_update(self, cr, uid, ids, product_id=None, line_id=None, add_qty=0, set_qty=0, linked_line_id=None, optional_product_ids=None, context=None):
def _cart_update(self, cr, uid, ids, product_id=None, line_id=None, add_qty=0, set_qty=0, context=None, *args):
""" Add or set product quantity, add_qty can be negative """
sol = self.pool.get('sale.order.line')
quantity = 0
for so in self.browse(cr, uid, ids, context=context):
line_id = so._cart_find_product_line(product_id, line_id, context=context)
if line_id != False:
line_ids = so._cart_find_product_line(product_id, line_id, context=context, *args)
if line_ids:
line_id = line_ids[0]
# Create line if no line with product_id can be located
if not line_id:
@ -132,9 +129,7 @@ class website(orm.Model):
_columns = {
'pricelist_id': fields.related('user_id','partner_id','property_product_pricelist',
type='many2one', relation='product.pricelist', string='Default pricelist'),
'company_pricelist_id': fields.related('company_id','partner_id','property_product_pricelist',
type='many2one', relation='product.pricelist', string='Default pricelist'),
'company_currency_id': fields.related('company_pricelist_id','currency_id',
'currency_id': fields.related('pricelist_id','currency_id',
type='many2one', relation='res.currency', string='Default pricelist'),
}
@ -230,7 +225,7 @@ class website(orm.Model):
})
def compute_curency(self, cr, uid, ids, from_amount, from_currency_id=None, context=None):
from_currency_id = from_currency_id or self.browse(cr, SUPERUSER_ID, ids[0]).company_currency_id.id
from_currency_id = from_currency_id or self.browse(cr, SUPERUSER_ID, ids[0]).currency_id.id
to_currency_id = self.pool.get("res.users").browse(cr, uid, uid).partner_id.property_product_pricelist.currency_id.id
return self.pool['res.currency'].compute(cr, uid, from_currency_id, to_currency_id, from_amount, context=context)

View File

@ -1,80 +1,5 @@
(function () {
'use strict';
openerp.Tour.register({
id: 'shop_customize',
name: "Customize the page and search a product",
path: '/shop',
mode: 'test',
steps: [
{
title: "open customize menu",
element: '#customize-menu-button',
},
{
title: "click on 'Product Attribute's Filters'",
element: "#customize-menu a:contains(Product Attribute's Filters)",
},
{
title: "select product attribute memory 16 Go",
waitNot: '#customize-menu:visible',
element: 'form.js_attributes label:contains(16 Go) input:not(:checked)',
},
{
title: "check the selection",
waitFor: 'form.js_attributes label:contains(16 Go) input:checked',
},
{
title: "select iPod",
waitNot: '.oe_website_sale .oe_product_cart:eq(2)',
element: '.oe_product_cart a:contains("iPod")',
},
{
title: "open customize menu 2",
waitFor: 'form[action^="/shop/cart/update"] label:contains(32 Go) input',
element: '#customize-menu-button',
},
{
title: "click on 'Confirm: Add To Cart'",
element: "#customize-menu a:contains(Confirm: Add To Cart)",
},
{
title: "click on 'Add to Cart' button",
waitNot: '#customize-menu:visible',
element: "a[data-toggle='modal']:contains(Add to Cart)",
},
{
title: "click in modal on 'Proceed to checkout' button",
element: '.modal a:contains("Proceed to checkout")',
},
{
title: "return to the iPod product",
waitFor: '#cart_products',
element: "a:contains(iPod)",
},
{
title: "open customize menu 3",
waitFor: 'form[action^="/shop/cart/update"] label:contains(32 Go) input',
element: '#customize-menu-button',
},
{
title: "click on 'Confirm: Add To Cart'",
element: "#customize-menu a:contains(Confirm: Add To Cart)",
},
{
title: "click on 'My Cart'",
waitFor: "a.a-submit:contains(Add to Cart)",
element: "a[href='/shop/cart']",
},
{
title: "remove iPod from cart",
element: '#cart_products a.js_add_cart_json:first',
},
{
title: "finish",
waitFor: '.my_cart_quantity:contains(1)',
},
]
});
openerp.Tour.register({
id: 'shop_buy_product',

View File

@ -85,7 +85,7 @@ $(document).ready(function () {
$('input.js_variant_change, select.js_variant_change').change(function (ev) {
var $ul = $(this).parents('ul.js_add_cart_variants:first');
var $parent = $ul.parents('.js_product:first');
var $porduct_id = $parent.find('input.product_id, input.optional_product_id').first();
var $product_id = $parent.find('input.product_id').first();
var $price = $parent.find(".oe_price:first .oe_currency_value");
var $default_price = $parent.find(".oe_default_price:first .oe_currency_value");
var variant_ids = $ul.data("attribute_value_ids");
@ -127,11 +127,11 @@ $(document).ready(function () {
if (product_id) {
$parent.removeClass("css_not_available");
$porduct_id.val(product_id);
$product_id.val(product_id);
$parent.find(".js_check_product").removeAttr("disabled");
} else {
$parent.addClass("css_not_available");
$porduct_id.val(0);
$product_id.val(0);
$parent.find(".js_check_product").attr("disabled", "disabled");
}
});
@ -139,32 +139,6 @@ $(document).ready(function () {
$('input.js_variant_change, select.js_variant_change', this).first().trigger('change');
});
$('#modal_optional_products').on('show.bs.modal', function () {
var $confirm = $('#product_confirmation .js_attributes');
if (!$confirm.size()) return;
$confirm.empty();
$('.js_add_cart_variants:first ul:first > li').each(function () {
var $li = $(this);
var $span = $("<div><span></span>: <span></span></div>");
var attr = $li.children().first().text();
var value = $li.find("label:has(input:checked) span:first").text();
if (!/\S/.test(value)) {
value = $li.find("label:has(input:checked) input").attr("title");
}
$span.children().first().text( attr );
$span.children().last().text( value );
$confirm.append($span);
});
});
$("a.js_add, a.js_remove").click(function (event) {
event.preventDefault();
var $parent = $(this).parents('.js_product:first');
$parent.find("a.js_add, span.js_remove").toggleClass("hidden");
$parent.find("input.js_optional_same_quantity").val( $(this).hasClass("js_add") ? 1 : 0 );
var $remove = $parent.find(".js_remove");
});
$("input.js_quantity").change(function (event) {
var qty = parseFloat($(this).val());
if (qty === 1) {

View File

@ -12,7 +12,6 @@ inject = [
class TestUi(openerp.tests.HttpCase):
def test_01_admin_shop_tour(self):
self.phantom_js("/", "openerp.Tour.run('shop', 'test')", "openerp.Tour.tours.shop", login="admin")
self.phantom_js("/", "openerp.Tour.run('shop_customize', 'test')", "openerp.Tour.tours.shop_customize", login="admin", inject=inject)
def test_02_admin_checkout(self):
self.phantom_js("/", "openerp.Tour.run('shop_buy_product', 'test')", "openerp.Tour.tours.shop_buy_product", login="admin", inject=inject)

View File

@ -393,79 +393,7 @@
<t t-call="website_sale.product_price"/>
<p t-if="len(product.product_variant_ids) > 1" class="css_not_available_msg bg-danger" style="padding: 15px;">Product not available</p>
<a class="btn btn-primary btn-lg mt8 js_check_product" href="#" data-toggle="modal" data-target="#modal_optional_products">Add to Cart</a>
</div>
<div id="modal_optional_products" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
<h4 class="modal-title" id="myModalLabel">Product to add in your shopping cart</h4>
</div>
<div class="modal-body">
<table class="table table-striped table-condensed">
<thead>
<tr>
<th colspan="2">Product</th>
<th style="min-width: 140px;"> </th>
<th width="100">Price</th>
<th width="120">Quantity</th>
</tr>
</thead>
<tbody>
<tr id="product_confirmation">
<td width="100">
<span t-field="product.image_medium" t-field-options='{"widget": "image" }'/>
</td>
<td colspan="2">
<strong t-field="product.name"/>
<div class="text-muted">
<div t-field="product.description_sale"/>
<div class="js_attributes"/>
</div>
</td>
<td>
<span t-attf-class="text-danger oe_default_price" t-att-style="'' if (website.compute_curency(product.lst_price) - product.price) &gt; 0.1 else 'display: none;'" style="text-decoration: line-through; white-space: nowrap;"
t-field="product.lst_price"
t-field-options='{
"widget": "monetary",
"from_currency": "website.company_currency_id",
"display_currency": "user_id.partner_id.property_product_pricelist.currency_id"
}'/><br/>
<span class="oe_price" style="white-space: nowrap;"
t-field="product.price"
t-field-options='{
"widget": "monetary",
"from_currency": "website.company_currency_id",
"display_currency": "user_id.partner_id.property_product_pricelist.currency_id"
}'/>
</td>
<td>
<div class="input-group">
<span class="input-group-addon">
<a t-attf-href="#" class="mb8 js_add_cart_json">
<i class="fa fa-minus"></i>
</a>
</span>
<input type="text" class="js_quantity form-control" data-min="1" name="add_qty" value="1"/>
<span class="input-group-addon">
<a t-attf-href="#" class="mb8 float_left js_add_cart_json">
<i class="fa fa-plus"></i>
</a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<a class="btn btn-default a-submit js_goto_shop"><i class="fa fa-chevron-left"></i> Continue shopping</a>
<a class="btn btn-primary pull-right a-submit"><i class="fa fa-shopping-cart fa-fw"></i> Proceed to checkout</a>
</div>
</div>
</div>
<a id="add_to_cart" class="btn btn-primary btn-lg mt8 js_check_product a-submit" href="#">Add to Cart</a>
</div>
</form>
@ -488,7 +416,7 @@
</template>
<template id="product_quantity" inherit_id="website_sale.product" optional="enabled" name="Select Quantity">
<xpath expr="//a[@data-target='#modal_optional_products']" position="before">
<xpath expr="//form" position="inside">
<div class="css_quantity input-group" style="width: 108px;">
<span class="input-group-addon">
<a t-attf-href="#" class="mb8 js_add_cart_json">

View File

@ -4,7 +4,6 @@ from openerp import SUPERUSER_ID
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models.website import slug
from openerp.addons.website_sale.controllers.main import QueryURL
from openerp.addons.website_sale.controllers.main import website_sale
class website_sale_options(website_sale):
@ -23,11 +22,12 @@ class website_sale_options(website_sale):
r.qcontext['optional_product_ids'] = optional_product_ids
return r
def cart_update(self, product_id, add_qty=1, set_qty=0, goto_shop=None, **kw):
@http.route(['/shop/cart/update_option_json'], type='json', auth="public", methods=['POST'], website=True)
def cart_options_update_json(self, product_id, add_qty=1, set_qty=0, goto_shop=None, **kw):
cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
order = request.website.sale_get_order(force_create=1)
prod_obj = pool['product.product']
line_id = None
optional_product_ids = []
for k, v in kw.items():
if "optional-product-" in k and int(kw.get(k.replace("product", "quantity"))):
@ -36,11 +36,16 @@ class website_sale_options(website_sale):
line_id, quantity = order._cart_update(product_id=int(product_id),
add_qty=int(add_qty), set_qty=int(set_qty),
optional_product_ids=optional_product_ids)
# options have all time the same quantity
for option_id in optional_product_ids:
order._cart_update(product_id=option_id, set_qty=value.get('quantity'), linked_line_id=value.get('line_id'))
order._cart_update(product_id=option_id, set_qty=quantity, linked_line_id=line_id)
return {
'quantity': quantity,
'cart_quantity': order.cart_quantity,
'website_sale.total': request.website._render("website_sale.total", {
'website_sale_order': request.website.sale_get_order()
})
}
if goto_shop:
return request.redirect("/shop/product/%s" % slug(prod_obj.browse(cr, uid, product_id).product_tmpl_id))
else:
return request.redirect("/shop/cart")

View File

@ -1 +1,2 @@
import product
import sale_order

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
from openerp import tools
from openerp.osv import osv, fields
class product_template(osv.Model):
_inherit = "product.template"
_columns = {
'optional_product_ids': fields.many2many('product.template','product_optional_rel','src_id','dest_id',string='Optional Products', help="Products to propose when add to cart."),
}

View File

@ -2,17 +2,19 @@
from openerp import SUPERUSER_ID
from openerp.osv import osv, orm, fields
from openerp.addons.web.http import request
from openerp.tools.translate import _
class sale_order(osv.Model):
_inherit = "sale.order"
def _cart_find_product_line(self, cr, uid, ids, product_id=None, line_id=None, linked_line_id=None, optional_product_ids=None, context=None):
for so in self.browse(cr, uid, ids, context=context):
def _cart_find_product_line(self, cr, uid, ids, product_id=None, line_id=None, context=None, *args):
line_ids = super(sale_order, self)._cart_find_product_line(cr, uid, ids, product_id, line_id, context=context)
linked_line_id = args.get('linked_line_id')
optional_product_ids = args.get('optional_product_ids')
domain = [('order_id', '=', so.id), ('product_id', '=', product_id)]
for so in self.browse(cr, uid, ids, context=context):
domain = [('order_id', '=', so.id), ('product_id', '=', product_id), ('id', 'in', line_ids)]
if line_id:
domain += [('id', '=', line_id)]
domain += linked_line_id and [('linked_line_id', '=', linked_line_id)] or [('linked_line_id', '=', False)]
@ -22,51 +24,35 @@ class sale_order(osv.Model):
else:
domain += [('option_line_ids', '=', False)]
order_line_id = None
order_line_ids = self.pool.get('sale.order.line').search(cr, SUPERUSER_ID, domain, context=context)
if order_line_ids:
order_line_id = order_line_ids[0]
return order_line_id
return self.pool.get('sale.order.line').search(cr, SUPERUSER_ID, domain, context=context)
def _cart_update(self, cr, uid, ids, product_id=None, line_id=None, add_qty=0, set_qty=0, linked_line_id=None, optional_product_ids=None, context=None):
def _cart_update(self, cr, uid, ids, product_id=None, line_id=None, add_qty=0, set_qty=0, context=None, *args):
""" Add or set product quantity, add_qty can be negative """
line_id, quantity = super(sale_order, self)._cart_update(cr, uid, ids, product_id, line_id, add_qty, set_qty, context=context, *args)
linked_line_id = args.get('linked_line_id')
sol = self.pool.get('sale.order.line')
quantity = 0
for so in self.browse(cr, uid, ids, context=context):
line_id = so._cart_find_product_line(product_id, line_id, linked_line_id, optional_product_ids, context=context)
values = {}
# Create line if no line with product_id can be located
if not line_id:
values = self._website_product_id_change(cr, uid, ids, so.id, product_id, context=context)
if linked_line_id and linked_line_id in map(int,so.order_line):
values["linked_line_id"] = linked_line_id
linked = sol.browse(cr, SUPERUSER_ID, linked_line_id, context=context)
values["name"] = _("%s\nLinked to: %s") % (values["name"], linked.product_id.name_get()[0][1])
line_id = sol.create(cr, SUPERUSER_ID, values, context=context)
if add_qty:
add_qty -= 1
# compute new quantity
if set_qty:
quantity = set_qty
elif add_qty != None:
quantity = sol.browse(cr, SUPERUSER_ID, line_id, context=context).product_uom_qty + (add_qty or 0)
if linked_line_id and linked_line_id in map(int,so.order_line):
linked = sol.browse(cr, SUPERUSER_ID, linked_line_id, context=context)
sol.write(cr, SUPERUSER_ID, [line_id], {
"name": _("%s\nOption for: %s") % (values["name"], linked.product_id.name_get()[0][1]),
"linked_line_id": linked_line_id
}, context=context)
# select linked product
option_ids = [line.id for line in so.order_line if line.linked_line_id.id == line_id]
# Remove zero of negative lines
if quantity <= 0:
sol.unlink(cr, SUPERUSER_ID, [line_id] + option_ids, context=context)
else:
# update line
values = self._website_product_id_change(cr, uid, ids, so.id, product_id, line_id, context=context)
values['product_uom_qty'] = quantity
sol.write(cr, SUPERUSER_ID, [line_id], values, context=context)
# change quantity of linked product
if option_ids:
sol.write(cr, SUPERUSER_ID, option_ids, {'product_uom_qty': quantity}, context=context)
if option_ids:
# Remove zero of negative lines
if quantity <= 0:
sol.unlink(cr, SUPERUSER_ID, option_ids, context=context)
else:
# update line
sol.write(cr, SUPERUSER_ID, option_ids, {
'product_uom_qty': quantity
}, context=context)
return (line_id, quantity)

View File

@ -1 +1,38 @@
$(document).ready(function () {
$('#add_to_cart').click(function (event) {
event.preventDefault();
openerp.jsonRpc("/shop/cart/update_json", 'call', {
'line_id': parseInt($input.data('line-id'),10),
'product_id': parseInt($input.data('product-id'),10),
'set_qty': value})
.then(function (data) {
if (!data.quantity) {
location.reload();
return;
}
if (data.option_ids.length) {
_.each(data.option_ids, function (line_id) {
$(".js_quantity[data-line-id="+line_id+"]").text(data.quantity);
});
}
var $q = $(".my_cart_quantity");
$q.parent().parent().removeClass("hidden", !data.quantity);
$q.html(data.cart_quantity).hide().fadeIn(600);
$input.val(data.quantity);
$("#cart_total").replaceWith(data['website_sale.total']);
});
return false;
});
$('form:has(#add_to_cart)').submit(function (event) {
event.preventDefault();
$(this).ajaxSubmit({
beforeSubmit: function () { console.log("beforeSubmit"); },
success: function () { console.log("success"); },
url: '/stqdfdsfdf'
});
return false;
});
});

View File

@ -0,0 +1,80 @@
(function () {
'use strict';
openerp.Tour.register({
id: 'shop_customize',
name: "Customize the page and search a product",
path: '/shop',
mode: 'test',
steps: [
{
title: "open customize menu",
element: '#customize-menu-button',
},
{
title: "click on 'Product Attribute's Filters'",
element: "#customize-menu a:contains(Product Attribute's Filters)",
},
{
title: "select product attribute memory 16 Go",
waitNot: '#customize-menu:visible',
element: 'form.js_attributes label:contains(16 Go) input:not(:checked)',
},
{
title: "check the selection",
waitFor: 'form.js_attributes label:contains(16 Go) input:checked',
},
{
title: "select iPod",
waitNot: '.oe_website_sale .oe_product_cart:eq(2)',
element: '.oe_product_cart a:contains("iPod")',
},
{
title: "open customize menu 2",
waitFor: 'form[action^="/shop/cart/update"] label:contains(32 Go) input',
element: '#customize-menu-button',
},
{
title: "click on 'Confirm: Add To Cart'",
element: "#customize-menu a:contains(Confirm: Add To Cart)",
},
{
title: "click on 'Add to Cart' button",
waitNot: '#customize-menu:visible',
element: "a[data-toggle='modal']:contains(Add to Cart)",
},
{
title: "click in modal on 'Proceed to checkout' button",
element: '.modal a:contains("Proceed to checkout")',
},
{
title: "return to the iPod product",
waitFor: '#cart_products',
element: "a:contains(iPod)",
},
{
title: "open customize menu 3",
waitFor: 'form[action^="/shop/cart/update"] label:contains(32 Go) input',
element: '#customize-menu-button',
},
{
title: "click on 'Confirm: Add To Cart'",
element: "#customize-menu a:contains(Confirm: Add To Cart)",
},
{
title: "click on 'My Cart'",
waitFor: "a.a-submit:contains(Add to Cart)",
element: "a[href='/shop/cart']",
},
{
title: "remove iPod from cart",
element: '#cart_products a.js_add_cart_json:first',
},
{
title: "finish",
waitFor: '.my_cart_quantity:contains(1)',
},
]
});
}());

View File

@ -0,0 +1 @@
import customize_test

View File

@ -0,0 +1,14 @@
import os
import openerp.tests
inject = [
("openerp.Tour", os.path.join(os.path.dirname(__file__), '../../web/static/src/js/tour.js')),
("openerp.Tour.ShopTest", os.path.join(os.path.dirname(__file__), "../static/src/js/website.tour.sale.js")),
]
@openerp.tests.common.at_install(False)
@openerp.tests.common.post_install(True)
class TestUi(openerp.tests.HttpCase):
def test_01_admin_shop_tour(self):
self.phantom_js("/", "openerp.Tour.run('shop_customize', 'test')", "openerp.Tour.tours.shop_customize", login="admin", inject=inject)

View File

@ -2,55 +2,138 @@
<openerp>
<data>
<template id="optional_products" inherit_id="website_sale.product" name="Optional Products">
<xpath expr="//tr[@id='product_confirmation']" position="after">
<tr t-if="optional_product_ids"><td colspan="4"><h4>Select Your Options:</h4></td></tr>
<t t-set="option_inc" t-value="0"/>
<tr class="js_product" t-foreach="optional_product_ids" t-as="product">
<td width="100">
<input type="hidden" class="optional_product_id" t-attf-name="optional-product-#{option_inc}" t-att-value="int(product.product_variant_ids[0]) if len(product.product_variant_ids) == 1 else '0'"/>
<span t-field="product.image_small" t-field-options='{"widget": "image"}'/>
</td>
<td>
<div class="pull-left">
<strong class="media-heading" t-field="product.name"/>
<div class="text-muted" t-field="product.description_sale"/>
</div>
</td>
<td>
<div class="pull-right">
<t t-call="website_sale.variants"/>
</div>
</td>
<td>
<t t-if="(website.compute_curency(product.lst_price) - product.price) &gt; 0.1">
<span class="text-danger" style="text-decoration: line-through; white-space: nowrap;"
t-field="product.lst_price"
t-field-options='{
"widget": "monetary",
"from_currency": "website.company_currency_id",
"display_currency": "user_id.partner_id.property_product_pricelist.currency_id"
}'/><br/>
</t>
<span class="oe_price" style="white-space: nowrap;"
t-field="product.price"
t-field-options='{
"widget": "monetary",
"display_currency": "user_id.partner_id.property_product_pricelist.currency_id"
}'/>
<p class="css_not_available_msg bg-danger" style="position:absolute; padding: 15px;">Product not available</p>
</td>
<td>
<input type="hidden" class="js_optional_same_quantity" t-attf-name="optional-quantity-#{option_inc}" value="0"/>
<a href="#" class="js_add"><strong>Add to Cart</strong></a>
<span class="js_remove hidden">
<span class="js_item">1 Item</span><span class="js_items hidden">5 Items</span><br/>
<a href="#" class="js_remove"><small>Remove from cart</small></a>
</span>
</td>
</tr>
<template id="debugger" inherit_id="website.debugger" name="Event Debugger">
<xpath expr='//t[@t-set="debugger_hook"]' position="after">
<script type="text/javascript" src="/website_sale_options/static/src/js/website_sale.test.js"></script>
</xpath>
</template>
<template id="product_options_script" inherit_id="website_sale.product" name="Script for Options">
<xpath expr="//t[@t-set='head']" position="inside">
<script type="text/javascript" src="/website_sale_options/static/src/js/website_sale.js"></script>
</xpath>
</template>
<template id="optional_products" name="Optional Products">
<div id="modal_optional_products" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
<h4 class="modal-title" id="myModalLabel">Product to add in your shopping cart</h4>
</div>
<div class="modal-body">
<table class="table table-striped table-condensed">
<thead>
<tr>
<th colspan="2">Product</th>
<th style="min-width: 140px;"> </th>
<th width="100">Price</th>
<th width="120">Quantity</th>
</tr>
</thead>
<tbody>
<tr id="product_confirmation">
<td width="100">
<span t-field="product.image_medium" t-field-options='{"widget": "image" }'/>
</td>
<td colspan="2">
<strong t-field="product.name"/>
<div class="text-muted">
<div t-field="product.description_sale"/>
<div class="js_attributes"/>
</div>
</td>
<td>
<span t-attf-class="text-danger oe_default_price" t-att-style="'' if (website.compute_curency(product.lst_price) - product.price) &gt; 0.1 else 'display: none;'" style="text-decoration: line-through; white-space: nowrap;"
t-field="product.lst_price"
t-field-options='{
"widget": "monetary",
"from_currency": "website.currency_id",
"display_currency": "user_id.partner_id.property_product_pricelist.currency_id"
}'/><br/>
<span class="oe_price" style="white-space: nowrap;"
t-field="product.price"
t-field-options='{
"widget": "monetary",
"from_currency": "website.currency_id",
"display_currency": "user_id.partner_id.property_product_pricelist.currency_id"
}'/>
</td>
<td>
<div class="input-group">
<span class="input-group-addon">
<a t-attf-href="#" class="mb8 js_add_cart_json">
<i class="fa fa-minus"></i>
</a>
</span>
<input type="text" class="js_quantity form-control" data-min="1" name="add_qty" value="1"/>
<span class="input-group-addon">
<a t-attf-href="#" class="mb8 float_left js_add_cart_json">
<i class="fa fa-plus"></i>
</a>
</span>
</div>
</td>
</tr>
<tr t-if="optional_product_ids"><td colspan="4"><h4>Select Your Options:</h4></td></tr>
<t t-set="option_inc" t-value="0"/>
<tr class="js_product" t-foreach="optional_product_ids" t-as="product">
<td width="100">
<input type="hidden" class="optional_product_id" t-attf-name="optional-product-#{option_inc}" t-att-value="int(product.product_variant_ids[0]) if len(product.product_variant_ids) == 1 else '0'"/>
<span t-field="product.image_small" t-field-options='{"widget": "image"}'/>
</td>
<td>
<div class="pull-left">
<strong class="media-heading" t-field="product.name"/>
<div class="text-muted" t-field="product.description_sale"/>
</div>
</td>
<td>
<div class="pull-right">
<t t-call="website_sale.variants"/>
</div>
</td>
<td>
<t t-if="(website.compute_curency(product.lst_price) - product.price) &gt; 0.1">
<span class="text-danger" style="text-decoration: line-through; white-space: nowrap;"
t-field="product.lst_price"
t-field-options='{
"widget": "monetary",
"from_currency": "website.currency_id",
"display_currency": "user_id.partner_id.property_product_pricelist.currency_id"
}'/><br/>
</t>
<span class="oe_price" style="white-space: nowrap;"
t-field="product.price"
t-field-options='{
"widget": "monetary",
"display_currency": "user_id.partner_id.property_product_pricelist.currency_id"
}'/>
<p class="css_not_available_msg bg-danger" style="position:absolute; padding: 15px;">Product not available</p>
</td>
<td>
<input type="hidden" class="js_optional_same_quantity" t-attf-name="optional-quantity-#{option_inc}" value="0"/>
<a href="#" class="js_add"><strong>Add to Cart</strong></a>
<span class="js_remove hidden">
<span class="js_item">1 Item</span><span class="js_items hidden">5 Items</span><br/>
<a href="#" class="js_remove"><small>Remove from cart</small></a>
</span>
</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<a class="btn btn-default a-submit js_goto_shop"><i class="fa fa-chevron-left"></i> Continue shopping</a>
<a class="btn btn-primary pull-right a-submit"><i class="fa fa-shopping-cart fa-fw"></i> Proceed to checkout</a>
</div>
</div>
</div>
</div>
</template>
</data>
</openerp>