[MERGE] with lp:~openerp-dev/openobject-addons/trunk-website-al and removed temporary solution.

bzr revid: dka@tinyerp.com-20140121054638-b7hbckj39vsk93tm
This commit is contained in:
Darshan Kalola (OpenERP) 2014-01-21 11:16:38 +05:30
commit 9ce241349f
58 changed files with 691 additions and 520 deletions

View File

@ -123,7 +123,7 @@ for a particular financial year and for preparation of vouchers there is a modul
'edi/invoice_action_data.xml',
'account_bank_view.xml',
'res_config_view.xml',
#'account_pre_install.yml'
'account_pre_install.yml'
],
'js': [
'static/src/js/account_move_reconciliation.js',

View File

@ -32,6 +32,7 @@
<record id="delivery_carrier" model="delivery.carrier">
<field name="name">The Poste</field>
<field name="normal_price">20</field>
<field name="partner_id" ref="res_partner_23"/>
<field name="product_id" ref="product_product_delivery"/>
</record>

View File

@ -2,7 +2,6 @@
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
try:
import simplejson as json
@ -17,9 +16,9 @@ _logger = logging.getLogger(__name__)
class AdyenController(http.Controller):
_return_url = '/payment/adyen/return/'
@website.route([
@http.route([
'/payment/adyen/return/',
], type='http', auth='public')
], type='http', auth='public', website=True)
def adyen_return(self, pspReference, **post):
""" Paypal IPN."""
post["pspReference"] = pspReference

View File

@ -4,7 +4,6 @@ import pprint
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
_logger = logging.getLogger(__name__)
@ -15,12 +14,12 @@ class OgoneController(http.Controller):
_exception_url = '/payment/ogone/test/exception'
_cancel_url = '/payment/ogone/test/cancel'
@website.route([
@http.route([
'/payment/ogone/accept', '/payment/ogone/test/accept',
'/payment/ogone/decline', '/payment/ogone/test/decline',
'/payment/ogone/exception', '/payment/ogone/test/exception',
'/payment/ogone/cancel', '/payment/ogone/test/cancel',
], type='http', auth='admin')
], type='http', auth='admin', website=True)
def ogone_form_feedback(self, **post):
""" Ogone contacts using GET, at least for accept """
_logger.info('Ogone: entering form_feedback with post data %s', pprint.pformat(post)) # debug

View File

@ -11,7 +11,6 @@ import urllib2
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
_logger = logging.getLogger(__name__)
@ -54,18 +53,18 @@ class PaypalController(http.Controller):
_logger.warning('Paypal: unrecognized paypal answer, received %s instead of VERIFIED or INVALID' % resp.text)
return res
@website.route([
@http.route([
'/payment/paypal/ipn/',
], type='http', auth='public', methods=['POST'])
], type='http', auth='public', methods=['POST'], website=True)
def paypal_ipn(self, **post):
""" Paypal IPN. """
_logger.info('Beginning Paypal IPN form_feedback with post data %s', pprint.pformat(post)) # debug
self.paypal_validate_data(**post)
return ''
@website.route([
@http.route([
'/payment/paypal/dpn',
], type='http', auth="public", methods=['POST'])
], type='http', auth="public", methods=['POST'], website=True)
def paypal_dpn(self, **post):
""" Paypal DPN """
_logger.info('Beginning Paypal DPN form_feedback with post data %s', pprint.pformat(post)) # debug
@ -73,9 +72,9 @@ class PaypalController(http.Controller):
self.paypal_validate_data(**post)
return request.redirect(return_url)
@website.route([
@http.route([
'/payment/paypal/cancel',
], type='http', auth="public")
], type='http', auth="public", website=True)
def paypal_cancel(self, **post):
""" When the user cancels its Paypal payment: GET on this route """
cr, uid, context = request.cr, request.uid, request.context

View File

@ -4,7 +4,6 @@ import pprint
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
_logger = logging.getLogger(__name__)
@ -12,9 +11,9 @@ _logger = logging.getLogger(__name__)
class OgoneController(http.Controller):
_accept_url = '/payment/transfer/feedback'
@website.route([
@http.route([
'/payment/transfer/feedback',
], type='http', auth='admin')
], type='http', auth='admin', website=True)
def transfer_form_feedback(self, **post):
cr, uid, context = request.cr, request.uid, request.context
_logger.info('Beginning form_feedback with post data %s', pprint.pformat(post)) # debug

View File

@ -145,7 +145,7 @@ function openerp_pos_db(instance, module){
for(var i = 0, len = products.length; i < len; i++){
var product = products[i];
var search_string = this._product_search_string(product);
var categ_id = product.public_categ_id ? product.public_categ_id[0] : this.root_category_id;
var categ_id = product.pos_categ_id ? product.pos_categ_id[0] : this.root_category_id;
if(!stored_categories[categ_id]){
stored_categories[categ_id] = [];
}

View File

@ -197,25 +197,19 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
}).then(function(packagings){
self.db.add_packagings(packagings);
return self.fetch('pos.category', ['id','name','parent_id','child_id','image'])
}).then(function(categories){
self.db.add_categories(categories);
return self.fetch(
'product.product',
['name', 'list_price','price', 'public_categ_id', 'taxes_id', 'ean13', 'default_code',
['name', 'list_price','price','pos_categ_id', 'taxes_id', 'ean13', 'default_code',
'to_weight', 'uom_id', 'uos_id', 'uos_coeff', 'mes_type', 'description_sale', 'description'],
[['sale_ok','=',true],['available_in_pos','=',true]],
{pricelist: self.pricelist.id} // context for price
);
}).then(function(products){
self.tmp_products = products;
var category_ids = _.without(_.uniq(_.map(products, function (product) {return product.public_categ_id[0] || 0;})), 0);
return self.fetch(
'product.public.category',
['id','name','parent_id','child_id','image'],
['|', ['id','=',category_ids], ['child_id','=',category_ids]]
);
}).then(function(categories){
self.db.add_categories(categories);
self.db.add_products(self.tmp_products);
self.db.add_products(products);
return self.fetch(
'account.bank.statement',

View File

@ -436,7 +436,8 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
},
get_image_url: function(category){
return instance.session.url('/web/binary/image', {model: 'product.public.category', field: 'image_medium', id: category.id});
return window.location.origin + '/web/binary/image?model=pos.category&field=image_medium&id='+category.id;
},
render_category: function( category, with_image ){
var cached = this.category_cache.get_node(category.id);

View File

@ -29,8 +29,9 @@ logger = logging.getLogger(__name__)
NOPE = object()
# Completely arbitrary limits
MAX_IMAGE_WIDTH, MAX_IMAGE_HEIGHT = IMAGE_LIMITS = (1024, 768)
class Website(openerp.addons.web.controllers.main.Home):
@website.route('/', type='http', auth="public", multilang=True)
@http.route('/', type='http', auth="public", website=True, multilang=True)
def index(self, **kw):
try:
main_menu = request.registry['ir.model.data'].get_object(request.cr, request.uid, 'website', 'main_menu')
@ -41,7 +42,7 @@ class Website(openerp.addons.web.controllers.main.Home):
pass
return self.page("website.homepage")
@website.route('/pagenew/<path:path>', type='http', auth="user")
@http.route('/pagenew/<path:path>', type='http', auth="user")
def pagenew(self, path, noredirect=NOPE):
web = request.registry['website']
try:
@ -59,7 +60,7 @@ class Website(openerp.addons.web.controllers.main.Home):
return werkzeug.wrappers.Response(url, mimetype='text/plain')
return werkzeug.utils.redirect(url)
@website.route('/website/theme_change', type='http', auth="admin")
@http.route('/website/theme_change', type='http', auth="admin", website=True)
def theme_change(self, theme_id=False, **kwargs):
imd = request.registry['ir.model.data']
view = request.registry['ir.ui.view']
@ -81,25 +82,33 @@ class Website(openerp.addons.web.controllers.main.Home):
return request.website.render('website.themes', {'theme_changed': True})
@website.route(['/website/snippets'], type='json', auth="public")
@http.route(['/website/snippets'], type='json', auth="public", website=True)
def snippets(self):
return request.website._render('website.snippets')
@website.route('/page/<page:page>', type='http', auth="public", multilang=True)
@http.route('/page/<page:page>', type='http', auth="public", website=True, multilang=True)
def page(self, page, **opt):
values = {
'path': page,
}
# allow shortcut for /page/<website_xml_id>
if '.' not in page:
page = 'website.%s' % page
try:
request.website.get_template(page)
except (Exception), e:
module, xmlid = page.split('.', 1)
model, view_id = request.registry["ir.model.data"].get_object_reference(request.cr, request.uid, module, xmlid)
values['main_object'] = request.registry["ir.ui.view"].browse(request.cr, request.uid, view_id, context=request.context)
except ValueError, e:
# page not found
if request.context['editable']:
page = 'website.page_404'
else:
return request.registry['ir.http']._handle_exception(e, 404)
return request.website.render(page, values)
@website.route('/website/reset_templates', type='http', auth='user', methods=['POST'])
@http.route('/website/reset_templates', type='http', auth='user', methods=['POST'], website=True)
def reset_template(self, templates, redirect='/'):
templates = request.httprequest.form.getlist('templates')
modules_to_update = []
@ -115,7 +124,7 @@ class Website(openerp.addons.web.controllers.main.Home):
module_obj.button_immediate_upgrade(request.cr, request.uid, module_ids, context=request.context)
return request.redirect(redirect)
@website.route('/website/customize_template_toggle', type='json', auth='user')
@http.route('/website/customize_template_toggle', type='json', auth='user', website=True)
def customize_template_set(self, view_id):
view_obj = request.registry.get("ir.ui.view")
view = view_obj.browse(request.cr, request.uid, int(view_id),
@ -129,7 +138,7 @@ class Website(openerp.addons.web.controllers.main.Home):
}, context=request.context)
return True
@website.route('/website/customize_template_get', type='json', auth='user')
@http.route('/website/customize_template_get', type='json', auth='user', website=True)
def customize_template_get(self, xml_id, optional=True):
imd = request.registry['ir.model.data']
view_model, view_theme_id = imd.get_object_reference(
@ -164,7 +173,7 @@ class Website(openerp.addons.web.controllers.main.Home):
})
return result
@website.route('/website/get_view_translations', type='json', auth='admin')
@http.route('/website/get_view_translations', type='json', auth='admin', website=True)
def get_view_translations(self, xml_id, lang=None):
lang = lang or request.context.get('lang')
views = self.customize_template_get(xml_id, optional=False)
@ -173,7 +182,7 @@ class Website(openerp.addons.web.controllers.main.Home):
irt = request.registry.get('ir.translation')
return irt.search_read(request.cr, request.uid, domain, ['id', 'res_id', 'value'], context=request.context)
@website.route('/website/set_translations', type='json', auth='admin')
@http.route('/website/set_translations', type='json', auth='admin', website=True)
def set_translations(self, data, lang):
irt = request.registry.get('ir.translation')
for view_id, trans in data.items():
@ -208,7 +217,7 @@ class Website(openerp.addons.web.controllers.main.Home):
irt.create(request.cr, request.uid, new_trans)
return True
@website.route('/website/attach', type='http', auth='user')
@http.route('/website/attach', type='http', auth='user', website=True)
def attach(self, func, upload):
req = request.httprequest
if req.method != 'POST':
@ -238,7 +247,7 @@ class Website(openerp.addons.web.controllers.main.Home):
window.parent['%s'](%s, %s);
</script>""" % (func, json.dumps(url), json.dumps(message))
@website.route(['/website/publish'], type='json', auth="public")
@http.route(['/website/publish'], type='json', auth="public", website=True)
def publish(self, id, object):
_id = int(id)
_object = request.registry[object]
@ -255,23 +264,23 @@ class Website(openerp.addons.web.controllers.main.Home):
obj = _object.browse(request.cr, request.uid, _id)
return bool(obj.website_published)
@website.route(['/website/kanban/'], type='http', auth="public", methods=['POST'])
@http.route(['/website/kanban/'], type='http', auth="public", methods=['POST'], website=True)
def kanban(self, **post):
return request.website.kanban_col(**post)
@website.route(['/robots.txt'], type='http', auth="public")
@http.route(['/robots.txt'], type='http', auth="public", website=True)
def robots(self):
response = request.website.render('website.robots', {'url_root': request.httprequest.url_root})
response.mimetype = 'text/plain'
return response
@website.route('/sitemap', type='http', auth='public', multilang=True)
@http.route('/sitemap', type='http', auth='public', website=True, multilang=True)
def sitemap(self):
return request.website.render('website.sitemap', {
'pages': request.website.enumerate_pages()
})
@website.route('/sitemap.xml', type='http', auth="public")
@http.route('/sitemap.xml', type='http', auth="public", website=True)
def sitemap_xml(self):
response = request.website.render('website.sitemap_xml', {
'pages': request.website.enumerate_pages()
@ -289,7 +298,7 @@ class Images(http.Controller):
response.set_data(f.read())
return response.make_conditional(request.httprequest)
@website.route('/website/image', auth="public")
@http.route('/website/image', auth="public", website=True)
def image(self, model, id, field, max_width=maxint, max_height=maxint):
Model = request.registry[model]
@ -354,5 +363,4 @@ class Images(http.Controller):
return response
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -150,11 +150,11 @@
</record>
<record model="ir.attachment">
<field name="name">landscape_tree</field>
<field name="datas_fname">landscape_tree.jpg</field>
<field name="name">imac</field>
<field name="datas_fname">imac.png</field>
<field name="res_model">ir.ui.view</field>
<field name="type">url</field>
<field name="url">/website/static/src/img/library/landscape_tree.jpg</field>
<field name="url">/website/static/src/img/library/imac.png</field>
</record>
<record model="ir.attachment">
@ -174,11 +174,11 @@
</record>
<record model="ir.attachment">
<field name="name">personal_laptop</field>
<field name="datas_fname">personal_laptop.jpg</field>
<field name="name">ipad</field>
<field name="datas_fname">ipad.png</field>
<field name="res_model">ir.ui.view</field>
<field name="type">url</field>
<field name="url">/website/static/src/img/library/personal_laptop.jpg</field>
<field name="url">/website/static/src/img/library/ipad.png</field>
</record>
<record model="ir.attachment">

View File

@ -38,15 +38,15 @@ class ir_http(orm.AbstractModel):
func = None
try:
func, arguments = self._find_handler()
request.cms = getattr(func, 'cms', False)
request.website_enabled = func.routing.get('website', False)
except werkzeug.exceptions.NotFound:
# either we have a language prefixed route, either a real 404
# in all cases, website processes them
request.cms = True
request.website_enabled = True
if request.cms:
if request.website_enabled:
if func:
self._authenticate(getattr(func, 'auth', None))
self._authenticate(func.routing['auth'])
else:
self._auth_method_public()
request.website = request.registry['website'].get_current_website(request.cr, request.uid, context=request.context)
@ -82,7 +82,7 @@ class ir_http(orm.AbstractModel):
def _handle_exception(self, exception=None, code=500):
if isinstance(exception, werkzeug.exceptions.HTTPException) and exception.response:
return exception.response
if getattr(request, 'cms', False) and request.website:
if getattr(request, 'website_enabled', False) and request.website:
values = dict(
exception=exception,
traceback=traceback.format_exc(exception),

View File

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
import fnmatch
import functools
import inspect
import logging
import math
@ -17,19 +16,11 @@ import openerp
from openerp.osv import orm, osv, fields
from openerp.tools.safe_eval import safe_eval
from openerp.addons.web import http
from openerp.addons.web.http import request, LazyResponse
from ..utils import slugify
logger = logging.getLogger(__name__)
def route(routes, *route_args, **route_kwargs):
def decorator(f):
f.cms = True
f.multilang = route_kwargs.pop('multilang', False)
return http.route(routes, *route_args, **route_kwargs)(f)
return decorator
def url_for(path_or_uri, lang=None, keep_query=None):
location = path_or_uri.strip()
url = urlparse.urlparse(location)
@ -101,7 +92,7 @@ class website(osv.osv):
def _get_menu_website(self, cr, uid, ids, context=None):
# IF a menu is changed, update all websites
return self.search(cr, uid, [], context=context)
def _get_menu(self, cr, uid, ids, name, arg, context=None):
root_domain = [('parent_id', '=', False)]
menus = self.pool.get('website.menu').search(cr, uid, root_domain, order='id', context=context)
@ -178,9 +169,7 @@ class website(osv.osv):
page = self.page_for_name(cr, uid, ids, name, module=module, context=context)
try:
return self.get_template(
cr, uid, ids, template=page, context=context
).exists()
self.pool["ir.model.data"].get_object_reference(cr, uid, module, name)
except:
return False
@ -193,6 +182,7 @@ class website(osv.osv):
def _get_languages(self, cr, uid, id, context=None):
website = self.browse(cr, uid, id)
return [(lg.code, lg.name) for lg in website.language_ids]
def get_languages(self, cr, uid, ids, context=None):
return self._get_languages(cr, uid, ids[0])
@ -218,28 +208,19 @@ class website(osv.osv):
translatable=not is_master_lang,
)
def get_template(self, cr, uid, ids, template, context=None):
IMD = self.pool["ir.model.data"]
try:
module, xmlid = template.split('.', 1)
model, id = IMD.get_object_reference(cr, uid, module, xmlid)
except ValueError: # catches both unpack errors and gor errors
module, xmlid = 'website', template
model, id = IMD.get_object_reference(cr, uid, module, xmlid)
return self.pool["ir.ui.view"].browse(cr, uid, id, context=context)
def _render(self, cr, uid, ids, template, values=None, context=None):
user = self.pool.get("res.users")
if not context:
context = {}
qweb_context = context.copy()
# Take a context
qweb_values = context.copy()
# add some values
if values:
qweb_context.update(values)
qweb_context.update(
request=request, # TODO maybe rename to _request to mark this attribute as unsafe
qweb_values.update(values)
# fill some defaults
qweb_values.update(
request=request,
json=simplejson,
website=request.website,
url_for=url_for,
@ -248,17 +229,12 @@ class website(osv.osv):
user_id=user.browse(cr, uid, uid),
quote_plus=quote_plus,
)
qweb_values.setdefault('editable', False)
context.update(
inherit_branding=qweb_context.setdefault('editable', False),
)
# in edit mode ir.ui.view will tag nodes
context['inherit_branding']=qweb_values['editable']
view = self.get_template(cr, uid, ids, template)
if 'main_object' not in qweb_context:
qweb_context['main_object'] = view
#context['debug'] = True
result = view.render(qweb_context, engine='website.qweb', context=context)
result = self.pool['ir.ui.view'].render(cr, uid, template, qweb_values, engine='website.qweb', context=context)
return result
def render(self, cr, uid, ids, template, values=None, status_code=None, context=None):
@ -328,10 +304,10 @@ class website(osv.osv):
converters = rule._converters.values()
return (
'GET' in methods
and endpoint.exposed == 'http'
and endpoint.auth in ('none', 'public')
and getattr(endpoint, 'cms', False)
'GET' in methods
and endpoint.routing['type'] == 'http'
and endpoint.routing['auth'] in ('none', 'public')
and endpoint.routing.get('website', False)
# preclude combinatorial explosion by only allowing a single converter
and len(converters) <= 1
# ensure all converters on the rule are able to generate values for
@ -513,7 +489,6 @@ class website(osv.osv):
html += request.website._render(template, {'object_id': object_id})
return html
class website_menu(osv.osv):
_name = "website.menu"
_description = "Website Menu"
@ -669,3 +644,5 @@ class SeoMetadata(osv.Model):
'website_meta_description': fields.text("Website meta description", size=160, translate=True),
'website_meta_keywords': fields.char("Website meta keywords", translate=True),
}
# vim:et:

View File

@ -1,5 +1,5 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_website_public,website,website.model_website,base.group_public,1,0,0,0
access_website_public,website,website.model_website,,1,0,0,0
access_website,website,website.model_website,base.group_user,1,0,0,0
access_website_menu,access_website_menu,model_website_menu,,1,0,0,0
access_website_converter_test,access_website_converter_test,model_website_converter_test,,1,1,1,1
@ -17,5 +17,5 @@ access_website_qweb_field_html,access_website_qweb_field_html,model_website_qweb
access_website_qweb_field_image,access_website_qweb_field_image,model_website_qweb_field_image,,0,0,0,0
access_website_qweb_field_monetary,access_website_qweb_field_monetary,model_website_qweb_field_monetary,,0,0,0,0
access_website_ir_ui_view,access_website_ir_ui_view,model_ir_ui_view,base.group_website_designer,1,1,1,1
access_seo_public,access_seo_public,model_website_seo_metadata,base.group_public,1,0,0,0
access_seo_public,access_seo_public,model_website_seo_metadata,,1,0,0,0
access_seo_designer,access_seo_designer,model_website_seo_metadata,base.group_website_designer,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_website_public website website.model_website base.group_public 1 0 0 0
3 access_website website website.model_website base.group_user 1 0 0 0
4 access_website_menu access_website_menu model_website_menu 1 0 0 0
5 access_website_converter_test access_website_converter_test model_website_converter_test 1 1 1 1
17 access_website_qweb_field_image access_website_qweb_field_image model_website_qweb_field_image 0 0 0 0
18 access_website_qweb_field_monetary access_website_qweb_field_monetary model_website_qweb_field_monetary 0 0 0 0
19 access_website_ir_ui_view access_website_ir_ui_view model_ir_ui_view base.group_website_designer 1 1 1 1
20 access_seo_public access_seo_public model_website_seo_metadata base.group_public 1 0 0 0
21 access_seo_designer access_seo_designer model_website_seo_metadata base.group_website_designer 1 1 1 1

View File

@ -95,6 +95,13 @@ h1.text-muted, h2.text-muted, h3.text-muted {
margin-top: 10px;
}
header a.navbar-brand.logo {
padding: 0 15px;
}
header a.navbar-brand img {
max-height: 50px;
}
/* ----- BOOTSTRAP FIX ----- */
.container .container {
padding-left: 0;
@ -167,7 +174,7 @@ footer {
}
.oe_structure.oe_empty:empty:before, [data-oe-type=html]:empty:before, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child:before, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:before {
content: "This page is under construction";
content: "Page under construction";
text-align: center;
display: block;
padding-top: 160px;

View File

@ -61,6 +61,13 @@ img.shadow
h1.text-muted, h2.text-muted, h3.text-muted
margin-top: 10px
header
a.navbar-brand.logo
padding: 0 15px
a.navbar-brand
img
max-height: 50px
/* ----- BOOTSTRAP FIX ----- */
.container
@ -125,7 +132,7 @@ footer
position: static
.oe_structure.oe_empty:empty:before, [data-oe-type=html]:empty:before, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child:before, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:before
content: 'This page is under construction'
content: 'Page under construction'
text-align: center
display: block
padding-top: 160px

Binary file not shown.

After

Width:  |  Height:  |  Size: 1002 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 885 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 469 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -638,16 +638,14 @@
var $selected = $(this);
var position = $selected.offset();
if ($selected.is('img')) {
var image_top = position.top + parseInt($selected.css('marginTop'), 10);
var image_left = position.left + parseInt($selected.css('marginLeft'), 10);
$link_button.hide();
// center button on image
$image_button.show().offset({
top: $selected.outerHeight() / 2
+ image_top
+ position.top
- $image_button.outerHeight() / 2,
left: $selected.outerWidth() / 2
+ image_left
+ position.left
- $image_button.outerWidth() / 2,
});
} else {

View File

@ -1126,8 +1126,6 @@
var grid = [-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11];
this.grid.w = [_.map(grid, function (v) {return 'col-md-offset-'+v;}), _.map(grid, function (v) {return width/12*v;}), 12];
this.grid.s = null;
return this.grid;
},
_drag_and_drop_after_insert_dropzone: function(){

View File

@ -19,73 +19,108 @@
});
this.registerSteps();
},
registerSteps: function () {
registerStep: function (step) {
var self = this;
this.tour.addSteps(_.map(this.steps, function (step) {
step.title = openerp.qweb.render('website.tour_popover_title', { title: step.title });
if (!step.element) {
step.orphan = true;
}
if (step.snippet) {
step.element = '#oe_snippets div.oe_snippet[data-snippet-id="'+step.snippet+'"] .oe_snippet_thumbnail';
}
if (step.trigger) {
if (step.trigger === 'click') {
step.title = openerp.qweb.render('website.tour_popover_title', { title: step.title });
if (!step.element) {
step.orphan = true;
}
if (step.snippet) {
step.element = '#oe_snippets div.oe_snippet[data-snippet-id="'+step.snippet+'"] .oe_snippet_thumbnail';
}
if (step.trigger) {
if (step.trigger === 'click') {
step.triggers = function (callback) {
$(step.element).one('click', function () {
(callback || self.moveToNextStep).apply(self);
});
};
} else if (step.trigger === 'reload') {
step.triggers = function (callback) {
var stack = JSON.parse(localStorage.getItem("website-reloads")) || [];
var index = stack.indexOf(step.stepId);
if (index !== -1 || window.localStorage.getItem("test-wait-reload")) {
stack.splice(index,1);
(callback || self.moveToNextStep).apply(self);
} else {
stack.push(step.stepId);
}
localStorage.setItem("website-reloads", JSON.stringify(stack));
};
} else if (step.trigger.url) {
step.triggers = function (callback) {
var stack = JSON.parse(localStorage.getItem("website-geturls")) || [];
var id = step.trigger.url.toString();
var index = stack.indexOf(id);
if (index !== -1) {
var url = new website.UrlParser(window.location.href);
var test = typeof step.trigger.url === "string" ?
step.trigger.url == url.pathname+url.search :
step.trigger.url.test(url.pathname+url.search);
if (!test) return;
stack.splice(index,1);
(callback || self.moveToNextStep).apply(self);
} else {
stack.push(id);
}
localStorage.setItem("website-geturls", JSON.stringify(stack));
};
} else if (step.trigger === 'drag') {
step.triggers = function (callback) {
self.onSnippetDragged(callback || self.moveToNextStep);
};
} else if (step.trigger.id) {
if (step.trigger.emitter && step.trigger.type === 'openerp') {
step.triggers = function (callback) {
$(step.element).one('click', function () {
(callback || self.moveToNextStep).apply(self);
step.trigger.emitter.on(step.trigger.id, self, function customHandler () {
step.trigger.emitter.off(step.trigger.id, customHandler);
(callback || self.moveToNextStep).apply(self, arguments);
});
};
} else if (step.trigger === 'drag') {
} else {
step.triggers = function (callback) {
self.onSnippetDragged(callback || self.moveToNextStep);
};
} else if (step.trigger && step.trigger.id) {
if (step.trigger.emitter && step.trigger.type === 'openerp') {
step.triggers = function (callback) {
step.trigger.emitter.on(step.trigger.id, self, function customHandler () {
step.trigger.emitter.off(step.trigger.id, customHandler);
(callback || self.moveToNextStep).apply(self, arguments);
});
};
} else {
step.triggers = function (callback) {
var emitter = _.isString(step.trigger.emitter) ? $(step.trigger.emitter) : (step.trigger.emitter || $(step.element));
emitter.on(step.trigger.id, function () {
(callback || self.moveToNextStep).apply(self, arguments);
});
};
}
} else if (step.trigger.modal) {
step.triggers = function (callback) {
var $doc = $(document);
function onStop () {
if (step.trigger.modal.stopOnClose) {
self.stop();
}
}
$doc.on('hide.bs.modal', onStop);
$doc.one('shown.bs.modal', function () {
$('.modal button.btn-primary').one('click', function () {
$doc.off('hide.bs.modal', onStop);
(callback || self.moveToNextStep).apply(self, [step.trigger.modal.afterSubmit]);
});
(callback || self.moveToNextStep).apply(self);
var emitter = _.isString(step.trigger.emitter) ? $(step.trigger.emitter) : (step.trigger.emitter || $(step.element));
if (!emitter.size()) throw "Emitter is undefined";
emitter.on(step.trigger.id, function () {
(callback || self.moveToNextStep).apply(self, arguments);
});
};
}
}
step.onShow = (function () {
var executed = false;
return function () {
if (!executed) {
_.isFunction(step.onStart) && step.onStart();
_.isFunction(step.triggers) && step.triggers();
executed = true;
} else if (step.trigger.modal) {
step.triggers = function (callback) {
var $doc = $(document);
function onStop () {
if (step.trigger.modal.stopOnClose) {
self.stop();
}
}
$doc.on('hide.bs.modal', onStop);
$doc.one('shown.bs.modal', function () {
$('.modal button.btn-primary').one('click', function () {
$doc.off('hide.bs.modal', onStop);
(callback || self.moveToNextStep).apply(self, [step.trigger.modal.afterSubmit]);
});
(callback || self.moveToNextStep).apply(self);
});
};
}());
return step;
}
}
step.onShow = (function () {
var executed = false;
return function () {
if (!executed) {
_.isFunction(step.onStart) && step.onStart();
_.isFunction(step.triggers) && step.triggers();
executed = true;
}
};
}());
return step;
},
registerSteps: function () {
var self = this;
this.tour.addSteps(_.map(this.steps, function (step) {
return self.registerStep(step);
}));
},
reset: function () {
@ -301,6 +336,9 @@
var actionSteps = _.filter(tour.steps, function (step) {
return step.trigger || step.sampleText;
});
window.onbeforeunload = function () {
window.localStorage.setItem("test-wait-reload", true);
};
function executeStep (step) {
window.localStorage.setItem(testId, step.stepId);
function next () {
@ -312,23 +350,32 @@
}
}
setTimeout(function () {
if (step.triggers) step.triggers(next);
var $element = $(step.element);
if (step.snippet && step.trigger === 'drag') {
website.TestConsole.dragAndDropSnippet(step.snippet);
} else if (step.trigger && step.trigger.id === 'change') {
$element.trigger($.Event("change", { srcElement: $element }));
} else if (step.sampleText) {
$element.val(step.sampleText);
$element.trigger($.Event("change", { srcElement: $element }));
} else if ($element.is(":visible")) { // Click by default
$element.trigger($.Event("click", { srcElement: $element }));
}
if (!step.triggers) next();
}, step.delay || defaultDelay);
var $element = $(step.element);
if (step.triggers) step.triggers(next);
window.localStorage.removeItem("test-wait-reload");
if (step.snippet && step.trigger === 'drag') {
website.TestConsole.dragAndDropSnippet(step.snippet);
} else if (step.trigger && step.trigger.id === 'change') {
$element.trigger($.Event("change", { srcElement: $element }));
} else if (step.sampleText) {
$element.val(step.sampleText);
$element.trigger($.Event("change", { srcElement: $element }));
} else if ($element.is(":visible")) { // Click by default
if (step.trigger.id === 'mousedown') {
$element.trigger($.Event("mousedown", { srcElement: $element }));
}
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
$element[0].dispatchEvent(evt);
if (step.trigger.id === 'mouseup') {
$element.trigger($.Event("mouseup", { srcElement: $element }));
}
}
if (!step.triggers) next();
}, step.delay || defaultDelay);
}
var url = new website.UrlParser(window.location.href);
if (tour.path && url.pathname !== tour.path) {
if (tour.path && url.pathname !== tour.path && !window.localStorage.getItem(testId)) {
window.localStorage.setItem(testId, actionSteps[0].stepId);
window.location.href = tour.path;
} else {

View File

@ -141,11 +141,11 @@ class WebsiteUiSuite(unittest.TestSuite):
except ValueError:
result.addError(self._test, 'Unexpected message: "%s"' % "\n".join(lines))
def full_path(filename):
return os.path.join(os.path.join(os.path.dirname(__file__), 'ui_suite'), filename)
def full_path(pyfile, filename):
return os.path.join(os.path.join(os.path.dirname(pyfile), 'ui_suite'), filename)
def load_tests(loader, base, _):
base.addTest(WebsiteUiSuite(full_path('dummy_test.js'), {}, 5.0))
base.addTest(WebsiteUiSuite(full_path('simple_dom_test.js'), { 'action': 'website.action_website_homepage' }, 60.0))
base.addTest(WebsiteUiSuite(full_path('homepage_test.js'), { 'action': 'website.action_website_homepage' }, 60.0))
base.addTest(WebsiteUiSuite(full_path(__file__, 'dummy_test.js'), {}, 5.0))
base.addTest(WebsiteUiSuite(full_path(__file__, 'simple_dom_test.js'), { 'action': 'website.action_website_homepage' }, 60.0))
base.addTest(WebsiteUiSuite(full_path(__file__, 'homepage_test.js'), { 'action': 'website.action_website_homepage' }, 60.0))
return base

View File

@ -683,11 +683,7 @@
</div>
<section class="oe_snippet_body mb16">
<div class="container">
<div class="row">
<div class="col-md-12 text-center mb16">
<h2>List of Features</h2>
<h4 class="text-muted">Add a great slogan</h4>
</div>
<div class="row mt16 mb16">
<div class="col-md-3 text-center">
<span class="fa fa-suitcase fa-5x"></span>
<h3 class="mt8 mb0">First Feature</h3>
@ -697,7 +693,7 @@
<div class="col-md-3 text-center">
<span class="fa fa-lock fa-5x"></span>
<h3 class="mt8 mb0">Second Feature</h3>
<p class="text-muted">Talk about what the customer would like to know, not what you want to show.</p>
<p class="text-muted">Write what the customer would like to know, not what you want to show.</p>
<p><a class="btn btn-success">Take Tour</a></p>
</div>
<div class="col-md-3 text-center">
@ -725,54 +721,46 @@
<section class="oe_snippet_body mb16">
<div class="container">
<div class="row">
<div class="col-md-5 text-center mb16">
<div class="col-md-5 text-center">
<h2>List of Features</h2>
<h4 class="text-muted">Add a great slogan</h4>
</div>
<div class="col-md-5 text-center mb16 col-md-offset-2">
<div class="col-md-5 text-center col-md-offset-2">
<h2>Second List</h2>
<h4 class="text-muted">Add a great slogan</h4>
</div>
</div><div class="row">
<div class="col-md-5">
<div class="col-md-5 mt16 mb16">
<div class="row">
<div class="col-md-12">
<span style="min-width: 45px" class="fa fa-3x fa-comment pull-left mb16"></span>
<h3 class="mt0 mb0">Blog</h3>
<p>OpenERP includes a full features enterprise blog to promote your messages.</p>
<h3 class="mt0 mb0">Change Icons</h3>
<p>Click on the icon to adapt it to your feature</p>
</div><div class="col-md-12">
<span style="min-width: 45px" class="fa fa-3x fa-columns pull-left mb16"></span>
<h3 class="mt0 mb0">Pricing Tables</h3>
<p>Use building blocks to use pricing tables to display your products or services.</p>
<h3 class="mt0 mb0">Duplicate</h3>
<p>Duplicate blocks to add more features.</p>
</div><div class="col-md-12">
<span style="min-width: 45px" class="fa fa-3x fa-user pull-left mb16"></span>
<h3 class="mt0 mb0">Log In &amp; Signup</h3>
<p>Clean &amp; simple Log In, Signup &amp; Forgot Your Password forms.</p>
</div><div class="col-md-12">
<span style="min-width: 45px" class="fa fa-3x fa-envelope pull-left mb16"></span>
<h3 class="mt0 mb0">Contact</h3>
<p>User-friendly contact form with Google Map integration.</p>
<h3 class="mt0 mb0">Delete Blocks</h3>
<p class="text-muted">Select and delete blocks to remove some features.</p>
</div>
</div>
</div>
<div class="col-md-5 col-md-offset-2">
<div class="col-md-5 col-md-offset-2 mt16 mb16">
<div class="row">
<div class="col-md-12">
<span style="min-width: 45px" class="fa fa-3x fa-magic pull-left mb16"></span>
<h3 class="mt0 mb0">Bootstrap</h3>
<p>Uses Twitter Bootstrap's sleek, intuitive, and powerful front-end framework.</p>
</div><div class="col-md-12">
<span style="min-width: 45px" class="fa fa-3x fa-font pull-left mb16"></span>
<h3 class="mt0 mb0">Google Web Fonts</h3>
<p>Royalty free, open source fonts for the people, by the people!</p>
<h3 class="mt0 mb0">Great Value</h3>
<p>Tell features the visitor would like to know, not what you'd like to say.</p>
</div><div class="col-md-12">
<span style="min-width: 45px" class="fa fa-3x fa-bolt pull-left mb16"></span>
<h3 class="mt0 mb0">Powerful &amp; slick jQuery</h3>
<p>Fantastic jQuery plugins such as Isotope and Bootstrap's inbuilt features.</p>
<h3 class="mt0 mb0">Change Background</h3>
<p>From the main container, you can change the background to highlight features.</p>
</div><div class="col-md-12">
<span style="min-width: 45px" class="fa fa-3x fa-picture-o pull-left mb16"></span>
<h3 class="mt0 mb0">Sample images</h3>
<p>Fantastic sample images fully licensed for use.</p>
<p>All these icons are licensed under creative commons so that you can use them.</p>
</div>
</div>
</div>
@ -891,7 +879,7 @@
</li>
</div>
<div data-snippet-style-id='background' data-selector="section, section[data-snippet-id='parallax'], div[data-snippet-id='carousel']">
<div data-snippet-style-id='background' data-selector="section, section[data-snippet-id='parallax'], div[data-snippet-id='carousel'], div[data-snippet-id='slider']">
<li class="dropdown-submenu">
<a tabindex="-1" href="#">Background</a>
<ul class="dropdown-menu">

View File

@ -96,8 +96,8 @@
<t t-foreach="website.menu_id.child_id" t-as="submenu">
<t t-call="website.submenu"/>
</t>
<li class="divider"/>
<li class="dropdown" t-ignore="true" t-if="user_id.id != website.public_user.id">
<li class="divider" groups="base.group_user,base.group_portal"/>
<li class="dropdown" t-ignore="true" groups="base.group_user,base.group_portal">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<b>
<span t-esc="user_id.name"/>
@ -162,7 +162,7 @@
</p>
</div>
<t t-set="languages" t-value="website.get_languages()"/>
<ul class="nav nav-pills js_language_selector" t-if="(len(languages) &gt; 1 or editable)">
<ul class="list-inline js_language_selector mt16" t-if="(len(languages) &gt; 1 or editable)">
<li t-foreach="languages" t-as="lg">
<a t-att-href="url_for('', lang=lg[0], keep_query='*')"
t-att-data-default-lang="editable and 'true' if lg[0] == website.default_lang_code else None">
@ -180,7 +180,7 @@
</div>
</div>
</div>
<div class="container mt16">
<div class="container mt16 mb8">
<div class="pull-right" t-ignore="true" t-if="not editable">
Create a <a href="http://openerp.com/apps/website">free website</a> with
<a class="label label-danger" href="https://openerp.com/apps/website">OpenERP</a>
@ -195,6 +195,14 @@
</html>
</template>
<template id="layout_logo_show" inherit_option_id="website.layout" name="Show Logo">
<xpath expr="//header//a[@class='navbar-brand']" position="replace">
<a href="/" class="navbar-brand logo">
<img src="/website/static/src/img/odoo_logo.png"/>
</a>
</xpath>
</template>
<template id="editor_head" inherit_id="website.layout" name="Editor" groups="base.group_website_publisher">
<xpath expr='//t[@name="layout_head"]' position="before">
<link rel='stylesheet' href='/website/static/src/css/snippets.css'/>
@ -231,11 +239,10 @@
</xpath>
</template>
<template id="show_sign_in" inherit_option_id="website.layout" inherit_id="website.layout" name="Show Sign In">
<xpath expr="//ul[@id='top_menu']" position="inside">
<li t-if="user_id.id == website.public_user.id">
<li class="divider" groups="base.group_public"/>
<li groups="base.group_public">
<a t-attf-href="/web#redirect=#{ quote_plus(url_for('', keep_query='*')) }">
<b>Sign in</b>
</a>
@ -674,30 +681,6 @@ Sitemap: <t t-esc="url_root"/>sitemap.xml
</div>
</section>
<div class="parallax oe_structure mt16 oe_medium mb64" data-scroll-background-ratio="0.6" data-snippet-id="parallax" style="background-image: url(http://localhost:8069/website/static/src/img/parallax/parallax_bg.jpg); background-attachment: scroll; background-position: 0px 0px; ">
<section class="mb32 mt16" data-snippet-id="references">
<div class="container">
<div class="row">
<div class="col-md-12 mt16 mb8">
<h1 class="text-center">What do customers say about us...?</h1>
</div>
<div class="col-md-4 col-md-offset-1 mt16 mb0">
<blockquote data-snippet-id="quote">
<p><span style="background-color:#FFFFFF;">Write here a quote from one of your customer. Quotes are are great way to give confidence in your products or services.</span></p>
<small><span style="background-color:#FFFFFF;">Author of this quote</span></small>
</blockquote>
</div>
<div class="col-md-4 col-md-offset-2 mt16 mb32">
<blockquote data-snippet-id="quote">
<p><span style="background-color:#FFFFFF;">OpenERP provides essential platform for our project management. Things are better organized and more visible with it.</span></p>
<small><span style="background-color:#FFFFFF;">John Doe, CEO</span></small>
</blockquote>
</div>
</div>
</div>
</section>
</div>
</div>
<div class="oe_structure"></div>
</div>

View File

@ -45,10 +45,10 @@ class WebsiteBlog(http.Controller):
group['date'] = "%s_%s" % (group['__domain'][0][2], group['__domain'][1][2])
return groups
@website.route([
@http.route([
'/blog',
'/blog/page/<int:page>/',
], type='http', auth="public", multilang=True)
], type='http', auth="public", website=True, multilang=True)
def blogs(self, page=1):
BYPAGE = 60
cr, uid, context = request.cr, request.uid, request.context
@ -67,7 +67,7 @@ class WebsiteBlog(http.Controller):
'pager': pager
})
@website.route([
@http.route([
'/blog/<model("blog.category"):category>/',
'/blog/<model("blog.category"):category>/page/<int:page>/',
'/blog/<model("blog.category"):category>/tag/<model("blog.tag"):tag>/',
@ -76,7 +76,7 @@ class WebsiteBlog(http.Controller):
'/blog/<model("blog.category"):category>/date/<string(length=21):date>/page/<int:page>/',
'/blog/<model("blog.category"):category>/tag/<model("blog.tag"):tag>/date/<string(length=21):date>/',
'/blog/<model("blog.category"):category>/tag/<model("blog.tag"):tag>/date/<string(length=21):date>/page/<int:page>/',
], type='http', auth="public", multilang=True)
], type='http', auth="public", website=True, multilang=True)
def blog(self, category=None, tag=None, date=None, page=1, **opt):
""" Prepare all values to display the blog.
@ -152,9 +152,9 @@ class WebsiteBlog(http.Controller):
}
return request.website.render("website_blog.blog_post_short", values)
@website.route([
@http.route([
'/blogpost/<model("blog.post"):blog_post>/',
], type='http', auth="public", multilang=True)
], type='http', auth="public", website=True, multilang=True)
def blog_post(self, blog_post, tag=None, date=None, page=1, enable_editor=None, **post):
""" Prepare all values to display the blog.
@ -219,7 +219,7 @@ class WebsiteBlog(http.Controller):
}
return request.website.render("website_blog.blog_post_complete", values)
@website.route(['/blogpost/comment'], type='http', auth="public", methods=['POST'])
@http.route(['/blogpost/comment'], type='http', auth="public", methods=['POST'], website=True)
def blog_post_comment(self, blog_post_id=0, **post):
cr, uid, context = request.cr, request.uid, request.context
if post.get('comment'):
@ -238,7 +238,7 @@ class WebsiteBlog(http.Controller):
context=dict(context, mail_create_nosubcribe=True))
return werkzeug.utils.redirect(request.httprequest.referrer + "#comments")
@website.route('/blogpost/new', type='http', auth="public", multilang=True)
@http.route('/blogpost/new', type='http', auth="public", website=True, multilang=True)
def blog_post_create(self, category_id, **post):
cr, uid, context = request.cr, request.uid, request.context
create_context = dict(context, mail_create_nosubscribe=True)
@ -251,7 +251,7 @@ class WebsiteBlog(http.Controller):
}, context=create_context)
return werkzeug.utils.redirect("/blogpost/%s/?enable_editor=1" % new_blog_post_id)
@website.route('/blogpost/duplicate', type='http', auth="public")
@http.route('/blogpost/duplicate', type='http', auth="public", website=True)
def blog_post_copy(self, blog_post_id, **post):
""" Duplicate a blog.

View File

@ -1,10 +1,5 @@
import os
import openerp.addons.website.tests.test_ui as test_ui
def full_path(filename):
return os.path.join(os.path.join(os.path.dirname(__file__), 'ui_suite'), filename)
import openerp.addons.website.tests.test_ui as test_ui,full_path
def load_tests(loader, base, _):
base.addTest(test_ui.WebsiteUiSuite(full_path('post_test.js'), { 'action': 'website.action_website_homepage' }, 60.0))
base.addTest(test_ui.WebsiteUiSuite(full_path(__file__,'post_test.js'), { 'action': 'website.action_website_homepage' }, 60.0))
return base

View File

@ -2,7 +2,6 @@
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
from openerp import SUPERUSER_ID
from urllib import quote_plus
@ -16,7 +15,7 @@ class contactus(http.Controller):
)
return url
@website.route(['/crm/contactus'], type='http', auth="public", multilang=True)
@http.route(['/crm/contactus'], type='http', auth="public", website=True, multilang=True)
def contactus(self, *arg, **post):
required_fields = ['contact_name', 'email_from', 'description']
post['user_id'] = False

View File

@ -9,20 +9,19 @@ from openerp.tools.translate import _
from openerp.addons.web.http import request
from openerp.addons.website.models import website
from openerp.addons.website_partner.controllers import main as website_partner
import werkzeug
class WebsiteCrmPartnerAssign(http.Controller):
_references_per_page = 20
@website.route([
@http.route([
'/partners/',
'/partners/page/<int:page>/',
'/partners/country/<int:country_id>',
'/partners/country/<country_name>-<int:country_id>',
'/partners/country/<int:country_id>/page/<int:page>/',
'/partners/country/<country_name>-<int:country_id>/page/<int:page>/',
], type='http', auth="public", multilang=True)
], type='http', auth="public", website=True, multilang=True)
def partners(self, country_id=0, page=0, **post):
country_obj = request.registry['res.country']
partner_obj = request.registry['res.partner']
@ -95,7 +94,7 @@ class WebsiteCrmPartnerAssign(http.Controller):
}
return request.website.render("website_crm_partner_assign.index", values)
@website.route(['/partners/<int:partner_id>/', '/partners/<partner_name>-<int:partner_id>/'], type='http', auth="public", multilang=True)
@http.route(['/partners/<int:partner_id>/', '/partners/<partner_name>-<int:partner_id>/'], type='http', auth="public", website=True, multilang=True)
def partners_ref(self, partner_id, **post):
partner = request.registry['res.partner'].browse(request.cr, SUPERUSER_ID, partner_id, context=request.context)
website.preload_records(partner)

