Browse Source

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
Son NK 5 years ago
parent
commit
2ca97368f8

+ 1 - 1
app/dashboard/templates/dashboard/billing.html

@@ -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
app/dashboard/views/custom_alias.py

@@ -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
app/dashboard/views/lifetime_licence.py

@@ -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
app/dashboard/views/pricing.py

@@ -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
app/models.py

@@ -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
server.py

@@ -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
templates/header.html

@@ -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>