[MERGE] from upstream
bzr revid: fva@openerp.com-20130820164644-eg5z05o2e339qf67
This commit is contained in:
+29
-28
@@ -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."),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
import controllers
|
||||
import website_contract
|
||||
@@ -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])
|
||||
@@ -0,0 +1 @@
|
||||
import controllers
|
||||
@@ -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&model=project.task&id=#{task.id}"><span t-field="task.name"/></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -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,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"/>
|
||||
|
||||
@@ -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 ('&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>
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user