witten
/
luminotes
Archived
1
0
Fork 0

Made signup support yearly subscriptions.

This commit is contained in:
Dan Helfman 2008-05-08 19:14:39 +00:00
parent 269c28983d
commit a6baa45435
6 changed files with 68 additions and 12 deletions

3
NEWS
View File

@ -1,3 +1,6 @@
1.3.20: May 8, 2008
* Made signup support yearly subscriptions.
1.3.19: May 8, 2008 1.3.19: May 8, 2008
* Support for yearly subscriptions. * Support for yearly subscriptions.

View File

@ -2,7 +2,7 @@ import cherrypy
from Expose import expose from Expose import expose
from Expire import strongly_expire from Expire import strongly_expire
from Validate import validate, Valid_int, Valid_string from Validate import validate, Valid_int, Valid_string, Valid_bool
from Notebooks import Notebooks from Notebooks import Notebooks
from Users import Users, grab_user_id from Users import Users, grab_user_id
from Files import Files from Files import Files
@ -60,9 +60,10 @@ class Root( object ):
invite_id = Valid_id( none_okay = True ), invite_id = Valid_id( none_okay = True ),
after_login = Valid_string( min = 0, max = 1000 ), after_login = Valid_string( min = 0, max = 1000 ),
plan = Valid_int( none_okay = True ), plan = Valid_int( none_okay = True ),
yearly = Valid_bool( none_okay = True ),
user_id = Valid_id( none_okay = True ), user_id = Valid_id( none_okay = True ),
) )
def default( self, note_title, invite_id = None, after_login = None, plan = None, user_id = None ): def default( self, note_title, invite_id = None, after_login = None, plan = None, yearly = False, user_id = None ):
""" """
Convenience method for accessing a note in the main notebook by name rather than by note id. Convenience method for accessing a note in the main notebook by name rather than by note id.
@ -74,6 +75,8 @@ class Root( object ):
@param after_login: URL to redirect to after login (optional, must start with "/") @param after_login: URL to redirect to after login (optional, must start with "/")
@type plan: int @type plan: int
@param plan: rate plan index (optional, defaults to None) @param plan: rate plan index (optional, defaults to None)
@type yearly: bool
@param yearly: True for yearly plan, False for monthly (optional, defaults to False)
@rtype: unicode @rtype: unicode
@return: rendered HTML page @return: rendered HTML page
""" """
@ -88,7 +91,7 @@ class Root( object ):
if after_login: if after_login:
return dict( redirect = u"%s/%s?after_login=%s" % ( https_url, note_title, after_login ) ) return dict( redirect = u"%s/%s?after_login=%s" % ( https_url, note_title, after_login ) )
if plan: if plan:
return dict( redirect = u"%s/%s?plan=%s" % ( https_url, note_title, plan ) ) return dict( redirect = u"%s/%s?plan=%s&yearly=%s" % ( https_url, note_title, plan, yearly ) )
else: else:
return dict( redirect = u"%s/%s" % ( https_url, note_title ) ) return dict( redirect = u"%s/%s" % ( https_url, note_title ) )

View File

