[MERGE] from upstream

bzr revid: fva@openerp.com-20130820164644-eg5z05o2e339qf67
This commit is contained in:
Frédéric van der Essen
2013-08-20 18:46:44 +02:00
19 changed files with 373 additions and 80 deletions
+29 -28
View File
@@ -289,6 +289,15 @@ class product_template(osv.osv):
_name = "product.template"
_description = "Product Template"
def _get_image(self, cr, uid, ids, name, args, context=None):
result = dict.fromkeys(ids, False)
for obj in self.browse(cr, uid, ids, context=context):
result[obj.id] = tools.image_get_resized_images(obj.image, avoid_resize_medium=True)
return result
def _set_image(self, cr, uid, id, name, value, args, context=None):
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
_columns = {
'name': fields.char('Name', size=128, required=True, translate=True, select=True),
'product_manager': fields.many2one('res.users','Product Manager'),
@@ -328,6 +337,26 @@ class product_template(osv.osv):
'mes_type': fields.selection((('fixed', 'Fixed'), ('variable', 'Variable')), 'Measure Type'),
'seller_ids': fields.one2many('product.supplierinfo', 'product_id', 'Supplier'),
'company_id': fields.many2one('res.company', 'Company', select=1),
# image: all image fields are base64 encoded and PIL-supported
'image': fields.binary("Image",
help="This field holds the image used as image for the product, limited to 1024x1024px."),
'image_medium': fields.function(_get_image, fnct_inv=_set_image,
string="Medium-sized image", type="binary", multi="_get_image",
store={
'product.product': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help="Medium-sized image of the product. It is automatically "\
"resized as a 128x128px image, with aspect ratio preserved, "\
"only when the image exceeds one of those sizes. Use this field in form views or some kanban views."),
'image_small': fields.function(_get_image, fnct_inv=_set_image,
string="Small-sized image", type="binary", multi="_get_image",
store={
'product.product': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help="Small-sized image of the product. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required."),
'product_variant_ids': fields.one2many('product.product', 'product_tmpl_id', 'Product Variants'),
}
def _get_uom_id(self, cr, uid, *args):
@@ -514,15 +543,6 @@ class product_product(osv.osv):
return result
def _get_image(self, cr, uid, ids, name, args, context=None):
result = dict.fromkeys(ids, False)
for obj in self.browse(cr, uid, ids, context=context):
result[obj.id] = tools.image_get_resized_images(obj.image, avoid_resize_medium=True)
return result
def _set_image(self, cr, uid, id, name, value, args, context=None):
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
def _get_name_template_ids(self, cr, uid, ids, context=None):
result = set()
template_ids = self.pool.get('product.product').search(cr, uid, [('product_tmpl_id', 'in', ids)])
@@ -567,25 +587,6 @@ class product_product(osv.osv):
}, select=True),
'color': fields.integer('Color Index'),
# image: all image fields are base64 encoded and PIL-supported
'image': fields.binary("Image",
help="This field holds the image used as image for the product, limited to 1024x1024px."),
'image_medium': fields.function(_get_image, fnct_inv=_set_image,
string="Medium-sized image", type="binary", multi="_get_image",
store={
'product.product': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help="Medium-sized image of the product. It is automatically "\
"resized as a 128x128px image, with aspect ratio preserved, "\
"only when the image exceeds one of those sizes. Use this field in form views or some kanban views."),
'image_small': fields.function(_get_image, fnct_inv=_set_image,
string="Small-sized image", type="binary", multi="_get_image",
store={
'product.product': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help="Small-sized image of the product. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required."),
'seller_info_id': fields.function(_calc_seller, type='many2one', relation="product.supplierinfo", string="Supplier Info", multi="seller_info"),
'seller_delay': fields.function(_calc_seller, type='integer', string='Supplier Lead Time', multi="seller_info", help="This is the average delay in days between the purchase order confirmation and the reception of goods for this product and for the default supplier. It is used by the scheduler to order requests based on reordering delays."),
'seller_qty': fields.function(_calc_seller, type='float', string='Supplier Quantity', multi="seller_info", help="This is minimum quantity to purchase from Main Supplier."),
+1 -1
View File
@@ -253,7 +253,7 @@
<template id="404">
<t t-call="website.layout">
<div class="container" t-if="editable">
<div class="container" t-if="editable and path">
<div class="well mt32">
<p>
This page does not exists, but you can create
+10 -8
View File
@@ -69,25 +69,27 @@ class website(osv.osv):
return values
def render(self, template, values={}):
view = request.registry.get("ir.ui.view")
context = {
'inherit_branding': values.get('editable', False),
}
try:
return request.registry.get("ir.ui.view").render(request.cr, request.uid, template, values, context=context)
return view.render(request.cr, request.uid, template, values, context=context)
except (osv.except_osv, orm.except_orm), err:
logger.error(err)
values['error'] = err[1]
return self.render('website.401', values)
except ValueError:
logger.error("Website Rendering Error.\n\n%s" % (traceback.format_exc()))
return self.render('website.404', values)
# except ValueError:
# logger.error("Website Rendering Error.\n\n%s" % (traceback.format_exc()))
# return self.render('website.404', values)
except Exception:
logger.error("Website Rendering Error.\n\n%s" % (traceback.format_exc()))
trace = traceback.format_exc()
logger.error("Website Rendering Error.\n\n%s" % trace)
if values['editable']:
values['traceback'] = traceback.format_exc()
return self.render('website.500', values)
values['traceback'] = trace
return view.render(request.cr, request.uid, 'website.500', values, context=context)
else:
return self.render('website.404', values)
return view.render(request.cr, request.uid, 'website.404', values, context=context)
def pager(self, url, total, page=1, step=30, scope=5, url_args=None):
# Compute Pager
+2
View File
@@ -0,0 +1,2 @@
import controllers
import website_contract
+18
View File
@@ -0,0 +1,18 @@
{
'name': 'Public References',
'category': 'Website',
'summary': 'Publish Your Public References',
'version': '1.0',
'description': """
OpenERP Blog
============
""",
'author': 'OpenERP SA',
'depends': ['website', 'sale'],
'data': [
'views/website_contract.xml',
],
'qweb': ['static/src/xml/*.xml'],
'installable': True,
}
@@ -0,0 +1 @@
import main
@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
import openerp
from openerp.addons.web import http
from openerp.addons.web.http import request
class website_contract(http.Controller):
@http.route(['/references/'], type='http', auth="public")
def blog(self, **post):
website = request.registry['website']
partner_obj = request.registry['res.partner']
account_obj = request.registry['account.analytic.account']
# public partner profile
project_ids = partner_obj.search(request.cr, openerp.SUPERUSER_ID, [('website_testimonial', "!=", False), ('website_published', '=', True)])
if request.uid != website.get_public_user().id:
contract_ids = account_obj.search(request.cr, openerp.SUPERUSER_ID, [(1, "=", 1)])
contract_project_ids = [contract.partner_id.id
for contract in account_obj.browse(request.cr, openerp.SUPERUSER_ID, contract_ids) if contract.partner_id]
# search for check access rules
project_ids += partner_obj.search(request.cr, request.uid, [('id', "in", contract_project_ids)])
project_ids = list(set(project_ids))
values = website.get_rendering_context({
'partner_ids': partner_obj.browse(request.cr, openerp.SUPERUSER_ID, project_ids)
})
return website.render("website_contract.index", values)
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Layout add nav and footer -->
<template id="footer_custom" inherit_id="website.layout" name="Custom Footer">
<xpath expr="//body/footer//a[@href='/page/website.aboutus']" position="after">
<li><a href="/references/">References</a></li>
</xpath>
</template>
<!-- Page -->
<template id="index" name="Projects">
<t t-call="website.layout">
<t t-set="title">References</t>
<div class="container">
<div class="thumbnails grid grid-align-top">
<div t-foreach="partner_ids" t-as="partner_id" class="span6">
<div class="media thumbnail">
<a class="pull-left" href="#">
<img class="media-object" t-att-src="partner_id.img('image_small')"/>
</a>
<div class="media-body">
<t t-call="website.publish"><t t-set="object" t-value="partner_id"/></t>
<h5 class="media-heading" t-field="partner_id.name"/>
<pre t-field="partner_id.website_testimonial"/>
</div>
</div>
</div>
</div>
</div>
</t>
</template>
</data>
</openerp>
@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
from openerp.osv import osv, fields
class hr(osv.osv):
_inherit = 'res.partner'
_columns = {
'website_published': fields.boolean('Available in the website'),
'website_testimonial': fields.text('Recommandation'),
}
def img(self, cr, uid, ids, field='image_small', context=None):
return "/website/image?model=%s&field=%s&id=%s" % (self._name, field, ids[0])
+1
View File
@@ -0,0 +1 @@
import controllers
+18
View File
@@ -0,0 +1,18 @@
{
'name': 'Public Project',
'category': 'Website',
'summary': 'Publish Your Public Projects',
'version': '1.0',
'description': """
OpenERP Blog
============
""",
'author': 'OpenERP SA',
'depends': ['website', 'project'],
'data': [
'views/website_project.xml',
],
'qweb': ['static/src/xml/*.xml'],
'installable': True,
}
@@ -0,0 +1 @@
import main
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
from openerp.addons.web import http
from openerp.addons.web.http import request
class website_project(http.Controller):
@http.route(['/projects/'], type='http', auth="public")
def blog(self, **post):
website = request.registry['website']
project_obj = request.registry['project.project']
project_ids = project_obj.search(request.cr, request.uid, [('privacy_visibility', "=", "public")])
values = website.get_rendering_context({
'project_ids': project_obj.browse(request.cr, request.uid, project_ids)
})
return website.render("website_project.index", values)
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Layout add nav and footer -->
<template id="footer_custom" inherit_id="website.layout" name="Custom Footer">
<xpath expr="//body/header//ul[@id='top_menu']/li[last()]" position="before">
<li><a href="/projects/">Projects</a></li>
</xpath>
</template>
<!-- Page -->
<template id="index" name="Projects">
<t t-call="website.layout">
<t t-set="title">Projects</t>
<div class="container">
<div t-foreach="project_ids" t-as="project_id">
<h4 t-field="project_id.name"/>
<div t-foreach="project_id.tasks" t-as="task">
<a t-attf-href="/admin#view_type=form&amp;model=project.task&amp;id=#{task.id}"><span t-field="task.name"/></a>
</div>
</div>
</div>
</t>
</template>
</data>
</openerp>
+26 -13
View File
@@ -4,6 +4,7 @@ from openerp import SUPERUSER_ID
from openerp.osv import osv
from openerp.addons.web import http
from openerp.addons.web.http import request
import random
import werkzeug
def get_order(order_id=None):
@@ -54,7 +55,7 @@ class Ecommerce(http.Controller):
def category(self, cat_id=0, page=0, **post):
website = request.registry['website']
product_obj = request.registry.get('product.product')
product_obj = request.registry.get('product.template')
domain = [("sale_ok", "=", True)]
if SUPERUSER_ID != request.uid:
@@ -65,20 +66,20 @@ class Ecommerce(http.Controller):
('name', 'ilike', "%%%s%%" % post.get("search")),
('description', 'ilike', "%%%s%%" % post.get("search")),
('description_website', 'ilike', "%%%s%%" % post.get("search")),
('pos_categ_id.name', 'ilike', "%%%s%%" % post.get("search"))]
('product_variant_ids.pos_categ_id.name', 'ilike', "%%%s%%" % post.get("search"))]
if cat_id:
cat_id = int(cat_id)
domain += [('pos_categ_id.id', 'child_of', cat_id)] + domain
domain += [('product_variant_ids.pos_categ_id.id', 'child_of', cat_id)] + domain
step = 20
product_count = len(product_obj.search(request.cr, request.uid, domain))
pager = website.pager(url="/shop/category/%s/" % cat_id, total=product_count, page=page, step=step, scope=7, url_args=post)
product_ids = product_obj.search(request.cr, request.uid, domain, limit=step, offset=pager['offset'])
product_ids = product_obj.search(request.cr, request.uid, domain, limit=step, offset=pager['offset'], order="website_published,name")
values = website.get_rendering_context({
'categories': self.get_categories(),
'current_category': cat_id,
'category_id': cat_id,
'products': product_obj.browse(request.cr, request.uid, product_ids),
'search': post.get("search"),
'pager': pager,
@@ -86,18 +87,18 @@ class Ecommerce(http.Controller):
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):
def product(self, cat_id=0, product_id=0, **post):
website = request.registry['website']
order = get_current_order()
product_id = product_id and int(product_id) or 0
product_obj = request.registry.get('product.product')
line = [line for line in order.order_line if line.product_id.id == product_id]
product_obj = request.registry.get('product.template')
product = product_obj.browse(request.cr, request.uid, product_id)
values = website.get_rendering_context({
'category_id': post.get('category_id') and int(post.get('category_id')) or None,
'search': post.get("search"),
'categories': self.get_categories(),
'product': product_obj.browse(request.cr, request.uid, product_id),
'product': product,
})
return website.render("website_sale.product", values)
@@ -105,15 +106,27 @@ class Ecommerce(http.Controller):
def mycart(self, **post):
order = get_current_order()
website = request.registry['website']
prod_obj = request.registry.get('product.product')
if post.get('code'):
pricelist_obj = request.registry.get('product.pricelist')
pricelist_ids = pricelist_obj.search(request.cr, SUPERUSER_ID, [('code', '=', post.get('code'))])
if pricelist_ids:
order.write({'pricelist_id': pricelist_ids[0]})
suggested_ids = []
for line in order.order_line:
suggested_ids += [p.id for p in line.product_id.suggested_product_ids for line in order.order_line]
suggested_ids = prod_obj.search(request.cr, request.uid, [('id', 'in', suggested_ids)])
# select 3 random products
suggested_products = []
while len(suggested_products) < 3 and suggested_ids:
index = random.randrange(0, len(suggested_ids))
suggested_products.append(suggested_ids.pop(index))
values = website.get_rendering_context({
'categories': self.get_categories(),
'suggested_products': prod_obj.browse(request.cr, request.uid, suggested_products),
})
return website.render("website_sale.mycart", values)
@@ -161,7 +174,7 @@ class Ecommerce(http.Controller):
return quantity
@http.route(['/shop/add_cart/<product_id>/', '/shop/<path:path>/add_cart/<product_id>/'], type='http', auth="public")
@http.route(['/shop/<path:path>/add_cart/', '/shop/add_cart/', '/shop/add_cart/<product_id>/', '/shop/<path:path>/add_cart/<product_id>/'], type='http', auth="public")
def add_cart(self, path=None, product_id=0, remove=None):
self.add_product_to_cart(product_id, number=(remove and -1 or 1))
if path:
@@ -1,3 +1,4 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_product_product_public,product.product.public,product.model_product_product,base.group_public,1,0,0,0
access_product_template_public,product.template.public,product.model_product_template,base.group_public,1,0,0,0
access_point_of_sale_category_public,point_of_sale.category.public,point_of_sale.model_pos_category,base.group_public,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_product_product_public product.product.public product.model_product_product base.group_public 1 0 0 0
3 access_product_template_public product.template.public product.model_product_template base.group_public 1 0 0 0
4 access_point_of_sale_category_public point_of_sale.category.public point_of_sale.model_pos_category base.group_public 1 0 0 0
@@ -1,6 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="product_template_public" model="ir.rule">
<field name="name">product: Public product template</field>
<field name="model_id" ref="product.model_product_template"/>
<field name="domain_force">[('website_published', '=', True), ("sale_ok", "=", True)]</field>
<field name="groups" eval="[(4, ref('base.group_public'))]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_unlink" eval="False"/>
</record>
<record id="product_product_public" model="ir.rule">
<field name="name">product: Public product</field>
<field name="model_id" ref="product.model_product_product"/>
+119 -27
View File
@@ -38,6 +38,7 @@
<group name="sale" position="before">
<group name="pos" string="Website">
<field name="website_published"/>
<field name="suggested_product_ids" widget="many2many_tags"/>
</group>
</group>
</field>
@@ -65,7 +66,7 @@
<xpath expr="//div[@id='shop_content']" position="before">
<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>
<li t-att-class=" '' if category_id 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>
@@ -80,7 +81,7 @@
<!-- List of categories -->
<template id="categories_recursive">
<li t-att-class="category.id == current_category and 'active' or ''">
<li t-att-class="category.id == category_id and 'active' or ''">
<a t-attf-href="/shop/category/#{ category.id }/" t-field="category.name"></a>
<ul t-if="category.child_id" class="nav nav-list">
<t t-foreach="category.child_id" t-as="category">
@@ -101,17 +102,16 @@
<t t-call="website.pager" >
<t t-set="classname">pull-left</t>
</t>
<form action="/shop/" method="get" class="navbar-search pull-right pagination">
<form t-attf-action="/shop/#{ category_id and ('category/%s/' % category_id) or ''}" method="get" class="navbar-search pull-right pagination">
<input type="text" name="search" class="search-query span2" placeholder="Search" t-att-value="search or '' or ''"/>
</form>
</div>
</div>
<div class='row grid grid-align-top'>
<div t-foreach="products" t-as="product" class="span2 mb16 thumbnail text-center">
<a t-attf-href="/shop/product/#{ product.id }/ ">
<t t-foreach="products" t-as="product">
<div t-attf-class="span2 mb16 thumbnail text-center #{not product.website_published and 'alert' or ''}">
<a t-attf-href="/shop/product/#{ product.id }/?#{ search and ('search=%s' % search) or ''}#{ category_id and ('&amp;category_id=%s' % category_id) or ''}">
<h5 t-field="product.name"> </h5>
</a>
<a t-attf-href="/shop/product/#{ product.id }/">
<img class="img-rounded" t-att-src="product.img('image_small')"/>
</a>
<div>
@@ -122,6 +122,7 @@
</div>
</div>
</div>
</t>
</div>
<div class="text-center">
<t t-call="website.pager" />
@@ -136,10 +137,24 @@
<t t-call="website_sale.layout">
<t t-set="title">Product</t>
<t t-set="shop_content">
<div class='navbar navbar-inverse'>
<div class='navbar-inner'>
<form t-attf-action="/shop/#{ category_id and ('category/%s/' % category_id) or ''}" method="get" class="navbar-search pull-right pagination">
<input type="text" name="search" class="search-query span2" placeholder="Search" t-att-value="search or '' or ''"/>
</form>
</div>
</div>
<div id="product_detail">
<t t-call="website.publish"><t t-set="object" t-value="product"/></t>
<h2 t-field="product.name"></h2>
<a t-attf-href="./add_cart/#{ product.id }/" class="btn btn-small btn-success pull-right">Add to cart</a>
<a t-if="not product.product_variant_ids" t-attf-href="/shop/add_cart/#{ product.id }/" class="btn btn-small btn-success pull-right">Add to cart</a>
<form t-if="len(product.product_variant_ids) > 1" action="/shop/add_cart/" class="pull-right">
<label class="radio" t-foreach="product.product_variant_ids" t-as="product">
<input type="radio" name="product_id" t-att-value="product.id" t-att-checked="product == product.product_variant_ids[0] or None"/>
<t t-esc="product.variants or ''">Standard</t>
</label><br/>
<button class="btn btn-small btn-success">Add to cart</button>
</form>
<img class="media-object" t-att-src="product.img('image')"/>
<div t-field="product.description_website"></div>
<div><t t-field="product.list_price" />€</div>
@@ -169,19 +184,24 @@
<!-- Page Shop my cart -->
<template id="mycart">
<template id="mycart" name="My cart">
<t t-call="website_sale.layout">
<t t-set="title">My cart</t>
<t t-set="shop_content">
<div class="span8 oe_mycart">
<h2>My Shopping Cart</h2>
<table class='table table-hover'>
<table class='table table-hover' id="mycart_products">
<colgroup>
<col width="80"/>
<col/>
<col width="80"/>
<col width="160"/>
</colgroup>
<thead>
<tr>
<th width="80">Product</th>
<th></th>
<th width="80">Price</th>
<th width="150">Quantity</th>
<th colspan="2">Product</th>
<th>Price</th>
<th>Quantity</th>
</tr>
</thead>
<tbody t-if="not order.order_line">
@@ -194,14 +214,16 @@
<a t-attf-href="/shop/product/#{ line.product_id.id }/"><img class="img-rounded" t-att-src="line.product_id.img('image_small')"/></a>
</td>
<td>
<a t-attf-href="/shop/product/#{ line.product_id.id }/"><span t-field="line.product_id.name"/></a><br/>
<a t-attf-href="/shop/product/#{ line.product_id.id }/">
<span t-field="line.product_id.name"/> <t t-if="line.product_id.variants">(<small t-field="line.product_id.variants"/>)</t>
</a><br/>
<small t-field="line.product_id.description_sale"/>
</td>
<td>
<span t-field="line.product_id.list_price"></span>€
</td>
<td>
<div class="mb8 mt8">
<div class="mb8 mt8 pull-right">
<input type="text" class="input-mini" t-att-data-id="line.product_id.id" 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>
@@ -210,21 +232,91 @@
</tr>
</t>
</tbody>
<tfoot>
<tr> <td colspan="3">Subtotal </td> <td><t t-esc="order.amount_untaxed"/> €</td></tr>
<tr> <td colspan="3">Taxes </td> <td><t t-esc="order.amount_tax"/> €</td></tr>
<tr> <td colspan="3"><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>
<table class='table table-hover table-condensed' id="mycart_total">
<colgroup>
<col width="80"/>
<col/>
<col width="80"/>
<col width="160"/>
</colgroup>
<thead>
<tr> <th colspan="3">Subtotal </th> <th><t t-esc="order.amount_untaxed"/> €</th></tr>
<tr> <th colspan="3">Taxes </th> <th><t t-esc="order.amount_tax"/> €</th></tr>
<tr> <th colspan="3"><h4>Total</h4></th> <th><h4><t t-esc="order.amount_total"/> €</h4></th></tr>
<tr>
<th colspan="4"><a t-if="order.order_line" href="/shop/checkout/" class="pull-right btn btn-success">Proceed To Payment</a></th>
</tr>
</thead>
</table>
</div>
</t>
</t>
</template>
<template id="suggested_products_list" inherit_id="website_sale.mycart" inherit_option_id="website_sale.mycart" name="Suggested Products in list view">
<xpath expr="//table[@id='mycart_products']" position="after">
<table t-if="suggested_products" class='table table-hover table-condensed'>
<colgroup>
<col/>
<col width="80"/>
<col width="160"/>
</colgroup>
<thead>
<tr>
<th>Suggested products</th>
</tr>
</thead>
<tbody>
<t t-foreach="suggested_products" t-as="product_id">
<tr>
<td>
<a t-attf-href="/shop/product/#{ product_id.id }/"><span t-field="product_id.name"/></a><br/>
<small t-field="product_id.description_sale"/>
</td>
<td>
<span t-field="product_id.list_price"></span>€
</td>
<td>
<div class="pull-right">
<a t-attf-href="./add_cart/#{ product_id.id }/" class="btn btn-small btn-success">+</a>
</div>
</td>
</tr>
</t>
</tbody>
</table>
</xpath>
</template>
<template id="suggested_products_cell" inherit_option_id="website_sale.mycart" name="Suggested Products in card view">
<xpath expr="//table[@id='mycart_products']" position="after">
<div class="mt16 mb32" t-if="suggested_products">
<h4>Suggested products</h4>
<div class='row mt16'>
<t t-foreach="suggested_products" t-as="product">
<div class='span2 thumbnail'>
<a t-attf-href="/shop/product/#{ product.id }/">
<div class='mt16 text-center'>
<img t-att-src="product.img('image_small')"/>
<h5 t-field='product.name'></h5>
</div>
</a>
</div>
</t>
</div>
</div>
</xpath>
</template>
<template id="reduction_code" inherit_option_id="website_sale.mycart" name="Reduction Code">
<xpath expr="//table[@id='mycart_total']" position="after">
<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>
</xpath>
</template>
<!-- Page confirm my cart -->
@@ -249,7 +341,7 @@
<tbody t-if="order.order_line">
<t t-foreach="order.order_line" t-as="line">
<tr>
<td><t t-esc="line.name"/></td>
<td><t t-esc="line.name"/> <t t-if="line.product_id.variants">(<small t-field="line.product_id.variants"/>)</t></td>
<td><t t-esc="line.product_uom_qty"/></td>
<td><t t-esc="line.product_id.list_price"/>€</td>
</tr>
+5 -3
View File
@@ -29,10 +29,12 @@ class product_pricelist(osv.osv):
}
class product_product(osv.osv):
_inherit = "product.product"
_inherit = "product.template"
_columns = {
'website_published': fields.boolean('Available in the website'),
'description_website': fields.html('Description for the website'),
'suggested_product_id': fields.many2one('product.product', 'Suggested For Product'),
'suggested_product_ids': fields.one2many('product.product', 'suggested_product_id', 'Suggested Products'),
}
def recommended_products(self, cr, uid, ids, context=None):
@@ -47,14 +49,14 @@ class product_product(osv.osv):
AND sol.product_id not in (%s)
GROUP BY sol.product_id
ORDER BY COUNT(sol.order_id) DESC
LIMIT 8
LIMIT 10
"""
cr.execute(query, (id, id))
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)])
product_ids = self.search(cr, uid, [("id", "in", product_ids)], limit=3)
return self.browse(cr, uid, product_ids)
def img(self, cr, uid, ids, field='image_small', context=None):