View File

@ -13,14 +13,14 @@ import urllib
class WebsiteCustomer(http.Controller):
_references_per_page = 20
@website.route([
@http.route([
'/customers/',
'/customers/page/<int:page>/',
'/customers/country/<int:country_id>',
'/customers/country/<country_name>-<int:country_id>',
'/customers/country/<int:country_id>/page/<int:page>/',
'/customers/country/<country_name>-<int:country_id>/page/<int:page>/',
], type='http', auth="public", multilang=True)
], type='http', auth="public", website=True, multilang=True)
def customers(self, country_id=0, page=0, **post):
cr, uid, context = request.cr, request.uid, request.context
partner_obj = request.registry['res.partner']
@ -76,7 +76,7 @@ class WebsiteCustomer(http.Controller):
}
return request.website.render("website_customer.index", values)
@website.route(['/customers/<int:partner_id>/', '/customers/<partner_name>-<int:partner_id>/'], type='http', auth="public", multilang=True)
@http.route(['/customers/<int:partner_id>/', '/customers/<partner_name>-<int:partner_id>/'], type='http', auth="public", website=True, multilang=True)
def customer(self, partner_id, **post):
partner = request.registry['res.partner'].browse(request.cr, SUPERUSER_ID, partner_id, context=request.context)
website.preload_records(partner)

