Merge pull request #635 from indentlabs/promo-bogos

BOGO promo
This commit is contained in:
Andrew Brown 2020-03-21 03:39:33 -05:00 committed by GitHub
commit 2a3356fdca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 255 additions and 62 deletions

View File

@ -33,6 +33,14 @@ class DataController < ApplicationController
@threads_posted_to = Thredded::Topic.where(id: @posts.pluck(:postable_id) - @topics.pluck(:id))
end
def collaboration
universe_ids = current_user.universes.pluck(:id)
@collaborators = Contributor.where(universe_id: universe_ids).includes(:user, :universe)#.uniq { |c| c.user_id }
@shared_universes = current_user.universes.where(id: @collaborators.pluck(:universe_id))
collaborating_ids = Contributor.where(user_id: current_user.id).pluck(:universe_id)
@collaborating_universes = Universe.where(id: collaborating_ids)
end
private
def set_sidenav_expansion

View File

@ -1,5 +1,5 @@
class PageUnlockPromoCode < ApplicationRecord
has_many :promotions
has_many :promotions, dependent: :destroy
has_many :users, -> { distinct }, through: :promotions
serialize :page_types, Array

View File

@ -31,6 +31,27 @@ class PaypalInvoice < ApplicationRecord
description: "Prepaid Premium subscription"
)
self.save!
if PromoService.active?(:promo_bogo) && (self.months == 3 || self.months == 6)
# During this promo, we create a separate Invoice + PromoCode also
self.user.paypal_invoices.create(
paypal_id: "None -- Created from promo_bogo promo",
status: self.status,
user_id: self.user_id,
months: self.months,
amount_cents: 0,
page_unlock_promo_code: PageUnlockPromoCode.create(
code: 'BOGO-' + (0...8).map { (65 + rand(26)).chr }.join + '-' + (0...8).map { (65 + rand(26)).chr }.join,
page_types: Rails.application.config.content_types[:premium].map(&:name),
uses_remaining: 1,
days_active: 30 * self.months.to_i,
internal_description: "promo_bogo duplicate code",
description: "Your free buy-one-get-one-free Premium Code",
),
approval_url: nil,
payer_id: self.payer_id
)
end
end
def activateable?

View File

