def account(self, redirect=None, **post): values = self._prepare_portal_layout_values() partner = request.env.user.partner_id values.update({ 'error': {}, 'error_message': [], }) if post and request.httprequest.method == 'POST': error, error_message = self.details_form_validate(post) values.update({'error': error, 'error_message': error_message}) values.update(post) if not error: values = { key: post[key] for key in self.MANDATORY_BILLING_FIELDS } values.update({ key: post[key] for key in self.OPTIONAL_BILLING_FIELDS if key in post }) for field in set(['country_id', 'state_id']) & set( values.keys()): try: values[field] = int(values[field]) except: values[field] = False values.update({'zip': values.pop('zipcode', '')}) partner.sudo().write(values) if redirect: return request.redirect(redirect) return request.redirect('/my/home') countries = request.env['res.country'].sudo().search([]) states = request.env['res.country.state'].sudo().search([]) values.update({ 'partner': partner, 'countries': countries, 'states': states, 'has_check_vat': hasattr(request.env['res.partner'], 'check_vat'), 'redirect': redirect, 'page_name': 'my_details', }) response = request.render("portal.portal_my_details", values) response.headers['X-Frame-Options'] = 'DENY' return response
def payment_token(self, pm_id, reference, amount, currency_id, partner_id=False, 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.')) values = { 'acquirer_id': token.acquirer_id.id, 'reference': reference, 'amount': float(amount), 'currency_id': int(currency_id), 'partner_id': int(partner_id), 'payment_token_id': int(pm_id), 'type': 'server2server', 'return_url': return_url, } if order_id: values['sale_order_ids'] = [(6, 0, [int(order_id)])] tx = request.env['payment.transaction'].sudo().with_context( lang=None).create(values) PaymentProcessing.add_payment_transaction(tx) try: tx.s2s_do_transaction() secret = request.env['ir.config_parameter'].sudo().get_param( 'database.secret') token_str = '%s%s%s' % ( tx.id, tx.reference, float_repr(tx.amount, precision_digits=tx.currency_id.decimal_places)) token = hmac.new(secret.encode('utf-8'), token_str.encode('utf-8'), hashlib.sha256).hexdigest() tx.return_url = return_url or '/website_payment/confirm?tx_id=%d&access_token=%s' % ( tx.id, token) except Exception as e: _logger.exception(e) return request.redirect('/payment/process')
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, str) 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 signup_restrict_users(self, *args, **kw): user_id = kw.get("signup", "0") user = request.env['res.users'].sudo().browse(int(user_id)) partner_id = user.partner_id.id user.active = False request.env.cr.commit() notification_email = "" config = request.env['res.config.settings'].sudo().search( [], order="id desc") if config: config = config[0] notification_email = config.email_notification or "" signup_user_template = request.env.ref( 'new_user_approval_bizople.email_template_apply_signup_confirmation_mail', raise_if_not_found=False) signup_user_template.sudo().email_from = notification_email signup_user_template.sudo().reply_to = notification_email signup_user_template.sudo().send_mail(partner_id, force_send=True) admin_user_template = request.env.ref( 'new_user_approval_bizople.email_template_signup_user_confirmation_mail', raise_if_not_found=False) admin_user_template.sudo().email_from = notification_email admin_user_template.sudo().email_to = notification_email admin_user_template.sudo().reply_to = notification_email admin_user_template.sudo().send_mail(partner_id, force_send=True) return request.redirect("/signup-thank-you")
def validate_email(self, token, user_id, email, **kwargs): done = request.env['res.users'].sudo().browse( int(user_id))._process_profile_validation_token(token, email) if done: request.session['validation_email_done'] = True url = kwargs.get('redirect_url', '/') return request.redirect(url)
def survey_retry(self, survey_token, answer_token, **post): """ This route is called whenever the user has attempts left and hits the 'Retry' button after failing the survey.""" access_data = self._get_access_data(survey_token, answer_token, ensure_token=True) if access_data['validity_code'] is not True and access_data[ 'validity_code'] != 'answer_done': return self._redirect_with_error(access_data, access_data['validity_code']) survey_sudo, answer_sudo = access_data['survey_sudo'], access_data[ 'answer_sudo'] if not answer_sudo: # attempts to 'retry' without having tried first return werkzeug.utils.redirect("/") try: retry_answer_sudo = survey_sudo._create_answer( user=request.env.user, partner=answer_sudo.partner_id, email=answer_sudo.email, invite_token=answer_sudo.invite_token, test_entry=answer_sudo.test_entry, **self._prepare_retry_additional_values(answer_sudo)) except: return werkzeug.utils.redirect("/") return request.redirect( '/survey/start/%s?%s' % (survey_sudo.access_token, keep_query('*', answer_token=retry_answer_sudo.token)))
def portal_chatter_post(self, res_model, res_id, message, redirect=None, attachment_ids='', attachment_tokens='', **kw): """Create a new `mail.message` with the given `message` and/or `attachment_ids` and redirect the user to the newly created message. The message will be associated to the record `res_id` of the model `res_model`. The user must have access rights on this target document or must provide valid identifiers through `kw`. See `_message_post_helper`. """ url = redirect or (request.httprequest.referrer and request.httprequest.referrer + "#discussion") or '/my' res_id = int(res_id) attachment_ids = [int(attachment_id) for attachment_id in attachment_ids.split(',') if attachment_id] attachment_tokens = [attachment_token for attachment_token in attachment_tokens.split(',') if attachment_token] self._portal_post_check_attachments(attachment_ids, attachment_tokens) if message or attachment_ids: # message is received in plaintext and saved in html if message: message = plaintext2html(message) post_values = { 'res_model': res_model, 'res_id': res_id, 'message': message, 'send_after_commit': False, 'attachment_ids': attachment_ids, } post_values.update((fname, kw.get(fname)) for fname in self._portal_post_filter_params()) message = _message_post_helper(**post_values) return request.redirect(url)
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.move', 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) acquirers = values.get('acquirers') if acquirers: country_id = values.get('partner_id') and values.get( 'partner_id')[0].country_id.id values['acq_extra_fees'] = acquirers.get_acquirer_extra_fees( invoice_sudo.amount_residual, invoice_sudo.currency_id, country_id) return request.render("account.portal_invoice_page", values)
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 signup_user_confirm_by_email(self, *args, **kw): user_id = kw.get("UserID", "0") website_user = request.env['website.user.confirmation'].sudo().browse( int(user_id)) user = request.env['res.users'].sudo().browse(website_user.user_id) user.active = True website_user.sudo().confirmation_state = "confirm" return request.redirect("/web/login")
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) return request.render("purchase.portal_my_purchase_order", values)
def pricelist(self, promo, **post): order = request.website.sale_get_order() coupon_status = request.env['sale.coupon.apply.code'].sudo( ).apply_coupon(order, promo) if coupon_status.get('not_found'): return super(WebsiteSale, self).pricelist(promo, **post) elif coupon_status.get('error'): request.session['error_promo_code'] = coupon_status['error'] return request.redirect(post.get('r', '/shop/cart'))
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 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 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 reset_template(self, view_id, mode='soft', redirect='/', **kwargs): """ This method will try to reset a broken view. Given the mode, the view can either be: - Soft reset: restore to previous architeture. - Hard reset: it will read the original `arch` from the XML file if the view comes from an XML file (arch_fs). """ view = request.env['ir.ui.view'].browse(int(view_id)) # Deactivate COW to not fix a generic view by creating a specific view.with_context(website_id=None).reset_arch(mode) return request.redirect(redirect)
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 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( 'sale.order', order_id, message, **{'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 survey_test(self, survey_token, **kwargs): """ Test mode for surveys: create a test answer, only for managers or officers testing their surveys """ survey_sudo, dummy = self._fetch_from_access_token(survey_token, False) try: answer_sudo = survey_sudo._create_answer(user=request.env.user, test_entry=True) except: return werkzeug.utils.redirect('/') return request.redirect( '/survey/start/%s?%s' % (survey_sudo.access_token, keep_query('*', answer_token=answer_sudo.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) return request.render("website_sale_comparison.product_compare", 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.move'].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 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 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 _serve_fallback(cls, exception): # serve attachment before parent = super(Http, cls)._serve_fallback(exception) if parent: # attachment return parent if not request.is_frontend: return False 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.redirect_type) return False
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 survey_start(self, survey_token, answer_token=None, email=False, **post): """ Start a survey by providing * a token linked to a survey; * a token linked to an answer or generate a new token if access is allowed; """ access_data = self._get_access_data(survey_token, answer_token, ensure_token=False) if access_data['validity_code'] is not True: return self._redirect_with_error(access_data, access_data['validity_code']) survey_sudo, answer_sudo = access_data['survey_sudo'], access_data[ 'answer_sudo'] if not answer_sudo: try: answer_sudo = survey_sudo._create_answer(user=request.env.user, email=email) except UserError: answer_sudo = False if not answer_sudo: try: survey_sudo.with_user( request.env.user).check_access_rights('read') survey_sudo.with_user( request.env.user).check_access_rule('read') except: return werkzeug.utils.redirect("/") else: return request.render("survey.403", {'survey': survey_sudo}) # Select the right page if answer_sudo.state == 'new': # Intro page data = {'survey': survey_sudo, 'answer': answer_sudo, 'page': 0} return request.render('survey.survey_init', data) else: return request.redirect( '/survey/fill/%s/%s' % (survey_sudo.access_token, answer_sudo.token))
def confirm(self, **kw): tx_id = int(kw.get('tx_id', 0)) access_token = kw.get('access_token') if tx_id: if access_token: tx = request.env['payment.transaction'].sudo().browse(tx_id) secret = request.env['ir.config_parameter'].sudo().get_param( 'database.secret') valid_token_str = '%s%s%s' % ( tx.id, tx.reference, float_repr(tx.amount, precision_digits=tx.currency_id.decimal_places)) valid_token = hmac.new(secret.encode('utf-8'), valid_token_str.encode('utf-8'), hashlib.sha256).hexdigest() if not consteq(ustr(valid_token), access_token): raise werkzeug.exceptions.NotFound else: 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.state_message or _( 'An error occured during the processing of this payment') PaymentProcessing.remove_payment_transaction(tx) return request.render('payment.confirm', { 'tx': tx, 'status': status, 'message': message }) else: return request.redirect('/my/home')