View File

@ -34,7 +34,7 @@ from openerp import tools
import urllib
class website_event(http.Controller):
@website.route(['/event/', '/event/page/<int:page>'], type='http', auth="public", multilang=True)
@http.route(['/event/', '/event/page/<int:page>'], type='http', auth="public", website=True, multilang=True)
def events(self, page=1, **searches):
cr, uid, context = request.cr, request.uid, request.context
event_obj = request.registry['event.event']
@ -161,7 +161,7 @@ class website_event(http.Controller):
return request.website.render("website_event.index", values)
@website.route(['/event/<model("event.event"):event>/page/<page:page>'], type='http', auth="public", multilang=True)
@http.route(['/event/<model("event.event"):event>/page/<page:page>'], type='http', auth="public", website=True, multilang=True)
def event_page(self, event, page, **post):
website.preload_records(event, on_error="website_event.404")
values = {
@ -170,7 +170,7 @@ class website_event(http.Controller):
}
return request.website.render(page, values)
@website.route(['/event/<model("event.event"):event>'], type='http', auth="public", multilang=True)
@http.route(['/event/<model("event.event"):event>'], type='http', auth="public", website=True, multilang=True)
def event(self, event, **post):
website.preload_records(event, on_error="website_event.404")
if event.menu_id and event.menu_id.child_id:
@ -181,7 +181,7 @@ class website_event(http.Controller):
target_url += '?enable_editor=1'
return request.redirect(target_url);
@website.route(['/event/<model("event.event"):event>/register'], type='http', auth="public", multilang=True)
@http.route(['/event/<model("event.event"):event>/register'], type='http', auth="public", website=True, multilang=True)
def event_register(self, event, **post):
website.preload_records(event, on_error="website_event.404")
values = {
@ -192,16 +192,17 @@ class website_event(http.Controller):
}
return request.website.render("website_event.event_description_full", values)
@website.route(['/event/add_cart'], type='http', auth="public", multilang=True)
@http.route(['/event/add_cart'], type='http', auth="public", website=True, multilang=True)
def add_cart(self, event_id, **post):
user_obj = request.registry['res.users']
order_line_obj = request.registry.get('sale.order.line')
ticket_obj = request.registry.get('event.event.ticket')
order_obj = request.registry.get('sale.order')
website = request.registry['website']
order = request.registry['website'].get_current_order(request.cr, request.uid, context=request.context)
order = website.ecommerce_get_current_order(request.cr, request.uid, context=request.context)
if not order:
order = request.registry['website']._get_order(request.cr, request.uid, context=request.context)
order = website.ecommerce_get_new_order(request.cr, request.uid, context=request.context)
partner_id = user_obj.browse(request.cr, SUPERUSER_ID, request.uid,
context=request.context).partner_id.id
@ -246,7 +247,7 @@ class website_event(http.Controller):
return request.redirect("/event/%s/" % event_id)
return request.redirect("/shop/checkout")
@website.route(['/event/publish'], type='json', auth="public")
@http.route(['/event/publish'], type='json', auth="public", website=True)
def publish(self, id, object):
# if a user publish an event, he publish all linked res.partner
event = request.registry[object].browse(request.cr, request.uid, int(id))
@ -258,7 +259,7 @@ class website_event(http.Controller):
return controllers.publish(id, object)
@website.route('/event/add_event/', type='http', auth="user", multilang=True, methods=['POST'])
@http.route('/event/add_event/', type='http', auth="user", multilang=True, methods=['POST'], website=True)
def add_event(self, event_name="New Event", **kwargs):
Event = request.registry.get('event.event')
date_begin = datetime.today() + timedelta(days=(15)) # FIXME: better defaults

