[WIP] website_sale: refactoring and use inherit_option_id
bzr revid: chm@openerp.com-20130812163123-3ako1rggjnszzi2h
This commit is contained in:
parent
ed5ad1c91d
commit
59ba4e7561
|
@ -27,6 +27,7 @@ def urlplus(url, params):
|
|||
url += "%s=%s&" % (k, urllib.quote_plus(v))
|
||||
return url
|
||||
|
||||
|
||||
class website(osv.osv):
|
||||
_name = "website" # Avoid website.website convention for conciseness (for new api). Got a special authorization from xmo and rco
|
||||
_description = "Website"
|
||||
|
@ -93,4 +94,25 @@ class website(osv.osv):
|
|||
for page in range(pmin, pmax+1):
|
||||
d["pages"].append({'url': "%spage/%s/" % (url, page), 'num': page})
|
||||
|
||||
return d
|
||||
return d
|
||||
|
||||
|
||||
class res_partner(osv.osv):
|
||||
_inherit = "res.partner"
|
||||
|
||||
def google_map_img(self, cr, uid, ids, zoom=8, width=298, height=298, context=None):
|
||||
partner = self.browse(cr, uid, ids[0], context=context)
|
||||
params = {
|
||||
'center': '%s, %s %s, %s' % (partner.street, partner.city, partner.zip, partner.country_id and partner.country_id.name_get()[0][1] or ''),
|
||||
'size': "%sx%s" % (height, width),
|
||||
'zoom': zoom,
|
||||
'sensor': 'false',
|
||||
}
|
||||
return urlplus('http://maps.googleapis.com/maps/api/staticmap' , params)
|
||||
|
||||
def google_map_link(self, cr, uid, ids, zoom=8, context=None):
|
||||
partner = self.browse(cr, uid, ids[0], context=context)
|
||||
params = {
|
||||
'q': '%s, %s %s, %s' % (partner.street, partner.city, partner.zip, partner.country_id and partner.country_id.name_get()[0][1] or ''),
|
||||
}
|
||||
return urlplus('https://maps.google.be/maps' , params)
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
import controllers
|
||||
import pricelist
|
||||
import product
|
||||
import website_sale
|
||||
|
|
|
@ -50,40 +50,6 @@ class Ecommerce(http.Controller):
|
|||
categories = category_obj.browse(request.cr, openerp.SUPERUSER_ID, category_ids)
|
||||
return categories
|
||||
|
||||
def render(self, template, values={}):
|
||||
website = request.registry['website']
|
||||
_values = {
|
||||
'categories': self.get_categories(),
|
||||
}
|
||||
_values.update(values)
|
||||
return website.render(template, _values)
|
||||
|
||||
def recommended_product(self, my_pids):
|
||||
if not my_pids:
|
||||
return []
|
||||
product_obj = request.registry.get('product.product')
|
||||
|
||||
my_pids = str(my_pids)[1:-1]
|
||||
product_ids = []
|
||||
query = """
|
||||
SELECT sol.product_id
|
||||
FROM sale_order_line as my
|
||||
LEFT JOIN sale_order_line as sol
|
||||
ON sol.order_id = my.order_id
|
||||
WHERE my.product_id in (%s)
|
||||
AND sol.product_id not in (%s)
|
||||
GROUP BY sol.product_id
|
||||
ORDER BY COUNT(sol.order_id) DESC
|
||||
LIMIT 8
|
||||
""" % (my_pids, my_pids)
|
||||
request.cr.execute(query)
|
||||
for p in request.cr.fetchall():
|
||||
product_ids.append(p[0])
|
||||
|
||||
# search to apply access rules
|
||||
product_ids = product_obj.search(request.cr, request.uid, [("id", "in", product_ids)])
|
||||
return product_obj.browse(request.cr, request.uid, product_ids)
|
||||
|
||||
@http.route(['/shop/', '/shop/category/<cat_id>/', '/shop/category/<cat_id>/page/<int:page>/', '/shop/page/<int:page>/'], type='http', auth="public")
|
||||
def category(self, cat_id=0, page=0, **post):
|
||||
|
||||
|
@ -105,12 +71,13 @@ class Ecommerce(http.Controller):
|
|||
product_ids = product_obj.search(request.cr, request.uid, domain, limit=step, offset=pager['offset'])
|
||||
|
||||
values = website.get_rendering_context({
|
||||
'categories': self.get_categories(),
|
||||
'current_category': cat_id,
|
||||
'products': product_obj.browse(request.cr, request.uid, product_ids),
|
||||
'search': post.get("search"),
|
||||
'pager': pager,
|
||||
})
|
||||
return self.render("website_sale.products", values)
|
||||
return website.render("website_sale.products", values)
|
||||
|
||||
@http.route(['/shop/product/<product_id>/'], type='http', auth="public")
|
||||
def product(self, cat_id=0, product_id=0):
|
||||
|
@ -121,32 +88,28 @@ class Ecommerce(http.Controller):
|
|||
product_obj = request.registry.get('product.product')
|
||||
|
||||
line = [line for line in order.order_line if line.product_id.id == product_id]
|
||||
quantity = line and int(line[0].product_uom_qty) or 0
|
||||
|
||||
values = website.get_rendering_context({
|
||||
'categories': self.get_categories(),
|
||||
'product': product_obj.browse(request.cr, request.uid, product_id),
|
||||
'quantity': quantity,
|
||||
'recommended_products': self.recommended_product([product_id]),
|
||||
})
|
||||
return self.render("website_sale.product", values)
|
||||
return website.render("website_sale.product", values)
|
||||
|
||||
@http.route(['/shop/mycart/'], type='http', auth="public")
|
||||
def mycart(self, **post):
|
||||
website = request.registry['website']
|
||||
order = get_current_order()
|
||||
website = request.registry['website']
|
||||
|
||||
if post.get('code'):
|
||||
pricelist_obj = request.registry.get('product.pricelist')
|
||||
pricelist_ids = pricelist_obj.search(request.cr, openerp.SUPERUSER_ID, [('code', '=', post.get('code'))])
|
||||
if pricelist_ids:
|
||||
order.write({'pricelist_id': pricelist_ids[0]})
|
||||
|
||||
my_pids = [line.product_id.id for line in order.order_line]
|
||||
|
||||
values = website.get_rendering_context({
|
||||
"recommended_products": self.recommended_product(my_pids),
|
||||
'categories': self.get_categories(),
|
||||
})
|
||||
|
||||
return self.render("website_sale.mycart", values)
|
||||
return website.render("website_sale.mycart", values)
|
||||
|
||||
def add_product_to_cart(self, product_id=0, number=1):
|
||||
context = {}
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
<a href="/shop/mycart/">
|
||||
<i class="icon-shopping-cart"></i>
|
||||
My cart
|
||||
<!-- FIXME: logic to obtain the shopping cart numer of items shall not be in the template. Move it in models or in controllers -->
|
||||
<!-- <span class="badge badge-success" t-if="order.order_line" t-esc="int(sum([l.product_uom_qty for l in order.order_line]))"/> -->
|
||||
<span class="badge badge-success" t-if="order.get_total_quantity()" t-esc="order.get_total_quantity()"/>
|
||||
</a>
|
||||
</li>
|
||||
</xpath>
|
||||
|
@ -44,7 +43,7 @@
|
|||
|
||||
<!-- Page Shop -->
|
||||
|
||||
<template id="page">
|
||||
<template id="layout_categories">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="head">
|
||||
<script type="text/javascript" src="/website_sale/static/src/js/website_sale.js"></script>
|
||||
|
@ -54,25 +53,21 @@
|
|||
<t t-set="title">Shop - <t t-raw="title">Categories</t></t>
|
||||
<div class="container mt48 oe_ecommerce">
|
||||
<div class="row">
|
||||
<t t-call='website_sale.categories' />
|
||||
<div class="span4">
|
||||
<ul class="nav nav-list">
|
||||
<li t-att-class=" '' if current_category else 'active' " class='active'><a href='/shop/'>All Products</a></li>
|
||||
<t t-foreach="categories" t-as="category">
|
||||
<t t-call="website_sale.categories_recursive"/>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
<t t-raw="shop_content" />
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- List of categories -->
|
||||
|
||||
<template id="categories">
|
||||
<div class="span4">
|
||||
<ul class="nav nav-list">
|
||||
<li t-att-class=" '' if current_category else 'active' " class='active'><a href='/shop/'>All Products</a></li>
|
||||
<t t-foreach="categories" t-as="category">
|
||||
<t t-call="website_sale.categories_recursive"/>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<!-- List of categories -->
|
||||
|
||||
<template id="categories_recursive">
|
||||
<li t-att-class="category.id == current_category and 'active' or ''">
|
||||
|
@ -88,7 +83,7 @@
|
|||
<!-- Product list -->
|
||||
|
||||
<template id="products">
|
||||
<t t-call="website_sale.page">
|
||||
<t t-call="website_sale.layout_categories">
|
||||
<t t-set="title">Product</t>
|
||||
<t t-set="shop_content">
|
||||
<div class='span8 navbar navbar-inverse'>
|
||||
|
@ -105,8 +100,6 @@
|
|||
<div class='row grid grid-align-top'>
|
||||
<t t-foreach="products" t-as="product">
|
||||
<t t-set="quantity" t-value="1"/>
|
||||
<!-- FIXME: logic to obtain a specific product count in the shopping cart shall not be in the template. Move it in models or in controllers -->
|
||||
<!-- <t t-set="quantity" t-value="([int(line.product_uom_qty) for line in (order.order_line or []) if line.product_id.id == product.id] + [0])[0]"/> -->
|
||||
<t t-call="website_sale.product_card"/>
|
||||
</t>
|
||||
</div>
|
||||
|
@ -130,38 +123,19 @@
|
|||
<div t-field="product.description_sale"></div>
|
||||
<div><span t-field="product.list_price"></span>€</div>
|
||||
<div class="mb8 mt8">
|
||||
<a t-if="quantity" t-att-href="'./remove_cart/%s/' % product.id" class="btn mb8 btn-small btn-inverse">Remove one</a>
|
||||
<a t-att-href="'./add_cart/%s/' % product.id" class="btn btn-small btn-success">Add to cart <t t-if="quantity">(<t t-esc="quantity"/>)</t></a>
|
||||
<a t-att-href="'./add_cart/%s/' % product.id" class="btn btn-small btn-success">Add to cart</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="product_recommended">
|
||||
<div class="well mt32" t-if="recommended_products">
|
||||
<h4>Customers who have bought this item also bought</h4>
|
||||
<div class='row mt16'>
|
||||
<t t-foreach="recommended_products or []" t-as="product">
|
||||
<div class='span2 thumbnail'>
|
||||
<a t-att-href="'/shop/product/%%s/' %% product.id">
|
||||
<div class='mt16 text-center'>
|
||||
<img t-att-src="'data:image/png;base64,' + product.image"/>
|
||||
<h5 t-field='product.name'></h5>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- product -->
|
||||
|
||||
<template id="product">
|
||||
<t t-call="website_sale.page">
|
||||
<template id="product" name="Product">
|
||||
<t t-call="website_sale.layout_categories">
|
||||
<t t-set="title">Product</t>
|
||||
<t t-set="shop_content">
|
||||
<div class="oe_product_detail span8">
|
||||
<div class="oe_product_detail span8" id="product_detail">
|
||||
<a href="#" t-att-data-id="product.id" class="pull-right" t-if="editable">
|
||||
<span t-att-class="'label label-success js_unpublish %%s' %% (not product.website_published and 'hidden' or '')">Click to Unpublish</span>
|
||||
<span t-att-class="'label label-important js_publish %%s' %% (product.website_published and 'hidden' or '')">Click to Publish</span>
|
||||
|
@ -169,41 +143,88 @@
|
|||
<h2 t-field="product.name"></h2>
|
||||
|
||||
<div class="oe_button_cart">
|
||||
<a t-if="quantity" t-att-href="'./remove_cart/%s/' % product.id" class="btn btn-small btn-inverse">Remove one</a>
|
||||
<a t-att-href="'./add_cart/%s/' % product.id" class="btn btn-small btn-success">Add to cart <t t-if="quantity">(<t t-esc="quantity"/>)</t></a>
|
||||
<a t-att-href="'./add_cart/%s/' % product.id" class="btn btn-small btn-success">Add to cart</a>
|
||||
</div>
|
||||
<img class="media-object" t-att-src="'data:image/png;base64,' + product.image"/>
|
||||
<div t-field="product.description_website"></div>
|
||||
<div class="oe_ecommerce_price"><t t-field="product.list_price" />€</div>
|
||||
<t t-call="website_sale.product_recommended"/>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
<template id="recommended_products" inherit_id="website_sale.product" inherit_option_id="website_sale.product" name="Recommended Products">
|
||||
<xpath expr="//div[@id='product_detail']" position="inside">
|
||||
<div class="well mt32" t-if="product.recommended_products()">
|
||||
<h4>Customers who have bought this item also bought</h4>
|
||||
<div class='row mt16'>
|
||||
<t t-foreach="product.recommended_products()" t-as="product">
|
||||
<div class='span2 thumbnail'>
|
||||
<a t-att-href="'/shop/product/%%s/' %% product.id">
|
||||
<div class='mt16 text-center'>
|
||||
<img t-att-src="'data:image/png;base64,' + product.image"/>
|
||||
<h5 t-field='product.name'></h5>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Page Shop my cart -->
|
||||
|
||||
<template id="mycart">
|
||||
<t t-call="website_sale.page">
|
||||
<t t-call="website_sale.layout_categories">
|
||||
<t t-set="title">My cart</t>
|
||||
<t t-set="shop_content">
|
||||
<div class="span8 oe_mycart">
|
||||
<h2>My Shopping Cart</h2>
|
||||
<h3 t-if="not order.order_line">Your cart is empty</h3>
|
||||
<div class='row mt32 grid grid-align-top'>
|
||||
<t t-foreach="order.order_line or []" t-as="line">
|
||||
<t t-set="product" t-value="line.product_id"/>
|
||||
<t t-set="quantity" t-value="int(line.product_uom_qty)"/>
|
||||
<t t-call="website_sale.product_card"/>
|
||||
</t>
|
||||
</div>
|
||||
<t t-call="website_sale.total"/>
|
||||
<table class='table-equalized' t-if="order.order_line">
|
||||
<thead>
|
||||
<tr><th>Product</th><th>Qty.</th><th>Price</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="order.order_line" t-as="line">
|
||||
<tr>
|
||||
<td>
|
||||
<a t-att-href="line.product_id"><span t-field="line.product_id.name"/></a>
|
||||
</td>
|
||||
<td>
|
||||
<a t-att-href="line.product_id"><img class="img-rounded" t-att-src="'data:image/png;base64,' + line.product_id.image"/></a>
|
||||
</td>
|
||||
<td>
|
||||
<span t-field="line.product_id.list_price"></span>€
|
||||
</td>
|
||||
<td>
|
||||
<div class="mb8 mt8">
|
||||
<input type="text" t-att-value="line.product_uom_qty"/>
|
||||
<a t-attf-href="./remove_cart/#{ line.product_id.id }/" class="btn mb8 btn-small btn-inverse">-</a>
|
||||
<a t-attf-href="./add_cart/#{ line.product_id.id }/" class="btn mb8 btn-small btn-success">+</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td colspan="2">
|
||||
<small t-field="line.product_id.description_sale"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
|
||||
<tfoot>
|
||||
<tr> <td>Subtotal </td> <td><t t-esc="order.amount_untaxed"/> €</td></tr>
|
||||
<tr> <td>Taxes </td> <td><t t-esc="order.amount_tax"/> €</td></tr>
|
||||
<tr> <td><h4>Total</h4></td> <td><h4><t t-esc="order.amount_total"/> €</h4></td></tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<form t-if="order.order_line" class="well form-search" action="/shop/mycart/" method="post">
|
||||
<input name="code" class='input' type="text" placeholder="Reduction Code..."/>
|
||||
<button class="btn">Apply Code</button>
|
||||
</form>
|
||||
<a t-if="order.order_line" href="/shop/checkout/"><button class="btn btn-success">Proceed To Payment</button></a>
|
||||
<t t-call="website_sale.product_recommended"/>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C)-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# published by the Free Software Foundation, either version of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
@ -33,4 +33,36 @@ class product_product(osv.osv):
|
|||
_columns = {
|
||||
'website_published': fields.boolean('Available in the website'),
|
||||
'description_website': fields.html('Description for the website'),
|
||||
}
|
||||
}
|
||||
|
||||
def recommended_products(self, cr, uid, ids, context=None):
|
||||
id = ids[0]
|
||||
product_ids = []
|
||||
query = """
|
||||
SELECT sol.product_id
|
||||
FROM sale_order_line as my
|
||||
LEFT JOIN sale_order_line as sol
|
||||
ON sol.order_id = my.order_id
|
||||
WHERE my.product_id in (%s)
|
||||
AND sol.product_id not in (%s)
|
||||
GROUP BY sol.product_id
|
||||
ORDER BY COUNT(sol.order_id) DESC
|
||||
LIMIT 8
|
||||
""" % (id, id)
|
||||
cr.execute(query)
|
||||
for p in cr.fetchall():
|
||||
product_ids.append(p[0])
|
||||
|
||||
# search to apply access rules
|
||||
product_ids = self.search(cr, uid, [("id", "in", product_ids)])
|
||||
return self.browse(cr, uid, product_ids)
|
||||
|
||||
|
||||
class sale_order(osv.osv):
|
||||
_inherit = "sale.order"
|
||||
|
||||
def get_total_quantity(self, cr, uid, ids, context=None):
|
||||
order = self.browse(cr, uid, ids[0], context=context)
|
||||
if order.order_line:
|
||||
result = sum([l.product_uom_qty for l in order.order_line])
|
||||
return result
|
||||
|
|
Loading…
Reference in New Issue