@ -7,12 +7,12 @@ class PaypalService < Service
request.request_body({
intent: "CAPTURE",
application_context: {
return_url: 'https://www.notebook.ai/my/billing/prepay/paid',
cancel_url: 'https://www.notebook.ai/my/billing/prepay',
brand_name: 'Notebook.ai by Indent Labs',
landing_page: 'BILLING',
return_url: 'https://www.notebook.ai/my/billing/prepay/paid',
cancel_url: 'https://www.notebook.ai/my/billing/prepay',
brand_name: 'Notebook.ai by Indent Labs',
landing_page: 'BILLING',
shipping_preference: 'NO_SHIPPING',
user_action: 'PAY_NOW'
user_action: 'PAY_NOW'
},
purchase_units: [{
amount: {
@ -143,7 +143,7 @@ class PaypalService < Service
client_id = Rails.application.config.paypal[:client_id]
client_secret = Rails.application.config.paypal[:client_secret]
environment = if Rails.env.production?
environment = if Rails.env.production?
PayPal::LiveEnvironment.new(client_id, client_secret)
else
PayPal::SandboxEnvironment.new(client_id, client_secret)

View File

@ -0,0 +1,13 @@
class PromoService < Service
def self.active?(promo_key)
[
Date.current >= Rails.application.config.promos.fetch(promo_key, {}).fetch(:start_date),
Date.current <= Rails.application.config.promos.fetch(promo_key, {}).fetch(:end_date)
].all?
rescue false
end
def self.end_date(promo_key)
Rails.application.config.promos.fetch(promo_key, {}).fetch(:end_date)
end
end

View File

@ -10,7 +10,7 @@
<% raw_model.contributors.each do |contributor| %>
<% next if contributor.user.nil? && (current_user != content.user) %>
<li class="collection-item avatar">
<i class="material-icons circle white-text">person</i>
<i class="material-icons circle white-text <%= User.color %>"><%= User.icon %></i>
<span class="title">
<%= contributor.user ? link_to(contributor.user.name, contributor.user) : "#{contributor.email} (invited)" %>
</span>

View File

@ -70,20 +70,6 @@
</div>
</div>
<% if current_user.notice_dismissals.where(notice_id: 5).none? %>
<!--
<div class="row">
<div class="col s12">
<div class="hoverable card-panel <%= Country.color %> lighten-6">
<%= link_to 'Dismiss this notice.', notice_dismissal_dismiss_path(notice_id: 5), class: 'blue-text text-lighten-4 right' %>
<i class="material-icons left"><%= Country.icon %></i>
New: Check out the new <span class="white-text">Country</span> page type, as well as tons of new fields on the other pages!
</div>
</div>
</div>
-->
<% end %>
<div class="row">
<% @all_content_types.sort_by(&:name).each.with_index do |content_type, i| %>
<div class="col s12 m6 l4">

View File

@ -0,0 +1,82 @@
<h4>
<%= link_to data_vault_path, class: 'grey-text tooltipped', style: 'position: relative; top: 4px;', data: {
position: 'bottom',
enterDelay: '500',
tooltip: "Back to your Data Vault"
} do %>
<i class="material-icons">arrow_back</i>
<% end %>
Collaboration on Notebook.ai
</h4>
<div class="grey-text uppercase">Your shared universes</div>
<% if @shared_universes.any? %>
<ul class="collapsible">
<% @shared_universes.reverse.each do |universe| %>
<li>
<div class="collapsible-header white-text <%= Universe.color %>">
<i class="material-icons"><%= Universe.icon %></i>
<%= universe.name %>
(<%= pluralize universe.contributors.count, 'collaborator' %>)
</div>
<div class="collapsible-body white">
<%= render partial: 'content/display/contributors', locals: { content: universe } %>
</div>
</li>
<% end %>
</ul>
<% else %>
<p>None yet!</p>
<% end %>
<div class="grey-text uppercase">Universes shared with you</div>
<% if @collaborating_universes.any? %>
<ul class="collapsible">
<% @collaborating_universes.each do |universe| %>
<li>
<div class="collapsible-header white-text <%= Universe.color %>">
<i class="material-icons"><%= Universe.icon %></i>
<%= universe.name %>
</div>
<div class="collapsible-body white">
<%= render partial: 'content/display/contributors', locals: { content: universe } %>
</div>
</li>
<% end %>
</ul>
<% else %>
<p>None yet!</p>
<% end %>
<% if @collaborators.any? %>
<div class="grey-text uppercase">Your collaborators</div>
<ul class="collapsible">
<% @collaborators.group_by { |c| c.user }.each do |collaborator, collab_list| %>
<li>
<div class="collapsible-header <%= User.color %> white-text">
<i class="material-icons"><%= User.icon %></i>
<%= collaborator.name %> <%= "(@#{collaborator.username})" if collaborator.username? %>
</div>
<div class="collapsible-body">
Contributing on:
<ul>
<% Universe.where(id: collab_list.pluck(:universe_id)).each do |universe| %>
<li class="clearfix">
<%= link_to universe, class: "#{Universe.color}-text" do %>
<i class="material-icons left"><%= Universe.icon %></i>
<%= universe.name %>
<% end %>
</li>
<% end %>
</ul>
</div>
</li>
<% end %>
</ul>
<% else %>
<p>None yet!</p>
<% end %>
<%= content_for :javascript do %>
$('.panel').show();
<% end %>

View File

@ -69,6 +69,20 @@
<% end %>
</div>
<div class="col s12 m12 l6">
<%= link_to discussions_path, class: 'black-text' do %>
<div class="hoverable card blue lighten-5">
<div class="card-content" style="overflow: hidden; height: <%= card_height %>px">
<i class="material-icons right blue-text" style="font-size: <%= icon_fsize %>rem; margin-top: <%= icon_yoffset %>rem; margin-left: 0; margin-right: <%= icon_xoffset %>rem">forum</i>
<div class="card-title">Discussion activity</div>
<p>
See your activity on the discussion boards.
</p>
</div>
</div>
<% end %>
</div>
<div class="col s12 m12 l6">
<%= link_to uploads_path, class: 'black-text' do %>
<div class="hoverable card amber lighten-5">
@ -83,19 +97,21 @@
<% end %>
</div>
<!--
<div class="col s12 m12 l6">
<%= link_to discussions_path, class: 'black-text' do %>
<div class="hoverable card blue lighten-5">
<%= link_to collaboration_path, class: 'black-text' do %>
<div class="hoverable card purple lighten-5">
<div class="card-content" style="overflow: hidden; height: <%= card_height %>px">
<i class="material-icons right blue-text" style="font-size: <%= icon_fsize %>rem; margin-top: <%= icon_yoffset %>rem; margin-left: 0; margin-right: <%= icon_xoffset %>rem">forum</i>
<div class="card-title">Discussion activity</div>
<i class="material-icons right purple-text" style="font-size: <%= icon_fsize %>rem; margin-top: <%= icon_yoffset %>rem; margin-left: 0; margin-right: <%= icon_xoffset %>rem"><%= Universe.icon %></i>
<div class="card-title">Collaboration</div>
<p>
See your activity on the discussion boards.
Learn more about collaborating on Notebook.ai and track which universes are shared.
</p>
</div>
</div>
<% end %>
</div>
-->
<div class="col s12 m12 l6">
<%= link_to privacy_policy_path, class: 'black-text' do %>

View File

@ -1,6 +1,21 @@
<div class="row">
<%= render partial: 'main/dashboard_header_links' %>
<% if PromoService.active?(:promo_bogo) %>
<% if current_user.notice_dismissals.where(notice_id: 6).none? %>
<div class="col s12">
<div class="hoverable card-panel orange lighten-5">
<%= link_to 'Dismiss this notice.', notice_dismissal_dismiss_path(notice_id: 6), class: 'blue-text right', style: 'padding: 0 10px;' %>
<%= link_to prepay_path, class: 'black-text' do %>
<i class="material-icons left">card_giftcard</i>
Limited-time Discount: Stay safe and stay home while worldbuilding with friends! Shareable 3-month and 6-month Premium Codes are buy-one-get-one-free until
<%= PromoService.end_date(:promo_bogo).strftime("%B %-d") %>. Happy worldbuilding!
<% end %>
</div>
</div>
<% end %>
<% end %>
<% if @content %>
<div class="col s12">
<%= render partial: 'cards/serendipitous/content_question', locals: {
@ -11,18 +26,6 @@
</div>
<% end %>
<% if current_user.created_at > 3.months.ago && current_user.notice_dismissals.where(notice_id: 4).none? %>
<div class="col s12">
<div class="hoverable card-panel orange lighten-5">
<%= link_to 'Dismiss this notice.', notice_dismissal_dismiss_path(notice_id: 4), class: 'blue-text right' %>
<%= link_to prepay_path, class: 'black-text' do %>
<i class="fa fa-paypal left"></i>
New in Notebook.ai: You can now purchase Premium for yourself &mdash; or your friends &mdash; with PayPal.
<% end %>
</div>
</div>
<% end %>
<%
s_width = 12
m_width = 6

View File

@ -14,6 +14,21 @@
</p>
<% end %>
<% if PromoService.active?(:promo_bogo) %>
<% if current_user.notice_dismissals.where(notice_id: 6).none? %>
<div class="col s12">
<div class="hoverable card-panel orange lighten-5">
<%= link_to 'Dismiss this notice.', notice_dismissal_dismiss_path(notice_id: 6), class: 'blue-text right', style: 'padding: 0 10px;' %>
<%= link_to prepay_path, class: 'black-text' do %>
<i class="material-icons left">card_giftcard</i>
Limited-time Discount: Stay safe and stay home while worldbuilding with friends! Shareable 3-month and 6-month Premium Codes are buy-one-get-one-free until
<%= PromoService.end_date(:promo_bogo).strftime("%B %-d") %>. Click this banner to get started.
<% end %>
</div>
</div>
<% end %>
<% end %>
<h4>Subscription Plan</h4>
<p>

View File

@ -1,14 +1,40 @@
<div class="row">
<div class="col s12 m10 offset-m1">
<div class="col s12">
<div class="hoverable card">
<div class="card-content">
<div class="card-title">You can now purchase sharable Premium Codes for yourself or others</div>
<p>
Making a purchase below will generate a single-use code that can be redeemed at any time for a Premium subscription on Notebook.ai.
You can purchase these codes for yourself if you'd like to prepay for a certain amount of months without a recurring monthly subscription,
or for others if you'd like to gift a Notebook.ai Premium membership to someone else! You can purchase as many codes as you'd like
and redeem them whenever you'd like.
</p>
<div class="card-title">Prepaid Premium Codes</div>
<div class="row">
<div class="col s12 m8 l9">
<p>
Making a purchase below will generate a single-use code that can be redeemed at any time for a Premium subscription on Notebook.ai.
You can purchase these codes for yourself if you'd like to prepay for a certain amount of months without a recurring monthly subscription,
or for others if you'd like to gift a Notebook.ai Premium membership to someone else!
</p>
<br />
<p>
You can purchase as many codes as you'd like and redeem them whenever you'd like.
</p>
<br />
<p>
While your Premium is active, you'll have access to <%= Rails.application.config.content_types[:premium].count %> additional worldbuilding
pages: you'll be able to create unlimited
<%=
Rails.application.config.content_types[:premium].map { |page|
"&nbsp;<strong class='#{page.color}-text'><i class='material-icons tiny'>#{page.icon}</i> #{page.name.pluralize}</strong>"
}.to_sentence.html_safe
%>!
</p>
</div>
<div class="col hide-on-small-only m4 l3">
<%= image_tag 'tristan/small.png',
class: 'tooltipped tristan',
data: {
position: 'left',
enterDelay: '500',
tooltip: "Hey, I'm Tristan! I'm here to help you around the site!"
} %>
</div>
</div>
</div>
</div>
</div>
@ -18,7 +44,7 @@
<div class="row">
<div class="col s12 m6">
<%= link_to prepay_paypal_gateway_path(months: 1), class: 'black-text' do %>
<div class="hoverable card blue lighten-4" style="height: 170px;">
<div class="hoverable card blue lighten-4" style="min-height: 170px;">
<div class="card-content">
<div class="card-title">
<i class="material-icons left">star</i>
@ -34,41 +60,53 @@
</div>
<div class="col s12 m6">
<%= link_to prepay_paypal_gateway_path(months: 3), class: 'black-text' do %>
<div class="hoverable card blue lighten-4" style="height: 170px;">
<div class="hoverable card yellow lighten-4" style="min-height: 170px;">
<div class="card-content">
<div class="card-title">
<i class="material-icons left">star</i>
3 months of Premium
<span class="badge yellow">includes limited-time offer</span>
</div>
<p>
All Premium features
for <strong>$24.00</strong><br />
for <strong>$24.00</strong>
(save $3.00 compared to monthly)
</p>
<br />
<p>
Limited-time offer: Purchasing this Premium Code before <%= PromoService.end_date(:promo_bogo).strftime("%B %-d") %>
will generate <strong>two</strong> Premium Codes for the price of one!
</p>
</div>
</div>
<% end %>
</div>
<div class="col s12 m6">
<%= link_to prepay_paypal_gateway_path(months: 6), class: 'black-text' do %>
<div class="hoverable card blue lighten-4" style="height: 170px;">
<div class="hoverable card yellow lighten-4" style="min-height: 170px">
<div class="card-content">
<div class="card-title">
<i class="material-icons left">star</i>
6 months of Premium
<span class="badge yellow">includes limited-time offer</span>
</div>
<p>
All Premium features
for <strong>$48.00</strong><br />
for <strong>$48.00</strong>
(save $6.00 compared to monthly)
</p>
<br />
<p>
Limited-time offer: Purchasing this Premium Code before <%= PromoService.end_date(:promo_bogo).strftime("%B %-d") %>
will generate <strong>two</strong> Premium Codes for the price of one!
</p>
</div>
</div>
<% end %>
</div>
<div class="col s12 m6">
<%= link_to prepay_paypal_gateway_path(months: 12), class: 'black-text' do %>
<div class="hoverable card blue lighten-4" style="height: 170px;">
<div class="hoverable card blue lighten-4" style="min-height: 170px;">
<div class="card-content">
<div class="card-title">
<i class="material-icons left">star</i>
@ -76,7 +114,7 @@
</div>
<p>
All Premium features
for <strong>$84.00</strong><br />
for <strong>$84.00</strong>
(save $24.00 compared to monthly)
</p>
</div>
@ -118,8 +156,13 @@
</div>
<p>
<% if invoice.page_unlock_promo_code.present? %>
<p>
Description: <%= invoice.page_unlock_promo_code.description %>
</p>
<% if invoice.activateable? %>
Promo code: <strong><%= invoice.page_unlock_promo_code.code %></strong>
<p>
Promo code: <strong><%= invoice.page_unlock_promo_code.code %></strong>
</p>
<% end %>
<% else %>
<% if invoice.status == 'APPROVED' %>
@ -172,7 +215,7 @@
</div>
<% else %>
<div class="card-action">
<% if invoice.page_unlock_promo_code && invoice.page_unlock_promo_code.uses_remaining.zero? %>
<% if invoice.page_unlock_promo_code && invoice.page_unlock_promo_code.uses_remaining.zero? && invoice.page_unlock_promo_code.promotions.any? %>
Activated <%= time_ago_in_words invoice.page_unlock_promo_code.promotions.last.created_at %> ago
<% else %>
<% if invoice.status == 'CREATED' %>

View File

@ -0,0 +1,5 @@
Rails.application.config.promos = {}
Rails.application.config.promos[:promo_bogo] = {}
Rails.application.config.promos[:promo_bogo][:start_date] = 'March 20, 2020'.to_date
Rails.application.config.promos[:promo_bogo][:end_date] = Rails.application.config.promos[:promo_bogo][:start_date] + 2.weeks

View File

@ -74,12 +74,13 @@ Rails.application.routes.draw do
# TODO delete deprecated/unused referrals controller/views
scope '/data' do
get '/', to: 'data#index', as: :data_vault
get '/usage', to: 'data#usage'
get '/recyclebin', to: 'data#recyclebin'
get '/archive', to: 'data#archive'
get '/uploads', to: 'data#uploads'
get '/discussions', to: 'data#discussions'
get '/', to: 'data#index', as: :data_vault
get '/usage', to: 'data#usage'
get '/recyclebin', to: 'data#recyclebin'
get '/archive', to: 'data#archive'
get '/uploads', to: 'data#uploads'
get '/discussions', to: 'data#discussions'
get '/collaboration', to: 'data#collaboration'
scope 'export' do
get '/', to: 'export#index', as: :notebook_export