View File

@ -2,6 +2,6 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_event_event_public,event.event.public,event.model_event_event,base.group_public,1,0,0,0
access_event_type_public,event.type.public,event.model_event_type,base.group_public,1,0,0,0
access_event_event_ticket_public,event.event.ticket.public,event_sale.model_event_event_ticket,,1,0,0,0
access_event_event_ticket_public,event.event.ticket.public,event_sale.model_event_event_ticket,event.group_event_manager,1,1,1,1
access_event_event_ticket_admin,event.event.ticket.admin,event_sale.model_event_event_ticket,event.group_event_manager,1,1,1,1
access_event_product_product_public,event.product.product.public,product.model_product_product,base.group_public,1,0,0,0
access_event_product_template_public,event.product.template.public,product.model_product_template,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_event_event_public event.event.public event.model_event_event base.group_public 1 0 0 0
3 access_event_type_public event.type.public event.model_event_type base.group_public 1 0 0 0
4 access_event_event_ticket_public event.event.ticket.public event_sale.model_event_event_ticket 1 0 0 0
5 access_event_event_ticket_public access_event_event_ticket_admin event.event.ticket.public event.event.ticket.admin event_sale.model_event_event_ticket event.group_event_manager 1 1 1 1
6 access_event_product_product_public event.product.product.public product.model_product_product base.group_public 1 0 0 0
7 access_event_product_template_public event.product.template.public product.model_product_template base.group_public 1 0 0 0

