Files
design-themes/theme_alan/controllers/controllers.py
T

404 lines
21 KiB
Python

# -*- coding: utf-8 -*-
import logging
import odoo
from odoo import http, _, fields
from odoo.http import request, route
from odoo.tools import lazy
from odoo.osv import expression
from odoo.exceptions import UserError
from odoo.addons.web.controllers.home import Home
from odoo.addons.web.controllers.utils import ensure_db
from odoo.addons.website.controllers.main import QueryURL
from odoo.addons.auth_oauth.controllers.main import OAuthLogin
from odoo.addons.auth_signup.models.res_users import SignupError
from odoo.addons.website_sale.controllers.main import WebsiteSale, TableCompute
from odoo.addons.website_sale.controllers.variant import WebsiteSaleVariantController
from odoo.addons.website.controllers.main import Website
from odoo.addons.http_routing.models.ir_http import slug
_logger = logging.getLogger(__name__)
class WebsiteSaleAlanVariant(WebsiteSaleVariantController):
@route()
def get_combination_info_website(self, *args, **kwargs):
res = super().get_combination_info_website(*args, **kwargs)
res.update({'bulk_save': False})
if "product_id" in res.keys():
product_id = request.env['product.product'].sudo().browse(res.get("product_id", 0))
current_pricelist = request.website._get_current_pricelist()
if current_pricelist:
pricelist_item_ids = current_pricelist.sudo()._get_applicable_rules(product_id, fields.Date.today())
template = request.env['ir.ui.view']._render_template("theme_alan.bulk_save_offers",{
'product': product_id,
'pricelist_item_ids': pricelist_item_ids })
get_offer_date = product_id._get_offer_timing(current_pricelist)
res.update({'bulk_save': template, 'offer_timer':get_offer_date})
res.update({'default_code':product_id.default_code, 'last_month_count': product_id.get_sale_count_last_month()})
return res
class WebsiteSaleAlanShop(WebsiteSale):
def hide_out_of_stock(self, product):
combination = product.sudo()._get_first_possible_combination()
combination = product.sudo()._get_combination_info(combination, add_qty=1)
product_id = request.env['product.product'].sudo().browse([combination['product_id']])
website = request.env['website'].get_current_website()
if not product_id.sudo().allow_out_of_stock_order and product_id.sudo().with_context(warehouse=website._get_warehouse_available()).virtual_available < 1:
return False
else:
return product.id
def _shop_lookup_products(self, attrib_set, options, post, search, website):
# No limit because attributes are obtained from complete product list
product_count, details, fuzzy_search_term = website._search_with_fuzzy("products_only", search,
limit=None,
order=self._get_search_order(post),
options=options)
search_result = details[0].get('results', request.env['product.template']).with_context(bin_size=True)
only_stock = request.session.get("stock", False)
if only_stock:
search_result = request.env["product.template"].sudo().browse(list([prod_id for prod_id in map(self.hide_out_of_stock, search_result) if prod_id != False]))
return fuzzy_search_term, product_count, search_result
def _rbt_count(self, search_product, brand_list, tag_list, attributes):
tag_count = { tag.id: len(tag.product_template_ids.sudo().filtered(lambda x: x in search_product)) for tag in tag_list}
attr_count = { attr.id : len(attr.pav_attribute_line_ids.mapped('product_tmpl_id').sudo().filtered(lambda x: x in search_product)) for attr in attributes.mapped('value_ids')}
brand_count = { brand.id : len(brand.brand_product_ids.sudo().filtered(lambda x: x in search_product)) for brand in brand_list}
return tag_count, attr_count, brand_count
def _count_category_products(self):
category_count = {}
all_categs = request.env['product.public.category'].search([('website_id', 'in', [False, request.website.id])]).sudo()
for rec in all_categs:
child_ids = all_categs.search([('id', 'child_of', rec.ids), ('website_id', 'in', [False, request.website.id])])
category_count[rec.id] = len(child_ids.mapped('product_tmpl_ids').sudo().filtered(lambda x: x.is_published))
return category_count
@route()
def shop(self, page=0, category=None, search='', min_price=0.0, max_price=0.0, ppg=False, **post):
# Session based PPG
if ppg:
request.session['ppg'] = ppg
else:
if request.session.get('ppg', False):
ppg = request.session['ppg']
else:
ppg = False
only_stock = request.session.get("stock", False)
if post.get("stock", False) == 'active':
only_stock = True
elif post.get("stock", False) == 'inactive':
only_stock = False
request.session["stock"] = only_stock
brand_list = request.httprequest.args.getlist('brand')
rating_list = request.httprequest.args.getlist('rating')
env_context = dict(request.env.context)
env_context.update({ 'brands':brand_list, 'rating':rating_list})
request.env.context = env_context
# Calling Super
res = super(WebsiteSaleAlanShop, self).shop(page, category, search, min_price, max_price, ppg, **post)
url = '/shop'
if category:
url = "/shop/category/%s" % slug(category)
as_search_prds = res.qcontext['search_product']
# Load More
if request.website.active_load_more:
as_ppg = res.qcontext['ppg']
ofst = 0
alan_pager = request.website.pager(url=url, total=res.qcontext['search_count'], page=page, step=as_ppg, scope=res.qcontext['search_count'], url_args=post)
for page in alan_pager.get('pages'):
page.update(prd_ids=as_search_prds[ofst:ofst + as_ppg].ids)
ofst += as_ppg
res.qcontext.update({'alan_pager':alan_pager})
# For Brands Filters
brand_ids = as_search_prds.mapped("product_brand_id")
brand_set = [int(brand) for brand in brand_list]
# For Rating Filters
rating_max = 1
if len(as_search_prds.sudo().mapped("rating_avg")):
rating_max = int(max(as_search_prds.sudo().mapped("rating_avg"))) + 1
rating_set = [int(rating) for rating in rating_list]
tag_count, attr_count, brand_count = self._rbt_count(res.qcontext.get('search_product'), brand_ids, res.qcontext.get('all_tags', False), res.qcontext.get('attributes', False))
category_count = self._count_category_products()
res.qcontext.update({
'stock_only':request.session["stock"],
'ppg_list':request.env['as.ppg'].search([]),
'as_shop':True,
'brands':brand_ids,
'brand_set': brand_set,
'ratings':rating_max,
'rating_set': rating_set,
'category_count': category_count,
'tag_count': tag_count,
'attr_count': attr_count,
'brand_count': brand_count,
'selected_brands': request.env['as.product.brand'].browse(brand_set),
'selected_tags' : request.env['product.tag'].browse(res.qcontext.get('tags')),
})
return res
@route('/nextpage/products', auth='public', type="json", website=True)
def nextpage_products(self, **kw):
if kw.get('product_ids'):
products = request.env['product.template'].sudo()
if kw.get('products'):
products = request.env['product.template'].sudo().browse(kw.get('products'))
website = request.env['website'].get_current_website()
pricelist = website.pricelist_id
ppg = int(request.session.get('ppg') or 20)
ppr = int(kw.get('ppr') or 4)
product_ids = request.env['product.template'].sudo().browse(kw.get('product_ids'))
products |= product_ids
fiscal_position_sudo = website.fiscal_position_id.sudo()
products_prices = lazy(lambda: product_ids._get_sales_prices(pricelist, fiscal_position_sudo))
keep = QueryURL('/shop',)
return request.env['ir.ui.view']._render_template("theme_alan.shop_page_next_products",{
'bins': lazy(lambda: TableCompute().process(product_ids.sudo(), ppg, ppr)),
'ppg':ppg,
'ppr':ppr,
'keep': keep,
'products': products,
'products_prices': products_prices,
'get_product_prices': lambda product: lazy(lambda: products_prices[product.id]),
'products_in_wishlist': request.env['product.wishlist'].sudo().current().product_id.product_tmpl_id,
})
return {}
@route('/get_similar_product', auth='public', type="json", website=True)
def similar_product(self, **kw):
product_id = kw.get('product_id')
domain = expression.AND([request.website.sale_product_domain(), [('id', '=', product_id)]])
product = request.env['product.template'].sudo().search(domain, limit=1)
if not product:
return False
else:
return request.env['ir.ui.view']._render_template("theme_alan.as_similar_product", {'products':product.alternative_product_ids})
@route()
def product(self, product, category='', search='', **kwargs):
res = super(WebsiteSaleAlanShop, self).product(product, category, search, **kwargs)
res.qcontext.update({'as_product_detail':True})
domain = request.website.sale_product_domain() + [('active','=',True), ('website_published','=',True)]
prod_lst = product.search(domain , order="website_sequence").mapped("id")
previous_product = next_product = False
if product.id in prod_lst:
last_product_idx = len(prod_lst) - 1
current_product_idx = prod_lst.index(product.id)
if current_product_idx != last_product_idx:
next_prod_id = prod_lst[current_product_idx + 1]
next_product = product.browse(next_prod_id)
if current_product_idx != 0:
prev_prod_id = prod_lst[current_product_idx - 1]
previous_product = product.browse(prev_prod_id)
res.qcontext.update({'next_product':next_product,'previous_product':previous_product})
return res
@route('/get_quick_view', auth='public', type="json", website=True)
def quick_view(self, **kw):
product_id = kw.get('product_id')
domain = expression.AND([request.website.sale_product_domain(), [('id', '=', product_id)]])
product = request.env['product.template'].search(domain, limit=1)
if not product:
return False
values = self._prepare_product_values(product, category='', search='', **kw)
return request.env['ir.ui.view']._render_template("theme_alan.as_quick_view", values=values)
@route('/advance/info/editor/<model("as.product.extra.info"):offer>', auth='user', type="http", website=True)
def offer_design(self, offer):
return request.render('theme_alan.as_product_advance_info_design', {'layout': offer})
@route('/get_advance_info', auth='public', type="json", website=True)
def get_advance_info(self, advance_info_id):
offer = request.env['as.product.extra.info'].sudo().search([('id','=',advance_info_id)], limit=1)
if offer.detail_description:
return offer.detail_description
return ""
@route('/get_color_product', auth='public', type="json", website=True)
def get_color_product(self, **kw):
product_id = kw.get('product_id')
domain = expression.AND([request.website.sale_product_domain(), [('id', '=', product_id)]])
product = request.env['product.template'].sudo().search(domain, limit=1)
if not product:
return False
else:
return request.env['ir.ui.view']._render_template("theme_alan.as_color_product_dialog",{
'product':product,
'product_variant':product.product_variant_ids,
})
class AlanShops(http.Controller):
@route(['/shop/brands', '/shop/brands/page/<int:page>'], type='http', auth="public", website=True)
def BrandPage(self, page=0):
domain = ['&',('active','=',True), ('website_id', 'in', (False, request.website.id))]
brands = request.env['as.product.brand'].sudo().search(domain, order="name asc")
total = brands.sudo().search_count([])
pager = request.website.pager(
url='/shop/brands',
total=total,
page=page,
step=30,
)
offset = pager['offset']
brands = brands[offset: offset + 30]
return request.render("theme_alan.brand_list", {'brands':brands, 'pager': pager})
@route('/get_mini_cart', auth='public', type="json", website=True)
def mini_cart(self, **kw):
order = request.website.sale_get_order()
suggested_products = order.website_order_line.sudo().product_id.mapped('accessory_product_ids').filtered(lambda x: (x.is_published and x.sale_ok) and x.allow_out_of_stock_order)
context = {'website_sale_order': order,'suggested_products':suggested_products}
value = { 'as_mini_cart_lines':request.env["ir.ui.view"]._render_template("theme_alan.as_mini_cart_lines", context),'as_mini_cart': request.env["ir.ui.view"]._render_template("theme_alan.as_mini_cart", context)}
return value
@route('/as_clear_cart', type="json", auth="public", website=True)
def as_clear_cart(self, **kw):
order = request.website.sale_get_order()
request.session['website_sale_cart_quantity'] = 0
order.unlink()
return {'empty_mini_cart': request.env["ir.ui.view"]._render_template("theme_alan.as_empty_mini_cart")}
@route('/get_alan_configuration', auth='public', type="json", website=True)
def get_alan_configuration(self, **kw):
website = request.website
data = {
'active_login_popup':website.active_login_popup,
'active_mini_cart':website.active_mini_cart,
'active_scroll_top':website.active_scroll_top,
'active_b2b_mode':website.active_b2b_mode,
'active_shop_quick_view': website.active_shop_quick_view,
'active_shop_rating': website.active_shop_rating,
'active_shop_similar_product': website.active_shop_similar_product,
'active_shop_offer_timer': website.active_shop_offer_timer ,
'active_shop_color_variant': website.active_shop_color_variant,
'active_shop_stock_info': website.active_shop_stock_info,
'active_shop_brand_info': website.active_shop_brand_info,
'active_shop_hover_image':website.active_shop_hover_image,
'active_shop_label':website.active_shop_label,
'active_shop_clear_filter':website.active_shop_clear_filter,
'active_shop_ppg':website.active_shop_ppg,
'active_stock_only':website.active_stock_only,
'active_load_more':website.active_load_more,
'active_brand_filter':website.active_brand_filter,
'active_rating_filter':website.active_rating_filter,
'active_attribute_count':website.active_attribute_count,
'active_attribute_search':website.active_attribute_search,
'active_product_label':website.active_product_label,
'active_product_offer_timer':website.active_product_offer_timer,
'active_product_reference':website.active_product_reference,
'active_product_category':website.active_product_category,
'active_product_brand':website.active_product_brand,
'active_product_advance_info':website.active_product_advance_info,
'active_product_variant_info':website.active_product_variant_info,
'active_product_accessory':website.active_product_accessory,
'active_product_alternative':website.active_product_alternative,
'active_product_pager':website.active_product_pager,
'active_product_sticky':website.active_product_sticky,
'active_product_bulk_save':website.active_product_bulk_save,
'active_last_month_count': website.active_last_month_count
}
return data
@route('/set_alan_configuration', auth='public', type="json", website=True)
def set_alan_configuration(self, is_active, setting):
request.website.write({ setting: is_active })
return True
class LoginPopup(Home):
@route('/get_login_popup', type='json', auth="public", website=True)
def alan_login_popup(self, **kwargs):
context = {}
providers = OAuthLogin.list_providers(self)
context.update(super().get_auth_signup_config())
context.update({'providers':providers})
signup_enabled = request.env['res.users']._get_signup_invitation_scope() == 'b2c'
reset_password_enabled = request.env['ir.config_parameter'].sudo().get_param('auth_signup.reset_password') == 'True'
website_logo = request.website.image_url(request.website,'logo')
context.update({'signup_enabled':signup_enabled ,"reset_password_enabled":reset_password_enabled,'website_logo':website_logo})
return request.env['ir.ui.view']._render_template("theme_alan.as_shop_login",context)
@route('/alan/login/authenticate', type='json', auth="none")
def alan_login_authenticate(self, **kwargs):
''' Login Authentication '''
ensure_db()
request.params['login_success'] = False
if not request.uid:
request.update_env(user=odoo.SUPERUSER_ID)
values = request.params.copy()
if request.httprequest.method == 'POST':
try:
uid = request.session.authenticate(request.db, request.params['login'], request.params['password'])
request.params['login_success'] = True
request.redirect(self._login_redirect(uid, redirect=None))
return request.params
except odoo.exceptions.AccessDenied as e:
if e.args == odoo.exceptions.AccessDenied().args:
values['error'] = _("Wrong login/password")
else:
values['error'] = e.args[0]
if 'login' not in values and request.session.get('auth_login'):
values['login'] = request.session.get('auth_login')
return values
@route('/alan/signup/authenticate', type="json", auth="public")
def alan_signup_authenticate(self,*args, **kw):
''' Signup Authentication '''
qcontext = super(LoginPopup,self).get_auth_signup_qcontext()
if 'error' not in qcontext and request.httprequest.method == 'POST':
try:
super(LoginPopup,self).do_signup(qcontext)
User = request.env['res.users']
user_sudo = User.sudo().search(
User._get_login_domain(qcontext.get('login')), order=User._get_login_order(), limit=1
)
template = request.env.ref('auth_signup.mail_template_user_signup_account_created', raise_if_not_found=False)
if user_sudo and template:
template.sudo().send_mail(user_sudo.id, force_send=True)
return {'signup_success':True}
except UserError as e:
qcontext['error'] = e.args[0]
except (SignupError, AssertionError) as e:
if request.env['res.users'].sudo().search([('login', '=', qcontext.get('login'))]):
qcontext['error'] = _('Another user is already registered using this email address.')
else:
_logger.error("%s", e)
qcontext['error'] = _('Could not create a new account.')
return qcontext
class B2BWebsite(Website):
@route()
def autocomplete(self, search_type=None, term=None, order=None, limit=5, max_nb_chars=999, options=None):
result = super().autocomplete(search_type, term, order, limit, max_nb_chars, options)
if request.env.user._is_public() and request.website.active_b2b_mode:
result['parts']['is_b2b_mode'] = True
else:
result['parts']['is_b2b_mode'] = False
return result
@route()
def hybrid_list(self, page=1, search='', search_type='all', **kw):
result = super().hybrid_list(page, search, search_type, **kw)
if request.env.user._is_public() and request.website.active_b2b_mode:
result.qcontext['is_b2b_mode'] = True
else:
result.qcontext['is_b2b_mode'] = False
return result