@ -217,8 +217,9 @@ class Users( object ):
signup_button = unicode, signup_button = unicode,
invite_id = Valid_id( none_okay = True ), invite_id = Valid_id( none_okay = True ),
rate_plan = Valid_int( none_okay = True ), rate_plan = Valid_int( none_okay = True ),
yearly = Valid_bool( none_okay = True ),
) )
def signup( self, username, password, password_repeat, email_address, signup_button, invite_id = None, rate_plan = None ): def signup( self, username, password, password_repeat, email_address, signup_button, invite_id = None, rate_plan = None, yearly = False ):
""" """
Create a new User based on the given information. Start that user with their own Notebook and a Create a new User based on the given information. Start that user with their own Notebook and a
"welcome to your wiki" Note. For convenience, login the newly created user as well. "welcome to your wiki" Note. For convenience, login the newly created user as well.
@ -238,6 +239,8 @@ class Users( object ):
@type rate_plan: int @type rate_plan: int
@param rate_plan: index of rate plan to signup for (optional). if greater than zero, redirect @param rate_plan: index of rate plan to signup for (optional). if greater than zero, redirect
to PayPal subscribe page after signup to PayPal subscribe page after signup
@type yearly: bool
@param yearly: True for a yearly rate plan, False for monthly (optional, defaults to False )
@rtype: json dict @rtype: json dict
@return: { 'redirect': url, 'authenticated': userdict } @return: { 'redirect': url, 'authenticated': userdict }
@raise Signup_error: passwords don't match or the username is unavailable @raise Signup_error: passwords don't match or the username is unavailable
@ -292,7 +295,7 @@ class Users( object ):
redirect = u"/notebooks/%s" % invite.notebook_id redirect = u"/notebooks/%s" % invite.notebook_id
# if there's a requested rate plan, then redirect to the PayPal subscribe page # if there's a requested rate plan, then redirect to the PayPal subscribe page
elif rate_plan and rate_plan > 0: elif rate_plan and rate_plan > 0:
redirect = u"/users/subscribe?rate_plan=%s" % rate_plan redirect = u"/users/subscribe?rate_plan=%s&yearly=%s" % ( rate_plan, yearly )
# otherwise, just redirect to the newly created notebook # otherwise, just redirect to the newly created notebook
else: else:
redirect = u"/notebooks/%s" % notebook.object_id redirect = u"/notebooks/%s" % notebook.object_id
@ -306,14 +309,17 @@ class Users( object ):
@grab_user_id @grab_user_id
@validate( @validate(
rate_plan = Valid_int(), rate_plan = Valid_int(),
yearly = Valid_bool( none_okay = True ),
user_id = Valid_id(), user_id = Valid_id(),
) )
def subscribe( self, rate_plan, user_id ): def subscribe( self, rate_plan, yearly = False, user_id = None ):
""" """
Submit a subscription form to PayPal, allowing the user to subscribe to the given rate plan. Submit a subscription form to PayPal, allowing the user to subscribe to the given rate plan.
@type rate_plan: int @type rate_plan: int
@param rate_plan: index of rate plan to subscribe to @param rate_plan: index of rate plan to subscribe to
@type yearly: bool
@param yearly: True for a yearly rate plan, False for monthly (optional, defaults to False )
@type user_id: unicode @type user_id: unicode
@param user_id: id of current logged-in user @param user_id: id of current logged-in user
@rtype: dict @rtype: dict
@ -324,7 +330,10 @@ class Users( object ):
raise Signup_error( u"The rate plan is invalid." ) raise Signup_error( u"The rate plan is invalid." )
plan = self.__rate_plans[ rate_plan ] plan = self.__rate_plans[ rate_plan ]
button = plan.get( u"button" ) if yearly:
button = plan.get( u"yearly_button" )
else:
button = plan.get( u"button" )
if not button or not button.strip(): if not button or not button.strip():
raise Signup_error( raise Signup_error(
u"Sorry, that rate plan is not configured for subscriptions. Please contact %s." % \ u"Sorry, that rate plan is not configured for subscriptions. Please contact %s." % \

View File

@ -253,6 +253,21 @@ class Test_root( Test_controller ):
assert result[ u"signup_plan" ] == 17 assert result[ u"signup_plan" ] == 17
assert result[ u"user" ].object_id == self.anonymous.object_id assert result[ u"user" ].object_id == self.anonymous.object_id
def test_default_with_plan_and_yearly( self ):
plan = u"17"
result = self.http_get(
"/my_note?plan=%s&yearly=True" % plan,
)
assert result
assert result[ u"notes" ]
assert len( result[ u"notes" ] ) == 1
assert result[ u"notes" ][ 0 ].object_id == self.anon_note.object_id
assert result[ u"notebook" ].object_id == self.anon_notebook.object_id
assert result[ u"signup_plan" ] == 17
assert result[ u"user" ].object_id == self.anonymous.object_id
def test_default_after_login( self ): def test_default_after_login( self ):
self.login() self.login()

View File

@ -103,7 +103,20 @@ class Test_users( Test_controller ):
rate_plan = u"2", rate_plan = u"2",
) ) ) )
assert result[ u"redirect" ] == u"/users/subscribe?rate_plan=2" assert result[ u"redirect" ] == u"/users/subscribe?rate_plan=2&yearly=False"
def test_signup_with_rate_plan_and_yearly( self ):
result = self.http_post( "/users/signup", dict(
username = self.new_username,
password = self.new_password,
password_repeat = self.new_password,
email_address = self.new_email_address,
signup_button = u"sign up",
rate_plan = u"2",
yearly = True,
) )
assert result[ u"redirect" ] == u"/users/subscribe?rate_plan=2&yearly=True"
def test_signup_without_email_address( self ): def test_signup_without_email_address( self ):
result = self.http_post( "/users/signup", dict( result = self.http_post( "/users/signup", dict(
@ -273,7 +286,7 @@ class Test_users( Test_controller ):
) ) ) )
session_id = result[ u"session_id" ] session_id = result[ u"session_id" ]
assert result[ u"redirect" ] == u"/users/subscribe?rate_plan=2" assert result[ u"redirect" ] == u"/users/subscribe?rate_plan=2&yearly=False"
user = self.database.last_saved_obj user = self.database.last_saved_obj
assert isinstance( user, User ) assert isinstance( user, User )
@ -341,6 +354,19 @@ class Test_users( Test_controller ):
assert form == plan[ u"button" ] % self.user.object_id assert form == plan[ u"button" ] % self.user.object_id
def test_subscribe_yearly( self ):
self.login()
result = self.http_post( "/users/subscribe", dict(
rate_plan = u"1",
yearly = True,
), session_id = self.session_id )
form = result.get( u"form" )
plan = self.settings[ u"global" ][ u"luminotes.rate_plans" ][ 1 ]
assert form == plan[ u"yearly_button" ] % self.user.object_id
def test_subscribe_with_free_rate_plan( self ): def test_subscribe_with_free_rate_plan( self ):
self.login() self.login()

View File

@ -187,13 +187,13 @@ class Upgrade_page( Product_page ):
separator = u"", separator = u"",
), ),
user and user.username not in ( u"anonymous", None ) and user.rate_plan != index \ user and user.username not in ( u"anonymous", None ) and user.rate_plan != index \
and yearly and ( plan.get( u"yearly_button" ).strip() and plan.get( u"yearly_button" ) % user.object_id or None ) or \ and ( yearly and ( plan.get( u"yearly_button" ).strip() and plan.get( u"yearly_button" ) % user.object_id or None ) or \
( plan.get( u"button" ).strip() and plan.get( u"button" ) % user.object_id or None ), ( plan.get( u"button" ).strip() and plan.get( u"button" ) % user.object_id or None ) ) or None,
) or None, ) or None,
( not user or user.username in ( u"anonymous", None ) ) and Div( ( not user or user.username in ( u"anonymous", None ) ) and Div(
A( A(
Img( src = u"/static/images/sign_up_button.png", width = "76", height = "23" ), Img( src = u"/static/images/sign_up_button.png", width = "76", height = "23" ),
href = u"/sign_up?plan=%s" % index, href = u"/sign_up?plan=%s&yearly=%s" % ( index, yearly ),
), ),
class_ = u"sign_up_button_area", class_ = u"sign_up_button_area",
) or None, ) or None,