View File

@ -1,10 +1,5 @@
import os
import openerp.addons.website.tests.test_ui as test_ui
def full_path(filename):
return os.path.join(os.path.join(os.path.dirname(__file__), 'ui_suite'), filename)
import openerp.addons.website.tests.test_ui as test_ui,full_path
def load_tests(loader, base, _):
base.addTest(test_ui.WebsiteUiSuite(full_path('event_test.js'), { 'action': 'website.action_website_homepage' }, 60.0))
base.addTest(test_ui.WebsiteUiSuite(full_path(__file__,'event_test.js'), { 'action': 'website.action_website_homepage' }, 60.0))
return base

View File

@ -30,7 +30,7 @@ import werkzeug.utils
controllers = controllers()
class website_event(http.Controller):
@website.route(['/event/<model("event.event"):event>/track/<model("event.track"):track>'], type='http', auth="public", multilang=True)
@http.route(['/event/<model("event.event"):event>/track/<model("event.track"):track>'], type='http', auth="public", website=True, multilang=True)
def event_track_view(self, event, track, **post):
# TODO: not implemented
website.preload_records(event, on_error="website_event.404")
@ -38,7 +38,7 @@ class website_event(http.Controller):
values = { 'track': track, 'event': track.event_id, 'main_object': track }
return request.website.render("website_event_track.track_view", values)
@website.route(['/event/<model("event.event"):event>/agenda/'], type='http', auth="public", multilang=True)
@http.route(['/event/<model("event.event"):event>/agenda/'], type='http', auth="public", website=True, multilang=True)
def event_agenda(self, event, tag=None, **post):
website.preload_records(event, on_error="website_event.404")
values = {
@ -47,10 +47,10 @@ class website_event(http.Controller):
}
return request.website.render("website_event_track.agenda", values)
@website.route([
@http.route([
'/event/<model("event.event"):event>/track/',
'/event/<model("event.event"):event>/track/tag/<model("event.track.tag"):tag>'
], type='http', auth="public", multilang=True)
], type='http', auth="public", website=True, multilang=True)
def event_tracks(self, event, tag=None, **post):
website.preload_records(event, on_error="website_event.404")
website.preload_records(tag)
@ -80,13 +80,13 @@ class website_event(http.Controller):
@website.route(['/event/<model("event.event"):event>/track_proposal/'], type='http', auth="public", multilang=True)
@http.route(['/event/<model("event.event"):event>/track_proposal/'], type='http', auth="public", website=True, multilang=True)
def event_track_proposal(self, event, **post):
website.preload_records(event, on_error="website_event.404")
values = { 'event': event }
return request.website.render("website_event_track.event_track_proposal", values)
@website.route(['/event/<model("event.event"):event>/track_proposal/post'], type='http', auth="public", methods=['POST'], multilang=True)
@http.route(['/event/<model("event.event"):event>/track_proposal/post'], type='http', auth="public", methods=['POST'], website=True, multilang=True)
def event_track_proposal_post(self, event, **post):
cr, uid, context = request.cr, request.uid, request.context

View File

@ -3,12 +3,11 @@
import openerp
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
from datetime import datetime
class google_map(http.Controller):
@website.route(['/google_map/'], type='http', auth="admin")
@http.route(['/google_map/'], type='http', auth="admin", website=True)
def google_map(self, *arg, **post):
values = {
'partner_ids': post.get('partner_ids', ""),
@ -18,7 +17,7 @@ class google_map(http.Controller):
}
return request.website.render("website_google_map.google_map", values)
@website.route(['/google_map/partners.json'], type='http', auth="admin")
@http.route(['/google_map/partners.json'], type='http', auth="admin", website=True)
def google_map_data(self, *arg, **post):
partner_obj = request.registry['res.partner']
@ -29,7 +28,7 @@ class google_map(http.Controller):
return partner_obj.google_map_json(request.cr, openerp.SUPERUSER_ID,
partner_ids, request.context)
@website.route(['/google_map/set_partner_position/'], type='http', auth="admin")
@http.route(['/google_map/set_partner_position/'], type='http', auth="admin", website=True)
def google_map_set_partner_position(self, *arg, **post):
partner_obj = request.registry['res.partner']

View File

