[WIP]
This commit is contained in:
parent
204a62499a
commit
7505cce2e9
|
@ -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()
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) > 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">
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
import product
|
||||
import sale_order
|
|
@ -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."),
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -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)',
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
}());
|
|
@ -0,0 +1 @@
|
|||
import customize_test
|
|
@ -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)
|
|
@ -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) > 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) > 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) > 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>
|
||||
|
|
Loading…
Reference in New Issue