Handle trial period

- user can upgrade to lifetime if in trial or free
- free or trial user can buy a subscription
- user has all features when in trial
This commit is contained in:
Son NK
2020-01-30 10:53:17 +07:00
parent 354e5f9a67
commit 2ca97368f8
7 changed files with 45 additions and 28 deletions
@@ -13,7 +13,7 @@
<h1> Billing </h1>
<p>
You are on the <b>{{ current_user.plan_name() }}</b> plan. Thank you very much for supporting SimpleLogin. 🙌
You are on the <b>{{ current_user.get_subscription().plan_name() }}</b> plan. Thank you very much for supporting SimpleLogin. 🙌
</p>
{% if sub.cancelled %}
+4 -1
View File
@@ -20,7 +20,10 @@ def custom_alias():
if not current_user.can_create_new_alias():
# notify admin
LOG.error("user %s tries to create custom alias", current_user)
flash("ony premium user can choose custom alias", "warning")
flash(
"You have reached free plan limit, please upgrade to create new aliases",
"warning",
)
return redirect(url_for("dashboard.index"))
user_custom_domains = [cd.domain for cd in current_user.verified_custom_domains()]
+1 -1
View File
@@ -24,7 +24,7 @@ class CouponForm(FlaskForm):
@login_required
def lifetime_licence():
# sanity check: make sure this page is only for free user
if current_user.is_premium():
if current_user.lifetime_or_active_subscription():
flash("You are already a premium user", "warning")
return redirect(url_for("dashboard.index"))
+2 -2
View File
@@ -13,8 +13,8 @@ from app.dashboard.base import dashboard_bp
@dashboard_bp.route("/pricing", methods=["GET", "POST"])
@login_required
def pricing():
# sanity check: make sure this page is only for free user
if current_user.is_premium():
# sanity check: make sure this page is only for free or trial user
if not current_user.should_upgrade():
flash("You are already a premium user", "warning")
return redirect(url_for("dashboard.index"))
+32 -19
View File
@@ -124,7 +124,7 @@ class User(db.Model, ModelMixin, UserMixin):
# user can use all premium features until this date
trial_end = db.Column(
ArrowType, default=lambda: arrow.now().shift(days=7), nullable=True
ArrowType, default=lambda: arrow.now().shift(days=7, hours=1), nullable=True
)
profile_picture = db.relationship(File)
@@ -146,11 +146,8 @@ class User(db.Model, ModelMixin, UserMixin):
return user
def should_upgrade(self):
return not self.is_premium()
def is_premium(self):
"""user is premium if they have a active subscription"""
def lifetime_or_active_subscription(self) -> bool:
"""True if user has lifetime licence or active subscription"""
if self.lifetime:
return True
@@ -160,7 +157,29 @@ class User(db.Model, ModelMixin, UserMixin):
return False
def can_create_new_alias(self):
def in_trial(self):
"""return True if user does not have lifetime licence or an active subscription AND is in trial period"""
if self.lifetime_or_active_subscription():
return False
return self.trial_end and arrow.now() < self.trial_end
def should_upgrade(self):
return not self.lifetime_or_active_subscription()
def is_premium(self) -> bool:
"""
user is premium if they:
- have a lifetime deal or
- in trial period or
- active subscription
"""
if self.lifetime_or_active_subscription():
return True
return self.trial_end and arrow.now() < self.trial_end
def can_create_new_alias(self) -> bool:
if self.is_premium():
return True
@@ -202,7 +221,6 @@ class User(db.Model, ModelMixin, UserMixin):
def suggested_names(self) -> (str, [str]):
"""return suggested name and other name choices """
other_name = convert_to_id(self.name)
return self.name, [other_name, "Anonymous", "whoami"]
@@ -211,17 +229,6 @@ class User(db.Model, ModelMixin, UserMixin):
names = self.name.split(" ")
return "".join([n[0].upper() for n in names if n])
def plan_name(self) -> str:
if self.is_premium():
sub = self.get_subscription()
if sub.plan == PlanEnum.monthly:
return "Monthly ($2.99/month)"
else:
return "Yearly ($29.99/year)"
else:
return "Free Plan"
def get_subscription(self):
"""return *active* subscription
TODO: support user unsubscribe and re-subscribe
@@ -643,6 +650,12 @@ class Subscription(db.Model, ModelMixin):
user = db.relationship(User)
def plan_name(self):
if self.plan == PlanEnum.monthly:
return "Monthly ($2.99/month)"
else:
return "Yearly ($29.99/year)"
class DeletedAlias(db.Model, ModelMixin):
"""Store all deleted alias to make sure they are NOT reused"""
+1 -1
View File
@@ -381,7 +381,7 @@ def setup_paddle_callback(app: Flask):
elif request.form.get("alert_name") == "subscription_cancelled":
subscription_id = request.form.get("subscription_id")
LOG.debug("Cancel subscription %s", subscription_id)
LOG.error("Cancel subscription %s", subscription_id)
sub: Subscription = Subscription.get_by(subscription_id=subscription_id)
if sub:
+4 -3
View File
@@ -25,15 +25,16 @@
{{ current_user.name }}
</span>
{% if current_user.is_premium() %}
{% if current_user.in_trial() %}
<small class="text-success d-block mt-1">Trial ends in {{ current_user.trial_end|dt }}</small>
{% elif current_user.lifetime_or_active_subscription() %}
<small class="text-success d-block mt-1">Premium</small>
{% endif %}
</span>
</a>
<div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow">
<a class="dropdown-item" href="{{ url_for('auth.logout') }}">
<i class="dropdown-icon fe fe-log-out"></i> Sign out
</a>