@ -2,11 +2,10 @@
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
class website_hr(http.Controller):
@website.route(['/page/website.aboutus'], type='http', auth="public", multilang=True)
@http.route(['/page/website.aboutus'], type='http', auth="public", website=True, multilang=True)
def blog(self, **post):
hr_obj = request.registry['hr.employee']
employee_ids = hr_obj.search(request.cr, request.uid, [('website_published', '=', True)],

View File

@ -2,7 +2,6 @@
from openerp.addons.web import http
from openerp.tools.translate import _
from openerp.addons.web.http import request
from openerp.addons.website.models import website
from openerp.addons.website.controllers.main import Website as controllers
controllers = controllers()
@ -10,12 +9,12 @@ import base64
class website_hr_recruitment(http.Controller):
@website.route([
@http.route([
'/jobs',
'/jobs/department/<model("hr.department"):department>/office/<model("res.partner"):office>',
'/jobs/department/<model("hr.department"):department>',
'/jobs/office/<model("res.partner"):office>'
], type='http', auth="public", multilang=True)
], type='http', auth="public", website=True, multilang=True)
def jobs(self, department=None, office=None):
JobsObj = request.registry['hr.job']
jobpost_ids = JobsObj.search(request.cr, request.uid, [],
@ -47,11 +46,11 @@ class website_hr_recruitment(http.Controller):
'office': office and office.id or None
})
@website.route(['/job/detail/<model("hr.job"):job>'], type='http', auth="public", multilang=True)
@http.route(['/job/detail/<model("hr.job"):job>'], type='http', auth="public", website=True, multilang=True)
def detail(self, job, **kwargs):
return request.website.render("website_hr_recruitment.detail", { 'job': job, 'main_object': job })
@website.route(['/job/success'], methods=['POST'], type='http', auth="admin", multilang=True)
@http.route(['/job/success'], methods=['POST'], type='http', auth="admin", website=True, multilang=True)
def success(self, **post):
data = {
'name': _('Online Form'),
@ -84,7 +83,7 @@ class website_hr_recruitment(http.Controller):
request.registry['ir.attachment'].create(request.cr, request.uid, attachment_values, context=request.context)
return request.website.render("website_hr_recruitment.thankyou", {})
@website.route(['/job/apply'], type='http', auth="public", multilang=True)
@http.route(['/job/apply'], type='http', auth="public", website=True, multilang=True)
def applyjobpost(self, job):
[job_object] = request.registry['hr.job'].browse(
request.cr, request.uid, [int(job)], context=request.context)
@ -93,7 +92,7 @@ class website_hr_recruitment(http.Controller):
'job': job_object
})
@website.route('/job/add_job_offer/', type='http', auth="user", multilang=True, methods=['POST'])
@http.route('/job/add_job_offer/', type='http', auth="user", methods=['POST'], website=True, multilang=True)
def add_job_offer(self, **kwargs):
Job = request.registry.get('hr.job')
job_id = Job.create(request.cr, request.uid, {

View File

@ -3,12 +3,11 @@
# from openerp import SUPERUSER_ID
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
class WebsiteEmailDesigner(http.Controller):
@website.route('/website_mail/email_designer/<model("email.template"):template>/', type='http', auth="public", multilang=True)
@http.route('/website_mail/email_designer/<model("email.template"):template>/', type='http', auth="public", website=True, multilang=True)
def index(self, template, **kw):
values = {
'template': template,
@ -16,6 +15,6 @@ class WebsiteEmailDesigner(http.Controller):
print template
return request.website.render("website_mail.designer_index", values)
@website.route(['/website_mail/snippets'], type='json', auth="public")
@http.route(['/website_mail/snippets'], type='json', auth="public", website=True)
def snippets(self):
return request.website._render('website_mail.email_designer_snippets')

View File

@ -22,7 +22,6 @@
from openerp import SUPERUSER_ID
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
class WebsiteMail(http.Controller):
@ -40,7 +39,7 @@ class WebsiteMail(http.Controller):
partner_ids = [user_obj.browse(request.cr, request.uid, request.uid, request.context).partner_id.id]
return partner_ids
@website.route(['/website_mail/follow/'], type='json', auth="public")
@http.route(['/website_mail/follow/'], type='json', auth="public", website=True)
def website_message_subscribe(self, id=0, object=None, message_is_follower="on", email=False, **post):
_id = int(id)
_message_is_follower = message_is_follower == 'on'

View File

@ -14,7 +14,7 @@ import urllib
class WebsiteMembership(http.Controller):
_references_per_page = 20
@website.route([
@http.route([
'/members/',
'/members/page/<int:page>/',
'/members/association/<int:membership_id>/',
@ -29,7 +29,7 @@ class WebsiteMembership(http.Controller):
'/members/association/<int:membership_id>/country/<int:country_id>',
'/members/association/<int:membership_id>/country/<country_name>-<int:country_id>/page/<int:page>/',
'/members/association/<int:membership_id>/country/<int:country_id>/page/<int:page>/',
], type='http', auth="public", multilang=True)
], type='http', auth="public", website=True, multilang=True)
def members(self, membership_id=None, country_name=None, country_id=0, page=0, **post):
cr, uid, context = request.cr, request.uid, request.context
product_obj = request.registry['product.product']
@ -92,7 +92,7 @@ class WebsiteMembership(http.Controller):
}
return request.website.render("website_membership.index", values)
@website.route(['/members/<int:partner_id>/', '/members/<partner_name>-<int:partner_id>/'], type='http', auth="public", multilang=True)
@http.route(['/members/<int:partner_id>/', '/members/<partner_name>-<int:partner_id>/'], type='http', auth="public", website=True, multilang=True)
def partners_ref(self, partner_id, **post):
partner = request.registry['res.partner'].browse(request.cr, SUPERUSER_ID, partner_id, context=request.context)
website.preload_records(partner)

View File

@ -34,7 +34,7 @@ def get_partner_template_value(partner):
return values
class WebsitePartner(http.Controller):
@website.route(['/partners/<int:partner_id>/', '/partners/<partner_name>-<int:partner_id>/'], type='http', auth="public", multilang=True)
@http.route(['/partners/<int:partner_id>/', '/partners/<partner_name>-<int:partner_id>/'], type='http', auth="public", website=True, multilang=True)
def partner(self, partner_id, **post):
""" Route for displaying a single partner / customer. """
partner = request.registry['res.partner'].browse(request.cr, SUPERUSER_ID, partner_id, context=request.context)

View File

@ -21,7 +21,6 @@
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
from openerp.osv import osv
@ -39,7 +38,7 @@ class Website(osv.Model):
class website_project(http.Controller):
@website.route(['/project/<int:project_id>/'], type='http', auth="public", multilang=True)
@http.route(['/project/<int:project_id>/'], type='http', auth="public", website=True, multilang=True)
def project(self, project_id=None, **post):
cr, uid, context = request.cr, request.uid, request.context
project_obj = request.registry['project.project']
@ -52,7 +51,7 @@ class website_project(http.Controller):
}
return request.website.render("website_project.index", render_values)
@website.route(['/project/task/<int:task_id>'], type='http', auth="public", multilang=True)
@http.route(['/project/task/<int:task_id>'], type='http', auth="public", website=True, multilang=True)
def task(self, task_id=None, **post):
cr, uid, context = request.cr, request.uid, request.context
task_obj = request.registry['project.task']

View File

@ -144,7 +144,7 @@ class Ecommerce(http.Controller):
return key_val
return False
@website.route(['/shop/filters/'], type='http', auth="public", multilang=True)
@http.route(['/shop/filters/'], type='http', auth="public", website=True, multilang=True)
def filters(self, **post):
index = []
filters = []
@ -190,18 +190,18 @@ class Ecommerce(http.Controller):
att = obj.read(request.cr, request.uid, att_ids, ["product_tmpl_id"], context=request.context)
return [r["product_tmpl_id"][0] for r in att]
@website.route(['/shop/pricelist'], type='http', auth="public", multilang=True)
@http.route(['/shop/pricelist'], type='http', auth="public", website=True, multilang=True)
def shop_promo(self, code, **post):
assert code, 'No pricelist code provided'
request.registry['website']._ecommerce_change_pricelist(request.cr, request.uid, code=code, context=request.context)
return request.redirect("/shop")
@website.route([
@http.route([
'/shop/',
'/shop/page/<int:page>/',
'/shop/category/<model("product.public.category"):category>/',
'/shop/category/<model("product.public.category"):category>/page/<int:page>/'
], type='http', auth="public", multilang=True)
], type='http', auth="public", website=True, multilang=True)
def shop(self, category=None, page=0, filters='', search='', **post):
cr, uid, context = request.cr, request.uid, request.context
product_obj = request.registry.get('product.template')
@ -257,7 +257,7 @@ class Ecommerce(http.Controller):
}
return request.website.render("website_sale.products", values)
@website.route(['/shop/product/<model("product.template"):product>/'], type='http', auth="public", multilang=True)
@http.route(['/shop/product/<model("product.template"):product>/'], type='http', auth="public", website=True, multilang=True)
def product(self, product, search='', category='', filters='', **kwargs):
website.preload_records(product, on_error="website_sale.404")
@ -286,7 +286,7 @@ class Ecommerce(http.Controller):
}
return request.website.render("website_sale.product", values)
@website.route(['/shop/product/comment'], type='http', auth="public", methods=['POST'])
@http.route(['/shop/product/comment'], type='http', auth="public", methods=['POST'], website=True)
def product_comment(self, product_template_id, **post):
cr, uid, context = request.cr, request.uid, request.context
if post.get('comment'):
@ -298,7 +298,7 @@ class Ecommerce(http.Controller):
context=dict(context, mail_create_nosubcribe=True))
return werkzeug.utils.redirect(request.httprequest.referrer + "#comments")
@website.route(['/shop/add_product/'], type='http', auth="user", multilang=True, methods=['POST'])
@http.route(['/shop/add_product/'], type='http', auth="user", methods=['POST'], website=True, multilang=True)
def add_product(self, name="New Product", category=0, **post):
Product = request.registry.get('product.product')
product_id = Product.create(request.cr, request.uid, {
@ -308,75 +308,7 @@ class Ecommerce(http.Controller):
return request.redirect("/shop/product/%s/?enable_editor=1" % product.product_tmpl_id.id)
def add_product_to_cart(self, product_id=0, order_line_id=0, number=1, set_number=-1):
order_line_obj = request.registry.get('sale.order.line')
order_obj = request.registry.get('sale.order')
order = self.get_order()
if not order:
order = request.registry['website'].ecommerce_get_new_order(request.cr, request.uid, context=request.context)
request.context = dict(request.context, pricelist=self.get_pricelist())
# set order_line_id and product_id
if order_line_id:
order_line = None
for line in order.order_line:
if line.id == order_line_id:
order_line = line
break
if order_line:
product_id = order_line.product_id.id
else:
order_line_id = None
else:
order_line_ids = order_line_obj.search(
request.cr, SUPERUSER_ID,
[('order_id', '=', order.id), ('product_id', '=', product_id)], context=request.context)
if order_line_ids:
order_line_id = order_line_ids[0]
if not order_line_id and not product_id:
return 0
# values initialisation
quantity = 0
values = {}
if order_line_id:
order_line_val = order_line_obj.read(request.cr, SUPERUSER_ID, [order_line_id], [], context=request.context)[0]
if not product_id:
product_id = order_line_val['product_id'][0]
if set_number >= 0:
quantity = set_number
else:
quantity = order_line_val['product_uom_qty'] + number
if quantity < 0:
quantity = 0
order_line_ids = [order_line_id]
else:
fields = [k for k, v in order_line_obj._columns.items()]
values = order_line_obj.default_get(request.cr, SUPERUSER_ID, fields, context=request.context)
quantity = 1
order_line_ids = []
# change and record value
vals = order_line_obj._recalculate_product_values(request.cr, request.uid, order_line_ids, product_id, context=request.context)
values.update(vals)
values['product_uom_qty'] = quantity
values['product_id'] = product_id
values['order_id'] = order.id
if order_line_id:
order_line_obj.write(request.cr, SUPERUSER_ID, [order_line_id], values, context=request.context)
if not quantity:
order_line_obj.unlink(request.cr, SUPERUSER_ID, [order_line_id], context=request.context)
else:
order_line_id = order_line_obj.create(request.cr, SUPERUSER_ID, values, context=request.context)
order_obj.write(request.cr, SUPERUSER_ID, [order.id], {'order_line': [(4, order_line_id)]}, context=request.context)
return quantity
@website.route(['/shop/mycart/'], type='http', auth="public", multilang=True)
@http.route(['/shop/mycart/'], type='http', auth="public", website=True, multilang=True)
def mycart(self, **post):
cr, uid, context = request.cr, request.uid, request.context
prod_obj = request.registry.get('product.product')
@ -411,30 +343,38 @@ class Ecommerce(http.Controller):
}
return request.website.render("website_sale.mycart", values)
@website.route(['/shop/add_cart/'], type='http', auth="public", multilang=True, methods=['POST'])
@http.route(['/shop/add_cart/'], type='http', auth="public", methods=['POST'], website=True, multilang=True)
def add_cart(self, product_id, remove=None, **kw):
self.add_product_to_cart(product_id=int(product_id))
request.registry['website']._ecommerce_add_product_to_cart(request.cr, request.uid,
product_id=int(product_id),
context=request.context)
return request.redirect("/shop/mycart/")
@website.route(['/shop/change_cart/<int:order_line_id>/'], type='http', auth="public", multilang=True)
@http.route(['/shop/change_cart/<int:order_line_id>/'], type='http', auth="public", website=True, multilang=True)
def add_cart_order_line(self, order_line_id=None, remove=None, **kw):
self.add_product_to_cart(order_line_id=order_line_id, number=(remove and -1 or 1))
request.registry['website']._ecommerce_add_product_to_cart(request.cr, request.uid,
order_line_id=order_line_id, number=(remove and -1 or 1),
context=request.context)
return request.redirect("/shop/mycart/")
@website.route(['/shop/add_cart_json/'], type='json', auth="public")
@http.route(['/shop/add_cart_json/'], type='json', auth="public", website=True)
def add_cart_json(self, product_id=None, order_line_id=None, remove=None):
quantity = self.add_product_to_cart(product_id=product_id, order_line_id=order_line_id, number=(remove and -1 or 1))
quantity = request.registry['website']._ecommerce_add_product_to_cart(request.cr, request.uid,
product_id=product_id, order_line_id=order_line_id, number=(remove and -1 or 1),
context=request.context)
order = self.get_order()
return [quantity,
order.get_number_of_products(),
order.amount_total,
request.website._render("website_sale.total", {'website_sale_order': order})]
@website.route(['/shop/set_cart_json/'], type='json', auth="public")
@http.route(['/shop/set_cart_json/'], type='json', auth="public", website=True)
def set_cart_json(self, path=None, product_id=None, order_line_id=None, set_number=0, json=None):
return self.add_product_to_cart(product_id=product_id, order_line_id=order_line_id, set_number=set_number)
return request.registry['website']._ecommerce_add_product_to_cart(request.cr, request.uid,
product_id=product_id, order_line_id=order_line_id, set_number=set_number,
context=request.context)
@website.route(['/shop/checkout/'], type='http', auth="public", multilang=True)
@http.route(['/shop/checkout/'], type='http', auth="public", website=True, multilang=True)
def checkout(self, **post):
cr, uid, context, registry = request.cr, request.uid, request.context, request.registry
@ -488,7 +428,7 @@ class Ecommerce(http.Controller):
return request.website.render("website_sale.checkout", values)
@website.route(['/shop/confirm_order/'], type='http', auth="public", multilang=True)
@http.route(['/shop/confirm_order/'], type='http', auth="public", website=True, multilang=True)
def confirm_order(self, **post):
cr, uid, context, registry = request.cr, request.uid, request.context, request.registry
order_line_obj = request.registry.get('sale.order')
@ -544,8 +484,8 @@ class Ecommerce(http.Controller):
billing_info['parent_id'] = company_id
if request.uid != request.registry['website'].get_public_user(cr, uid, context):
partner_id = orm_user.browse(cr, uid, uid, context=context).partner_id.id
orm_parter.write(cr, uid, [partner_id], billing_info, context=context)
partner_id = orm_user.browse(cr, SUPERUSER_ID, uid, context=context).partner_id.id
orm_parter.write(cr, SUPERUSER_ID, [partner_id], billing_info, context=context)
else:
partner_id = orm_parter.create(cr, SUPERUSER_ID, billing_info, context=context)
@ -587,7 +527,7 @@ class Ecommerce(http.Controller):
return request.redirect("/shop/payment/")
@website.route(['/shop/payment/'], type='http', auth="public", multilang=True)
@http.route(['/shop/payment/'], type='http', auth="public", website=True, multilang=True)
def payment(self, **post):
""" Payment step. This page proposes several payment means based on available
payment.acquirer. State at this point :
@ -645,8 +585,8 @@ class Ecommerce(http.Controller):
return request.website.render("website_sale.payment", values)
@website.route(['/shop/payment/transaction/<int:acquirer_id>'],
type='http', methods=['POST'], auth="public")
@http.route(['/shop/payment/transaction/<int:acquirer_id>'],
type='http', methods=['POST'], auth="public", website=True)
def payment_transaction(self, acquirer_id, **post):
""" Hook method that creates a payment.transaction and redirect to the
acquirer, using post values to re-create the post action.
@ -688,7 +628,7 @@ class Ecommerce(http.Controller):
acquirer_total_url = '%s?%s' % (acquirer_form_post_url, urllib.urlencode(post))
return request.redirect(acquirer_total_url)
@website.route('/shop/payment/get_status/<int:sale_order_id>', type='json', auth="public", multilang=True)
@http.route('/shop/payment/get_status/<int:sale_order_id>', type='json', auth="public", website=True, multilang=True)
def payment_get_status(self, sale_order_id, **post):
cr, uid, context = request.cr, request.uid, request.context
@ -713,7 +653,7 @@ class Ecommerce(http.Controller):
'state': tx.state,
}
@website.route('/shop/payment/validate/', type='http', auth="public", multilang=True)
@http.route('/shop/payment/validate/', type='http', auth="public", website=True, multilang=True)
def payment_validate(self, transaction_id=None, sale_order_id=None, **post):
""" Method that should be called by the server when receiving an update
for a transaction. State at this point :
@ -754,7 +694,7 @@ class Ecommerce(http.Controller):
return request.redirect('/shop/confirmation/%s' % order.id)
@website.route(['/shop/confirmation/<int:sale_order_id>'], type='http', auth="public", multilang=True)
@http.route(['/shop/confirmation/<int:sale_order_id>'], type='http', auth="public", website=True, multilang=True)
def payment_confirmation(self, sale_order_id, **post):
""" End of checkout process controller. Confirmation is basically seing
the status of a sale.order. State at this point :
@ -770,7 +710,7 @@ class Ecommerce(http.Controller):
return request.website.render("website_sale.confirmation", {'order': order})
@website.route(['/shop/change_sequence/'], type='json', auth="public")
@http.route(['/shop/change_sequence/'], type='json', auth="public", website=True)
def change_sequence(self, id, sequence):
product_obj = request.registry.get('product.template')
if sequence == "top":
@ -782,7 +722,7 @@ class Ecommerce(http.Controller):
elif sequence == "down":
product_obj.set_sequence_down(request.cr, request.uid, [id], context=request.context)
@website.route(['/shop/change_styles/'], type='json', auth="public")
@http.route(['/shop/change_styles/'], type='json', auth="public", website=True)
def change_styles(self, id, style_id):
product_obj = request.registry.get('product.template')
product = product_obj.browse(request.cr, request.uid, id, context=request.context)
@ -804,7 +744,7 @@ class Ecommerce(http.Controller):
return not active
@website.route(['/shop/change_size/'], type='json', auth="public")
@http.route(['/shop/change_size/'], type='json', auth="public", website=True)
def change_size(self, id, x, y):
product_obj = request.registry.get('product.template')
product = product_obj.browse(request.cr, request.uid, id, context=request.context)

