General description of the subscription model
Team has to pick a subscription plan and agree to be a paying customer for a minimum number of terms. A term is 3 months. The customer is billed in advance of each term. Until the agreement is fulfilled, the current subscription can not be canceled or downgraded, but an upgrade to a more expensive plan is possible. During an active subscription the user may choose to queue the next subscription. User count can be changed, with proration. Users are rewarded with coupons for referring other customers, and coupons provide free subscription time.
Key Team properties
- currentPlanID
- subscriptionTermsLeft – The number of terms (term = 3 months) that the team has yet to pay. This value is decreased after each successful payment.
- subscriptionExpirationDate – The date until which the service can be used. This value is increased after each successful payment.
- nextPlanID – The queued subscription.
- studentExpirationDate – Expiration of the team’s student proof.
- subscriptionStatus
- currentCouponID – ID of the active coupon (see “Coupon system”)
- nextCouponID – The queued coupon.
- graceExpirationDate – Grace period during which the Team can use the application, but has to successfully pay soon or the application becomes blocked. (see “Expiration check”)
- userSeatCount – number of user seats that the Team has paid for. This value is checked during active paid subscriptions when new users are added: if the new actual user count is bigger than this value – payment should be requested.
- currentTermStartTimestamp – used for accurately calculating prorations and visualizing subscription progress.
- currentTermEndTimestamp – used for accurately calculating prorations and visualizing subscription progress.
- suspended – true/false.
- suspendedReason
- suspendedDate
Possible subscription statuses
ACTIVE_SUBSCRIPTION
- team may not cancel current subscription plan
- team may not downgrade current subscription plan
- team may upgrade current subscription plan
- team may add and remove users
- team may modify subscription queue
PAUSED_SUBSCRIPTION
- team may not cancel current subscription plan
- team may resume subscription plan
- team may add and remove users
ACTIVE_FREE_SUBSCRIPTION
- every team has this subscription in the beginning by default
- team may upgrade to a paid plan at any time, any time remaining in the free subscription is lost
- team may redeem a coupon at any time, any time remaining in the free subscription is lost
- team may not cancel this subscription
- team may add and remove users
- team may modify subscription queue
NO_SUBSCRIPTION
- there is no active subscription and the team has no debts
- team may start a new subscription
- team may redeem a coupon
- team may add and remove users
Subscription queue
At any time during an active subscription (free, paid or coupon), the user may queue the next subscription (or coupon) to automatically start when the current one ends. Whenever an active subscription is nearing its end (20 days before fulfillment), the user is e-mailed a reminder of the queue, and is informed of his current settings.
The queue options are:
- Prolong – subscribe to a new identical subscription plan – same plan and same period as in the current subscription.
- nextPlanID is set to currentPlanID.
- nextCouponID is set to null.
- Subscribe to a new subscription plan, different from the current one. Can be any plan and any period.
- nextPlanID is set to the chosen Plan’s ID.
- nextCouponID is set to null.
- Redeem a Coupon (only visible if this team has Coupons available).
- nextPlanID is set to null.
- nextCouponID is set to the chosen Coupon’s ID.
- Do not create a new subscription. In this case the PROMMPT application will become inaccessible after the current subscription ends.
- nextPlanID is set to null.
- nextCouponID is set to null.
When the expiration date comes, the system uses the nextPlanID or nextCouponID value to create a new subscription for the Team.
- If nextPlanID is not null:
- currentPlanID is set to nextPlanID
- currentCouponID is set to null
- nextPlanID remains as it is
- nextCouponID remains null
- If nextCouponID is not null:
- nextPlanID is set to currentPlanID (may or may not be null)
- currentPlanID is set to null
- currentCouponID is set to nextCouponID
- nextCouponID is set to null
Whenever a new subscription starts for the Team manually, the following occurs:
- currentPlanID is set to nextPlanID
- nextPlanID remains as it is
Whenever a new coupon-based subscription starts for the Team manually, the following occurs:
- currentCouponID is set to nextCouponID
- nextCouponID is set to null
Whenever a subscription is upgraded manually, the following occurs:
- if nextPlanID is not null: nextPlanID is set to new upgraded currentPlanID
- if nextCouponID is not null: nextCouponID remains as it is
Whenever current user count exceeds the limit of the queued subscription plan, the following occurs:
- nextPlanID is set to null
Whenever a subscription expires and nothing is queued:
- currentCouponID is set to null
- currentPlanID is set to null
Subscription queue for Free accounts
If the current status is ACTIVE_FREE_SUBSCRIPTION, the user can choose whether to subscribe to a new plan immediately (manually), or queue it after the Free subscription ends. If there is at least one Coupon available, the user can choose whether to redeem the Coupon immediately (manually), or queue it after the Free subscription ends.
The Team needs to have all the required billing information filled out before subscribing to a new plan.
Payments
Payments are accomplished using Stripe’s Charge API. Team Administrator enters their payment details before attempting to pay, which are sent to Stripe and stored in a Stripe Customer object. The Stripe Customer object’s ID is saved in our database. Whenever a charge is required, a request is sent to Stripe to charge the Customer. This action is synchronous: we can immediately tell whether the payment was successful or not.
Payment attempt moments
- New subscription is started
- if the payment succeeeds: the new subscription starts, Team object is updated
- if the payment fails: nothing changes
- Active subscription enters new term
- if the payment succeeds: new term is entered, Team object is updated
- if the payment fails: graceExpirationDate is set, user has to update their card details and re-attempt payment manually
- New queued subscription is started
- if the payment succeeds: the new subscription starts, Team object is updated
- if the payment fails: status is set to NO_SUBSCRIPTION
- User seat count increased during subscription (ACTIVE_SUBSCRIPTION)
- if the payment succeeds: user seat count is increased and a member/invitation is added, Team object is updated
- if the payment fails: nothing changes
- Upgrade during subscription
- if the payment succeeds: plan is upgraded, Team object is updated
- if the payment fails: nothing changes
- Resume a paused subscription
- if the payment succeeds: subscription is active again, Team object is updated
- if the payment fails: nothing changes
Status is changed at these moments
- Team manually subscribes to a new plan:
- Team subscribes to a paid plan, current status NO_SUBSCRIPTION or ACTIVE_FREE_SUBSCRIPTION: status changed to ACTIVE_SUBSCRIPTION
- Team redeems a Coupon, current status NO_SUBSCRIPTION or ACTIVE_FREE_SUBSCRIPTION: status changed to ACTIVE_SUBSCRIPTION
- Whenever expiration date for a team arrives:
- if subscriptionTermsLeft > 0 and currently active subscription is a paid one and required tax information is missing:
- Status is set to PAUSED_SUBSCRIPTION (see “Superadmin changes country data”)
- if subscriptionTermsLeft == 0 and status is ACTIVE_SUBSCRIPTION or ACTIVE_FREE_SUBSCRIPTION:
- If nextPlanID is not null, payment attempted
- If the payment is successful:
- currentPlanID is set to nextPlanID
- currentCouponID is set to null
- nextPlanID remains as it is
- nextCouponID remains null
- status set to ACTIVE_SUBSCRIPTION, subscription data is updated
- If the payment failedd:
- status set to NO_SUBSCRIPTION
- If nextCouponID is not null:
- nextPlanID is set to currentPlanID (may or may not be null)
- currentPlanID is set to null
- currentCouponID is set to nextCouponID
- nextCouponID is set to null
- status set to ACTIVE_SUBSCRIPTION, subscription data is updated (see “Coupon system”)
- If both nextPlanID and nextCouponID are null:
- status set to NO_SUBSCRIPTION
- currentCouponID is set to null
- currentPlanID is set to null
- Whenever grace period ends (graceExpirationDate > subscriptionExpirationDate and graceExpirationDate > now)
- Current status changed from ACTIVE_SUBSCRIPTION to PAUSED_SUBSCRIPTION
Expiration check
The subscription service API shall have an endpoint for checking whether a team should have access to PROMMPT services. The endpoint returns a status (ACTIVE, GRACE or INACTIVE), the subscription’s expiration date, and grace period’s expiration date (if status is GRACE).
The application is accessible if all 3 of these conditions are True:
- Status is either ACTIVE_SUBSCRIPTION or ACTIVE_FREE_SUBSCRIPTION
- Team’s subscriptionExpirationDate is in the future or graceExpirationDate is in the future
- Team is not suspended
The application is inaccessible in all other cases (status INACTIVE).
This means that if the subscription has technically expired, the team is still able to use the service with current settings for the duration of the grace period. When the grace period is over, the team is locked out of the service.
The Grace period is controlled by the graceExpirationDate field, which is set to 7 days in the future (or other similar value, depending on the configuration set by superadmin) at these moments:
- Active subscription enters new term and the payment fails
Term expiration event
Whenever a subscription term expires, a scheduled action may be required: a credit card charge may be needed, the status of the subscription may change (see “Status is changed at these moments”) and a queued subscription or coupon may have to be started (see “Subscription queue”). Because of this, it is necessary to listen to the event of term expiration.
This expiration detection shall be performed with a simple check (as described in “Status is changed at these moments”), which occurs every day at 00:00. Term’s expiration date is rounded by date, in other words: if the term was started on January 15th, the term will last until May 14th (included), and expire on May 15th at 00:00.
Term expiration check is not performed for suspended Teams.
Term equals 3 calendar months. In other words: the expiration date will be the same as the term beginning date, but 3 months forward. If the date is bigger than the amount of days in the last month, then the last day of the last month is set as the expiration date.
User actions
- Team admin has the option to create a new subscription, choosing a plan and period at these moments:
- When the current plan is Free (status ACTIVE_FREE_SUBSCRIPTION)
- When there is no active subscription (status NO_SUBSCRIPTION)
- Team admin has the option to redeem an available Coupon, which starts a free custom subscription for a limited time:
- When the current plan is Free (status ACTIVE_FREE_SUBSCRIPTION)
- When there is no active subscription (status NO_SUBSCRIPTION)
- Team admin has the option to upgrade a subscription plan at these moments:
- When there is a currently active subscription (status ACTIVE_SUBSCRIPTION) and no Coupon is active
- Team admin has the option to queue the next subscription plan at these moments:
- At any time, except when status is NO_SUBSCRIPTION
- Team admin has the option to queue the next Coupon at these moments:
- At any time, except when status is NO_SUBSCRIPTION
- Team admin has the option to change the user count (within user limits, see “User limit changes”):
- User count can be decreased at any moment
- User count can be increased at any moment
- Team admin is unable to do anything while the Team is suspended.
Resuming a paused subscription
Whenever a team admin decides to resume a paused subscription, payment is attempted. If the payment is successful, the status of the subscription is set to ACTIVE_SUBSCRIPTION, the remaining properties remain unchanged.
The ability to resume a paused subscription is disabled if the Team’s required tax information is missing (for example, if the Tax ID for customers in a specific country became required while a Team with no Tax ID already had an active subscription).
Note: subscription will start from the moment of the resuming, but the term will be 7 days (grace period) less. The next subscriptionExpirationDate is calculated this way: current date + length of a term – (previous graceExpirationDate – previous subscriptionExpirationDate). This ensures that the Team is given exactly as much subscription time as they have paid for.
Team suspension
Teams can be suspended manually by the superadmin, or as a result of an automated event (e.g. when the API receives a notification from Stripe that this Team has issued a chargeback).
Suspended Teams are unable to use the application, and the administration is unable to perform any actions in the Dashboard. The only way to end the suspension is for the Superadmin to perform a Manual Action to unsuspend the Team.
Daily cron job should ignore Teams that are suspended, to avoid attempting charges or status changes. The Team is essentially “frozen”.
If the Superadmin unsuspends the Team, the suspendedDate property is used to calculate the end date for the currently active subscription term (if a subscription is active). The idea is to give the Team as much time till the end of the term as they had when the suspension began. In other words, the Team’s subscription resumes right where it left off. The same logic also applies to unfinished grace periods, coupons and free subscriptions.
The time compensation is accomplished by advancing all relevant dates by the length of the suspension. For example, if a Team with an active paid subscription is unsuspended, the service adds the length of the suspension to the dates that describe the beginning and the end of the active term. This ensures that the length of the term stays the same, so all the progress visualizations stay accurate, and all the proration prices that depend on the term completion percentage are also accurate. The only downside is that after both dates are shifted, it looks as if the term started at a later date, when historically it might not be true. This is acceptable, because the term’s beginning date is not shown in raw format to the user, and is only used internally for things like displaying progress bars and calculating prorations.
A suspended Team is blocked from performing any actions in the Dashboard. The Billing, Members, Subscription and Referrals pages are inaccessible, and the Team Dashboard page displays a warning that the Team is currently suspended and the reason of the suspension. The Invoices and Activity pages remain accessible.
Pending invitations from suspended Teams are hidden to the invited users. Members may not leave the suspended team (as that would modify the team’s state), and non-members may not issue new invitation requests to suspended teams. However, invitation requests that already exist can be revoked by users, because that action does not modify the Team’s state.
Stripe integration
- Payment data is only stored at Stripe, and does not pass through our servers at all. Stripe returns our service a token, which can be used to receive a Customer object. Each Team in our database will be tied to a Customer object at Stripe.
- Charge API is used for charging Customers. The action is synchronous and we will immediately know if the payment has succeeded or failed.
- Charge refunds are handled by Stripe. If a refund is issued, a new Stripe Refund object is created, which is linked to a Payment in our database, so that we can read detailed information about the Refund should it fail. https://stripe.com/docs/refunds
- Dispute webhook is used to update Invoices in the local DB with relevant information from Stripe (https://stripe.com/docs/disputes).
Proration calculation
Proration is calculated at these times:
- Team with active paid subscription upgrades the subscription plan
- subtotal = (new plan’s base price – current plan’s base price) * user seat count * ((current term total seconds – current term seconds elapsed) / current term total seconds)
- sales tax is added to subtotal
- Team with active paid subscription adds a new user seat
- subtotal = current plan’s base price * ((current term total seconds – current term seconds elapsed) / current term total seconds)
- sales tax is added to subtotal
Accurate proration can be calculated using the currentTermStartTimestamp and currentTermEndTimestamp properties of the Team, as well as the timestamp of the moment the payment is attempted.
Team’s currentTermStartTimestamp and currentTermEndTimestamp values are reset at these moments:
- When a new subscription is started
- When a subscription enters a new term
- When a paid subscription is resumed
User notifications (Dashboard)
Notifications are sent out to users (or groups of users) when specific events happen. Each user can instantly view unread notifications in the Dashboard’s header, and view all previous notifications (up to 50) in the dedicated Notifications page.
Notifications have three different priority levels (Info, Warning, Error), and can be clicked to lead the user to a specific page in the Dashboard. For example, if a Team moderator receives a notification that a new user was added to the Team, they can click the notification to go to the Team’s Members page.
Below is a list of notifications and recipients.
20 days before Team’s subscription expires if the subscription queue is empty. |
Inform the user that they can queue a subscription plan to begin automatically after the current one ends. |
Team’s administrator. |
Subscription expires. |
Inform the user that the current subscription has expired. |
Team’s administrator. |
Queued subscription begins. |
Inform the user that a new subscription was successfuly started. |
Team’s administrator. |
Queued subscription failed to start due to a failed payment. |
Inform the user of the error and its reason, and that a Grace period is started. |
Team’s administrator. |
Queued subscription failed to start due to current user count exceeding the maximum user count of the new plan. |
Inform the user of the error and its reason. |
Team’s administrator. |
New subscription term starts. |
Inform the user that a new term was successfuly started. |
Team’s administrator. |
New subscription term failed to start due to a failed payment. |
Inform the user of the error and its reason, and that a Grace period is started. |
Team’s administrator. |
Grace period expires. |
Inform the team that their subscription is now paused. |
Team’s administrator. |
Superadmin disables a plan, and that plan is queued to be the next plan for a team. |
Inform the team that their subscription queue is cleared, and that they should queue a different plan. |
Team’s administrator. |
Team member is promoted to a moderator. |
Inform the team member of their new role. |
Affected user. |
Team member is demoted to a regular member. |
Inform the team member of their new role. |
Affected user. |
Team member is removed from the Team by a moderator/admin. |
Inform the team of the membership change. Inform the user that they’re removed from the team. |
Affected user, moderators and administrator of the Team. |
Team member voluntarily leaves the Team. |
Inform the team of the membership change. |
Moderators and administrator of the Team. |
Team is suspended. |
Inform the team of the suspension and its reason. |
All team members. |
Team is unsuspended. |
Inform the team of the unsuspension. |
All team members. |
User’s pending invitation is revoked. |
Inform the user of the invitation change. Inform the team of the moderator’s action. |
Affected user, moderators and administrator of the Team. |
User declines a pending invitation. |
Inform the team of the membership change. |
Moderators and administrator of the Team. |
User accepts a pending invitation. |
Inform the team of the membership change. |
Moderators and administrator of the Team. |
User requests to join a team. |
Inform the team of a new request. |
Moderators and administrator of the Team. |
User revokes their request to join a team. |
Inform the team of the request’s change. |
Moderators and administrator of the Team. |
User’s request is declined. |
Inform the user of the team’s action. Inform the team of the moderator’s action. |
Affected user, moderators and administrator of the Team. |
User’s request is accepted. |
Inform the user of the team’s action. Inform the team of the moderator’s action. |
Affected user, moderators and administrator of the Team. |
A new invitation is created for a user. |
Inform the user of the new invitation (if this user is in the system). Inform the team of the moderator’s action. |
Affected user (if such user already exists), moderators and administrator of the Team. |
User notifications (E-mail)
Some notifications, particularly the most critical ones that happen as a result of scheduled events, are also sent to the user by e-mail.
Subscription expires. |
Inform the user that their team’s subscription ended, and that they can start a new one using Dashboard. |
Team’s administrator. |
New subscription term failed to start due to a failed payment. |
Inform the user of the failed payment and the start of a Grace period. Inform the user that they should fix their payment details and re-attempt the payment manually before the Grace period ends. |
Team’s administrator. |
Queued subscription failed to start due to a failed payment. |
Inform the user of the failed payment and the start of a Grace period. Inform the user that they should fix their payment details and re-attempt the payment manually before the Grace period ends. |
Team’s administrator. |
Queued subscription failed to start due to current user count exceeding the maximum user count of the new plan. |
Inform the user that the queued subscription was not started and ask them to choose a new plan in the Dashboard. |
Team’s administrator. |
Grace period expires. |
Inform the user that their team’s Grace period expired, and the subscription is now paused. Inform the user that they should fix their payment details and re-attempt the payment manually. |
Team’s administrator. |
Mass notifications
Superadmin can manually send Dashboard notifications to specific groups of users. It’s possible to send a message to all teams or a specific team, and further filter recipients by their role in the team. This way, for example, it is possible to target Administrators of all Teams to notify them of an upcoming promotion.
Notification 20 days before current subscription expires
This kind of notification shall be handled by an expiration check, which is performed using a cron job once a day (at 00:00).
The job checks whether this is the last term of the subscription and the current date equals the date of a Team’s expiration minus 20 days. This check is performed for every Team with an active subscription.
Manual actions
These are actions that a superadmin can perform to handle exceptional customers. These actions are safe to use.
- Cancel a team’s active subscription (required status: ACTIVE_SUBSCRIPTION or PAUSED_SUBSCRIPTION):
- Sets the status of the team to NO_SUBSCRIPTION
- Sets subscriptionTermsLeft to 0
- Resets subscriptionExpirationDate, so that the team may not use the service
- Resets graceExpirationDate
- Resets currentTermStartTimestamp, currentTermEndTimestamp
- Sets nextPlanID of the team to null
- Sets nextCouponID of the team to null
- Sets currentPlanID of the team to null
- Sets currentCouponID of the team to null
- Force fulfillment (required status: ACTIVE_SUBSCRIPTION, no active coupon)
- Sets subscriptionTermsLeft of the team to 0
- Sets nextPlanID of the team to null
- Sets nextCouponID of the team to null
- Add coupon:
- Manually create a new custom Coupon
- Immediately assign it to a Team
- Suspend team:
- Set values for “suspended”, “suspendedReason” and “suspendedDate” properties of the team
- Notify Team administrator
- Unsuspend team:
- Set “suspended” to false
- Notify Team administrator
- If there’s an ongoing subscription term or grace period – recalculate the expiration date based on previous values and suspendedDate
Manual override
The superadmin panel shall provide total control to manually override team properties. This way exceptions can be made for specific customers. Unlike Manual Actions, this is almost as direct as modifying the database, is considered a dangerous operation, and should rarely (if ever) be used.
Activity logs
Team admins can view their team’s Activity Log, which displays all the critical actions done with the team in chronological order. Examples: user invitations, successful payments, subscription plan upgrades.
Superadmins have a similar Activity Log, which can be used to track changes made in the superadmin panel, including Manual Actions and Manual Overrides.
This can be done in a separate Logging Service using appropriate tech, e.g. Elastic.
Superadmin notifications
The superadmin is notified of all successful and failed payment attempts, as well as changes in teams’ subscriptions and failures of refunds. These notifications can be viewed and filtered in superadmin’s panel.
The system would send an e-mail to the superadmin every day, with aggregated information for events that happened that day.
This can be done in a separate Logging Service using appropriate tech, e.g. Elastic.
Invoices
Stripe does not create invoices. All data must be kept in our own database. Each successful payment is backed by an invoice. Failed payments have no invoices attached to them.
Invoice objects in the database contain snapshots of the relevant information at the time, such as Team’s billing address, shipping address, PROMMPT address, sales tax, subtotal, total, invoice items, and other details. Because each invoice represents an actual payment, each invoice is linked to a Stripe Charge object. Relevant information regarding the payment status, refunds and disputes can always returned from Stripe using the Charge object’s ID, however, for optimization reasons this information will also be stored in our database.
In order to keep this information up-to-date, the Subscription service will expose a Dispute webhook (https://stripe.com/docs/disputes), which will update the relevant Invoice object in our DB whenever new information is available.
Invoices are stored in a single database table. Multiple invoice items can be stored as a JSON object in one of the invoice’s columns.
Invoices can be viewed in the Dashboard and downloaded in PDF format. All invoices are in English.
Invoices have unique IDs assigned to them, which are used for tax purposes. The format for this ID field is: CustomerID-MMYY-Num, where:
- CustomerID is a numeric ID of the Team (autoincremented Team ID from the database).
- MMYY is a 4 digit combination of month and year.
- Num is an incrementing invoice number (starting from 1) for this customer, which resets every month (in other words – the number is in the CustomerID-MMYY scope).
Technical note: all prices and sums should be stored in the database in cents, but displayed in euros.
Registration process
- Anybody can create a PROMMPT account using Auth0.
- PROMMPT-branded Auth0 form is present on the Dashboard website, and on the WordPress-powered prommpt.com homepage. Sign-in, Social Sign-in, Sign-up, Social Sign-up and account linking are supported in both of these locations.
- Newly created accounts do not belong to any Team.
- Any account can create any amount of Teams, which they would be administrators of.
- All new Teams are automatically subscribed to the Free plan.
- Any account can join someone’s existing Team in the following ways:
- By requesting an invitation: user enters the name of the Team they want to be a part of, and the admin of that Team receives a request to add this user to their team, which they can accept or decline.
- By being invited by a team admin. A team admin can invite members by entering their e-mail address in a form. The potential member does not necessarily have to be already a PROMMPT user. The potential member receives an invitation by e-mail, and our service stores the e-mail address in the database. Whenever our service detects a customer with that e-mail in our system – the user is displayed an invitation in the UI, which they can accept or decline.
- Any user can leave any team at any time, except for the admin.
- Teams can not be removed.
- Team admins can kick members.
Member roles
Members of a Team belong to one of the three roles: administrator, moderator and member.
- Member – a basic user, the default role for every new member in the team. Regular Members may use the PROMMPT application as everyone else, but hold no other privileges in the Team.
- Moderator – an advanced user, promoted to this role by an Administrator. Moderators have the ability to invite new members, accept or decline invitation requests, and remove members from the Team. Moderators may not demote other Moderators or the Administrator.
- Administrator – the original creator of the Team. They can not be removed from the team or demoted to a lower role. The Administrator has all privileges of a Moderator, as well as the ability to change roles of members, fill out the Team’s billing information, manage subscriptions, view invoices and the activity log.
User limit changes
- Administrators and Moderators may add (via invitations and invitation requests) and remove users:
- Users can be removed at any time
- Users can be added at any time
- Teams may not add more users than the current subscription’s limit. If the limit is reached – the Team has to upgrade the subscription plan before being able to add more users.
- If no there is no active subscription, the Team may add as many users as the most expensive Plan allows (50 users).
- In the case that a Team has no active subscription (status is NO_SUBSCRIPTION), the Team may not subscribe to a lesser Plan if the current user count exceeds the limit for that plan.
Example: Team has 30 users and no active subscription. Team may not subscribe to Standard, because the limit for Standard is 25 users, but the Team may subscribe to Pro, because the limit for Pro is 50 users. The Team can also reduce the current user count by kicking 5 users out, in which case they will again get the ability to subscribe to Standard.
- If a Team adds new users or invitations during an active paid subscription – they are charged for each new user seat added. If a user is removed from the Team, however, the already paid amount is not refunded. Instead, the empty user seat remains, which can be filled by a new user. The user seat count is re-calculated and reset to the actual user count whenever the payment for the term is made (at the beginning of the term, or when resuming a subscription, or when paying during a grace period).
Example: Team with 10 users starts a new subscription, pays for 10 user seats. After 1 month they add 2 more users and immediately pay for 2 additional seats for the remaining 2 months. Currently the Team has 12 seats. One of the users leaves or gets kicked out of the Team – there are now 11 users but still 12 seats. A new user gets invited instead, and since there are more seats than users – they get added immediately with no charge. When the next term starts – the Team is charged for the next period for the existing number of users – 12.
To implement the reserved user seat behavior explained above, the userSeatCount property of the Team object is used:
- userSeatCount is set to actual user count whenever a payment for a term is made.
- If the Team is in an active paid subscription and removes a user or invitation, the userSeatCount value is unaffected.
- If the Team is in an active paid subscription and adds a user or invitation, and the current actual user+invitation count is greater than or equals userSeatCount value, then payment is requested and userSeatCount is increased by 1.
- If the Team is in an active paid subscription and adds a user or invitation, and the current actual user+invitation count is less than userSeatCount value, then no payment is requested, and userSeatCount remains unaffected.
Students
- If a Team has a valid studentExpirationDate property, they have a new plan available: Student Paid.
- Superadmin can check uploaded student proof, then manually set the studentExpirationDate value for a Team.
User interface
- The login and registration of PROMMPT users are handled by the same form, in the index of the Subscription Dashboard. The form is a customized Auth0 form with PROMMPT branding. The form allows sign ins, sign ups, and social logins.
- The Subscription Dashboard will include a Profile page, where the user can change their basic info.
- The sidebar of the Dashboard shall consist of two parts – Me and Team.
- The “Me” section:
- Profile
- Join Team (list of teams that have invited you, list of your invitation requests, form to send invitation requests)
- Create New Team
- The “Team” section will only be visible if the user is in AT LEAST ONE Team. The header of the “Team” section shall have a dropdown control, where the user can switch to a different current team.
- Home (displays general information about the team, including its current Subscription plan, Subscription status, user count, user seat count, user limit and expiration date)
- Members (list of team members, admin can kick users here, as well as invite new members by e-mail)
- Subscription (team admin only – subscribe/upgrade, view and redeem coupons)
- Billing (team admin only – billing address, tax id, subject, etc.)
- Invoices (team admin only)
- Activity Log (team admin only)
- Referrals (team admin and moderators)
- Superadmin panel:
- Activity Log
- Countries (edit country list, tax rates for corporate and private entities in different countries, determine whether tax ID is required if the customer is from this country)
- Mass Notify (mass notifications)
- Plans (edit plan descriptions, rebates and limits)
- Teams (list all teams with their basic info; include ability to view, accept and decline student proof for a team)
- Config Vars (various configuration variables, e.g. PROMMPT billing address, grace period length, etc.)
- Invoices (list all invoices, their details, raw Stripe Charge object’s content of each invoice, history of each specific invoice)
- Manual Actions
- Manual Override
Validation requirements
- Auth0 automatically sends verification e-mails. Users may only log in after verifying their e-mail (unless they use social login).
- Paid Subscriptions can be chosen only if the Team has all information filled out, including billing address, shipping address, payment info (via Stripe’s component), entity type (corporate or private), in some cases tax id, etc.
- VATs can be automatically validated using this service: http://ec.europa.eu/taxation_customs/vies/technicalInformation.html
Referral system
- Each Team has a referral URL, which they can send to other potential customers.
- If a new user has signed up for PROMMPT using a referral URL, and created a Team of their own, and became a paying customer (subscribed for a paid plan) – the original referrer gets rewarded.
- When a user visits a PROMMPT referral URL – the token is stored in a cookie, so that if they sign up now, or even a week later – we still know which Team originally referred this user, and can associate the referrer with the new user during signup.
- Teams get rewarded for referring paying customers.
- Teams are assigned coupons, which they can redeem at any time. Coupons give free subscription time.
Coupon system
PROMMPT Coupons are tied to Teams and are given out as rewards for referring other customers. Coupons are used for adding free subscription time.
These are not to be confused with Stripe Coupons.
Each Coupon is essentially a custom subscription, which the user can activate the same way they would begin or queue a paid subscription, but for free. These subscriptions have the same limits as the most expensive paid subscription (Pro).
Available Coupons shall be listed in the Subscription section of the dashboard, where the Team Administrator can choose to Redeem Now (instantly begin a new free Subscription – only available if the current status is ACTIVE_FREE_SUBSCRIPTION or NO_SUBSCRIPTION), or to Redeem after Expiration (queue the subscription, not available if the current status is NO_SUBSCRIPTION). This way the Team Administrator can queue and redeem Coupons without affecting any current subscriptions. Another advantage is that Coupons can be redeemed even if the Team never had a paid subscription before.
Whenever a Coupon is redeemed:
- Team’s status becomes ACTIVE_SUBSCRIPTION
- Team’s nextPlanID becomes currentPlanID (may or may not be null)
- Team’s currentPlanID becomes null
- Team’s nextCouponID becomes null
- Team’s currentCouponID becomes the ID of this coupon
- The Coupon’s isRedeemed property becomes true (see “Key Coupon properties”)
- Team’s subscriptionExpirationDate is set to today’s date + length of the Coupon
- Team’s subscriptionTermsLeft is set to 0
Subscriptions granted by Coupons can not be paused or canceled.
Key Coupon properties
- teamID – Coupons are tied to Teams.
- freeDays – How many free days this Coupon provides.
- isRedeemed – True or false. If true – may not be used again.
Student ambassadors
Teams can be manually set by a superadmin to be Ambassador-type. These Teams are always subscribed to the Student plan, for free (no expiration limit and no invoices), and may not upgrade or downgrade the plan.
Taxes
Sales taxes are modified by the superadmin for each country and customer entity type, and are calculated and included in each invoice by our service. Modified taxes only affect payments made after the changes were saved by the superadmin, and do not apply to invoices issued before that.
Taxes are calculated from the subtotal (Plan price per user * user count), and are included in the total sum. Taxes are also applied to prorations (see “Proration calculation”).
Taxes are mathematically rounded, if required.
Scenarios
New manual sign up
New visitor to PROMMPT decides to create a new account. They are directed to the Subscription Dashboard, where they use the Auth0 form to sign up. They can sign up using username + password, or via Social Login. The user only enters basic information during sign up, which is stored at Auth0.
New manual sign up from the prommpt.com homepage
Because the prommpt.com homepage has the same Auth0 form as the Dashboard, the user may sign up there as well. After signing up and signing in, they remain on the prommpt.com website, where they can, for example, visit the Support page and create a new ticket. When the user is ready to start using PROMMPT – they can visit the Dashboard website and log in using the same account there.
New user’s first login
Newly created user logs into Subscription Dashboard. The User has no Teams or Invitations, so they immediately see a dialog window with two big buttons with descriptions: “Create a new Team”, “Join an existing Team”. The user can close the dialog and join or create a team later, using the menu items in the sidebar (see “User interface”). The user also has the ability to change their profile data, which is sent to Auth0.
User with no Team logs into PROMMPT app
Any user with a PROMMPT account may log into the PROMMPT iOS app, as long as the account is valid (verified e-mail). If the user has no Team, the PROMMPT app displays a message after successful login that they need to create or join a Team in the Subscription Dashboard in order to use the app.
User creates a new Team
User can create an unlimited number of Teams in the Subscription Dashboard. Only one value is required to create a Team: the name of the team. The name should be unique, and may not be changed later. The team name may only include characters A-Z, a-z, 0-9, ‘-‘ and ‘_’.
The newly created Team is automatically subscribed to the Free plan. The creator becomes the Administrator of the Team. The User is warned of this before the Team is created.
User switches active Team in the Subscription Dashboard
If a User is in one or more Teams, they see a dropdown in the sidebar of the Dashboard, which lets them select one of the Teams they belong to. Whenever a Team is selected, the User’s dashboard is updated – the sidebar will display a “Team” section below the “Me” section, displaying the menu items that are relevant to the user’s team, based on the user’s role in the Team (for example, Billing menu item should only be visible and accessible to the Administrator of a Team).
User sends invitation request to an existing Team
If a user decides to “Join an existing Team” (using the big button they see on the first login, or by clicking the menu item in the sidebar), they are presented with an input field, where they can enter a name of a Team.
- If a Team with such a name exists, and if the User does not already belong to this Team, and if the User has no pending invitation requests for this Team, and the Team has no pending invitations for this User – the service creates a new invitation request on behalf of the User. The Team’s Administrator and Moderators will be able to view pending invitation requests in the dashboard of their Team (“Members” section). Admins and Moderators can decline or accept invitation requests from Users.
- If a Team with such a name exists, and if the Team has a pending invitation for this User – the user is automatically accepted into the Team (same result as in “User accepts Team’s invitation” scenario).
The “Join Team” view for the User should list all existing pending invitation requests, as well as all pending Team invitations for this user.
Note: invitation requests are different from Team invitations. Invitation requests are made by Users and sent to Teams. Team invitations are made by Teams and sent to Users.
Note 2: Team invitations count as reserved user seats. It will not be possible to invite more users than there are user seats remaining. Reserver user seats, however, are not billed while they’re “empty”.
Team Administrator or Moderator declines a user’s invitation request
Team Administrator or Moderator may choose to decline a User’s invitation request. The invitation request disappears from the Team’s “Members” view. The User is notified by the Dashboard that their request has been declined. They can try sending a new request now. The invitation request is marked as “declined”.
Team Administrator or Moderator accepts a user’s invitation request
Team Administrator or Moderator may choose to accept a User’s invitation request.
Payment is required if the current status is ACTIVE_SUBSCRIPTION, there’s no active Coupon, no active Grace period, and the current user+invitations sum equals or is greater than userSeatCount.
If payment is required, payment for the new user seat (if there’s an active paid subscription) is requested immediately. If the payment is successful: the User immediately becomes a Member of the Team, with the default role set to “Member”. The invitation request is removed.
If the payment was unsuccessful – the user does not become a member and the invitation request remains unchanged.
Note: Team may not accept new users if that would exceed the user limit of the Team (e.g. if the Team’s current plan is Standard, they may not accept a new member if the user count is already at 25). In this case the invitation can not be accepted, and will remain pending.
Team Administrator or Moderator invites a User
Team Administrator or Moderator may manually invite a new User to their Team. The user does not have to already exist in PROMMPT. The Team invites a User by entering their E-mail address.
- If the User does not exist in the system, they are sent an E-mail informing them of the invite, and asking them to sign up.
- If the User already exists in the system, they are sent a notification in the Dashboard, as well as an invitation E-mail.
- If the User already exists in the system, and if the User has a pending invitation request to this Team, they are automatically accepted into the Team (provided the Team’s user limit allows it.). The behavior is the same as in the scenario “Team Administrator or Moderator accepts a user’s invitation request”.
The Team Administrator and Moderators can see all pending invitations in the “Members” section. They can also cancel pending invitations.
Inviting a user equals reserving a user spot, so the payment is requested immediately (if payment is required). If the payment succeeds – the invitation is created. Otherwise – nothing changes.
Payment is required if the current status is ACTIVE_SUBSCRIPTION, there’s no active Coupon, no active Grace period, and the current user+invitations sum equals or is greater than userSeatCount.
Note: Team may not invite new users if that would exceed the user limit of the Team, because invited users count as reserved seats. For example: if the Team’s current plan is Standard (max 25 users), they may not invite a new User if they already have 20 active users and 5 pending Team invitations.
User receives Team’s invitation
If a User has a new pending Team invitation, they see a notification in the Dashboard. They can see all currently pending Team invitations in the “Join Team” view. Users can accept or decline these invitations.
User declines Team’s invitation
If a User declines a Team’s invitation – they do not join the Team. The Team is notified of this, and can retry if they wish. The invitation is marked as “declined”.
User accepts Team’s invitation
If a User accepts a Team’s invitation, they become a member of the Team. We can already assume that the Team’s user limit allows this, because Team invitations count as reserved user seats. The invitation is then removed.
New user’s first login, if the user was invited to a Team by E-mail
Potential User was invited by a Team by E-mail. The User signs up for PROMMPT (with the E-mail address that the invitation was sent to), and, since their E-mail is known by our service, they are instantly invited to the Team. At this point the scenario is the same as “User receives Team’s invitation”.
Team Administrator can promote any Member of the Team they control to Moderator. The new Moderator is informed of this via notification in the Dashboard.
Team Administrator demotes a Moderator to Member
Team Administrator can demote any Moderator of the Team they control to Member. The Member is informed of this via notification in the Dashboard.
User leaves a Team
Any User can leave a Team at any time, except if that User is an Administrator. Team Administrators and Moderators will receive a notification in the Dashboard of this User leaving the Team.
Team Administrator or Moderator kicks a User
Team Administrator and Moderators can choose to kick any Member of the Team they control. Administrators can also kick Moderators, but Moderators may not kick other Moderators. Whenever a User is kicked – the User, the Administrator, and the Moderators all receive a notification of the kick.
User with one or more Teams logs into PROMMPT app
If the User belongs to only one Team, they are instantly taken to the regular PROMMPT app in the context of that one Team.
If the User belongs to multiple Teams, they have to choose which Team to sign into before proceeding into PROMMPT app. The User can at any time go back to the initial screen and choose a different Team to sign into.
User with one or more Teams logs into Subscription Dashboard
If the User belongs to one or more Teams, one of the Teams in the dropdown in the sidebar is always active. If such a User logs into the Dashboard, one of their Teams immediately becomes active. For the dropdown’s behavior, see scenario “User switches active Team in the Subscription Dashboard”.
Team Administrator enters the “Billing” section of their Team, and fills out the required billing information, which consists of two parts.
The first part is a form that lets the Administrator enter or update information that is stored in the Subscription Service’s database. This information includes:
All of the fields are required (tax ID may or may not be required based on the rules set by superadmin, see “Superadmin changes country data”). This effectively means that once the values have been set, they can only be modified and never deleted.
The second part can be edited by the User independently of the first, and is related to the payment info. The User is presented with a button titled “Change Payment Information”, which displays Stripe’s pop-up dialog, where they enter the credit card number and the related info.
Technical note: credit card info is sent securely to Stripe, which returns a token for us, that we can use to link the Stripe Customer object with our Team object in our database.
The User can change these details at any time.
Team with active Free subscription enters the Home page of their Team dashboard
The Home view displays the following information:
- Currently active subscription (Free), its expiration date
- Summary of currently available coupons, brief instructions on how to acquire coupons, link to Referrals section
- Current user count (active users, reserved users aka pending Team invitations) and user limit (5 users)
- Offer to immediately upgrade to a paid plan, with a link to the Subscription page
- If the Team does not have the required billing information, an appropriate message is displayed with a link to the Billing page
Team with active Free subscription enters the Subscription page of their Team dashboard
The Subscription view displays information about the currently active subscription similarly to the Home page, as well as:
- A message to fill out billing information, if it is currently missing
- Blocks with all available subscription plans, with pricing information, periods, description, and buttons:
- Subscribe Immediately (disabled if billing information is missing)
- Subscribe after Expiration (disabled if billing information is missing, invisible if the Free subscription has expired)
- If the Team has any Coupons available – blocks with all available coupons, with buttons:
- Redeem Immediately
- Redeem after Expiration (invisible if the Free subscription has expired)
Team’s active Free subscription expires in 20 days
The Team Administrator receives a notification (in the Dashboard, and by E-mail), that the Free subscription is about to expire, and that they can queue a new subscription, or subscribe to a paid plan immediately. The notification reminds them that billing information is required to upgrade to a paid plan. The Administrator is informed of their current queue settings (by default – no new subscription will be started).
The Team’s Home page displays the same information, with a link to the Subscription page.
Team’s active Paid subscription expires in 20 days
The Team Administrator receives a notification (in the Dashboard, and by E-mail), that the current subscription is about to expire, and that they can queue a new subscription. The Administrator is informed of their current queue settings (by default – subscription is prolonged).
The options are:
- Prolong current subscription (identical subscription of the same plan and the same period is created) – this action is default, and requires no user action
- Change subscription – the user would have to enter the Subscription Service and choose a new plan in the Subscription view
- Redeem a Coupon – the user would have to enter the Subscription Service and choose an available Coupon in the Subscription view (only visible if one or more Coupons are available)
- Do not re-subscribe – the user would have to enter the Subscription Service and manually Cancel the queued Subscription
The Team’s Home page displays the same warning information, with a link to the Subscription page.
Team’s active Coupon subscription expires in 20 days
The Team Administrator receives a notification (in the Dashboard, and by E-mail), that the current subscription is about to expire, and that they can queue a new subscription. The Administrator is informed of their current queue settings (by default – no new subscription will be started).
The options are:
- New subscription – the user would have to enter the Subscription Service and choose a new plan in the Subscription view
- Redeem a Coupon – the user would have to enter the Subscription Service and choose an available Coupon in the Subscription view (only visible if one or more Coupons are available)
- Do not re-subscribe – the user would have to enter the Subscription Service and manually Cancel the queued Subscription
By default, previously active plan is selected to be in the queue. If there was no active subscription plan immediately before starting the coupon, then the queue is empty.
The Team’s Home page displays the same warning information, with a link to the Subscription page.
Team’s active subscription expires
Team is notified that their Free or Paid subscription has expired. The Team no longer has an active subscription and may not use the PROMMPT iOS app. If there is no new subscription queued up – no new subscription is started.
Team with an expired subscription subscribes to a paid plan
The system first checks whether or not the current user count of the Team does not exceed the limit for the chosen plan. E.g. a Team with 30 current users can not subscribe to a new Standard plan (with a limit of 25).
Payment is attempted immediately. If it succeeds – the Team enters new subscription, expiration date is updated, an invoice is generated. If the payment fails – the subscription is not started. The generated invoice is sent to the Administrator by E-mail, and is now also accessible in the Invoices page of the Team. The Team is now successfully enjoying their paid subscription plan, until the term is over.
Team with an expired subscription redeems a Coupon
Team immediately enters a new subscription for free. There is no Grace period, and no attempt to charge the user’s card. No requests to Stripe are made.
Team with active Free subscription upgrades to a paid plan
Current Free subscription immediately expires. The rest of the procedure is the same as in the scenario “Team with an expired subscription subscribes to a paid plan”.
Team with active Free subscription redeems a Coupon
Current Free subscription immediately expires. The rest of the procedure is the same as in the scenario “Team with an expired subscription redeems a Coupon”.
Team with an active subscription adds a new subscription to the queue
The Team Administrator selects a paid plan in the Subscriptions view, and clicks the “Subscribe after Expiration” button in that plan’s block. This option is not available if the required billing information is missing, or if the subscription has already expired.
This option is also not available if the current Team’s user count exceeds the limit of the queued subscription plan. For example, if the Team currently has 30 users (or, for example, 20 users + 10 pending Team invitations), they can not queue a new subscription of Standard plan, as it only allows a maximum of 25 users. The Team has to decrease the user count first, or queue a Subscription of a more expensive plan.
Unredeemed Coupons can be queued in a similar fashion – “Redeem after Expiration”.
Team has a subscription in the queue, but the current subscription is still active
The Team Administrator can view the details about the queued subscription in the Home and Subscription views. They can cancel the queued subscription at any time before the current subscription expires. They can also change the queued subscription’s plan or the queued coupon by choosing a different plan or coupon in the Subscriptions view and clicking the respective “Subscribe after Expiration” or “Redeem after Expiration” button.
Team’s subscription expires and they have a new subscription queued up
Once the current subscription expires, the service automatically attempts to subscribe the Team to a paid plan according to the settings the Team’s Administrator provided. The rest of the procedure is the same as in the scenario “Team with an expired subscription subscribes to a paid plan”.
Team’s subscription expires and they have a new coupon queued up
Once the current subscription expires, the service automatically attempts to redeem the queued Coupon according to the settings the Team’s Administrator provided. The rest of the procedure is the same as in the scenario “Team with an expired subscription redeems a Coupon”.
Team’s Grace period ended
The Team is no longer able to use the PROMMPT iOS application. The current active subscription becomes paused. The Team can not change their subscription settings, but they can resume the paused subscription manually.
Team tries to resume a paused subscription
Charge attempt is immediately made. If the payment fails – nothing changes. If the payment succeeds – the Team’s subscription continues.
The next subscriptionExpirationDate is calculated this way: current date + length of a term – (previous graceExpirationDate – previous subscriptionExpirationDate). This ensures that the Team is given exactly as much subscription time as they have paid for.
Team updates payment data and pays for subscription during Grace period
Charge attempt is immediately made. If the payment fails – nothing changes. If the payment succeeds – the Team’s subscription continues.
The next subscriptionExpirationDate is calculated this way: previous subscriptionExpirationDate + length of a term. This ensures that the Team is given exactly as much subscription time as they have paid for.
Team with active paid subscription enters a new term
In general, the entire scenario is very similar to “Team with an expired subscription subscribes to a paid plan”. The only difference is that the state of the subscription is already active before the term begins.
Team with no active subscription enters the Home page of their Team dashboard
The Home view displays the following information:
- Message that there’s no active subscription, application is inaccessible
- Summary of currently available coupons, brief instructions on how to acquire coupons, link to Referrals section
- Current user count (active users, reserved users aka pending Team invitations) and user limit (50 users – limit of the most expensive plan)
- Offer to immediately upgrade to a paid plan, with a link to the Subscription page
- If the Team does not have the required billing information, an appropriate message is displayed with a link to the Billing page
Team with no active subscription enters the Subscription page of their Team dashboard
The Subscription view displays information that there’s no active subscription similarly to the Home page, as well as:
- A message to fill out billing information, if it is currently missing
- Blocks with all available subscription plans, with pricing information, periods, description, and buttons:
- Subscribe Immediately (disabled if billing information is missing)
- If the Team has any Coupons available – blocks with all available coupons, with buttons:
Note: the available subscription plans are determined based on the current user count. For example, if the current user count is 30, then the Standard plan is not available, since that has a maximum of 25 users.
Team with paused subscription enters the Home page of their Team dashboard
The Home view displays the following information:
- Warning that there is a paused subscription, and the application is inaccessible
- Summary of currently available coupons, brief instructions on how to acquire coupons, link to Referrals section
- Current user count (active users, reserved users aka pending Team invitations) and user limit (according to the current plan)
- Offer to resume the subscription, with a link to the Subscription page
Team with paused subscription enters the Subscription page of their Team dashboard
The Subscription view displays information that there’s a paused subscription similarly to the Home page, as well as a button that resumes the subscription. Nothing else is available.
If the Team’s required tax information is missing (see “Superadmin changes country data”), the Resume button is disabled.
Scenario “Team tries to resume a paused subscription” is started when the Administrator presses the resume button.
Team with active subscription enters the Home page of their Team dashboard
The Home view displays the following information:
- Information that there is an active subscription, and when it expires. If the current subscription is granted by a Coupon, then information about that Coupon is displayed instead.
- Summary of currently available coupons, brief instructions on how to acquire coupons, link to Referrals section.
- Current user count (active users, reserved users aka pending Team invitations) and user limit (according to the current plan).
- Available user seats (userSeatCount), which the Team has already paid for.
- Offer to upgrade the subscription, with a link to the Subscription page (only available if the currently active subscription is not granted by a Coupon).
Team with active subscription enters the Subscription page of their Team dashboard
The Subscription view displays information about the active subscription, as well as blocks with all available (more expensive than current) subscription plans, with “Upgrade” buttons.
Note: only subscription plans with the same period as the current subscription are available.
Stripe fails to charge the customer
When Stripe fails to charge the customer, our service sends out a notification to the Team Administrator. The actions that follow depend on the specific scenario.
Stripe successfully charges the customer
The Team Administrator is notified of the successful payment and thanked. The actions that follow depend on the specific scenario
Team upgrades plan in the middle of an active Paid subscription
A charge attempt is immediately made. If the payment is successful – the subscription is upgraded. The other properties, such as the remaining subscription time, remain unchanged. If the payment is a failure – nothing is changed.
If there’s a currently queued subscription plan, the queued plan should be upgraded to the new current plan as well. The Team Administrator is notified of this in the dashboard and by email.
Team changes user count in the middle of an active Free subscription
Team can freely change the user count without any charges within the 5 user limit while the Free subscription is active.
Team changes user count in the middle of an active Paid subscription
Team can freely change the user count by creating Team invitations (reserved user seats), accepting invitation requests, kicking users, or having the users leave the Team on their own. Adding new users beyond the userSeatCount value results in payment requests. This behavior is explained in detail in “User limit changes”.
Note: the sum of reserved user seats and active seats must not exceed the user limit for that Subscription plan.
Team changes user count while there is no active subscription
Team can freely change user count without being charged. The upper user limit is the limit of the most expensive Plan available (50 users). The Team is charged when a new paid Subscription begins.
Team changes user count while there is a paused subscription
Team can freely change user count without being charged. The charges are applied when the Team resumes the subscription.
Team changes user count while there is an active coupon
Team can freely change user count without being charged. The upper user limit is the limit of the most expensive Plan available (50 users). The Team is charged when a new paid Subscription begins.
The new user count is immediately checked against the queued subscription’s limit, see scenario “Team’s user count exceeds queued subscription plan’s user limit”.
Team’s user count exceeds queued subscription plan’s user limit
If there’s a currently queued paid Subscription, the system checks whether or not the queued Subscription’s limit is exceeded by the new user count. If so – the queued Subscription is removed from the queue, and the Team Administrator is informed about this by a notification and E-mail. The Team’s options are now to queue a higher plan Subscription, or decrease the current user count and queue the previous Subscription again, or leave everything as it is – no new Subscription will be queued.
Team refers other users to PROMMPT
Team Administrators and Moderators can go to the Referrals section in the Dashboard to get a Team referral URL, which they can publicly share to refer other customers and earn rewards for that.
New customer uses a referral link to sign up for PROMMPT
When a new user referred by an existing Team signs up for PROMMPT, the referrer is notified of this, but no reward is given out yet.
Referred customer successfully pays for a subscription
When a referred customer successfully pays for an invoice as an Administrator of any of their Teams for the first time – we consider this user a paying customer and reward the original referrer with a coupon. The Administrator of the referrer Team gets a notification of the new available Coupon in the Dashboard and by E-mail.
Team administrator enters the Invoices page of their Team dashboard
There is a list of all successfully paid invoices. Entire invoice history is always available. Each invoice can be viewed in the browser, or downloaded as PDF.
Invoices can be filtered by year and by month, and sorted by date.
If the invoice was refunded or disputed, it is marked as such.
Superadmin updates rebate/base price of a plan
Whenever the superadmin updates details of a plan, every new invoice made after the update will use the updated prices.
Superadmin sends mass notifications
Superadmin has the option to send out mass notifications via an interface in the Dashboard. The recipients can be filtered by team and role in the team. All previously sent mass notifications are visible in the History section.
Team asks for a refund
There is no automated way to refund invoices. If there’s a dispute, a Team should open a Support Ticket and discuss the terms with PROMMPT administration and request a refund there.
Superadmin enters the Invoices page of the Superadmin dashboard
All invoices for all teams are listed here. They can be viewed and downloaded in PDF format. Refunded and disputed invoices are marked as such. Each Invoice is linked to a Stripe Charge object, which is synchronized with Stripe on certain webhook events, and is displayed in raw json format. Each Invoice also has its own event history, which is displayed in chronological order.
Superadmin refunds an invoice
Superadmin can issue full or partial refunds using Stripe’s control panel. The SubS API will catch relevant events using the Stripe webhook, and update the relevant Invoice objects.
NOTE: this does NOT roll back any settings, such as subscriptionTermsLeft or subscriptionExpirationDate. In fact, there is no change to the Subscription at all.
Refund fails
A refund can fail if the customer’s bank has been unable to process a payment correctly (e.g., a closed bank account or a problem with the card). The bank returns the refunded amount to Stripe, which adds it back to PROMMPT’s Stripe account’s balance. The administrator is notified that the Refund failed by e-mail. Stripe’s reason for why the Refund failed is included in the notification. The administrator may at this point decide what to do next, and seek an alternative way of refunding the invoice.
Superadmin cancels a subscription
If it is required to forcefully cancel a subscription, superadmin can do so by going to the Manual Actions page and using the “Cancel subscription” feature. The affected Team may no longer use the service, as their status is set to NO_SUBSCRIPTION (see “Manual actions”). The Administrator of the affected Team is notified that their Subscription has been cancelled by PROMMPT.
Superadmin forces fulfillment of a subscription
If it is required to forcefully fulfill a subscription, superadmin can do so by going to the Manual Actions page and using the “Force fulfillment” feature. The service from now on assumes that the current subscription term of the affected Team is their last term in the Subscription (see “Manual actions”).
Superadmin creates a new Coupon for a Team
Superadmin can manually create and give Coupons to Teams using the Manual Actions page. They can choose the number of days this Coupon provides and select a Team that this Coupon will be assigned to. The receiving Team’s Administrator will be notified that they received a new Coupon.
Superadmin changes country data
The Countries page in the superadmin displays a list of countries from our database. The countries can be selected from this dataset by customers when filling out billing and shipping address information.
Each country has multiple fields that the superadmin can modify:
- Sales tax for corporate customers from this country
- Sales tax for private customers from this country
- Flag whether tax ID is a requirement for a corporate customer from this country
- Flag whether tax ID is a requirement for a private customer from this country
Whenever sales tax data for a country is changed, the following happens:
- The new taxes will be applied to new payments
In the case that requirements for a customer change while they already have an active subscription and don’t fulfill the requirements (e.g. a tax ID becomes required for a customer that has no tax ID, but is in the middle of an active subscription – note that this should be a really rare case), the following happens:
- If the Team’s current status is PAUSED_SUBSCRIPTION:
- Team may not resume subscription until the required tax information is filled out.
- If the Team’s current status is ACTIVE_SUBSCRIPTION:
- Team may finish the current subscription term, however the next term does not start until the required tax information is filled out – the payment is not attempted and the status is set to PAUSED_SUBSCRIPTION.
Customer files a dispute (charge-back)
A dispute occurs when the customer questions the invoice payment with their bank or credit card company. The money is refunded to the customer from the Stripe account’s balance, along with a dispute fee ($15) if the customer is from US.
A dispute resolution process is then started, which is guided by Stripe in their dashboard. The company administrator can submit evidence and other information to prove that the payment was correct. The customer’s bank reviews the evidence and decides whether you win or lose the dispute. In case of a victory – the full amount, including the fee, is returned to the Stripe account’s balance.
This process is not automated and always requires action from the company administrator. More information can be found here: https://stripe.com/docs/disputes , https://support.stripe.com/topics/disputes-and-fraud
The dispute will trigger an event in our API, which will automatically suspend the Team that made the chargeback. Superadmin immediately receives a notification of the chargeback by e-mail.
The relevant invoice object in our database will be updated based on the new information from Stripe. The status of the invoice will be set to DISPUTED, and the history of the invoice will be updated.
Customer files a dispute inquiry
Some card issuers may begin to investigate a payment before creating a formal dispute, and request further information about it. This is known as either an “inquiry” or “retrieval”, depending on the card brand. Unlike a formal dispute, no funds have been withdrawn and the payment it relates to can still be refunded.
Inquiries appear as Disputes in Stripe panel, and also require evidence from the company that the charge was legitimate. If the inquiry is resolved in our favor, the dispute disappears, and no fee is taken. If the inquiry is lost, the inquiry becomes a formal dispute, and the bank withdraws the funds as well as a fee.
While an inquiry is active, it is possible to refund the charge without a fee.
To address this kind of behavior, the SubS API will mark the respective invoice as DISPUTED whenever a dispute or an inquiry is detected. However, the Team is only suspended after the payment funds are withdrawn from our Stripe account (immediately when a formal dispute occurs, or whenever an inquiry is escalated to a dispute). This ensures that misunderstandings can be resolved without interrupting the Team’s subscription.
More information on dispute inquiries: https://stripe.com/docs/disputes#inquiries-and-retrievals
Team suspension
On January 1st, Team A has an active subscription, and the current term expires on January 20th (in 19 days). However, the Team gets suspended. On January 10th the Team gets unsuspended, and we begin a new term that starts on January 10th (the date when suspension was lifted) and ends on January 29th (10 + 19 days). In other words, the Team resumes the subscription right where they left off.