def payment_token(self, pm_id, reference, amount, currency_id, return_url=None, **kwargs): token = request.env['payment.token'].browse(int(pm_id)) order_id = kwargs.get('order_id') if not token: return request.redirect('/website_payment/pay?error_msg=%s' % _('Cannot setup the payment.')) partner_id = request.env.user.partner_id.id if not request.env.user._is_public() else False values = { 'acquirer_id': token.acquirer_id.id, 'reference': reference, 'amount': float(amount), 'currency_id': int(currency_id), 'partner_id': partner_id, 'payment_token_id': pm_id, 'type': 'form_save' if token.acquirer_id.save_token != 'none' and partner_id else 'form', 'return_url': return_url, } if order_id: values['sale_order_ids'] = [(6, 0, [order_id])] tx = request.env['payment.transaction'].sudo().with_context(lang=None).create(values) PaymentProcessing.add_payment_transaction(tx) try: res = tx.s2s_do_transaction() tx.return_url = return_url or '/website_payment/confirm?tx_id=%d' % tx.id return request.redirect('/payment/process') except Exception as e: return request.redirect('/payment/process')
def validate_email(self, token, id, email, forum_id=None, **kwargs): if forum_id: try: forum_id = int(forum_id) except ValueError: forum_id = None done = request.env['res.users'].sudo().browse(int(id)).process_forum_validation_token(token, email, forum_id=forum_id)[0] if done: request.session['validation_email_done'] = True if forum_id: return request.redirect("/forum/%s" % int(forum_id)) return request.redirect('/forum')
def jobs_add(self, **kwargs): # avoid branding of website_description by setting rendering_bundle in context job = request.env['hr.job'].with_context(rendering_bundle=True).create( { 'name': _('Job Title'), }) return request.redirect("/jobs/detail/%s?enable_editor=1" % slug(job))
def actions_server(self, path_or_xml_id_or_id, **post): ServerActions = request.env['ir.actions.server'] action = action_id = None # find the action_id: either an xml_id, the path, or an ID if isinstance(path_or_xml_id_or_id, pycompat.string_types) and '.' in path_or_xml_id_or_id: action = request.env.ref(path_or_xml_id_or_id, raise_if_not_found=False) if not action: action = ServerActions.search( [('website_path', '=', path_or_xml_id_or_id), ('website_published', '=', True)], limit=1) if not action: try: action_id = int(path_or_xml_id_or_id) except ValueError: pass # check it effectively exists if action_id: action = ServerActions.browse(action_id).exists() # run it, return only if we got a Response object if action: if action.state == 'code' and action.website_published: action_res = action.run() if isinstance(action_res, werkzeug.wrappers.Response): return action_res return request.redirect('/')
def reset_template(self, templates, redirect='/', **kwargs): """ This method will try to reset a list of broken views ids. It will read the original `arch` from the view's XML file (arch_fs). Views without an `arch_fs` can't be reset, except views created when dropping a snippet in specific oe_structure that create an inherited view doing an xpath. Note: The `arch_fs` field is automatically erased when there is a write on the `arch` field. This method is typically useful to reset specific views. In that case we read the XML file from the generic view. """ templates = request.httprequest.form.getlist('templates') for temp_id in templates: view = request.env['ir.ui.view'].browse(int(temp_id)) if 'oe_structure' in view.key: # Particular xpathing view created in edit mode view.unlink() continue xml_view = view._get_original_view( ) # view might already be the xml_view if xml_view.arch_fs: view_file_arch = xml_view.with_context( read_arch_from_file=True).arch # Deactivate COW to not fix a generic view by creating a specific view.with_context(website_id=None).arch_db = view_file_arch if view == xml_view: view.model_data_id.write({'noupdate': False}) return request.redirect(redirect)
def registration_confirm(self, event, **post): order = request.website.sale_get_order(force_create=1) attendee_ids = set() registrations = self._process_registration_details(post) for registration in registrations: ticket = request.env['event.event.ticket'].sudo().browse( int(registration['ticket_id'])) cart_values = order.with_context( event_ticket_id=ticket.id, fixed_price=True)._cart_update( product_id=ticket.product_id.id, add_qty=1, registration_data=[registration]) attendee_ids |= set(cart_values.get('attendee_ids', [])) # free tickets -> order with amount = 0: auto-confirm, no checkout if not order.amount_total: order.action_confirm() # tde notsure: email sending ? attendees = request.env['event.registration'].browse( list(attendee_ids)).sudo() # clean context and session, then redirect to the confirmation page request.website.sale_reset() urls = event._get_event_resource_urls(list(attendee_ids)) return request.render( "website_event.registration_complete", { 'attendees': attendees, 'event': event, 'google_url': urls.get('google_url'), 'iCal_url': urls.get('iCal_url') }) return request.redirect("/shop/checkout")
def add(self, order_id, option_id, access_token=None, **post): try: order_sudo = self._document_check_access('sale.order', order_id, access_token=access_token) except (AccessError, MissingError): return request.redirect('/my') option_sudo = request.env['sale.order.option'].sudo().browse(option_id) if order_sudo != option_sudo.order_id: return request.redirect(order_sudo.get_portal_url()) option_sudo.add_option_to_order() return request.redirect( option_sudo.order_id.get_portal_url(anchor='details'))
def portal_chatter_post(self, res_model, res_id, message, **kw): url = request.httprequest.referrer if message: # message is received in plaintext and saved in html message = plaintext2html(message) _message_post_helper(res_model, int(res_id), message, **kw) url = url + "#discussion" return request.redirect(url)
def post_toggle_correct(self, forum, post, **kwargs): if post.parent_id is False: return request.redirect('/') if not request.session.uid: return {'error': 'anonymous_user'} # set all answers to False, only one can be accepted (post.parent_id.child_ids - post).write(dict(is_correct=False)) post.is_correct = not post.is_correct return post.is_correct
def portal_my_project(self, project_id=None, access_token=None, **kw): try: project_sudo = self._document_check_access('project.project', project_id, access_token) except (AccessError, MissingError): return request.redirect('/my') values = self._project_get_page_view_values(project_sudo, access_token, **kw) return request.render("project.portal_my_project", values)
def payment(self, **post): order = request.website.sale_get_order() carrier_id = post.get('carrier_id') if carrier_id: carrier_id = int(carrier_id) if order: order._check_carrier_quotation(force_carrier_id=carrier_id) if carrier_id: return request.redirect("/shop/payment") return super(WebsiteSaleDelivery, self).payment(**post)
def event(self, event, **post): if not event.can_access_from_current_website(): raise werkzeug.exceptions.NotFound() if event.menu_id and event.menu_id.child_id: target_url = event.menu_id.child_id[0].url else: target_url = '/event/%s/register' % str(event.id) if post.get('enable_editor') == '1': target_url += '?enable_editor=1' return request.redirect(target_url)
def get_wishlist(self, count=False, **kw): values = request.env['product.wishlist'].with_context( display_default_code=False).current() if count: return request.make_response( json.dumps(values.mapped('product_id').ids)) if not len(values): return request.redirect("/shop") return request.render("website_sale_wishlist.product_wishlist", dict(wishes=values))
def portal_my_task(self, task_id, access_token=None, **kw): try: task_sudo = self._document_check_access('project.task', task_id, access_token) except (AccessError, MissingError): return request.redirect('/my') # ensure attachment are accessible with access token inside template for attachment in task_sudo.attachment_ids: attachment.generate_access_token() values = self._task_get_page_view_values(task_sudo, access_token, **kw) return request.render("project.portal_my_task", values)
def invoice_pay_token(self, invoice_id, pm_id=None, **kwargs): """ Use a token to perform a s2s transaction """ error_url = kwargs.get('error_url', '/my') access_token = kwargs.get('access_token') params = {} if access_token: params['access_token'] = access_token invoice_sudo = request.env['account.invoice'].sudo().browse( invoice_id).exists() if not invoice_sudo: params['error'] = 'pay_invoice_invalid_doc' return request.redirect(_build_url_w_params(error_url, params)) success_url = kwargs.get( 'success_url', "%s?%s" % (invoice_sudo.access_url, url_encode( {'access_token': access_token}) if access_token else '')) try: token = request.env['payment.token'].sudo().browse(int(pm_id)) except (ValueError, TypeError): token = False token_owner = invoice_sudo.partner_id if request.env.user._is_public( ) else request.env.user.partner_id if not token or token.partner_id != token_owner: params['error'] = 'pay_invoice_invalid_token' return request.redirect(_build_url_w_params(error_url, params)) vals = { 'payment_token_id': token.id, 'type': 'server2server', 'return_url': _build_url_w_params(success_url, params), } tx = invoice_sudo._create_payment_transaction(vals) PaymentProcessing.add_payment_transaction(tx) params['success'] = 'pay_invoice' return request.redirect('/payment/process')
def portal_my_purchase_order(self, order_id=None, access_token=None, **kw): try: order_sudo = self._document_check_access('purchase.order', order_id, access_token=access_token) except (AccessError, MissingError): return request.redirect('/my') values = self._purchase_order_get_page_view_values( order_sudo, access_token, **kw) if order_sudo.company_id: values['res_company'] = order_sudo.company_id return request.render("purchase.portal_my_purchase_order", values)
def decline(self, order_id, access_token=None, **post): try: order_sudo = self._document_check_access('sale.order', order_id, access_token=access_token) except (AccessError, MissingError): return request.redirect('/my') message = post.get('decline_message') query_string = False if order_sudo.has_to_be_signed() and message: order_sudo.action_cancel() _message_post_helper( message=message, res_id=order_id, res_model='sale.order', **{'token': access_token} if access_token else {}) else: query_string = "&message=cant_reject" return request.redirect( order_sudo.get_portal_url(query_string=query_string))
def portal_my_picking_report(self, picking_id, access_token=None, **kw): """ Print delivery slip for customer, using either access rights or access token to be sure customer has access """ try: picking_sudo = self._stock_picking_check_access(picking_id, access_token=access_token) except exceptions.AccessError: return request.redirect('/my') # print report as sudo, since it require access to product, taxes, payment term etc.. and portal does not have those access rights. pdf = request.env.ref('stock.action_report_delivery').sudo().render_qweb_pdf([picking_sudo.id])[0] pdfhttpheaders = [ ('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ] return request.make_response(pdf, headers=pdfhttpheaders)
def _serve_fallback(cls, exception): # serve attachment before parent = super(Http, cls)._serve_fallback(exception) if parent: # attachment return parent website_page = cls._serve_page() if website_page: return website_page redirect = cls._serve_redirect() if redirect: return request.redirect(_build_url_w_params(redirect.url_to, request.params), code=redirect.type) return False
def payment_token(self, order_id, pm_id=None, **kwargs): order = request.env['sale.order'].sudo().browse(order_id) if not order: return request.redirect("/my/orders") if not order.order_line or pm_id is None or not order.has_to_be_paid(): return request.redirect(order.get_portal_url()) # try to convert pm_id into an integer, if it doesn't work redirect the user to the quote try: pm_id = int(pm_id) except ValueError: return request.redirect(order.get_portal_url()) # Create transaction vals = { 'payment_token_id': pm_id, 'type': 'server2server', 'return_url': order.get_portal_url(), } tx = order._create_payment_transaction(vals) PaymentProcessing.add_payment_transaction(tx) return request.redirect('/payment/process')
def mailing(self, mailing_id, email=None, res_id=None, token="", **post): mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id) if mailing.exists(): res_id = res_id and int(res_id) if not self._valid_unsubscribe_token(mailing_id, res_id, email, str(token)): raise exceptions.AccessDenied() if mailing.mailing_model_real == 'mail.mass_mailing.contact': # Unsubscribe directly + Let the user choose his subscriptions mailing.update_opt_out(email, mailing.contact_list_ids.ids, True) contacts = request.env['mail.mass_mailing.contact'].sudo().search([('email', '=', email)]) subscription_list_ids = contacts.mapped('subscription_list_ids') # In many user are found : if user is opt_out on the list with contact_id 1 but not with contact_id 2, # assume that the user is not opt_out on both # TODO DBE Fixme : Optimise the following to get real opt_out and opt_in opt_out_list_ids = subscription_list_ids.filtered(lambda rel: rel.opt_out).mapped('list_id') opt_in_list_ids = subscription_list_ids.filtered(lambda rel: not rel.opt_out).mapped('list_id') opt_out_list_ids = set([list.id for list in opt_out_list_ids if list not in opt_in_list_ids]) unique_list_ids = set([list.list_id.id for list in subscription_list_ids]) list_ids = request.env['mail.mass_mailing.list'].sudo().browse(unique_list_ids) unsubscribed_list = ', '.join(str(list.name) for list in mailing.contact_list_ids if list.is_public) return request.render('mass_mailing.page_unsubscribe', { 'contacts': contacts, 'list_ids': list_ids, 'opt_out_list_ids': opt_out_list_ids, 'unsubscribed_list': unsubscribed_list, 'email': email, 'mailing_id': mailing_id, 'res_id': res_id, 'show_blacklist_button': request.env['ir.config_parameter'].sudo().get_param('mass_mailing.show_blacklist_buttons'), }) else: blacklist_rec = request.env['mail.blacklist'].sudo()._add(email) self._log_blacklist_action( blacklist_rec, mailing_id, _("""Requested blacklisting via unsubscribe link.""")) return request.render('mass_mailing.page_unsubscribed', { 'email': email, 'mailing_id': mailing_id, 'res_id': res_id, 'show_blacklist_button': request.env['ir.config_parameter'].sudo().get_param( 'mass_mailing.show_blacklist_buttons'), }) return request.redirect('/web')
def confirm(self, **kw): tx_id = int(kw.get('tx_id', 0)) if tx_id: tx = request.env['payment.transaction'].browse(tx_id) if tx.state in ['done', 'authorized']: status = 'success' message = tx.acquirer_id.done_msg elif tx.state == 'pending': status = 'warning' message = tx.acquirer_id.pending_msg else: status = 'danger' message = tx.acquirer_id.error_msg PaymentProcessing.remove_payment_transaction(tx) return request.render('payment.confirm', {'tx': tx, 'status': status, 'message': message}) else: return request.redirect('/my/home')
def index(self, **kw): homepage = request.website.homepage_id if homepage and (homepage.sudo().is_visible or request.env.user.has_group('base.group_user') ) and homepage.url != '/': return request.env['ir.http'].reroute(homepage.url) website_page = request.env['ir.http']._serve_page() if website_page: return website_page else: top_menu = request.website.menu_id first_menu = top_menu and top_menu.child_id and top_menu.child_id.filtered( lambda menu: menu.is_visible) if first_menu and first_menu[0].url not in ('/', '', '#') and ( not (first_menu[0].url.startswith(('/?', '/#', ' ')))): return request.redirect(first_menu[0].url) raise request.not_found()
def start_survey(self, survey, token=None, **post): UserInput = request.env['survey.user_input'] # Test mode if token and token == "phantom": _logger.info("[survey] Phantom mode") user_input = UserInput.create({ 'survey_id': survey.id, 'test_entry': True }) data = {'survey': survey, 'page': None, 'token': user_input.token} return request.render('survey.survey_init', data) # END Test mode # Controls if the survey can be displayed errpage = self._check_bad_cases(survey, token=token) if errpage: return errpage # Manual surveying if not token: vals = {'survey_id': survey.id} if not request.env.user._is_public(): vals['partner_id'] = request.env.user.partner_id.id user_input = UserInput.create(vals) else: user_input = UserInput.sudo().search([('token', '=', token)], limit=1) if not user_input: return request.render("survey.403", {'survey': survey}) # Do not open expired survey errpage = self._check_deadline(user_input) if errpage: return errpage # Select the right page if user_input.state == 'new': # Intro page data = {'survey': survey, 'page': None, 'token': user_input.token} return request.render('survey.survey_init', data) else: return request.redirect('/survey/fill/%s/%s' % (survey.id, user_input.token))
def product_compare(self, **post): values = {} product_ids = [ int(i) for i in post.get('products', '').split(',') if i.isdigit() ] if not product_ids: return request.redirect("/shop") # use search to check read access on each record/ids products = request.env['product.product'].search([('id', 'in', product_ids)]) values['products'] = products.with_context(display_default_code=False) res = OrderedDict() attrs = products.mapped( 'product_tmpl_id.valid_product_template_attribute_line_ids.attribute_id' ).filtered(lambda x: x.create_variant != 'no_variant') for attr in attrs.sorted(lambda att: (att.category_id.sequence, att.sequence)): cat_name = attr.category_id.name or _('Uncategorized') res.setdefault(cat_name, OrderedDict()).setdefault(attr.name, [' - '] * len(products)) for num, product in enumerate(products): for var in product.product_tmpl_id.valid_product_template_attribute_line_ids.filtered( lambda x: x.attribute_id.create_variant != 'no_variant'): cat_name = var.attribute_id.category_id.name or _( 'Uncategorized') att_name = var.attribute_id.name val = product.attribute_value_ids.filtered( lambda x: x.attribute_id == var.attribute_id) if val: res[cat_name][att_name][num] = val[0].name values['specs'] = res values['compute_currency'] = self._get_compute_currency_and_context( products[:1].product_tmpl_id)[0] return request.render("website_sale_comparison.product_compare", values)
def portal_my_invoice_detail(self, invoice_id, access_token=None, report_type=None, download=False, **kw): try: invoice_sudo = self._document_check_access('account.invoice', invoice_id, access_token) except (AccessError, MissingError): return request.redirect('/my') if report_type in ('html', 'pdf', 'text'): return self._show_report(model=invoice_sudo, report_type=report_type, report_ref='account.account_invoices', download=download) values = self._invoice_get_page_view_values(invoice_sudo, access_token, **kw) PaymentProcessing.remove_payment_transaction( invoice_sudo.transaction_ids) return request.render("account.portal_invoice_page", values)
def portal_order_page(self, order_id, report_type=None, access_token=None, message=False, download=False, **kw): try: order_sudo = self._document_check_access('sale.order', order_id, access_token=access_token) except (AccessError, MissingError): return request.redirect('/my') if report_type in ('html', 'pdf', 'text'): return self._show_report(model=order_sudo, report_type=report_type, report_ref='sale.action_report_saleorder', download=download) # use sudo to allow accessing/viewing orders for public user # only if he knows the private token # Log only once a day if order_sudo: now = fields.Date.today().isoformat() session_obj_date = request.session.get('view_quote_%s' % order_sudo.id) if isinstance(session_obj_date, date): session_obj_date = session_obj_date.isoformat() if session_obj_date != now and request.env.user.share and access_token: request.session['view_quote_%s' % order_sudo.id] = now body = _('Quotation viewed by customer') _message_post_helper( res_model='sale.order', res_id=order_sudo.id, message=body, token=order_sudo.access_token, message_type='notification', subtype="mail.mt_note", partner_ids=order_sudo.user_id.sudo().partner_id.ids) values = { 'sale_order': order_sudo, 'message': message, 'token': access_token, 'return_url': '/shop/payment/validate', 'bootstrap_formatting': True, 'partner_id': order_sudo.partner_id.id, 'report_type': 'html', } if order_sudo.company_id: values['res_company'] = order_sudo.company_id if order_sudo.has_to_be_paid(): domain = expression.AND( [[ '&', ('website_published', '=', True), ('company_id', '=', order_sudo.company_id.id) ], [ '|', ('specific_countries', '=', False), ('country_ids', 'in', [order_sudo.partner_id.country_id.id]) ]]) acquirers = request.env['payment.acquirer'].sudo().search(domain) values['acquirers'] = acquirers.filtered(lambda acq: ( acq.payment_flow == 'form' and acq.view_template_id) or ( acq.payment_flow == 's2s' and acq. registration_view_template_id)) values['pms'] = request.env['payment.token'].search([ ('partner_id', '=', order_sudo.partner_id.id) ]) if order_sudo.state in ('draft', 'sent', 'cancel'): history = request.session.get('my_quotations_history', []) else: history = request.session.get('my_orders_history', []) values.update(get_records_pager(history, order_sudo)) return request.render('sale.sale_order_portal_template', values)
def blog(self, blog=None, tag=None, page=1, **opt): """ Prepare all values to display the blog. :return dict values: values for the templates, containing - 'blog': current blog - 'blogs': all blogs for navigation - 'pager': pager of posts - 'active_tag_ids' : list of active tag ids, - 'tags_list' : function to built the comma-separated tag list ids (for the url), - 'tags': all tags, for navigation - 'state_info': state of published/unpublished filter - 'nav_list': a dict [year][month] for archives navigation - 'date': date_begin optional parameter, used in archives navigation - 'blog_url': help object to create URLs """ if not blog.can_access_from_current_website(): raise werkzeug.exceptions.NotFound() date_begin, date_end, state = opt.get('date_begin'), opt.get( 'date_end'), opt.get('state') published_count, unpublished_count = 0, 0 domain = request.website.website_domain() BlogPost = request.env['blog.post'] Blog = request.env['blog.blog'] blogs = Blog.search(domain, order="create_date asc") # retrocompatibility to accept tag as slug active_tag_ids = tag and [int(unslug(t)[1]) for t in tag.split(',')] or [] if active_tag_ids: fixed_tag_slug = ",".join( slug(t) for t in request.env['blog.tag'].browse( active_tag_ids).exists()) if fixed_tag_slug != tag: new_url = request.httprequest.full_path.replace( "/tag/%s" % tag, "/tag/%s" % fixed_tag_slug, 1) if new_url != request.httprequest.full_path: # check that really replaced and avoid loop return request.redirect(new_url, 301) domain += [('tag_ids', 'in', active_tag_ids)] if blog: domain += [('blog_id', '=', blog.id)] if date_begin and date_end: domain += [("post_date", ">=", date_begin), ("post_date", "<=", date_end)] if request.env.user.has_group('website.group_website_designer'): count_domain = domain + [("website_published", "=", True), ("post_date", "<=", fields.Datetime.now()) ] published_count = BlogPost.search_count(count_domain) unpublished_count = BlogPost.search_count(domain) - published_count if state == "published": domain += [("website_published", "=", True), ("post_date", "<=", fields.Datetime.now())] elif state == "unpublished": domain += [ '|', ("website_published", "=", False), ("post_date", ">", fields.Datetime.now()) ] else: domain += [("post_date", "<=", fields.Datetime.now())] blog_url = QueryURL('', ['blog', 'tag'], blog=blog, tag=tag, date_begin=date_begin, date_end=date_end) blog_posts = BlogPost.search(domain, order="post_date desc") pager = request.website.pager( url=request.httprequest.path.partition('/page/')[0], total=len(blog_posts), page=page, step=self._blog_post_per_page, url_args=opt, ) pager_begin = (page - 1) * self._blog_post_per_page pager_end = page * self._blog_post_per_page blog_posts = blog_posts[pager_begin:pager_end] all_tags = blog.all_tags()[blog.id] # function to create the string list of tag ids, and toggle a given one. # used in the 'Tags Cloud' template. def tags_list(tag_ids, current_tag): tag_ids = list(tag_ids) # required to avoid using the same list if current_tag in tag_ids: tag_ids.remove(current_tag) else: tag_ids.append(current_tag) tag_ids = request.env['blog.tag'].browse(tag_ids).exists() return ','.join(slug(tag) for tag in tag_ids) tag_category = sorted(all_tags.mapped('category_id'), key=lambda category: category.name.upper()) other_tags = sorted(all_tags.filtered(lambda x: not x.category_id), key=lambda tag: tag.name.upper()) values = { 'blog': blog, 'blogs': blogs, 'main_object': blog, 'other_tags': other_tags, 'state_info': { "state": state, "published": published_count, "unpublished": unpublished_count }, 'active_tag_ids': active_tag_ids, 'tags_list': tags_list, 'blog_posts': blog_posts, 'blog_posts_cover_properties': [json.loads(b.cover_properties) for b in blog_posts], 'pager': pager, 'nav_list': self.nav_list(blog), 'blog_url': blog_url, 'date': date_begin, 'tag_category': tag_category, } response = request.render("website_blog.blog_post_short", values) return response
def update_line_dict(self, line_id, remove=False, unlink=False, order_id=None, access_token=None, input_quantity=False, **kwargs): try: order_sudo = self._document_check_access('sale.order', order_id, access_token=access_token) except (AccessError, MissingError): return request.redirect('/my') if order_sudo.state not in ('draft', 'sent'): return False order_line = request.env['sale.order.line'].sudo().browse(int(line_id)) if order_line.order_id != order_sudo: return False if unlink: order_line.unlink() return False # return False to reload the page, the line must move back to options and the JS doesn't handle it if input_quantity is not False: quantity = input_quantity else: number = -1 if remove else 1 quantity = order_line.product_uom_qty + number if quantity < 0: quantity = 0.0 order_line.write({'product_uom_qty': quantity}) currency = order_sudo.currency_id format_price = partial(formatLang, request.env, digits=currency.decimal_places) results = { 'order_line_product_uom_qty': str(quantity), 'order_line_price_total': format_price(order_line.price_total), 'order_line_price_subtotal': format_price(order_line.price_subtotal), 'order_amount_total': format_price(order_sudo.amount_total), 'order_amount_untaxed': format_price(order_sudo.amount_untaxed), 'order_amount_tax': format_price(order_sudo.amount_tax), 'order_amount_undiscounted': format_price(order_sudo.amount_undiscounted), } try: results['order_totals_table'] = request.env[ 'ir.ui.view'].render_template( 'sale.sale_order_portal_content_totals_table', {'sale_order': order_sudo}) except ValueError: pass return results
def _dispatch(cls): """ Before executing the endpoint method, add website params on request, such as - current website (record) - multilang support (set on cookies) - geoip dict data are added in the session Then follow the parent dispatching. Reminder : Do not use `request.env` before authentication phase, otherwise the env set on request will be created with uid=None (and it is a lazy property) """ request.routing_iteration = getattr(request, 'routing_iteration', 0) + 1 func = None routing_error = None # locate the controller method try: if request.httprequest.method == 'GET' and '//' in request.httprequest.path: new_url = request.httprequest.path.replace( '//', '/') + '?' + request.httprequest.query_string.decode( 'utf-8') return werkzeug.utils.redirect(new_url, 301) rule, arguments = cls._find_handler(return_rule=True) func = rule.endpoint request.is_frontend = func.routing.get('website', False) except werkzeug.exceptions.NotFound as e: # either we have a language prefixed route, either a real 404 # in all cases, website processes them request.is_frontend = True routing_error = e request.is_frontend_multilang = ( request.is_frontend and (not func or (func and func.routing.get( 'multilang', func.routing['type'] == 'http')))) cls._geoip_setup_resolver() cls._geoip_resolve() # check authentication level try: if func: cls._authenticate(func.routing['auth']) elif request.uid is None and request.is_frontend: cls._auth_method_public() except Exception as e: return cls._handle_exception(e) # For website routes (only), add website params on `request` cook_lang = request.httprequest.cookies.get('frontend_lang') if request.is_frontend: request.redirect = lambda url, code=302: werkzeug.utils.redirect( url_for(url), code) cls._add_dispatch_parameters(func) path = request.httprequest.path.split('/') if request.routing_iteration == 1: is_a_bot = cls.is_a_bot() nearest_lang = not func and cls.get_nearest_lang(path[1]) url_lang = nearest_lang and path[1] # if lang in url but not the displayed or default language --> change or remove # or no lang in url, and lang to dispay not the default language --> add lang # and not a POST request # and not a bot or bot but default lang in url if ((url_lang and (url_lang != request.lang or url_lang == cls._get_default_lang().code)) or (not url_lang and request.is_frontend_multilang and request.lang != cls._get_default_lang().code) and request.httprequest.method != 'POST') \ and (not is_a_bot or (url_lang and url_lang == cls._get_default_lang().code)): if url_lang: path.pop(1) if request.lang != cls._get_default_lang().code: path.insert(1, request.lang) path = '/'.join(path) or '/' routing_error = None redirect = request.redirect( path + '?' + request.httprequest.query_string.decode('utf-8')) redirect.set_cookie('frontend_lang', request.lang) return redirect elif url_lang: request.uid = None path.pop(1) routing_error = None return cls.reroute('/'.join(path) or '/') if request.lang == cls._get_default_lang().code: context = dict(request.context) context['edit_translations'] = False request.context = context if routing_error: return cls._handle_exception(routing_error) # removed cache for auth public result = super(IrHttp, cls)._dispatch() if request.is_frontend and cook_lang != request.lang and hasattr( result, 'set_cookie'): result.set_cookie('frontend_lang', request.lang) return result