View File

@ -24,7 +24,7 @@
</record>
<record id="website_sale.image_promo" model="website.product.style">
<field name="name">Promo Ribbon</field>
<field name="name">Sale Ribbon</field>
<field name="html_class">oe_ribbon_promo</field>
</record>
<record id="website_sale.image_full" model="website.product.style">

View File

@ -57,6 +57,73 @@ class Website(orm.Model):
# Ecommerce quotation management
# ************************************************************
def _ecommerce_add_product_to_cart(self, cr, uid, product_id=0, order_line_id=0, number=1, set_number=-1, context=None):
order = self.ecommerce_get_current_order(cr, uid, context=context)
if not order:
order = self.ecommerce_get_new_order(cr, uid, context=context)
order_line_obj = self.pool.get('sale.order.line')
order_obj = self.pool.get('sale.order')
context = dict(context, pricelist=self.ecommerce_get_pricelist_id(cr, uid, None, context=context))
# set order_line_id and product_id
if order_line_id:
order_line = None
for line in order.order_line:
if line.id == order_line_id:
order_line = line
break
if order_line:
product_id = order_line.product_id.id
else:
order_line_id = None
else:
order_line_ids = order_line_obj.search(cr, SUPERUSER_ID,
[('order_id', '=', order.id), ('product_id', '=', product_id)], context=context)
if order_line_ids:
order_line_id = order_line_ids[0]
if not order_line_id and not product_id:
return 0
# values initialisation
quantity = 0
values = {}
if order_line_id:
order_line_val = order_line_obj.read(cr, SUPERUSER_ID, [order_line_id], [], context=context)[0]
if not product_id:
product_id = order_line_val['product_id'][0]
if set_number >= 0:
quantity = set_number
else:
quantity = order_line_val['product_uom_qty'] + number
if quantity < 0:
quantity = 0
order_line_ids = [order_line_id]
else:
fields = [k for k, v in order_line_obj._columns.items()]
values = order_line_obj.default_get(cr, SUPERUSER_ID, fields, context=context)
quantity = 1
order_line_ids = []
# change and record value
vals = order_line_obj._recalculate_product_values(cr, uid, order_line_ids, product_id, context=context)
values.update(vals)
values['product_uom_qty'] = quantity
values['product_id'] = product_id
values['order_id'] = order.id
if order_line_id:
order_line_obj.write(cr, SUPERUSER_ID, [order_line_id], values, context=context)
if not quantity:
order_line_obj.unlink(cr, SUPERUSER_ID, [order_line_id], context=context)
else:
order_line_id = order_line_obj.create(cr, SUPERUSER_ID, values, context=context)
order_obj.write(cr, SUPERUSER_ID, [order.id], {'order_line': [(4, order_line_id)]}, context=context)
return quantity
def _ecommerce_get_quotation_values(self, cr, uid, context=None):
""" Generate the values for a new ecommerce quotation. """
SaleOrder = self.pool.get('sale.order')
@ -86,8 +153,7 @@ class Website(orm.Model):
order_id = self._ecommerce_create_quotation(cr, uid, context=context)
request.httprequest.session['ecommerce_order_id'] = order_id
order = SaleOrder.browse(cr, SUPERUSER_ID, order_id, context=context)
return SaleOrder.browse(cr, uid, order_id, context=dict(request.context, pricelist=order.pricelist_id.id))
return SaleOrder.browse(cr, SUPERUSER_ID, order_id, context=context)
def ecommerce_get_current_order(self, cr, uid, context=None):
SaleOrder = self.pool.get('sale.order')

View File

@ -1,14 +1,14 @@
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_product_category_,product.category.public,product.model_product_category,base.group_public,1,0,0,0
access_product_category_public,product.category.public,product.model_product_public_category,base.group_public,1,0,0,0
access_product_pricelist_version_public,product.pricelist.version.public,product.model_product_pricelist_version,base.group_public,1,0,0,0
access_product_pricelist_public,product.pricelist.public,product.model_product_pricelist,base.group_public,1,0,0,0
access_product_pricelist_item_public,product.pricelist.item.public,product.model_product_pricelist_item,base.group_public,1,0,0,0
access_product_product_price_type_public,product.price.type.public,product.model_product_price_type,base.group_public,1,0,0,0
access_product_product_public,product.product.public,product.model_product_product,,1,0,0,0
access_product_template_public,product.template.public,product.model_product_template,,1,0,0,0
access_product_category_public,product.category.public,product.model_product_category,,1,0,0,0
access_product_public_category_public,product.category.public,product.model_product_public_category,,1,0,0,0
access_product_pricelist_version_public,product.pricelist.version.public,product.model_product_pricelist_version,,1,0,0,0
access_product_pricelist_public,product.pricelist.public,product.model_product_pricelist,,1,0,0,0
access_product_pricelist_item_public,product.pricelist.item.public,product.model_product_pricelist_item,,1,0,0,0
access_product_product_price_type_public,product.price.type.public,product.model_product_price_type,,1,0,0,0
access_product_characteristic,product.characteristic.public,website_sale.model_product_characteristic,,1,0,0,0
access_product_characteristic_value,product.characteristic.value.public,website_sale.model_product_characteristic_value,,1,0,0,0
access_product_characteristic_product,product.characteristic.product.public,website_sale.model_product_characteristic_product,,1,0,0,0
access_website_product_style,website.product.style.public,website_sale.model_website_product_style,,1,0,0,0
access_product_supplierinfo,product.supplierinfo.public,product.model_product_supplierinfo,base.group_public,1,0,0,0
access_product_supplierinfo,product.supplierinfo.public,product.model_product_supplierinfo,,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_product_category_ access_product_category_public product.category.public product.model_product_category base.group_public 1 0 0 0
5 access_product_category_public access_product_public_category_public product.category.public product.model_product_public_category base.group_public 1 0 0 0
6 access_product_pricelist_version_public product.pricelist.version.public product.model_product_pricelist_version base.group_public 1 0 0 0
7 access_product_pricelist_public product.pricelist.public product.model_product_pricelist base.group_public 1 0 0 0
8 access_product_pricelist_item_public product.pricelist.item.public product.model_product_pricelist_item base.group_public 1 0 0 0
9 access_product_product_price_type_public product.price.type.public product.model_product_price_type base.group_public 1 0 0 0
10 access_product_characteristic product.characteristic.public website_sale.model_product_characteristic 1 0 0 0
11 access_product_characteristic_value product.characteristic.value.public website_sale.model_product_characteristic_value 1 0 0 0
12 access_product_characteristic_product product.characteristic.product.public website_sale.model_product_characteristic_product 1 0 0 0
13 access_website_product_style website.product.style.public website_sale.model_website_product_style 1 0 0 0
14 access_product_supplierinfo product.supplierinfo.public product.model_product_supplierinfo base.group_public 1 0 0 0

View File

@ -6,6 +6,7 @@
website.EditorBar.include({
start: function () {
this.registerTour(new website.EditorShopTour(this));
this.registerTour(new website.EditorShopTest(this));
return this._super();
},
});
@ -156,4 +157,154 @@
},
});
website.Test = website.Tour.extend({
registerStep: function (step) {
var self = this;
var step = this._super(step);
if (step.beforeTrigger || step.afterTrigger) {
var fn = step.triggers;
step.triggers = function (callback) {
if (step.beforeTrigger) step.beforeTrigger();
if (!step.afterTrigger) {
fn.call(step, callback);
} else {
fn.call(step, function () {
(callback || self.moveToNextStep).apply(self);
step.afterTrigger();
});
}
};
}
return step;
}
});
website.EditorShopTest = website.Test.extend({
id: 'shoptest',
name: "Try to by 3 products",
path: '/shop',
init: function (editor) {
var self = this;
self.steps = [
{
stepId: 'begin-test',
title: 'begin-test',
template: self.popover({ next: "Start Test"}),
backdrop: true,
},
{
stepId: 'display-ipod',
element: '.oe_product_cart a:contains("iPod")',
trigger: 'click',
},
{
stepId: 'display-wait-ipod',
trigger: 'reload',
},
{
stepId: 'choose-ipod',
element: 'input[name="product_id"]:not([checked])',
trigger: {
id: 'mouseup',
},
},
{
stepId: 'add-ipod',
element: 'form[action="/shop/add_cart/"] button',
trigger: {
url: '/shop/mycart/',
},
},
{
stepId: 'add-suggested-product',
element: 'form[action="/shop/add_cart/"] button:contains("Add to Cart")',
trigger: 'reload',
},
{
stepId: 'more-product',
element: '.oe_mycart a.js_add_cart_json:eq(1)',
trigger: 'click',
},
{
stepId: 'less-product',
element: '.oe_mycart a.js_add_cart_json:eq(2)',
trigger: 'reload',
},
{
stepId: 'number-product',
element: '.oe_mycart input.js_quantity',
trigger: 'reload',
beforeTrigger: function (tour, callback) {
if (parseInt($(".oe_mycart input.js_quantity").val(),10) !== 1)
$(".oe_mycart input.js_quantity").val("1").change();
},
afterTrigger: function (tour, callback) {
if ($(".oe_mycart input.js_quantity").size() !== 1)
throw "Can't remove suggested item from my cart";
if (parseInt($(".oe_mycart input.js_quantity").val(),10) !== 1)
throw "Can't defined number of items in my cart";
},
},
{
stepId: 'go-checkout-product',
element: 'a[href="/shop/checkout/"]',
trigger: {
url: '/shop/checkout/',
},
},
{
stepId: 'confirm-false-checkout-product',
element: 'form[action="/shop/confirm_order/"] button',
trigger: {
url: '/shop/confirm_order/',
},
beforeTrigger: function (tour, callback) {
$("input[name='phone']").val("");
},
},
{
stepId: 'confirm-checkout-product',
element: 'form[action="/shop/confirm_order/"] button',
trigger: {
url: '/shop/payment/',
},
beforeTrigger: function (tour, callback) {
$("input[name='phone']").val("123");
$("input[name='street']").val("123");
$("input[name='city']").val("123");
$("input[name='zip']").val("123");
$("select[name='country_id']").val("21");
},
},
{
stepId: 'delivery-checkout-product',
element: 'input[name="delivery_type"]:eq(1)',
trigger: 'reload',
},
{
stepId: 'acquirer-checkout-product',
element: 'input[name="acquirer"]',
trigger: 'mouseup',
},
{
stepId: 'pay-checkout-product',
element: 'button:contains("Pay Now")',
trigger: 'click',
},
{
stepId: 'end-test',
title: "end-test",
backdrop: true,
},
];
return this._super();
},
trigger: function () {
return (this.resume() && this.testUrl(/^\/shop\//)) || this._super();
},
});
}());

