def render_comments(self): """ Render comments GET: Return json of all the comments of this post. POST: Create new comment for this post. """ if self.state != 'Published': abort(404) # Add re_captcha if the configuration has such an option and user # is guest if 're_captcha_public' in CONFIG.options and request.is_guest_user: comment_form = GuestCommentForm( request.form, captcha={'ip_address': request.remote_addr} ) else: comment_form = PostCommentForm(request.form) if request.method == 'GET': if self.nereid_user == request.nereid_user: return jsonify(comments=[ comment.serialize() for comment in self.comments ]) return jsonify(comments=[ comment.serialize() for comment in self.comments if not comment.is_spam ]) # If post does not allow guest comments, # then dont allow guest user to comment if not self.allow_guest_comments and request.is_guest_user: flash('Guests are not allowed to write comments') if request.is_xhr: return jsonify( success=False, errors=['Guests are not allowed to write comments'] ) return redirect(url_for( 'blog.post.render', user_id=self.nereid_user.id, uri=self.uri )) if request.method == 'POST' and comment_form.validate(): self.write([self], { 'comments': [('create', [{ 'nereid_user': current_user.id if not current_user.is_anonymous() else None, 'name': current_user.display_name if not current_user.is_anonymous() else comment_form.name.data, 'content': comment_form.content.data, }])] }) if request.is_xhr: return jsonify(success=True) if comment_form.validate() \ else jsonify(success=False, errors=comment_form.errors) return redirect(url_for( 'blog.post.render', user_id=self.nereid_user.id, uri=self.uri ))
def default_price_list(): """Get the pricelist of active user. In the event that the logged in user does not have a pricelist set against the user, the channel's pricelist is chosen. :param user: active record of the nereid user """ User = Pool().get('res.user') user = User(Transaction().user) channel_price_list = user.current_channel.price_list.id if \ user.current_channel else None if not has_request_context(): # Not a nereid request return channel_price_list # If control reaches here, then this is a nereid request. Lets try # and personalise the pricelist of the user logged in. if current_user.is_anonymous(): # Sorry anonymous users, you get the shop price return channel_price_list if current_user.party.sale_price_list: # There is a sale pricelist for the specific user's party. return current_user.party.sale_price_list.id return channel_price_list
def get_timezone(): """ Returns the timezone that should be used for this request as `pytz.timezone` object. This returns `None` if used outside of a request. """ ctx = _request_ctx_stack.top tzinfo = getattr(ctx, 'babel_tzinfo', None) if tzinfo is None: babel = ctx.app.extensions['babel'] if babel.timezone_selector_func is None: if not current_user.is_anonymous() and current_user.timezone: tzinfo = timezone(current_user.timezone) elif ctx.request.nereid_website.company.timezone: tzinfo = timezone(ctx.request.nereid_website.company.timezone) else: tzinfo = babel.default_timezone else: rv = babel.timezone_selector_func() if rv is None: tzinfo = babel.default_timezone else: if isinstance(rv, basestring): tzinfo = timezone(rv) else: tzinfo = rv ctx.babel_tzinfo = tzinfo return tzinfo
def get_timezone(): """ Returns the timezone that should be used for this request as `pytz.timezone` object. This returns `None` if used outside of a request. """ ctx = _request_ctx_stack.top tzinfo = getattr(ctx, 'babel_tzinfo', None) if tzinfo is None: babel = ctx.app.extensions['babel'] if babel.timezone_selector_func is None: if not current_user.is_anonymous() and current_user.timezone: tzinfo = timezone(current_user.timezone) else: tzinfo = timezone(ctx.request.nereid_website.timezone) else: rv = babel.timezone_selector_func() if rv is None: tzinfo = babel.default_timezone else: if isinstance(rv, basestring): tzinfo = timezone(rv) else: tzinfo = rv ctx.babel_tzinfo = tzinfo return tzinfo
def get_payment_form(cls): ''' Return a payment form ''' NereidCart = Pool().get('nereid.cart') cart = NereidCart.open_cart() payment_form = PaymentForm() # add possible alternate payment_methods payment_form.alternate_payment_method.choices = [ (m.id, m.name) for m in cart.get_alternate_payment_methods() ] # add profiles of the registered user if not current_user.is_anonymous(): payment_form.payment_profile.choices = [ (p.id, p.rec_name) for p in current_user.party.get_payment_profiles() ] if (cart.sale.shipment_address == cart.sale.invoice_address) or ( not cart.sale.invoice_address): payment_form.use_shipment_address.data = "y" return payment_form
def render(self, confirmation=None): """Render given sale order :param sale: ID of the sale Order :param confirmation: If any value is provided for this field then this page is considered the confirmation page. This also passes a `True` if such an argument is proved or a `False` """ NereidUser = Pool().get('nereid.user') # This Ugly type hack is for a bug in previous versions where some # parts of the code passed confirmation as a text confirmation = False if confirmation is None else True # Try to find if the user can be shown the order access_code = request.values.get('access_code', None) if current_user.is_anonymous(): if not access_code: # No access code provided, user is not authorized to # access order page return NereidUser.unauthorized_handler() if access_code != self.guest_access_code: # Invalid access code abort(403) else: if self.party.id != request.nereid_user.party.id: # Order does not belong to the user abort(403) return render_template( 'sale.jinja', sale=self, confirmation=confirmation )
def default_price_list(user=None): """Get the pricelist of active user. In the event that the logged in user does not have a pricelist set against the user, the guest user's pricelist is chosen. :param user: active record of the nereid user """ if not has_request_context(): # Not a nereid request return None if user is not None and user.party.sale_price_list: # If a user was provided and the user has a pricelist, use # that return user.party.sale_price_list.id if not current_user.is_anonymous() and \ current_user.party.sale_price_list: # If the currently logged in user has a pricelist defined, use # that return current_user.party.sale_price_list.id # Since there is no pricelist for the user, use the guest user's # pricelist if one is defined. guest_user = request.nereid_website.guest_user if guest_user.party.sale_price_list: return guest_user.party.sale_price_list.id return None
def default_price_list(): """Get the pricelist of active user. In the event that the logged in user does not have a pricelist set against the user, the shop's pricelist is chosen. :param user: active record of the nereid user """ User = Pool().get('res.user') user = User(Transaction().user) shop_price_list = user.shop.price_list.id if user.shop else None if not has_request_context(): # Not a nereid request return shop_price_list # If control reaches here, then this is a nereid request. Lets try # and personalise the pricelist of the user logged in. if current_user.is_anonymous(): # Sorry anonymous users, you get the shop price return shop_price_list if current_user.party.sale_price_list: # There is a sale pricelist for the specific user's party. return current_user.party.sale_price_list.id return shop_price_list
def _user_status(self): """ Add facebook_id to the user_status if the user is logged in """ rv = super(Website, self)._user_status() if not current_user.is_anonymous() and request.nereid_user.facebook_id: rv["facebook_id"] = request.nereid_user.facebook_id return rv
def confirm(cls, sales): "Send an email after sale is confirmed" super(Sale, cls).confirm(sales) if has_request_context(): for sale in sales: # Change party name to invoice address name for guest user if current_user.is_anonymous(): sale.party.name = sale.invoice_address.name sale.party.save()
def validate_payment_profile(self, payment_profile): """ Checks if payment profile belongs to right party """ if not current_user.is_anonymous() and \ payment_profile.party != current_user.party: # verify that the payment profile belongs to the registered # user. flash(_('The payment profile chosen is invalid')) return redirect( url_for('nereid.checkout.payment_method') )
def _get_receiver_email_address(self): """ Update reciever's email address(s) """ to_emails = set() if self.party.email: to_emails.add(self.party.email.lower()) if has_request_context() and not current_user.is_anonymous() and \ current_user.email: to_emails.add(current_user.email.lower()) return list(to_emails)
def nereid_pay_using_credit_card(self, credit_card_form, amount): ''' Complete using the given card. If the user is registered and the save card option is given, then first save the card and delegate to :meth:`_complete_using_profile` with the profile thus obtained. Otherwise a payment transaction is created with the given card data. ''' AddPaymentProfileWizard = Pool().get( 'party.party.payment_profile.add', type='wizard' ) gateway = request.nereid_website.credit_card_gateway if not current_user.is_anonymous() and \ credit_card_form.add_card_to_profiles.data and \ request.nereid_website.save_payment_profile: profile_wiz = AddPaymentProfileWizard( AddPaymentProfileWizard.create()[0] # Wizard session ) profile_wiz.card_info.party = self.party profile_wiz.card_info.address = self.invoice_address profile_wiz.card_info.provider = gateway.provider profile_wiz.card_info.gateway = gateway profile_wiz.card_info.owner = credit_card_form.owner.data profile_wiz.card_info.number = credit_card_form.number.data profile_wiz.card_info.expiry_month = \ credit_card_form.expiry_month.data profile_wiz.card_info.expiry_year = \ unicode(credit_card_form.expiry_year.data) profile_wiz.card_info.csc = credit_card_form.cvv.data with Transaction().set_context(return_profile=True): profile = profile_wiz.transition_add() return self.nereid_pay_using_profile( profile.id, amount ) return self._pay_using_credit_card( gateway, { 'owner': credit_card_form.owner.data, 'number': credit_card_form.number.data, 'expiry_month': credit_card_form.expiry_month.data, 'expiry_year': unicode(credit_card_form.expiry_year.data), 'cvv': credit_card_form.cvv.data, }, amount )
def login(cls): """ Simple login based on the email and password Required post data see :class:LoginForm """ login_form = LoginForm(request.form) if not current_user.is_anonymous() and request.args.get('next'): return redirect(request.args['next']) if request.method == 'POST' and login_form.validate(): NereidUser = Pool().get('nereid.user') user = NereidUser.authenticate( login_form.email.data, login_form.password.data ) # Result can be the following: # 1 - Browse record of User (successful login) # 2 - None - Login failure without message # 3 - Any other false value (no message is shown. useful if you # want to handle the message shown to user) if user: # NOTE: Translators leave %s as such flash(_("You are now logged in. Welcome %(name)s", name=user.display_name)) if login_user(user, remember=login_form.remember.data): if request.is_xhr: return jsonify({ 'success': True, 'user': user.serialize(), }) else: return redirect( request.values.get( 'next', url_for('nereid.website.home') ) ) else: flash(_("Your account has not been activated yet!")) elif user is None: flash(_("Invalid login credentials")) failed_login.send(form=login_form) if request.is_xhr: rv = jsonify(message="Bad credentials") rv.status_code = 401 return rv return render_template('login.jinja', login_form=login_form)
def _process_payment(cls, cart): """ This is separated so that other modules can easily modify the behavior of processing payment independent of this module. """ NereidCart = Pool().get('nereid.cart') PaymentProfile = Pool().get('party.payment_profile') PaymentMethod = Pool().get('nereid.website.payment_method') cart = NereidCart.open_cart() payment_form = cls.get_payment_form() credit_card_form = cls.get_credit_card_form() if not current_user.is_anonymous() and \ payment_form.payment_profile.data: # Regd. user with payment_profile rv = cart.sale._add_sale_payment( payment_profile=PaymentProfile( payment_form.payment_profile.data ) ) if isinstance(rv, BaseResponse): # Redirects only if payment profile is invalid. # Then do not confirm the order, just redirect return rv return cls.confirm_cart(cart) elif payment_form.alternate_payment_method.data: # Checkout using alternate payment method rv = cart.sale._add_sale_payment( alternate_payment_method=PaymentMethod( payment_form.alternate_payment_method.data ) ) if isinstance(rv, BaseResponse): # If the alternate payment method introduced a # redirect, then save the order and go to that cls.confirm_cart(cart) return rv return cls.confirm_cart(cart) elif request.nereid_website.credit_card_gateway and \ credit_card_form.validate(): # validate the credit card form and checkout using that cart.sale._add_sale_payment( credit_card_form=credit_card_form ) return cls.confirm_cart(cart)
def _user_status(): """Returns the commonly required status parameters of the user This method could be inherited and components could be added """ rv = { 'messages': map(unicode, get_flashed_messages()), } if current_user.is_anonymous(): rv.update({'logged_id': False}) else: rv.update({ 'logged_in': True, 'name': request.nereid_user.display_name }) return rv
def create(cls, vlist): ''' Create a Task and add current user as participant of the project :param vlist: List of dictionaries of values to create ''' for values in vlist: if has_request_context(): if values['type'] == 'task' and not current_user.is_anonymous(): values.setdefault('participants', []).append( ('add', [current_user.id]) ) else: # TODO: identify the nereid user through employee pass return super(Task, cls).create(vlist)
def create(cls, vlist): ''' Create a Task and add current user as participant of the project :param vlist: List of dictionaries of values to create ''' for values in vlist: if has_request_context(): if values['type'] == 'task' and not current_user.is_anonymous( ): values.setdefault('participants', []).append( ('add', [current_user.id])) else: # TODO: identify the nereid user through employee pass return super(Task, cls).create(vlist)
def sale_price(self, quantity=0): """Return the Sales Price. A wrapper designed to work as a context variable in templating The price is calculated from the pricelist associated with the current user. The user in the case of guest user is logged in user. In the event that the logged in user does not have a pricelist set against the user, the guest user's pricelist is chosen. Finally if neither the guest user, nor the regsitered user has a pricelist set against them then the list price is displayed as the list price of the product :param quantity: Quantity """ Sale = Pool().get('sale.sale') price_list = Sale.default_price_list() if current_user.is_anonymous(): customer = request.nereid_website.guest_user.party else: customer = current_user.party # Build a Cache key to store in cache cache_key = key_from_list([ Transaction().cursor.dbname, Transaction().user, customer.id, price_list, self.id, quantity, request.nereid_currency.id, 'product.product.sale_price', ]) price = cache.get(cache_key) if price is None: # There is a valid pricelist, now get the price with Transaction().set_context( customer=customer.id, price_list=price_list, currency=request.nereid_currency.id): price = self.get_sale_price([self], quantity)[self.id] # Now convert the price to the session currency cache.set(cache_key, price, 60 * 5) return price
def sale_price(self, quantity=0): """Return the Sales Price. A wrapper designed to work as a context variable in templating The price is calculated from the pricelist associated with the current user. The user in the case of guest user is logged in user. In the event that the logged in user does not have a pricelist set against the user, the guest user's pricelist is chosen. Finally if neither the guest user, nor the regsitered user has a pricelist set against them then the list price is displayed as the list price of the product :param quantity: Quantity """ Sale = Pool().get('sale.sale') price_list = Sale.default_price_list() if current_user.is_anonymous(): customer = request.nereid_website.guest_user.party else: customer = current_user.party # Build a Cache key to store in cache cache_key = key_from_list([ Transaction().cursor.dbname, Transaction().user, customer.id, price_list, self.id, quantity, request.nereid_currency.id, 'product.product.sale_price', ]) price = cache.get(cache_key) if price is None: # There is a valid pricelist, now get the price with Transaction().set_context( customer=customer.id, price_list=price_list, currency=request.nereid_currency.id ): price = self.get_sale_price([self], quantity)[self.id] # Now convert the price to the session currency cache.set(cache_key, price, 60 * 5) return price
def _user_status(): """Returns the commonly required status parameters of the user This method could be inherited and components could be added """ rv = { 'messages': map(unicode, get_flashed_messages()), } if current_user.is_anonymous(): rv.update({ 'logged_id': False }) else: rv.update({ 'logged_in': True, 'name': request.nereid_user.display_name }) return rv
def _get_email_template_context(self): """ Update context """ context = super(Sale, self)._get_email_template_context() if has_request_context() and not current_user.is_anonymous(): customer_name = current_user.display_name else: customer_name = self.party.name context.update({ 'url_for': lambda *args, **kargs: url_for(*args, **kargs), 'has_request_context': lambda *args, **kargs: has_request_context( *args, **kargs), 'current_user': current_user, 'customer_name': customer_name, 'to_json': lambda *args, **kargs: json.dumps(*args, **kargs), }) return context
def _process_payment(cls, cart): """ This is separated so that other modules can easily modify the behavior of processing payment independent of this module. """ NereidCart = Pool().get('nereid.cart') cart = NereidCart.open_cart() payment_form = cls.get_payment_form() credit_card_form = cls.get_credit_card_form() amount_to_checkout = cart.sale._get_amount_to_checkout() if not current_user.is_anonymous() and \ payment_form.payment_profile.data: # Regd. user with payment_profile rv = cart.sale.nereid_pay_using_profile( payment_form.payment_profile.data, amount_to_checkout) if isinstance(rv, BaseResponse): # Redirects only if payment profile is invalid. # Then do not confirm the order, just redirect return rv return cls.confirm_cart(cart) elif payment_form.alternate_payment_method.data: # Checkout using alternate payment method rv = cart.sale.nereid_pay_using_alternate_payment_method( payment_form, amount_to_checkout) if isinstance(rv, BaseResponse): # If the alternate payment method introduced a # redirect, then save the order and go to that cls.confirm_cart(cart) return rv return cls.confirm_cart(cart) elif request.nereid_website.credit_card_gateway and \ credit_card_form.validate(): # validate the credit card form and checkout using that cart.sale.nereid_pay_using_credit_card(credit_card_form, amount_to_checkout) return cls.confirm_cart(cart)
def add_comment_to_sale(self): """ Add comment to sale. User can add comment or note to sale order. """ comment_is_allowed = False if self.state not in ['confirmed', 'processing']: abort(403) if current_user.is_anonymous(): access_code = request.values.get('access_code', None) if access_code and access_code == self.guest_access_code: # No access code provided comment_is_allowed = True elif current_user.is_authenticated() and \ current_user.party == self.party: comment_is_allowed = True if not comment_is_allowed: abort(403) if request.form.get('comment') and not self.comment \ and self.state == 'confirmed': self.comment = request.form.get('comment') self.save() if request.is_xhr: return jsonify({ 'message': 'Comment Added', 'comment': self.comment, }) flash(_('Comment Added')) return redirect(request.referrer)
def billing_address(cls): ''' Choose or Create a billing address ''' NereidCart = Pool().get('nereid.cart') Address = Pool().get('party.address') PaymentProfile = Pool().get('party.payment_profile') cart = NereidCart.open_cart() address_form = cls.get_new_address_form() if request.method == 'POST': if request.form.get('use_shipment_address'): if not cart.sale.shipment_address: # Without defining shipment address, the user is # trying to set invoice_address as shipment_address return redirect( url_for('nereid.checkout.shipping_address')) cart.sale.invoice_address = cart.sale.shipment_address cart.sale.save() return redirect(url_for('nereid.checkout.payment_method')) if request.form.get('payment_profile'): payment_profile = PaymentProfile( request.form.get('payment_profile', type=int)) if payment_profile and \ cart.sale.invoice_address != payment_profile.address: cart.sale.invoice_address = payment_profile.address cart.sale.save() return redirect(url_for('nereid.checkout.payment_method')) if not current_user.is_anonymous() and request.form.get('address'): # Registered user has chosen an existing address address = Address(request.form.get('address', type=int)) if address.party != cart.sale.party: flash(_('The address chosen is not valid')) return redirect(url_for('nereid.checkout.billing_address')) else: # Guest user or registered user creating an address. Only # difference is that the party of address depends on guest or # not if not address_form.validate(): address = None else: if current_user.is_anonymous() and cart.sale.invoice_address \ and cart.sale.invoice_address != cart.sale.shipment_address: # noqa # Save to the same address if the guest user # is just trying to update the address address = cart.sale.invoice_address else: address = Address() address.party = cart.sale.party address.name = address_form.name.data address.street = address_form.street.data address.streetbis = address_form.streetbis.data address.zip = address_form.zip.data address.city = address_form.city.data address.country = address_form.country.data address.subdivision = address_form.subdivision.data if address_form.phone.data: # create contact mechanism phone = \ cart.sale.party.add_contact_mechanism_if_not_exists( 'phone', address_form.phone.data ) address.phone_number = phone.id address.save() if address is not None: # Finally save the address to the shipment cart.sale.invoice_address = address cart.sale.save() return redirect(url_for('nereid.checkout.payment_method')) addresses = [] if not current_user.is_anonymous(): addresses.extend(current_user.party.addresses) return render_template( 'checkout/billing_address.jinja', addresses=addresses, address_form=address_form, )
def sign_in(cls): ''' Step 1: Sign In or Register GET ~~~ Renders a sign-in or register page. If guest checkout is enabled, then an option to continue as guest is also permitted, in which case the email is a required field. POST ~~~~ For guest checkout, this sign in would create a new party with the name as the current session_id and move the shopping cart's sale to the new user's ownership Designer notes: The registration or login must contact the corresponding handlers. Login and Registraion handlers are designed to handle a `next` parameter where the user would be redirected to if the operation was successful. The next url is provided in the context OTOH, if the user desires to checkout as guest, the user is required to fill in the email and submit the form, which posts the email to this handler. ''' NereidCart = Pool().get('nereid.cart') NereidUser = Pool().get('nereid.user') Party = Pool().get('party.party') if not current_user.is_anonymous(): form = cls.sign_in_form( email=current_user.email, checkout_mode='account', ) else: # Guest user form = cls.sign_in_form( email=session.get('email'), checkout_mode='guest', ) if form.validate_on_submit(): if form.checkout_mode.data == 'guest': if not cls.allowed_as_guest(form.email.data): return render_template( 'checkout/signin-email-in-use.jinja', email=form.email.data ) cart = NereidCart.open_cart() party_name = unicode(_( 'Guest with email: %(email)s', email=form.email.data )) if cart.sale.party == request.nereid_website.guest_user.party: # Create a party with the email as email, and session as # name, but attach the session to it. party, = Party.create([{ 'name': party_name, 'nereid_session': session.sid, 'addresses': [], 'contact_mechanisms': [('create', [{ 'type': 'email', 'value': form.email.data, }])] }]) cart.sale.party = party # TODO: Avoid this if the user comes to sign-in twice. cart.sale.shipment_address = None cart.sale.invoice_address = None cart.sale.save() else: # Perhaps the email changed ? party = cart.sale.party party.name = party_name # contact_mechanism of email type will always be there for # Guest user contact_mechanism = filter( lambda c: c.type == 'email', party.contact_mechanisms )[0] contact_mechanism.value = form.email.data contact_mechanism.save() party.email = form.email.data party.save() return redirect( url_for('nereid.checkout.shipping_address') ) else: # The user wants to use existing email to login user = NereidUser.authenticate( form.email.data, form.password.data ) if user: # FIXME: Remove remember_me login_user(user, remember=form.remember.data) return redirect( url_for('nereid.checkout.shipping_address') ) else: failed_login.send() if not current_user.is_anonymous(): # Registered user with a fresh login can directly proceed to # step 2, which is filling the shipping address # # if this is a recent sign-in by a registred user # automatically proceed to the shipping_address step return redirect(url_for('nereid.checkout.shipping_address')) return render_template( 'checkout/signin.jinja', form=form, next=url_for('nereid.checkout.shipping_address') )
def shipping_address(cls): ''' Choose or Create a shipping address Guest users are only allowed to create a new address while registered users are allowed to either choose an address or create a new one. GET ~~~ Renders the shipping_address selection/creation page. The template context would have an addresses variable which carries a list of addresses in the case of registered users. For guest users the variable would be empty. POST ~~~~ **Registered User**: If `address` (the id of the chosen address) is in the POST values, then the address is validated and stored as the `shipment_address` in the sale. If not, the new address form is validated to see if a new address has to be created for the party. **Guest User**: New address data has to be provided and validated to create the new address. Once the address is set succesfully, the delivery_options page is shown ''' NereidCart = Pool().get('nereid.cart') Address = Pool().get('party.address') cart = NereidCart.open_cart() address = None if current_user.is_anonymous() and cart.sale.shipment_address: address = cart.sale.shipment_address address_form = cls.get_new_address_form(address) if request.method == 'POST': if not current_user.is_anonymous() and request.form.get('address'): # Registered user has chosen an existing address address = Address(request.form.get('address', type=int)) if address.party != cart.sale.party: flash(_('The address chosen is not valid')) return redirect( url_for('nereid.checkout.shipping_address') ) else: # Guest user or registered user creating an address. Only # difference is that the party of address depends on guest or # not if not address_form.validate(): address = None else: if current_user.is_anonymous() and \ cart.sale.shipment_address: # Save to the same address if the guest user # is just trying to update the address address = cart.sale.shipment_address else: address = Address() address.party = cart.sale.party address.name = address_form.name.data address.street = address_form.street.data address.streetbis = address_form.streetbis.data address.zip = address_form.zip.data address.city = address_form.city.data address.country = address_form.country.data address.subdivision = address_form.subdivision.data if address_form.phone.data: # create contact mechanism phone = \ cart.sale.party.add_contact_mechanism_if_not_exists( 'phone', address_form.phone.data ) address.phone_number = phone.id address.save() if address is not None: # Finally save the address to the shipment cart.sale.shipment_address = address cart.sale.save() return redirect( url_for('nereid.checkout.validate_address') ) addresses = [] if not current_user.is_anonymous(): addresses.extend(current_user.party.addresses) return render_template( 'checkout/shipping_address.jinja', addresses=addresses, address_form=address_form, )
def billing_address(cls): ''' Choose or Create a billing address ''' NereidCart = Pool().get('nereid.cart') Address = Pool().get('party.address') PaymentProfile = Pool().get('party.payment_profile') cart = NereidCart.open_cart() address = None if current_user.is_anonymous() and cart.sale.invoice_address: address = cart.sale.invoice_address address_form = cls.get_new_address_form(address) if request.method == 'POST': if request.form.get('use_shipment_address'): if not cart.sale.shipment_address: # Without defining shipment address, the user is # trying to set invoice_address as shipment_address return redirect( url_for('nereid.checkout.shipping_address') ) cart.sale.invoice_address = cart.sale.shipment_address cart.sale.save() return redirect( url_for('nereid.checkout.payment_method') ) if request.form.get('payment_profile'): payment_profile = PaymentProfile( request.form.get('payment_profile', type=int) ) if payment_profile and \ cart.sale.invoice_address != payment_profile.address: cart.sale.invoice_address = payment_profile.address cart.sale.save() return redirect( url_for('nereid.checkout.payment_method') ) if not current_user.is_anonymous() and request.form.get('address'): # Registered user has chosen an existing address address = Address(request.form.get('address', type=int)) if address.party != cart.sale.party: flash(_('The address chosen is not valid')) return redirect( url_for('nereid.checkout.billing_address') ) else: # Guest user or registered user creating an address. Only # difference is that the party of address depends on guest or # not if not address_form.validate(): address = None else: if ( current_user.is_anonymous() and cart.sale.invoice_address and cart.sale.invoice_address != cart.sale.shipment_address ): # Save to the same address if the guest user # is just trying to update the address address = cart.sale.invoice_address else: address = Address() address.party = cart.sale.party address.name = address_form.name.data address.street = address_form.street.data address.streetbis = address_form.streetbis.data address.zip = address_form.zip.data address.city = address_form.city.data address.country = address_form.country.data address.subdivision = address_form.subdivision.data if address_form.phone.data: # create contact mechanism phone = \ cart.sale.party.add_contact_mechanism_if_not_exists( 'phone', address_form.phone.data ) address.phone_number = phone.id address.save() if address is not None: # Finally save the address to the shipment cart.sale.invoice_address = address cart.sale.save() return redirect( url_for('nereid.checkout.payment_method') ) addresses = [] if not current_user.is_anonymous(): addresses.extend(current_user.party.addresses) return render_template( 'checkout/billing_address.jinja', addresses=addresses, address_form=address_form, )
def new_opportunity(cls): """ Web handler to create a new sale opportunity """ if config.has_option('nereid', 're_captcha_public_key'): contact_form = ContactUsForm( request.form, captcha={'ip_address': request.remote_addr} ) else: contact_form = ContactUsForm(request.form) if request.method == 'POST': if not contact_form.validate(): return jsonify({ "success": False, "message": "Field validation error", "errors": contact_form.errors, }) ContactMech = Pool().get('party.contact_mechanism') Party = Pool().get('party.party') Config = Pool().get('sale.configuration') sale_config = Config(1) contact_data = contact_form.data # Create Party company = request.nereid_website.company.id if request.remote_addr and geoip: detected_country = geoip.country_name_by_addr( request.remote_addr ) else: detected_country = None party, = Party.create([{ 'name': contact_data.get('company') or contact_data['name'], 'addresses': [ ('create', [{ 'name': contact_data['name'], }]) ], }]) if contact_data.get('website'): # Create website as contact mech ContactMech.create([{ 'type': 'website', 'party': party.id, 'website': contact_data['website'], }]) if contact_data.get('phone'): # Create phone as contact mech and assign as phone ContactMech.create([{ 'type': 'phone', 'party': party.id, 'other_value': contact_data['phone'], }]) # Create email as contact mech and assign as email ContactMech.create([{ 'type': 'email', 'party': party.id, 'email': contact_data['email'], }]) # Create sale opportunity if not current_user.is_anonymous() and current_user.employee: employee = current_user.employee.id description = 'Created by %s' % \ current_user.display_name else: employee = sale_config.website_employee.id description = 'Created from website' lead, = cls.create([{ 'party': party.id, 'company': company, 'employee': employee, 'address': party.addresses[0].id, 'description': description, 'comment': contact_data['comment'], 'ip_address': request.remote_addr, 'detected_country': detected_country, }]) lead.send_notification_mail() if request.is_xhr or request.is_json: return jsonify({ "success": True, "message": "Contact saved", "lead_id": lead.id, }) return redirect(request.args.get( 'next', url_for('sale.opportunity.admin_lead', active_id=lead.id) )) return render_template('crm/sale_form.jinja', form=contact_form)
def sign_in(cls): ''' Step 1: Sign In or Register GET ~~~ Renders a sign-in or register page. If guest checkout is enabled, then an option to continue as guest is also permitted, in which case the email is a required field. POST ~~~~ For guest checkout, this sign in would create a new party with the name as the current session_id and move the shopping cart's sale to the new user's ownership Designer notes: The registration or login must contact the corresponding handlers. Login and Registraion handlers are designed to handle a `next` parameter where the user would be redirected to if the operation was successful. The next url is provided in the context OTOH, if the user desires to checkout as guest, the user is required to fill in the email and submit the form, which posts the email to this handler. ''' NereidCart = Pool().get('nereid.cart') NereidUser = Pool().get('nereid.user') Party = Pool().get('party.party') if not current_user.is_anonymous(): form = cls.sign_in_form( email=current_user.email, checkout_mode='account', ) else: # Guest user form = cls.sign_in_form( email=session.get('email'), checkout_mode='guest', ) if form.validate_on_submit(): if form.checkout_mode.data == 'guest': if not cls.allowed_as_guest(form.email.data): return render_template( 'checkout/signin-email-in-use.jinja', email=form.email.data) cart = NereidCart.open_cart() party_name = unicode( _('Guest with email: %(email)s', email=form.email.data)) if cart.sale.party == request.nereid_website.guest_user.party: # Create a party with the email as email, and session as # name, but attach the session to it. party, = Party.create([{ 'name': party_name, 'nereid_session': session.sid, 'addresses': [], 'contact_mechanisms': [('create', [{ 'type': 'email', 'value': form.email.data, }])] }]) cart.sale.party = party # TODO: Avoid this if the user comes to sign-in twice. cart.sale.shipment_address = None cart.sale.invoice_address = None cart.sale.save() else: # Perhaps the email changed ? party = cart.sale.party party.name = party_name # contact_mechanism of email type will always be there for # Guest user contact_mechanism = filter(lambda c: c.type == 'email', party.contact_mechanisms)[0] contact_mechanism.value = form.email.data contact_mechanism.save() party.email = form.email.data party.save() return redirect(url_for('nereid.checkout.shipping_address')) else: # The user wants to use existing email to login user = NereidUser.authenticate(form.email.data, form.password.data) if user: # FIXME: Remove remember_me login_user(user, remember=form.remember.data) return redirect( url_for('nereid.checkout.shipping_address')) else: failed_login.send() if not current_user.is_anonymous(): # Registered user with a fresh login can directly proceed to # step 2, which is filling the shipping address # # if this is a recent sign-in by a registred user # automatically proceed to the shipping_address step return redirect(url_for('nereid.checkout.shipping_address')) return render_template( 'checkout/signin.jinja', form=form, next=url_for('nereid.checkout.shipping_address'))
def shipping_address(cls): ''' Choose or Create a shipping address Guest users are only allowed to create a new address while registered users are allowed to either choose an address or create a new one. GET ~~~ Renders the shipping_address selection/creation page. The template context would have an addresses variable which carries a list of addresses in the case of registered users. For guest users the variable would be empty. POST ~~~~ **Registered User**: If `address` (the id of the chosen address) is in the POST values, then the address is validated and stored as the `shipment_address` in the sale. If not, the new address form is validated to see if a new address has to be created for the party. **Guest User**: New address data has to be provided and validated to create the new address. Once the address is set succesfully, the delivery_options page is shown ''' NereidCart = Pool().get('nereid.cart') Address = Pool().get('party.address') cart = NereidCart.open_cart() address_form = cls.get_new_address_form() if request.method == 'POST': if not current_user.is_anonymous() and request.form.get('address'): # Registered user has chosen an existing address address = Address(request.form.get('address', type=int)) if address.party != cart.sale.party: flash(_('The address chosen is not valid')) return redirect( url_for('nereid.checkout.shipping_address')) else: # Guest user or registered user creating an address. Only # difference is that the party of address depends on guest or # not if not address_form.validate(): address = None else: if current_user.is_anonymous() and \ cart.sale.shipment_address: # Save to the same address if the guest user # is just trying to update the address address = cart.sale.shipment_address else: address = Address() address.party = cart.sale.party address.name = address_form.name.data address.street = address_form.street.data address.streetbis = address_form.streetbis.data address.zip = address_form.zip.data address.city = address_form.city.data address.country = address_form.country.data address.subdivision = address_form.subdivision.data if address_form.phone.data: # create contact mechanism phone = \ cart.sale.party.add_contact_mechanism_if_not_exists( 'phone', address_form.phone.data ) address.phone_number = phone.id address.save() if address is not None: # Finally save the address to the shipment cart.sale.shipment_address = address cart.sale.save() return redirect(url_for('nereid.checkout.validate_address')) addresses = [] if not current_user.is_anonymous(): addresses.extend(current_user.party.addresses) return render_template( 'checkout/shipping_address.jinja', addresses=addresses, address_form=address_form, )
def render_comments(self): """ Render comments GET: Return json of all the comments of this post. POST: Create new comment for this post. """ if self.state != 'Published': abort(404) # Add re_captcha if the configuration has such an option and user # is guest if 're_captcha_public' in CONFIG.options and request.is_guest_user: comment_form = GuestCommentForm( request.form, captcha={'ip_address': request.remote_addr}) else: comment_form = PostCommentForm(request.form) if request.method == 'GET': if self.nereid_user == request.nereid_user: return jsonify(comments=[ comment.serialize() for comment in self.comments ]) return jsonify(comments=[ comment.serialize() for comment in self.comments if not comment.is_spam ]) # If post does not allow guest comments, # then dont allow guest user to comment if not self.allow_guest_comments and request.is_guest_user: flash('Guests are not allowed to write comments') if request.is_xhr: return jsonify( success=False, errors=['Guests are not allowed to write comments']) return redirect( url_for('blog.post.render', user_id=self.nereid_user.id, uri=self.uri)) if request.method == 'POST' and comment_form.validate(): self.write( [self], { 'comments': [('create', [{ 'nereid_user': current_user.id if not current_user.is_anonymous() else None, 'name': current_user.display_name if not current_user.is_anonymous() else comment_form.name.data, 'content': comment_form.content.data, }])] }) if request.is_xhr: return jsonify(success=True) if comment_form.validate() \ else jsonify(success=False, errors=comment_form.errors) return redirect( url_for('blog.post.render', user_id=self.nereid_user.id, uri=self.uri))
def default_user(): if not current_user.is_anonymous(): return current_user.id
def new_opportunity(cls): """ Web handler to create a new sale opportunity """ if 're_captcha_public' in CONFIG.options: contact_form = ContactUsForm( request.form, captcha={'ip_address': request.remote_addr}) else: contact_form = ContactUsForm(request.form) if request.method == 'POST': if not contact_form.validate(): return jsonify({ "success": False, "message": "Field validation error", "errors": contact_form.errors, }) ContactMech = Pool().get('party.contact_mechanism') Party = Pool().get('party.party') Config = Pool().get('sale.configuration') config = Config(1) contact_data = contact_form.data # Create Party company = request.nereid_website.company.id if request.remote_addr and geoip: detected_country = geoip.country_name_by_addr( request.remote_addr) else: detected_country = None party, = Party.create([{ 'name': contact_data.get('company') or contact_data['name'], 'addresses': [('create', [{ 'name': contact_data['name'], }])], }]) if contact_data.get('website'): # Create website as contact mech ContactMech.create([{ 'type': 'website', 'party': party.id, 'website': contact_data['website'], }]) if contact_data.get('phone'): # Create phone as contact mech and assign as phone ContactMech.create([{ 'type': 'phone', 'party': party.id, 'other_value': contact_data['phone'], }]) # Create email as contact mech and assign as email ContactMech.create([{ 'type': 'email', 'party': party.id, 'email': contact_data['email'], }]) # Create sale opportunity if not current_user.is_anonymous() and current_user.employee: employee = current_user.employee.id description = 'Created by %s' % \ current_user.display_name else: employee = config.website_employee.id description = 'Created from website' lead, = cls.create([{ 'party': party.id, 'company': company, 'employee': employee, 'address': party.addresses[0].id, 'description': description, 'comment': contact_data['comment'], 'ip_address': request.remote_addr, 'detected_country': detected_country, }]) lead.send_notification_mail() if request.is_xhr or request.is_json: return jsonify({ "success": True, "message": "Contact saved", "lead_id": lead.id, }) return redirect( request.args.get( 'next', url_for('sale.opportunity.admin_lead', active_id=lead.id))) return render_template('crm/sale_form.jinja', form=contact_form)