View File

@ -55,7 +55,7 @@ $(document).ready(function () {
}
set_my_cart_quantity(data[1]);
$link.parents(".input-group:first").find(".js_quantity").val(data[0]);
$('[data-oe-model="sale.order"][data-oe-field="amount_total"]').replaceWith(data[3]);
$('#mycart_total').replaceWith(data[3]);
});
return false;
});

View File

@ -0,0 +1 @@
import test_ui

View File

@ -0,0 +1,6 @@
import openerp.addons.website.tests.test_ui as test_ui,full_path
def load_tests(loader, base, _):
base.addTest(test_ui.WebsiteUiSuite(full_path(__file__,'website_sale-sale_process-test.js'),
{ 'action': 'website.action_website_homepage' }, 60.0))
return base

View File

@ -0,0 +1,31 @@
var testRunner = require('../../../website/tests/ui_suite/ui_test_runner.js');
var waitFor = testRunner.waitFor;
testRunner.run(function websiteSaleTest (page, timeout) {
page.evaluate(function () { localStorage.clear(); });
waitFor(function clientReady () {
return page.evaluate(function () {
return window.$ && window.openerp && window.openerp.website
&& window.openerp.website.TestConsole
&& window.openerp.website.TestConsole.test('shoptest');
});
}, function executeTest () {
page.evaluate(function () {
window.openerp.website.TestConsole.test('shoptest').run(true);
});
waitFor(function testExecuted () {
var after = page.evaluate(function () {
return window.$ && $('button[data-action=edit]').is(":visible") && {
image: $('#wrap [data-snippet-id=image-text]').length,
text: $('#wrap [data-snippet-id=text-block]').length,
};
});
var result = after && (after.image === 1) && (after.text === 1);
return result;
}, function finish () {
console.log('{ "event": "success" }');
phantom.exit();
}, 4*timeout/5);
}, timeout/5);
});

View File

@ -546,29 +546,7 @@
</tr>
</tbody>
</table>
<table class='pull-right mb16' id="mycart_total" t-if="website_sale_order">
<colgroup>
<col width="100"/>
<col width="120"/>
</colgroup>
<thead>
<tr style="border-top: 1px solid #000" id="order_total">
<th><h3>Total:</h3></th>
<th class="text-right">
<h3><t t-call="website_sale.total"/></h3>
</th>
</tr>
<tr class="text-muted" id="order_total_taxes">
<td><abbr title="Taxes may be updated after providing shipping address">Taxes:</abbr></td>
<td class="text-right">
<span t-field="website_sale_order.amount_tax" t-field-options='{
"widget": "monetary",
"display_currency": "website.pricelist_id.currency_id"
}'/>
</td>
</tr>
</thead>
</table>
<t t-call="website_sale.total"/>
<div class="clearfix"/>
<a href="/shop" class="btn btn-default mb32"><span class="fa fa-long-arrow-left"/> Continue Shopping</a>
<a t-if="website_sale_order and website_sale_order.website_order_line" href="/shop/checkout/" class="btn btn-primary pull-right mb32">Process Checkout <span class="fa fa-long-arrow-right"/></a>
@ -750,7 +728,7 @@
<div class="row">
<div class="col-md-8 oe_mycart">
<h3 class="page-header mt16">Billing Information
<small t-if="user_id.id == website.public_user.id"> or
<small groups="base.group_public"> or
<a t-if="not partner" t-attf-href="/web#action=redirect&amp;url=#{ request.httprequest.url }">sign in</a>
</small>
</h3>
@ -945,30 +923,7 @@
</tr>
</tbody>
</table>
<table class='pull-right mb16' id="mycart_total">
<colgroup>
<col width="100"/>
<col width="120"/>
</colgroup>
<thead>
<tr style="border-top: 1px solid #000" id="order_total">
<th><h3>Total:</h3></th>
<th class="text-right">
<h3><span t-field="website_sale_order.amount_total" t-field-options='{
"widget": "monetary",
"display_currency": "website.pricelist_id.currency_id"
}'/></h3>
</th>
</tr>
<tr class="text-muted" id="order_total_taxes">
<td>Taxes:</td>
<td class="text-right"><span t-field="website_sale_order.amount_tax" t-field-options='{
"widget": "monetary",
"display_currency": "website.pricelist_id.currency_id"
}'/></td>
</tr>
</thead>
</table>
<t t-call="website_sale.total"/>
<div class="clearfix"/>
<div class="oe_structure"/>
</div>
@ -997,12 +952,12 @@
</div>
</div>
<div class="js_payment mb64 row" t-if="acquirers" id="payment_method">
<h4>Choose your Payment Method</h4>
<div class="js_payment mb64" t-if="acquirers" id="payment_method">
<div class="col-lg-5 col-sm-6">
<h4>Payment Method:</h4>
<t t-foreach="acquirers or []" t-as="acquirer">
<label t-if="acquirer.button" class="oe_sale_acquirer_logo" style="display: block;">
<input t-att-value="acquirer.id" type="radio" name="acquirer"/>
<input t-att-value="acquirer.id" type="radio" name="acquirer" t-att-checked="acquirers[0] == acquirer"/>
<img class="media-object" style="width: 60px; display: inline-block;"
t-att-title="acquirer.name"
t-att-src="'/payment_acquirer_%s/static/src/img/%s_icon.png' % (acquirer.name, acquirer.name)"/>
@ -1011,7 +966,7 @@
</div>
<div class="col-lg-3 col-sm-3">
<t t-foreach="acquirers or []" t-as="acquirer">
<div t-att-data-id="acquirer.id" t-raw="acquirer.button" class="oe_sale_acquirer_button hidden"/>
<div t-att-data-id="acquirer.id" t-raw="acquirer.button" class="oe_sale_acquirer_button hidden pull-right"/>
</t>
</div>
</div>
@ -1075,11 +1030,36 @@
</t>
</template>
<!-- Page Shop my cart and payment total -->
<template id="total">
<span t-field="website_sale_order.amount_total" t-field-options='{
"widget": "monetary",
"display_currency": "website.pricelist_id.currency_id"
}'/>
<table class='pull-right mb16' id="mycart_total" t-if="website_sale_order">
<colgroup>
<col width="100"/>
<col width="120"/>
</colgroup>
<thead>
<tr style="border-top: 1px solid #000" id="order_total">
<th><h3>Total:</h3></th>
<th class="text-right">
<h3><span t-field="website_sale_order.amount_total" t-field-options='{
"widget": "monetary",
"display_currency": "website.pricelist_id.currency_id"
}'/></h3>
</th>
</tr>
<tr class="text-muted" id="order_total_taxes">
<td><abbr title="Taxes may be updated after providing shipping address">Taxes:</abbr></td>
<td class="text-right">
<span t-field="website_sale_order.amount_tax" t-field-options='{
"widget": "monetary",
"display_currency": "website.pricelist_id.currency_id"
}'/>
</td>
</tr>
</thead>
</table>
</template>
</data>
</openerp>

View File

@ -1,13 +1,13 @@
# -*- coding: utf-8 -*-
from openerp.addons.website_sale.controllers.main import Ecommerce
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
from openerp import SUPERUSER_ID
class Ecommerce(Ecommerce):
@website.route(['/shop/payment/'], type='http', auth="public", multilang=True)
@http.route(['/shop/payment/'], type='http', auth="public", website=True, multilang=True)
def payment(self, **post):
cr, uid, context = request.cr, request.uid, request.context
order = self.get_order()
@ -18,6 +18,7 @@ class Ecommerce(Ecommerce):
SaleOrder = request.registry['sale.order']
SaleOrder.write(cr, SUPERUSER_ID, [order.id], {'carrier_id': carrier_id}, context=context)
SaleOrder.delivery_set(cr, SUPERUSER_ID, [order.id], context=context)
return request.redirect("/shop/payment/")
res = super(Ecommerce, self).payment(**post)
return res

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from openerp.osv import orm, fields
from openerp import SUPERUSER_ID
class delivery_carrier(orm.Model):
@ -44,5 +45,5 @@ class SaleOrder(orm.Model):
delivery_ctx = dict(context, order_id=order.id)
DeliveryCarrier = self.pool.get('delivery.carrier')
delivery_ids = DeliveryCarrier.search(cr, uid, [], context=context)
values['deliveries'] = DeliveryCarrier.browse(cr, uid, delivery_ids, context=delivery_ctx)
values['deliveries'] = DeliveryCarrier.browse(cr, SUPERUSER_ID, delivery_ids, context=delivery_ctx)
return values

View File

@ -6,17 +6,35 @@ from openerp import SUPERUSER_ID
class Website(orm.Model):
_inherit = 'website'
def _ecommerce_get_quotation_values(self, cr, uid, context=None):
""" Override the quotation values generation to add carrier_id data """
values = super(Website, self)._ecommerce_get_quotation_values(cr, uid, context=context)
DeliveryCarrier = self.pool.get('delivery.carrier')
carrier_ids = DeliveryCarrier.search(cr, uid, [(1,"=",1)], context=context, limit=1)
# By default, select the first carrier
if carrier_ids:
values['carrier_id'] = carrier_ids[0]
return values
def _ecommerce_create_quotation(self, cr, uid, context=None):
order_id = super(Website, self)._ecommerce_create_quotation(cr, uid, context=context)
self.pool['sale.order'].delivery_set(cr, SUPERUSER_ID, [order_id], context=context)
order = self.pool['sale.order'].browse(cr, SUPERUSER_ID, order_id, context=context)
self._check_carrier_quotation(cr, uid, order, context=context)
return order_id
def _ecommerce_add_product_to_cart(self, cr, uid, product_id=0, order_line_id=0, number=1, set_number=-1, context=None):
quantity = super(Website, self)._ecommerce_add_product_to_cart(cr, uid,
product_id=product_id, order_line_id=order_line_id, number=number, set_number=set_number,
context=context)
order = self.ecommerce_get_current_order(cr, uid, context=context)
return self._check_carrier_quotation(cr, uid, order, context=context) and quantity or None
def _check_carrier_quotation(self, cr, uid, order, context=None):
# check to add or remove carrier_id
carrier_id = False
for line in order.website_order_line:
if line.product_id.type != "service":
carrier_id = True
break
if not carrier_id:
order.write({'carrier_id': None}, context=context)
self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context)
return None
elif not order.carrier_id:
carrier_ids = self.pool.get('delivery.carrier').search(cr, uid, [], context=context)
order.write({'carrier_id': carrier_ids[0]}, context=context)
order.delivery_set(context=context)
return None
return carrier_id

View File

@ -2,7 +2,7 @@
<openerp>
<data>
<template id="mycart_delivery" name="Delivery Costs" inherit_id="website_sale.mycart">
<template id="mycart_delivery" name="Delivery Costs" inherit_id="website_sale.total">
<xpath expr="//tr[@id='order_total_taxes']" position="after">
<tr class="text-muted" id="order_delivery">
<td><abbr title="Delivery will be updated after choosing a new delivery method">Delivery:</abbr></td>
@ -21,20 +21,8 @@
<script type="text/javascript" src="/website_sale_delivery/static/src/js/website_sale_delivery.js"></script>
</xpath>
<xpath expr="//tr[@id='order_total_taxes']" position="after">
<tr class="text-muted" id="order_delivery">
<td><abbr title="Delivery will be updated after choosing a new delivery method">Delivery:</abbr></td>
<td class="text-right">
<span t-field="order.amount_delivery" t-field-options='{
"widget": "monetary",
"display_currency": "website.pricelist_id.currency_id"
}'/>
</td>
</tr>
</xpath>
<xpath expr="//div[@id='payment_method']" position="before">
<div t-if="len(deliveries)" class="row" id="delivery_carrier">
<div t-if="deliveries" class="row" id="delivery_carrier">
<h4>Choose your Delivery Method</h4>
<div class="col-lg-5 col-sm-6">
<ul class="list-unstyled">