mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-14 07:00:01 -04:00
Merge branch 'prepaid-v2' into master
This commit is contained in:
parent
ad0dfef50f
commit
928f72e2cf
23 changed files with 961 additions and 61 deletions
|
@ -26,6 +26,7 @@ module.exports = class CocoRouter extends Backbone.Router
|
|||
'account/subscription': go('account/SubscriptionView')
|
||||
'account/subscription/sale': go('account/SubscriptionSaleView')
|
||||
'account/invoices': go('account/InvoicesView')
|
||||
'account/prepaid': go('account/PrepaidView')
|
||||
|
||||
'admin': go('admin/MainAdminView')
|
||||
'admin/candidates': go('admin/CandidatesView')
|
||||
|
|
|
@ -243,3 +243,8 @@ module.exports.getCoursePraise = getCoursePraise = ->
|
|||
}
|
||||
]
|
||||
praise[_.random(0, praise.length - 1)]
|
||||
|
||||
module.exports.getPrepaidCodeAmount = getPrepaidCodeAmount = (price=999, users=0, months=0) ->
|
||||
return 0 unless users > 0 and months > 0
|
||||
total = price * users * months
|
||||
total
|
||||
|
|
|
@ -1129,6 +1129,7 @@
|
|||
recently_played: "Recently Played"
|
||||
no_recent_games: "No games played during the past two weeks."
|
||||
payments: "Payments"
|
||||
prepaid: "Prepaid"
|
||||
purchased: "Purchased"
|
||||
sale: "Sale"
|
||||
subscription: "Subscription"
|
||||
|
@ -1159,6 +1160,14 @@
|
|||
retrying: "Server error, retrying."
|
||||
success: "Successfully paid. Thanks!"
|
||||
|
||||
account_prepaid:
|
||||
purchase_code: "Purchase a Subscription Code"
|
||||
purchase_amount: "Amount"
|
||||
purchase_total: "Total"
|
||||
purchase_button: "Submit Purchase"
|
||||
your_codes: "Your Codes:"
|
||||
redeem_codes: "Redeem a Subscription Code"
|
||||
|
||||
loading_error:
|
||||
could_not_load: "Error loading from server"
|
||||
connection_failure: "Connection failed."
|
||||
|
|
14
app/models/Prepaid.coffee
Normal file
14
app/models/Prepaid.coffee
Normal file
|
@ -0,0 +1,14 @@
|
|||
CocoModel = require './CocoModel'
|
||||
schema = require 'schemas/models/prepaid.schema'
|
||||
|
||||
module.exports = class Prepaid extends CocoModel
|
||||
@className: "Prepaid"
|
||||
urlRoot: '/db/prepaid'
|
||||
|
||||
openSpots: ->
|
||||
@get('maxRedeemers') - @get('redeemers')?.length
|
||||
|
||||
userHasRedeemed: (userID) ->
|
||||
for redeemer in @get('redeemers')
|
||||
return redeemer.date if redeemer.userID is userID
|
||||
return null
|
3
app/styles/account/account-prepaid-view.sass
Normal file
3
app/styles/account/account-prepaid-view.sass
Normal file
|
@ -0,0 +1,3 @@
|
|||
|
||||
#users, #months
|
||||
max-width: 100px
|
|
@ -4,14 +4,14 @@ block content
|
|||
|
||||
if me.get('anonymous')
|
||||
p(data-i18n="account_settings.not_logged_in") Log in or create an account to change your settings.
|
||||
|
||||
|
||||
else
|
||||
ol.breadcrumb
|
||||
li
|
||||
a(href="/")
|
||||
span.glyphicon.glyphicon-home
|
||||
li.active(data-i18n="nav.account")
|
||||
|
||||
|
||||
#account-links.panel.panel-default
|
||||
.panel-heading(data-i18n="nav.account")
|
||||
ul.list-group
|
||||
|
@ -23,4 +23,6 @@ block content
|
|||
a.btn.btn-lg.btn-primary(href="/account/payments", data-i18n="account.payments")
|
||||
li.list-group-item
|
||||
a.btn.btn-lg.btn-primary(href="/account/subscription", data-i18n="account.subscription")
|
||||
li.list-group-item
|
||||
a.btn.btn-lg.btn-primary(href="/account/prepaid") Prepaid Codes
|
||||
|
||||
|
|
19
app/templates/account/prepaid-redeem-modal.jade
Normal file
19
app/templates/account/prepaid-redeem-modal.jade
Normal file
|
@ -0,0 +1,19 @@
|
|||
extends /templates/core/modal-base
|
||||
|
||||
block modal-header-content
|
||||
h3 Prepaid Code Details (#{ppc.get('code')})
|
||||
|
||||
block modal-body-content
|
||||
if redeemedOn
|
||||
p You redeemed this code: #{redeemedOn}
|
||||
else
|
||||
if ppc.openSpots()
|
||||
p: strong Adds #{ppc.get('properties').months} month(s) to your current subscription.
|
||||
p You can redeem this code.
|
||||
else
|
||||
p You cannot redeem this code.
|
||||
|
||||
block modal-footer-content
|
||||
button#close.btn.btn-primary(type="button", data-dismiss="modal") Cancel
|
||||
if !redeemedOn && ppc.openSpots() > 0
|
||||
button#redeem.btn.btn-primary(type="button", data-dismiss="modal") Redeem Code To My Account
|
99
app/templates/account/prepaid-view.jade
Normal file
99
app/templates/account/prepaid-view.jade
Normal file
|
@ -0,0 +1,99 @@
|
|||
extends /templates/base
|
||||
|
||||
block content
|
||||
|
||||
if me.get('anonymous')
|
||||
p(data-i18n="account_settings.not_logged_in") Log in or create an account to change your settings.
|
||||
|
||||
else
|
||||
ol.breadcrumb
|
||||
li
|
||||
a(href="/")
|
||||
span.glyphicon.glyphicon-home
|
||||
li
|
||||
a(href="/account", data-i18n="nav.account")
|
||||
li.active(data-i18n="account.prepaid")
|
||||
|
||||
.row
|
||||
.col-md-12
|
||||
.panel.panel-default
|
||||
.panel-heading
|
||||
.panel-title
|
||||
a(data-toggle="collapse" href="#purchasepanel")
|
||||
span(data-i18n="account_prepaid.purchase_code")
|
||||
.panel-collapse.collapse(class=ppc ? "": "in")#purchasepanel
|
||||
.panel-body
|
||||
p Subscription Codes can be redeemed to add premium subscription time to one or more Code Combat accounts.
|
||||
p Each Code Combat account can only redeem a particular Subscription Code once.
|
||||
p Subscription Code months will be added to the end of any existing subscription on the account.
|
||||
.form-horizontal
|
||||
.form-group
|
||||
label.control-label.col-md-2(for="users") Users
|
||||
.col-md-2
|
||||
input#users.form-control(name="users", type="number", value="#{purchase.users}", min=1)
|
||||
.form-group
|
||||
label.control-label.col-md-2(for="months") Months
|
||||
.col-md-2
|
||||
input#months.form-control(name="months", type="number", value="#{purchase.months}", min=1)
|
||||
.form-group
|
||||
label.control-label.col-md-2(data-i18n="account_prepaid.purchase_total")
|
||||
.col-md-10
|
||||
p.form-control-static $
|
||||
span#total #{purchase.total}
|
||||
button#purchase-button.btn.btn-success.pull-right(data-i18n="account_prepaid.purchase_button")
|
||||
.row
|
||||
.col-md-12
|
||||
.panel.panel-default
|
||||
.panel-heading
|
||||
.panel-title
|
||||
a(data-toggle="collapse" href="#redeempanel")
|
||||
span(data-i18n="account_prepaid.redeem_codes")
|
||||
.panel-collapse.collapse.in#redeempanel
|
||||
.panel-body
|
||||
.form-horizontal
|
||||
.form-group
|
||||
label.control-label.col-md-2(for="ppc") Code:
|
||||
.col-md-10
|
||||
input#ppc.form-control(name="ppc", type="text", value="#{ppc}" required)
|
||||
button#redeem-button.btn.btn-success.pull-right View Code Details
|
||||
.row
|
||||
.col-md-12
|
||||
.panel.panel-default
|
||||
.panel-heading
|
||||
.panel-title
|
||||
a(data-toggle="collapse" href="#codeslist")
|
||||
span(data-i18n="account_prepaid.your_codes")
|
||||
.panel-collapse.collapse.in#codeslist
|
||||
.panel-body
|
||||
if codes && codes.length
|
||||
table.table.table-striped
|
||||
tr
|
||||
th
|
||||
span(title="You can copy the code's link and send it to someone.") Code
|
||||
span.glyphicon.glyphicon-question-sign(aria-hidden="true")
|
||||
th Months
|
||||
th Quantity
|
||||
th Status
|
||||
for code in codes.models
|
||||
if code.get('type') === 'terminal_subscription'
|
||||
- var owner = (code.get('creator') == me.id ? true : false)
|
||||
- var properties = code.get('properties')
|
||||
- var redeemers = code.get('redeemers')
|
||||
if redeemers
|
||||
- var redeemed = redeemers.length
|
||||
else
|
||||
- var redeemed = '0'
|
||||
tr
|
||||
td
|
||||
a(href="/account/prepaid?_ppc=#{code.get('code')}")= code.get('code')
|
||||
td= properties.months || '-'
|
||||
if owner
|
||||
td= code.get('maxRedeemers') - redeemed
|
||||
else
|
||||
td -
|
||||
if owner
|
||||
td Purchased
|
||||
else
|
||||
td Redeemed
|
||||
else
|
||||
p No codes yet!
|
|
@ -119,6 +119,15 @@ block content
|
|||
else
|
||||
button.start-subscription-button.btn.btn-lg.btn-success(data-i18n="subscribe.subscribe_title") Subscribe
|
||||
|
||||
// - Prepaid Codes
|
||||
.panel.panel-default
|
||||
.panel-heading
|
||||
h3 Prepaid Codes
|
||||
.panel-body
|
||||
p
|
||||
span You can
|
||||
a(href="/account/prepaid") purchase a prepaid code
|
||||
span that can be applied to your own account or given to others.
|
||||
//- Sponsored Subscriptions
|
||||
|
||||
.panel.panel-default
|
||||
|
|
|
@ -63,6 +63,16 @@ block content
|
|||
if freeSubLink
|
||||
input#free-sub-input(type="text", readonly, value="#{freeSubLink}")
|
||||
|
||||
.form-inline
|
||||
.form-group
|
||||
label(for="users") Users
|
||||
input#users.form-control(name="users", type="number", min=1)
|
||||
.form-group
|
||||
label(for="months") Months
|
||||
input#months.form-control(name="months", type="number", min=1)
|
||||
a#terminal-create.btn.btn-default Create Terminal Subscription Code
|
||||
|
||||
|
||||
hr
|
||||
|
||||
h3 Achievements
|
||||
|
|
|
@ -37,6 +37,8 @@ block header
|
|||
a(href="/account/payments", data-i18n="account.payments")
|
||||
li
|
||||
a(href="/account/subscription", data-i18n="account.subscription")
|
||||
li
|
||||
a(href="/account/prepaid") Prepaid Codes
|
||||
li
|
||||
a#logout-button(data-i18n="login.log_out")
|
||||
|
||||
|
@ -44,7 +46,7 @@ block header
|
|||
button.btn.btn-sm.btn-primary.header-font.signup-button(data-i18n="login.sign_up")
|
||||
button.btn.btn-sm.btn-default.header-font.login-button(data-i18n="login.log_in")
|
||||
select.language-dropdown.form-control
|
||||
|
||||
|
||||
|
||||
block outer_content
|
||||
#site-content-area
|
||||
|
@ -75,15 +77,15 @@ block footer
|
|||
if !isIE
|
||||
a.twitter-follow-button(href="https://twitter.com/CodeCombat", data-show-count="true", data-show-screen-name="false", data-dnt="true", data-align="right", data-i18n="nav.twitter_follow") Follow
|
||||
iframe.github-star-button(src="https://ghbtns.com/github-btn.html?user=codecombat&repo=codecombat&type=watch&count=true", allowtransparency="true", frameborder="0", scrolling="0", width="110", height="20")
|
||||
|
||||
|
||||
#footer-credits
|
||||
span
|
||||
span
|
||||
span © All Rights Reserved
|
||||
br
|
||||
span CodeCombat 2015
|
||||
img#footer-logo(src="/images/pages/base/logo.png", alt="CodeCombat")
|
||||
span
|
||||
span Site Design by
|
||||
span
|
||||
span Site Design by
|
||||
br
|
||||
a(href="http://www.fullyillustrated.com/") Fully Illustrated
|
||||
//a.firebase-bade(href="https://www.firebase.com/") // Not using right now
|
||||
|
|
27
app/views/account/PrepaidRedeemModal.coffee
Normal file
27
app/views/account/PrepaidRedeemModal.coffee
Normal file
|
@ -0,0 +1,27 @@
|
|||
ModalView = require 'views/core/ModalView'
|
||||
template = require 'templates/account/prepaid-redeem-modal'
|
||||
{me} = require 'core/auth'
|
||||
|
||||
|
||||
module.exports = class PrepaidRedeemModal extends ModalView
|
||||
id: 'prepaid-redeem-modal'
|
||||
template: template
|
||||
closeButton: true
|
||||
|
||||
events:
|
||||
'click #redeem' : 'onRedeemClicked'
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
@ppc = options.ppc
|
||||
hasRedeemed = @ppc.userHasRedeemed(me.get('_id'))
|
||||
@redeemedOn = new moment(hasRedeemed).calendar() if hasRedeemed
|
||||
|
||||
getRenderData: ->
|
||||
c = super()
|
||||
c.ppc = @ppc
|
||||
c.redeemedOn = @redeemedOn if @redeemedOn
|
||||
c
|
||||
|
||||
onRedeemClicked: ->
|
||||
@trigger 'confirm-redeem'
|
179
app/views/account/PrepaidView.coffee
Normal file
179
app/views/account/PrepaidView.coffee
Normal file
|
@ -0,0 +1,179 @@
|
|||
RootView = require 'views/core/RootView'
|
||||
template = require 'templates/account/prepaid-view'
|
||||
stripeHandler = require 'core/services/stripe'
|
||||
{getPrepaidCodeAmount} = require '../../core/utils'
|
||||
CocoCollection = require 'collections/CocoCollection'
|
||||
Prepaid = require '../../models/Prepaid'
|
||||
utils = require 'core/utils'
|
||||
RedeemModal = require 'views/account/PrepaidRedeemModal'
|
||||
forms = require 'core/forms'
|
||||
|
||||
|
||||
module.exports = class PrepaidView extends RootView
|
||||
id: 'prepaid-view'
|
||||
template: template
|
||||
className: 'container-fluid'
|
||||
|
||||
events:
|
||||
'change #users': 'onUsersChanged'
|
||||
'change #months': 'onMonthsChanged'
|
||||
'click #purchase-button': 'onPurchaseClicked'
|
||||
'click #redeem-button': 'onRedeemClicked'
|
||||
|
||||
subscriptions:
|
||||
'stripe:received-token': 'onStripeReceivedToken'
|
||||
|
||||
baseAmount: 9.99
|
||||
|
||||
constructor: (options) ->
|
||||
super(options)
|
||||
@purchase =
|
||||
total: @baseAmount
|
||||
users: 3
|
||||
months: 3
|
||||
@updateTotal()
|
||||
|
||||
@codes = new CocoCollection([], { url: '/db/user/'+me.id+'/prepaid_codes', model: Prepaid })
|
||||
@codes.on 'add', (code) =>
|
||||
@render?()
|
||||
@codes.on 'sync', (code) =>
|
||||
@render?()
|
||||
|
||||
@supermodel.loadCollection(@codes, 'prepaid', {cache: false})
|
||||
@ppc = utils.getQueryVariable('_ppc') ? ''
|
||||
|
||||
getRenderData: ->
|
||||
c = super()
|
||||
c.purchase = @purchase
|
||||
c.codes = @codes
|
||||
c.ppc = @ppc
|
||||
c
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
@$el.find("span[title]").tooltip()
|
||||
|
||||
statusMessage: (message, type='alert') ->
|
||||
noty text: message, layout: 'topCenter', type: type, killer: false, timeout: 5000, dismissQueue: true, maxVisible: 3
|
||||
|
||||
updateTotal: ->
|
||||
@purchase.total = getPrepaidCodeAmount(@baseAmount, @purchase.users, @purchase.months)
|
||||
@renderSelectors("#total", "#users", "#months")
|
||||
|
||||
|
||||
# Form Input Callbacks
|
||||
onUsersChanged: (e) ->
|
||||
newAmount = $(e.target).val()
|
||||
newAmount = 1 if newAmount < 1
|
||||
@purchase.users = newAmount
|
||||
el = $('#purchasepanel')
|
||||
if newAmount < 3 and @purchase.months < 3
|
||||
message = "Either Users or Months must be greater than 2"
|
||||
err = [message: message, property: 'users', formatted: true]
|
||||
forms.clearFormAlerts(el)
|
||||
forms.applyErrorsToForm(el, err)
|
||||
else
|
||||
forms.clearFormAlerts(el)
|
||||
|
||||
@updateTotal()
|
||||
|
||||
onMonthsChanged: (e) ->
|
||||
newAmount = $(e.target).val()
|
||||
newAmount = 1 if newAmount < 1
|
||||
@purchase.months = newAmount
|
||||
el = $('#purchasepanel')
|
||||
if newAmount < 3 and @purchase.users < 3
|
||||
message = "Either Users or Months must be greater than 2"
|
||||
err = [message: message, property: 'months', formatted: true]
|
||||
forms.clearFormAlerts(el)
|
||||
forms.applyErrorsToForm(el, err)
|
||||
else
|
||||
forms.clearFormAlerts(el)
|
||||
|
||||
@updateTotal()
|
||||
|
||||
onPurchaseClicked: (e) ->
|
||||
return unless $("#users").val() >= 3 or $("#months").val() >= 3
|
||||
@purchaseTimestamp = new Date().getTime()
|
||||
@stripeAmount = @purchase.total * 100
|
||||
@description = "Prepaid Code for " + @purchase.users + " users / " + @purchase.months + " months"
|
||||
|
||||
stripeHandler.open
|
||||
amount: @stripeAmount
|
||||
description: @description
|
||||
bitcoin: true
|
||||
alipay: if me.get('chinaVersion') or (me.get('preferredLanguage') or 'en-US')[...2] is 'zh' then true else 'auto'
|
||||
|
||||
onRedeemClicked: (e) ->
|
||||
@ppc = $('#ppc').val()
|
||||
|
||||
unless @ppc
|
||||
@statusMessage "You must enter a code.", "error"
|
||||
return
|
||||
options =
|
||||
url: '/db/prepaid/-/code/'+ @ppc
|
||||
method: 'GET'
|
||||
|
||||
options.success = (model, res, options) =>
|
||||
redeemModal = new RedeemModal ppc: model
|
||||
redeemModal.on 'confirm-redeem', @confirmRedeem
|
||||
@openModalView redeemModal
|
||||
|
||||
options.error = (model, res, options) =>
|
||||
console.warn 'Error getting Prepaid Code'
|
||||
|
||||
prepaid = new Prepaid()
|
||||
prepaid.fetch(options)
|
||||
# @supermodel.addRequestResource('get_prepaid', options, 0).load()
|
||||
|
||||
|
||||
confirmRedeem: =>
|
||||
|
||||
options =
|
||||
url: '/db/subscription/-/subscribe_prepaid'
|
||||
method: 'POST'
|
||||
data: { ppc: @ppc }
|
||||
|
||||
options.error = (model, res, options, foo) =>
|
||||
console.error 'FAILED redeeming prepaid code'
|
||||
msg = model.responseText ? ''
|
||||
@statusMessage "Error: Could not redeem prepaid code. #{msg}", "error"
|
||||
|
||||
options.success = (model, res, options) =>
|
||||
console.log 'SUCCESS redeeming prepaid code'
|
||||
@statusMessage "Prepaid Code Redeemed!", "success"
|
||||
@supermodel.loadCollection(@codes, 'prepaid', {cache: false})
|
||||
@codes.fetch()
|
||||
|
||||
@supermodel.addRequestResource('subscribe_prepaid', options, 0).load()
|
||||
|
||||
|
||||
onStripeReceivedToken: (e) ->
|
||||
# TODO: show that something is happening in the UI
|
||||
options =
|
||||
url: '/db/prepaid/-/purchase'
|
||||
method: 'POST'
|
||||
|
||||
options.data =
|
||||
amount: @stripeAmount
|
||||
description: @description
|
||||
stripe:
|
||||
token: e.token.id
|
||||
timestamp: @purchaseTimestamp
|
||||
type: 'terminal_subscription'
|
||||
maxRedeemers: @purchase.users
|
||||
months: @purchase.months
|
||||
|
||||
options.error = (model, response, options) =>
|
||||
console.error 'FAILED: Prepaid purchase', response
|
||||
console.error options
|
||||
@statusMessage "Error purchasing prepaid code", "error"
|
||||
# Not sure when this will happen. Stripe popup seems to give appropriate error messages.
|
||||
|
||||
options.success = (model, response, options) =>
|
||||
console.log 'SUCCESS: Prepaid purchase', model.code
|
||||
@statusMessage "Successfully purchased Prepaid Code!", "success"
|
||||
@codes.add(model)
|
||||
|
||||
@statusMessage "Finalizing purchase...", "information"
|
||||
@supermodel.addRequestResource('purchase_prepaid', options, 0).load()
|
|
@ -15,6 +15,7 @@ module.exports = class MainAdminView extends RootView
|
|||
'click #increment-button': 'incrementUserAttribute'
|
||||
'click #user-search-result': 'onClickUserSearchResult'
|
||||
'click #create-free-sub-btn': 'onClickFreeSubLink'
|
||||
'click #terminal-create': 'onClickTerminalSubLink'
|
||||
|
||||
getRenderData: ->
|
||||
context = super()
|
||||
|
@ -89,3 +90,27 @@ module.exports = class MainAdminView extends RootView
|
|||
options.error = (model, response, options) =>
|
||||
console.error 'Failed to create prepaid', response
|
||||
@supermodel.addRequestResource('create_prepaid', options, 0).load()
|
||||
|
||||
onClickTerminalSubLink: (e) =>
|
||||
@freeSubLink = ''
|
||||
return unless me.isAdmin()
|
||||
|
||||
options =
|
||||
url: '/db/prepaid/-/create'
|
||||
method: 'POST'
|
||||
data:
|
||||
type: 'terminal_subscription'
|
||||
maxRedeemers: parseInt($("#users").val())
|
||||
months: parseInt($("#months").val())
|
||||
|
||||
options.success = (model, response, options) =>
|
||||
# TODO: Don't hardcode domain.
|
||||
if application.isProduction()
|
||||
@freeSubLink = "https://codecombat.com/account/prepaid?_ppc=#{model.code}"
|
||||
else
|
||||
@freeSubLink = "http://localhost:3000/account/prepaid?_ppc=#{model.code}"
|
||||
@render?()
|
||||
options.error = (model, response, options) =>
|
||||
console.error 'Failed to create prepaid', response
|
||||
@supermodel.addRequestResource('create_prepaid', options, 0).load()
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
AnalyticsString = require '../analytics/AnalyticsString'
|
||||
log = require 'winston'
|
||||
mongoose = require 'mongoose'
|
||||
config = require '../../server_config'
|
||||
|
||||
module.exports =
|
||||
isID: (id) -> _.isString(id) and id.length is 24 and id.match(/[a-f0-9]/gi)?.length is 24
|
||||
|
@ -21,6 +22,9 @@ module.exports =
|
|||
# Grabs latest subscription (e.g. in case of a resubscribe)
|
||||
return done() unless customerID?
|
||||
return done() unless options.subscriptionID? or options.userID?
|
||||
# Some prepaid tests were calling this in such a way that stripe wasn't defined.
|
||||
stripe = require('stripe')(config.stripe.secretKey) unless stripe
|
||||
|
||||
subscriptionID = options.subscriptionID
|
||||
userID = options.userID
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ User = require '../users/User'
|
|||
{findStripeSubscription} = require '../lib/utils'
|
||||
{getSponsoredSubsAmount} = require '../../app/core/utils'
|
||||
StripeUtils = require '../lib/stripe_utils'
|
||||
moment = require 'moment'
|
||||
|
||||
recipientCouponID = 'free'
|
||||
|
||||
|
@ -38,6 +39,7 @@ class SubscriptionHandler extends Handler
|
|||
return @getStripeSubscriptions(req, res) if args[1] is 'stripe_subscriptions'
|
||||
return @getSubscribers(req, res) if args[1] is 'subscribers'
|
||||
return @purchaseYearSale(req, res) if args[1] is 'year_sale'
|
||||
return @subscribeWithPrepaidCode(req, res) if args[1] is 'subscribe_prepaid'
|
||||
super(arguments...)
|
||||
|
||||
getStripeEvents: (req, res) ->
|
||||
|
@ -117,23 +119,24 @@ class SubscriptionHandler extends Handler
|
|||
log.debug 'Analytics error:\n' + err
|
||||
@sendSuccess(res, userMap)
|
||||
|
||||
cancelSubscriptionImmediately: (user, subscription, done) =>
|
||||
return done() unless user and subscription
|
||||
stripe.customers.cancelSubscription subscription.customer, subscription.id, (err) =>
|
||||
return done(err) if err
|
||||
stripeInfo = _.cloneDeep(user.get('stripe') ? {})
|
||||
delete stripeInfo.planID
|
||||
delete stripeInfo.prepaidCode
|
||||
delete stripeInfo.subscriptionID
|
||||
user.set('stripe', stripeInfo)
|
||||
user.save (err) =>
|
||||
return done(err) if err
|
||||
done()
|
||||
|
||||
|
||||
purchaseYearSale: (req, res) ->
|
||||
return @sendForbiddenError(res) unless req.user?
|
||||
return @sendForbiddenError(res) if req.user?.get('stripe')?.sponsorID
|
||||
|
||||
cancelSubscriptionImmediately = (user, subscription, done) =>
|
||||
return done() unless user and subscription
|
||||
stripe.customers.cancelSubscription subscription.customer, subscription.id, (err) =>
|
||||
return done(err) if err
|
||||
stripeInfo = _.cloneDeep(user.get('stripe') ? {})
|
||||
delete stripeInfo.planID
|
||||
delete stripeInfo.prepaidCode
|
||||
delete stripeInfo.subscriptionID
|
||||
user.set('stripe', stripeInfo)
|
||||
user.save (err) =>
|
||||
return done(err) if err
|
||||
done()
|
||||
|
||||
StripeUtils.getCustomer req.user, req.body.stripe?.token, (err, customer) =>
|
||||
if err
|
||||
@logSubscriptionError(req.user, "Purchase year sale get customer: #{JSON.stringify(err)}")
|
||||
|
@ -142,7 +145,7 @@ class SubscriptionHandler extends Handler
|
|||
findStripeSubscription customer.id, subscriptionID: req.user.get('stripe')?.subscriptionID, (subscription) =>
|
||||
stripeSubscriptionPeriodEndDate = new Date(subscription.current_period_end * 1000) if subscription
|
||||
|
||||
cancelSubscriptionImmediately req.user, subscription, (err) =>
|
||||
@cancelSubscriptionImmediately req.user, subscription, (err) =>
|
||||
if err
|
||||
@logSubscriptionError(user, "Purchase year sale Stripe cancel subscription error: #{JSON.stringify(err)}")
|
||||
return @sendDatabaseError(res, err)
|
||||
|
@ -192,6 +195,95 @@ class SubscriptionHandler extends Handler
|
|||
@logSubscriptionError(req.user, "Year sub sale HipChat tower msg error: #{JSON.stringify(error)}")
|
||||
@sendSuccess(res, user)
|
||||
|
||||
subscribeWithPrepaidCode: (req, res) ->
|
||||
return @sendForbiddenError(res) unless req.user?
|
||||
return @sendBadInputError(res,"You must provide a valid prepaid code") unless req.body?.ppc
|
||||
|
||||
# Check if code exists and has room for more redeemers
|
||||
Prepaid.findOne({ code: req.body.ppc?.toString() }).exec (err, prepaid) =>
|
||||
if err
|
||||
@logSubscriptionError(req.user, "Redeem Prepaid Code find: #{JSON.stringify(err)}")
|
||||
return @sendDatabaseError(res, err)
|
||||
|
||||
return @sendForbiddenError(res) if prepaid is null
|
||||
|
||||
oldRedeemers = prepaid.get('redeemers') ? []
|
||||
return @sendForbiddenError(res) if oldRedeemers.length >= prepaid.get('maxRedeemers')
|
||||
|
||||
months = parseInt(prepaid.get('properties')?.months)
|
||||
return @sendForbiddenError(res) if isNaN(months) or months < 1
|
||||
|
||||
for redeemer in oldRedeemers
|
||||
return @sendForbiddenError(res) if redeemer.userID.equals(req.user._id)
|
||||
|
||||
customerID = req.user.get('stripe')?.customerID
|
||||
|
||||
unless customerID
|
||||
@redeemCode(req, res, oldRedeemers, months)
|
||||
else
|
||||
stripe.customers.retrieve customerID, (err, customer) =>
|
||||
if err
|
||||
@logSubscriptionError(req.user, "Redeem Prepaid Code get customer: #{JSON.stringify(err)}")
|
||||
return @sendDatabaseError(res, err)
|
||||
|
||||
findStripeSubscription customer.id, subscriptionID: req.user.get('stripe')?.subscriptionID, (subscription) =>
|
||||
stripeSubscriptionPeriodEndDate = null
|
||||
if subscription
|
||||
stripeSubscriptionPeriodEndDate = new Date(subscription.current_period_end * 1000)
|
||||
|
||||
|
||||
@cancelSubscriptionImmediately req.user, subscription, (err) =>
|
||||
if err
|
||||
@logSubscriptionError(user, "Redeem Prepaid Code Stripe cancel subscription error: #{JSON.stringify(err)}")
|
||||
return @sendDatabaseError(res, err)
|
||||
|
||||
@redeemCode(req, res, oldRedeemers, months, stripeSubscriptionPeriodEndDate)
|
||||
|
||||
redeemCode: (req, res, oldRedeemers, months, startDate=null) =>
|
||||
return @sendForbiddenError(res) unless req.user?
|
||||
return @sendForbiddenError(res) unless req.body?.ppc
|
||||
return @sendForbiddenError(res) unless oldRedeemers
|
||||
return @sendForbiddenError(res) if isNaN(months) or months < 1
|
||||
|
||||
newRedeemerPush = { $push: { redeemers : { date: new Date().toISOString(), userID: req.user._id } }}
|
||||
|
||||
# Only update the prepaid document if the length of the redeemers array hasn't changed in the db.
|
||||
# This will probably fail if redeemers isn't defined. new terminal_subscriptions created should be sure to set the redeemers array
|
||||
# TODO: find a better way?
|
||||
Prepaid.update { 'code': req.body.ppc, 'redeemers': { $size: oldRedeemers.length }}, newRedeemerPush, (err, num, info) =>
|
||||
if err
|
||||
@logSubscriptionError(req.user, "Subscribe with Prepaid Code update: #{JSON.stringify(err)}")
|
||||
return @sendDatabaseError(res, err)
|
||||
|
||||
return @sendNotFoundError(res, "Error while updating prepaid redeemer") if num isnt 1
|
||||
|
||||
|
||||
# Add terminal subscription to User, extending existing subscriptions
|
||||
# TODO: refactor this into some form useable by both this and purchaseYearSale?
|
||||
stripeInfo = _.cloneDeep(req.user.get('stripe') ? {})
|
||||
endDate = new moment()
|
||||
if startDate
|
||||
endDate = new moment(startDate)
|
||||
else if _.isString(stripeInfo.free) and new moment().isBefore(new moment(stripeInfo.free))
|
||||
endDate = new moment(stripeInfo.free)
|
||||
|
||||
endDate = endDate.add(months, 'months')
|
||||
stripeInfo.free = endDate.toISOString().substring(0, 10)
|
||||
req.user.set('stripe', stripeInfo)
|
||||
|
||||
# Add gems to User
|
||||
purchased = _.clone(req.user.get('purchased'))
|
||||
purchased ?= {}
|
||||
purchased.gems ?= 0
|
||||
purchased.gems += subscriptions.basic.gems * months
|
||||
req.user.set('purchased', purchased)
|
||||
|
||||
req.user.save (err, user) =>
|
||||
if err
|
||||
@logSubscriptionError(req.user, "User save error: #{JSON.stringify(err)}")
|
||||
return @sendDatabaseError(res, err)
|
||||
@sendSuccess(res, user)
|
||||
|
||||
subscribeUser: (req, user, done) ->
|
||||
if (not req.user) or req.user.isAnonymous() or user.isAnonymous()
|
||||
return done({res: 'You must be signed in to subscribe.', code: 403})
|
||||
|
|
|
@ -2,6 +2,8 @@ mongoose = require 'mongoose'
|
|||
config = require '../../server_config'
|
||||
PrepaidSchema = new mongoose.Schema {}, {strict: false, minimize: false,read:config.mongo.readpref}
|
||||
|
||||
PrepaidSchema.index({code: 1}, { unique: true })
|
||||
|
||||
PrepaidSchema.statics.generateNewCode = (done) ->
|
||||
tryCode = ->
|
||||
code = _.sample("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 8).join('')
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
Handler = require '../commons/Handler'
|
||||
Prepaid = require './Prepaid'
|
||||
StripeUtils = require '../lib/stripe_utils'
|
||||
{getPrepaidCodeAmount} = require '../../app/core/utils'
|
||||
|
||||
# TODO: Should this happen on a save() call instead of a prepaid/-/create post?
|
||||
# TODO: Probably a better way to create a unique 8 charactor string property using db voodoo
|
||||
|
@ -7,31 +9,113 @@ Prepaid = require './Prepaid'
|
|||
PrepaidHandler = class PrepaidHandler extends Handler
|
||||
modelClass: Prepaid
|
||||
jsonSchema: require '../../app/schemas/models/prepaid.schema'
|
||||
allowedMethods: ['POST']
|
||||
allowedMethods: ['GET','POST']
|
||||
|
||||
baseAmount: 999
|
||||
|
||||
logPurchaseError: (user, msg) ->
|
||||
console.warn "Prepaid Purchase Error: [#{user.get('slug')} (#{user._id})] '#{msg}'"
|
||||
|
||||
hasAccess: (req) ->
|
||||
req.user?.isAdmin()
|
||||
|
||||
getByRelationship: (req, res, args...) ->
|
||||
relationship = args[1]
|
||||
return @getPrepaid(req, res, args[2]) if relationship is 'code'
|
||||
return @createPrepaid(req, res) if relationship is 'create'
|
||||
return @purchasePrepaid(req, res) if relationship is 'purchase'
|
||||
super arguments...
|
||||
|
||||
getPrepaid: (req, res, code) ->
|
||||
return @sendForbiddenError(res) unless req.user?
|
||||
return @sendNotFoundError(res, "You must specify a code") unless code
|
||||
|
||||
Prepaid.findOne({ code: code.toString() }).exec (err, prepaid) =>
|
||||
if err
|
||||
console.warn "Get Prepaid Code Error [#{req.user.get('slug')} (#{req.user.id})]: #{JSON.stringify(err)}"
|
||||
return @sendDatabaseError(res, err)
|
||||
|
||||
return @sendNotFoundError(res, "Code not found") unless prepaid
|
||||
|
||||
@sendSuccess(res, prepaid.toObject())
|
||||
|
||||
createPrepaid: (req, res) ->
|
||||
return @sendForbiddenError(res) unless @hasAccess(req)
|
||||
return @sendForbiddenError(res) unless req.body.type is 'subscription'
|
||||
return @sendForbiddenError(res) unless req.body.type in ['subscription','terminal_subscription']
|
||||
return @sendForbiddenError(res) unless req.body.maxRedeemers > 0
|
||||
|
||||
Prepaid.generateNewCode (code) =>
|
||||
return @sendDatabaseError(res, 'Database error.') unless code
|
||||
prepaid = new Prepaid
|
||||
# TODO: change the creator to use ObjectID like with the terminal_subscription
|
||||
options =
|
||||
creator: req.user.id
|
||||
type: req.body.type
|
||||
code: code
|
||||
maxRedeemers: req.body.maxRedeemers
|
||||
properties:
|
||||
couponID: 'free'
|
||||
properties: {}
|
||||
redeemers: []
|
||||
|
||||
if req.body.type is 'subscription'
|
||||
options.properties.couponID = 'free'
|
||||
|
||||
if req.body.type is 'terminal_subscription'
|
||||
options.properties.months = req.body.months
|
||||
options.creator = req.user._id
|
||||
|
||||
prepaid = new Prepaid options
|
||||
prepaid.save (err) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
@sendSuccess(res, prepaid.toObject())
|
||||
|
||||
purchasePrepaid: (req, res) ->
|
||||
return @sendForbiddenError(res) unless req.user?
|
||||
return @sendForbiddenError(res) unless req.body.type is 'terminal_subscription'
|
||||
|
||||
maxRedeemers = parseInt(req.body.maxRedeemers)
|
||||
months = parseInt(req.body.months)
|
||||
|
||||
return @sendForbiddenError(res) unless isNaN(maxRedeemers) is false and maxRedeemers > 0
|
||||
return @sendForbiddenError(res) unless isNaN(months) is false and months > 0
|
||||
return @sendError(res, 403, "Users or Months must be greater than 3") if maxRedeemers < 3 and months < 3
|
||||
|
||||
StripeUtils.getCustomer req.user, req.body.stripe?.token, (err, customer) =>
|
||||
if err
|
||||
@logPurchaseError(req.user, "getCustomer error: #{JSON.stringify(err)}")
|
||||
return @sendDatabaseError(res, err)
|
||||
|
||||
metadata =
|
||||
type: req.body.type
|
||||
userID: req.user._id + ''
|
||||
timestamp: parseInt(req.body.stripe?.timestamp)
|
||||
description: req.body.description
|
||||
maxRedeemers: maxRedeemers
|
||||
months: months
|
||||
productID: 'prepaid ' + req.body.type
|
||||
|
||||
amount = getPrepaidCodeAmount(@baseAmount, maxRedeemers, months)
|
||||
|
||||
StripeUtils.createCharge req.user, amount, metadata, (err, charge) =>
|
||||
if err
|
||||
@logPurchaseError(req.user, "createCharge error: #{JSON.stringify(err)}")
|
||||
return @sendDatabaseError(res, err)
|
||||
|
||||
StripeUtils.createPayment req.user, charge, (err, payment) =>
|
||||
if err
|
||||
@logPurchaseError(req.user, "createPayment error: #{JSON.stringify(err)}")
|
||||
return @sendDatabaseError(res, err)
|
||||
|
||||
Prepaid.generateNewCode (code) =>
|
||||
return @sendDatabaseError(res, 'Database error.') unless code
|
||||
prepaid = new Prepaid
|
||||
creator: req.user._id
|
||||
type: req.body.type
|
||||
code: code
|
||||
maxRedeemers: req.body.maxRedeemers
|
||||
redeemers: []
|
||||
properties:
|
||||
months: req.body.months
|
||||
prepaid.save (err) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
@sendSuccess(res, prepaid.toObject())
|
||||
|
||||
module.exports = new PrepaidHandler()
|
||||
|
|
|
@ -46,14 +46,18 @@ module.exports.setup = (app) ->
|
|||
|
||||
invoiceID = req.body.data.object.id
|
||||
stripe.invoices.retrieve invoiceID, (err, invoice) =>
|
||||
return res.send(500, '') if err
|
||||
if err
|
||||
logStripeWebhookError("Retrieve invoice error: #{JSON.stringify(err)}")
|
||||
return res.send(500, '')
|
||||
unless invoice.total or invoice.discount?.coupon?.id is 'free'
|
||||
# invoices made when trialing, probably given for people who resubscribe after unsubscribing
|
||||
return res.send(200, '')
|
||||
return res.send(200, '') unless invoice.lines?.data?.length > 0
|
||||
|
||||
getUserID invoice.customer, (err, userID) =>
|
||||
return res.send(500, '') if err
|
||||
if err
|
||||
logStripeWebhookError("Get user ID error: #{JSON.stringify(err)}")
|
||||
return res.send(500, '')
|
||||
|
||||
# User is recipient if no metadata.id
|
||||
recipientID = invoice.lines.data[0].metadata?.id or userID
|
||||
|
@ -62,7 +66,9 @@ module.exports.setup = (app) ->
|
|||
subscriptionID = invoice.lines.data[0].subscription or invoice.lines.data[0].id
|
||||
|
||||
User.findById recipientID, (err, recipient) =>
|
||||
return res.send(500, '') if err
|
||||
if err
|
||||
logStripeWebhookError("Find recipient user error: #{JSON.stringify(err)}")
|
||||
return res.send(500, '')
|
||||
return res.send(200) unless recipient # just for the sake of testing...
|
||||
|
||||
Payment.findOne {'stripe.invoiceID': invoiceID}, (err, payment) =>
|
||||
|
@ -82,7 +88,9 @@ module.exports.setup = (app) ->
|
|||
payment.set 'gems', 3500 if invoice.lines.data[0].plan?.id is 'basic'
|
||||
|
||||
payment.save (err) =>
|
||||
return res.send(500, '') if err
|
||||
if err
|
||||
logStripeWebhookError("Save payment error: #{JSON.stringify(err)}")
|
||||
return res.send(500, '')
|
||||
return res.send(201, '') if invoice.lines.data[0].plan?.id isnt 'basic'
|
||||
|
||||
# Update purchased gems
|
||||
|
@ -94,7 +102,9 @@ module.exports.setup = (app) ->
|
|||
purchased.gems = gems
|
||||
recipient.set('purchased', purchased)
|
||||
recipient.save (err) ->
|
||||
return res.send(500, '') if err
|
||||
if err
|
||||
logStripeWebhookError("Save recipient user error: #{JSON.stringify(err)}")
|
||||
return res.send(500, '')
|
||||
return res.send(201, '')
|
||||
|
||||
handleSubscriptionDeleted = (req, res) ->
|
||||
|
|
|
@ -23,6 +23,7 @@ UserRemark = require './remarks/UserRemark'
|
|||
{isID} = require '../lib/utils'
|
||||
hipchat = require '../hipchat'
|
||||
sendwithus = require '../sendwithus'
|
||||
Prepaid = require '../prepaids/Prepaid'
|
||||
|
||||
serverProperties = ['passwordHash', 'emailLower', 'nameLower', 'passwordReset', 'lastIP']
|
||||
candidateProperties = [
|
||||
|
@ -305,6 +306,7 @@ UserHandler = class UserHandler extends Handler
|
|||
return @avatar(req, res, args[0]) if args[1] is 'avatar'
|
||||
return @getByIDs(req, res) if args[1] is 'users'
|
||||
return @getNamesByIDs(req, res) if args[1] is 'names'
|
||||
return @getPrepaidCodes(req, res) if args[1] is 'prepaid_codes'
|
||||
return @nameToID(req, res, args[0]) if args[1] is 'nameToID'
|
||||
return @getLevelSessionsForEmployer(req, res, args[0]) if args[1] is 'level.sessions' and args[2] is 'employer'
|
||||
return @getLevelSessions(req, res, args[0]) if args[1] is 'level.sessions'
|
||||
|
@ -453,6 +455,11 @@ UserHandler = class UserHandler extends Handler
|
|||
|
||||
sendMail emailParams
|
||||
|
||||
getPrepaidCodes: (req, res) ->
|
||||
orQuery = [{ creator: req.user._id }, { 'redeemers.userID' : req.user._id }]
|
||||
Prepaid.find({}).or(orQuery).exec (err, documents) =>
|
||||
@sendSuccess(res, documents)
|
||||
|
||||
agreeToCLA: (req, res) ->
|
||||
return @sendForbiddenError(res) unless req.user
|
||||
doc =
|
||||
|
|
|
@ -120,11 +120,33 @@ wrapUpGetUser = (email, user, done) ->
|
|||
GLOBAL.getURL = (path) ->
|
||||
return 'http://localhost:3001' + path
|
||||
|
||||
GLOBAL.createPrepaid = (type, maxRedeemers, done) ->
|
||||
GLOBAL.createPrepaid = (type, maxRedeemers, months, done) ->
|
||||
options = uri: GLOBAL.getURL('/db/prepaid/-/create')
|
||||
options.json =
|
||||
type: type
|
||||
maxRedeemers: maxRedeemers
|
||||
if months
|
||||
options.json.months = months
|
||||
request.post options, done
|
||||
|
||||
GLOBAL.fetchPrepaid = (ppc, done) ->
|
||||
options = uri: GLOBAL.getURL('/db/prepaid/-/code/'+ppc)
|
||||
request.get options, done
|
||||
|
||||
GLOBAL.purchasePrepaid = (type, maxRedeemers, months, done) ->
|
||||
options = uri: GLOBAL.getURL('/db/prepaid/-/purchase')
|
||||
options.json =
|
||||
type: type
|
||||
maxRedeemers: maxRedeemers
|
||||
months: months
|
||||
stripe:
|
||||
timestamp: new Date().getTime()
|
||||
request.post options, done
|
||||
|
||||
GLOBAL.subscribeWithPrepaid = (ppc, done) =>
|
||||
options = url: GLOBAL.getURL('/db/subscription/-/subscribe_prepaid')
|
||||
options.json =
|
||||
ppc: ppc
|
||||
request.post options, done
|
||||
|
||||
newUserCount = 0
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
require '../common'
|
||||
config = require '../../../server_config'
|
||||
moment = require 'moment'
|
||||
{findStripeSubscription} = require '../../../server/lib/utils'
|
||||
|
||||
describe '/db/prepaid', ->
|
||||
prepaidURL = getURL('/db/prepaid')
|
||||
prepaidCreateURL = getURL('/db/prepaid/-/create')
|
||||
|
||||
headers = {'X-Change-Plan': 'true'}
|
||||
|
||||
joeData = null
|
||||
stripe = require('stripe')(config.stripe.secretKey)
|
||||
joeCode = null
|
||||
|
||||
verifyPrepaid = (user, prepaid, done) ->
|
||||
expect(prepaid.creator).toEqual(user.id)
|
||||
expect(prepaid.type).toEqual('subscription')
|
||||
|
@ -13,12 +22,12 @@ describe '/db/prepaid', ->
|
|||
done()
|
||||
|
||||
it 'Clear database users and prepaids', (done) ->
|
||||
clearModels [User, Prepaid], (err) ->
|
||||
clearModels [User, Prepaid, Payment], (err) ->
|
||||
throw err if err
|
||||
done()
|
||||
|
||||
it 'Anonymous creates prepaid code', (done) ->
|
||||
createPrepaid 'subscription', 1, (err, res, body) ->
|
||||
createPrepaid 'subscription', 1, 0, (err, res, body) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(401)
|
||||
done()
|
||||
|
@ -26,7 +35,7 @@ describe '/db/prepaid', ->
|
|||
it 'Non-admin creates prepaid code', (done) ->
|
||||
loginNewUser (user1) ->
|
||||
expect(user1.isAdmin()).toEqual(false)
|
||||
createPrepaid 'subscription', 4, (err, res, body) ->
|
||||
createPrepaid 'subscription', 4, 0, (err, res, body) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
|
@ -37,18 +46,35 @@ describe '/db/prepaid', ->
|
|||
user1.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user1.isAdmin()).toEqual(true)
|
||||
createPrepaid 'subscription', 1, (err, res, body) ->
|
||||
createPrepaid 'subscription', 1, 0, (err, res, body) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(200)
|
||||
verifyPrepaid user1, body, done
|
||||
|
||||
it 'Admin creates prepaid code with type terminal_subscription', (done) ->
|
||||
loginNewUser (user1) ->
|
||||
user1.set('permissions', ['admin'])
|
||||
user1.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user1.isAdmin()).toEqual(true)
|
||||
createPrepaid 'terminal_subscription', 2, 3, (err, res, body) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.creator).toEqual(user1.id)
|
||||
expect(body.type).toEqual('terminal_subscription')
|
||||
expect(body.maxRedeemers).toEqual(2)
|
||||
expect(body.properties?.months).toEqual(3)
|
||||
expect(body.code).toMatch(/^\w{8}$/)
|
||||
done()
|
||||
|
||||
|
||||
it 'Admin creates prepaid code with invalid type', (done) ->
|
||||
loginNewUser (user1) ->
|
||||
user1.set('permissions', ['admin'])
|
||||
user1.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user1.isAdmin()).toEqual(true)
|
||||
createPrepaid 'bulldozer', 1, (err, res, body) ->
|
||||
createPrepaid 'bulldozer', 1, 0, (err, res, body) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
|
@ -59,7 +85,7 @@ describe '/db/prepaid', ->
|
|||
user1.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user1.isAdmin()).toEqual(true)
|
||||
createPrepaid null, 1, (err, res, body) ->
|
||||
createPrepaid null, 1, 0, (err, res, body) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
|
@ -70,7 +96,7 @@ describe '/db/prepaid', ->
|
|||
user1.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user1.isAdmin()).toEqual(true)
|
||||
createPrepaid 'subscription', 0, (err, res, body) ->
|
||||
createPrepaid 'subscription', 0, 0, (err, res, body) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
|
@ -89,7 +115,7 @@ describe '/db/prepaid', ->
|
|||
user1.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user1.isAdmin()).toEqual(true)
|
||||
createPrepaid 'subscription', 1, (err, res, prepaid) ->
|
||||
createPrepaid 'subscription', 1, 0, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(200)
|
||||
request.get {uri: prepaidURL}, (err, res, body) ->
|
||||
|
@ -104,3 +130,231 @@ describe '/db/prepaid', ->
|
|||
break
|
||||
expect(found).toEqual(true)
|
||||
done() unless found
|
||||
|
||||
# *** Purchase Prepaid Codes *** #
|
||||
it 'Anonymous submits a prepaid purchase', (done) ->
|
||||
logoutUser () ->
|
||||
purchasePrepaid 'terminal_subscription', 3, 3, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(401)
|
||||
done()
|
||||
|
||||
it 'Should error if type isnt terminal_subscription', (done) ->
|
||||
loginNewUser (user1) ->
|
||||
purchasePrepaid 'subscription', 3, 3, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
|
||||
it 'Should error if maxRedeemers is invalid', (done) ->
|
||||
loginNewUser (user1) ->
|
||||
purchasePrepaid 'terminal_subscription', -1, 3, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
purchasePrepaid 'terminal_subscription', 'foo', 3, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
|
||||
it 'Should error if months is invalid', (done) ->
|
||||
loginNewUser (user1) ->
|
||||
purchasePrepaid 'terminal_subscription', 3, -1, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
purchasePrepaid 'terminal_subscription', 3, 'foo', (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
|
||||
it 'Should error if maxRedeemers and months are less than 3', (done) ->
|
||||
loginNewUser (user1) ->
|
||||
purchasePrepaid 'terminal_subscription', 1, 1, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
|
||||
it 'User submits valid prepaid code purchase', (done) ->
|
||||
stripe.tokens.create {
|
||||
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
|
||||
}, (err, token) ->
|
||||
stripeTokenID = token.id
|
||||
loginJoe (joe) ->
|
||||
joeData = joe.toObject()
|
||||
joeData.stripe = {
|
||||
token: stripeTokenID
|
||||
planID: 'basic'
|
||||
}
|
||||
request.put {uri: getURL('/db/user'), json: joeData, headers: headers }, (err, res, body) ->
|
||||
joeData = body
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(joeData.stripe.customerID).toBeDefined()
|
||||
expect(firstSubscriptionID = joeData.stripe.subscriptionID).toBeDefined()
|
||||
expect(joeData.stripe.planID).toBe('basic')
|
||||
expect(joeData.stripe.token).toBeUndefined()
|
||||
purchasePrepaid 'terminal_subscription', 3, 3, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(prepaid.type).toEqual('terminal_subscription')
|
||||
expect(prepaid.code).toBeDefined()
|
||||
# Saving this code for later tests
|
||||
joeCode = prepaid.code
|
||||
expect(prepaid.creator).toBeDefined()
|
||||
expect(prepaid.maxRedeemers).toEqual(3)
|
||||
expect(prepaid.properties).toBeDefined()
|
||||
expect(prepaid.properties.months).toEqual(3)
|
||||
done()
|
||||
|
||||
it 'Should have logged a Payment with the correct amount', (done) ->
|
||||
loginJoe (joe) ->
|
||||
query =
|
||||
purchaser: joe._id
|
||||
Payment.find query, (err, payments) ->
|
||||
expect(err).toBeNull()
|
||||
expect(payments).not.toBeNull()
|
||||
expect(payments.length).toEqual(1)
|
||||
expect(payments[0].get('amount')).toEqual(8991)
|
||||
done()
|
||||
|
||||
|
||||
it 'Anonymous cant redeem a prepaid code', (done) ->
|
||||
logoutUser () ->
|
||||
subscribeWithPrepaid joeCode, (err, res) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res?.statusCode).toEqual(401)
|
||||
done()
|
||||
|
||||
|
||||
it 'User cant redeem a nonexistant prepaid code', (done) ->
|
||||
loginJoe (joe) ->
|
||||
subscribeWithPrepaid 'abc123', (err, res) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toEqual(403)
|
||||
done()
|
||||
|
||||
it 'User cant redeem empty code', (done) ->
|
||||
loginJoe (joe) ->
|
||||
subscribeWithPrepaid '', (err, res) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toEqual(422)
|
||||
done()
|
||||
|
||||
it 'Anonymous cant fetch a prepaid code', (done) ->
|
||||
expect(joeCode).not.toBeNull()
|
||||
logoutUser () ->
|
||||
fetchPrepaid joeCode, (err, res) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toEqual(403)
|
||||
done()
|
||||
|
||||
it 'User can fetch a prepaid code', (done) ->
|
||||
expect(joeCode).not.toBeNull()
|
||||
loginJoe (joe) ->
|
||||
fetchPrepaid joeCode, (err, res, body) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toEqual(200)
|
||||
|
||||
expect(body).toBeDefined()
|
||||
return done() unless body
|
||||
|
||||
prepaid = JSON.parse(body)
|
||||
expect(prepaid.code).toEqual(joeCode)
|
||||
expect(prepaid.maxRedeemers).toEqual(3)
|
||||
expect(prepaid.properties?.months).toEqual(3)
|
||||
done()
|
||||
|
||||
it 'Creator can redeeem a prepaid code', (done) ->
|
||||
loginJoe (joe) ->
|
||||
expect(joeCode).not.toBeNull()
|
||||
expect(joeData.stripe?.customerID).toBeDefined()
|
||||
expect(joeData.stripe?.subscriptionID).toBeDefined()
|
||||
return done() unless joeData.stripe?.customerID
|
||||
|
||||
# joe has a stripe subscription, so test if the months are added to the end of it.
|
||||
stripe.customers.retrieve joeData.stripe.customerID, (err, customer) =>
|
||||
expect(err).toBeNull()
|
||||
|
||||
findStripeSubscription customer.id, subscriptionID: joeData.stripe?.subscriptionID, (subscription) =>
|
||||
if subscription
|
||||
stripeSubscriptionPeriodEndDate = new moment(subscription.current_period_end * 1000)
|
||||
else
|
||||
expect(stripeSubscriptionPeriodEndDate).toBeDefined()
|
||||
return done()
|
||||
|
||||
subscribeWithPrepaid joeCode, (err, res, result) =>
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toEqual(200)
|
||||
endDate = stripeSubscriptionPeriodEndDate.add(3, 'months').toISOString().substring(0, 10)
|
||||
expect(result?.stripe?.free).toEqual(endDate)
|
||||
expect(result?.purchased?.gems).toEqual(14000)
|
||||
findStripeSubscription customer.id, subscriptionID: joeData.stripe?.subscriptionID, (subscription) =>
|
||||
expect(subscription).toBeNull()
|
||||
done()
|
||||
|
||||
it 'User can redeem a prepaid code', (done) ->
|
||||
loginSam (sam) ->
|
||||
subscribeWithPrepaid joeCode, (err, res, result) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toEqual(200)
|
||||
endDate = new moment().add(3, 'months').toISOString().substring(0, 10)
|
||||
expect(result?.stripe?.free).toEqual(endDate)
|
||||
expect(result?.purchased?.gems).toEqual(10500)
|
||||
done()
|
||||
|
||||
it 'Wont allow the same person to redeem twice', (done) ->
|
||||
loginSam (sam) ->
|
||||
subscribeWithPrepaid joeCode, (err, res, result) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toEqual(403)
|
||||
done()
|
||||
|
||||
it 'Will return redeemed code as part of codes list', (done) ->
|
||||
loginSam (sam) ->
|
||||
request.get "#{getURL('/db/user')}/#{sam.id}/prepaid_codes", (err, res) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toEqual(200)
|
||||
codes = JSON.parse res.body
|
||||
expect(codes.length).toEqual(1)
|
||||
done()
|
||||
|
||||
it 'Third user can redeem a prepaid code', (done) ->
|
||||
loginNewUser (user) ->
|
||||
subscribeWithPrepaid joeCode, (err, res, result) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toEqual(200)
|
||||
endDate = new moment().add(3, 'months').toISOString().substring(0, 10)
|
||||
expect(result?.stripe?.free).toEqual(endDate)
|
||||
expect(result?.purchased?.gems).toEqual(10500)
|
||||
done()
|
||||
|
||||
it 'Fourth user cannot redeem code', (done) ->
|
||||
loginNewUser (user) ->
|
||||
subscribeWithPrepaid joeCode, (err, res, result) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toEqual(403)
|
||||
done()
|
||||
|
||||
|
||||
it 'Can fetch a list of purchased and redeemed prepaid codes', (done) ->
|
||||
loginJoe (joe) ->
|
||||
purchasePrepaid 'terminal_subscription', 3, 1, (err, res, prepaid) ->
|
||||
request.get "#{getURL('/db/user')}/#{joe.id}/prepaid_codes", (err, res) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toEqual(200);
|
||||
codes = JSON.parse res.body
|
||||
expect(codes.length).toEqual(2)
|
||||
expect(codes[0].maxRedeemers).toEqual(3)
|
||||
expect(codes[0].properties).toBeDefined()
|
||||
expect(codes[0].properties.months).toEqual(3)
|
||||
done()
|
||||
|
||||
it 'Test for injection', (done) ->
|
||||
loginNewUser (user) ->
|
||||
code = { $exists: true }
|
||||
subscribeWithPrepaid code, (err, res, result) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).not.toEqual(200)
|
||||
done()
|
||||
# TODO: add a bunch of parallel tests trying to redeem a code with a high maxRedeemers (50?) to see what happens
|
||||
|
||||
|
|
|
@ -297,6 +297,8 @@ describe 'Subscriptions', ->
|
|||
return done() unless sponsorCustomerID and sponsorStripe.sponsorSubscriptionID
|
||||
stripe.customers.retrieveSubscription sponsorCustomerID, sponsorStripe.sponsorSubscriptionID, (err, subscription) ->
|
||||
expect(err).toBeNull()
|
||||
expect(subscription?).toBe(true)
|
||||
return done() unless subscription?
|
||||
expect(subscription.plan.amount).toEqual(1)
|
||||
expect(subscription.customer).toEqual(sponsorCustomerID)
|
||||
expect(subscription.quantity).toEqual(utils.getSponsoredSubsAmount(subPrice, numSponsored, sponsorStripe.subscriptionID?))
|
||||
|
@ -361,6 +363,7 @@ describe 'Subscriptions', ->
|
|||
Payment.findOne paymentQuery, (err, payment) ->
|
||||
expect(err).toBeNull()
|
||||
expect(payment).not.toBeNull()
|
||||
return done() if payment is null
|
||||
expect(payment.get('amount')).toEqual(0)
|
||||
expect(payment.get('gems')).toBeGreaterThan(subGems - 1)
|
||||
done()
|
||||
|
@ -406,6 +409,8 @@ describe 'Subscriptions', ->
|
|||
expect(user.get('stripe').customerID).toBeDefined()
|
||||
expect(user.get('stripe').planID).toBeUndefined()
|
||||
expect(user.get('stripe').token).toBeUndefined()
|
||||
expect(user.get('stripe').subscriptionID).toBeDefined()
|
||||
return done() unless user.get('stripe').subscriptionID
|
||||
stripe.customers.retrieveSubscription user.get('stripe').customerID, user.get('stripe').subscriptionID, (err, subscription) ->
|
||||
expect(err).toBeNull()
|
||||
expect(subscription).not.toBeNull()
|
||||
|
@ -422,11 +427,11 @@ describe 'Subscriptions', ->
|
|||
expect(err).toBeNull()
|
||||
return done() if err
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.stripe.customerID).toBeDefined()
|
||||
expect(body.stripe?.customerID).toBeDefined()
|
||||
updatedUser = body
|
||||
|
||||
# Call webhooks for invoices
|
||||
options = customer: body.stripe.customerID, limit: 100
|
||||
options = customer: body.stripe?.customerID, limit: 100
|
||||
stripe.invoices.list options, (err, invoices) ->
|
||||
expect(err).toBeNull()
|
||||
expect(invoices).not.toBeNull()
|
||||
|
@ -569,7 +574,7 @@ describe 'Subscriptions', ->
|
|||
user1.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user1.isAdmin()).toEqual(true)
|
||||
createPrepaid 'subscription', 1, (err, res, prepaid) ->
|
||||
createPrepaid 'subscription', 1, 0, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
subscribeUser user1, null, prepaid.code, ->
|
||||
Prepaid.findById prepaid._id, (err, prepaid) ->
|
||||
|
@ -584,6 +589,8 @@ describe 'Subscriptions', ->
|
|||
expect(err).toBeNull()
|
||||
stripeInfo = user1.get('stripe')
|
||||
expect(stripeInfo.prepaidCode).toEqual(prepaid.get('code'))
|
||||
expect(stripeInfo.subscriptionID).toBeDefined()
|
||||
return done() unless stripeInfo.subscriptionID
|
||||
|
||||
# Delete subscription
|
||||
stripe.customers.retrieveSubscription stripeInfo.customerID, stripeInfo.subscriptionID, (err, subscription) ->
|
||||
|
@ -612,7 +619,7 @@ describe 'Subscriptions', ->
|
|||
subscribeUser user1, token, null, ->
|
||||
User.findById user1.id, (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
createPrepaid 'subscription', 1, (err, res, prepaid) ->
|
||||
createPrepaid 'subscription', 1, 0, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
subscribeUser user1, null, prepaid.code, ->
|
||||
Prepaid.findById prepaid._id, (err, prepaid) ->
|
||||
|
@ -627,6 +634,7 @@ describe 'Subscriptions', ->
|
|||
stripe.customers.retrieveSubscription customerID, subscriptionID, (err, subscription) ->
|
||||
expect(err).toBeNull()
|
||||
expect(subscription).not.toBeNull()
|
||||
return done() unless subscription
|
||||
expect(subscription.discount?.coupon?.id).toEqual('free')
|
||||
done()
|
||||
|
||||
|
@ -646,7 +654,7 @@ describe 'Subscriptions', ->
|
|||
request.put {uri: userURL, json: requestBody, headers: headers }, (err, res, updatedUser) ->
|
||||
expect(err).toBeNull()
|
||||
expect(res.statusCode).toBe(200)
|
||||
createPrepaid 'subscription', 1, (err, res, prepaid) ->
|
||||
createPrepaid 'subscription', 1, 0, (err, res, prepaid) ->
|
||||
subscribeUser user1, null, prepaid.code, ->
|
||||
Prepaid.findById prepaid._id, (err, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
|
@ -660,7 +668,7 @@ describe 'Subscriptions', ->
|
|||
stripe.customers.retrieveSubscription customerID, subscriptionID, (err, subscription) ->
|
||||
expect(err).toBeNull()
|
||||
expect(subscription).not.toBeNull()
|
||||
expect(subscription.discount?.coupon?.id).toEqual('free')
|
||||
expect(subscription?.discount?.coupon?.id).toEqual('free')
|
||||
done()
|
||||
|
||||
it 'Subscribe with prepaid, then cancel', (done) ->
|
||||
|
@ -669,7 +677,7 @@ describe 'Subscriptions', ->
|
|||
user1.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user1.isAdmin()).toEqual(true)
|
||||
createPrepaid 'subscription', 1, (err, res, prepaid) ->
|
||||
createPrepaid 'subscription', 1, 0, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
subscribeUser user1, null, prepaid.code, ->
|
||||
Prepaid.findById prepaid._id, (err, prepaid) ->
|
||||
|
@ -691,7 +699,7 @@ describe 'Subscriptions', ->
|
|||
user1.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user1.isAdmin()).toEqual(true)
|
||||
createPrepaid 'subscription', 1, (err, res, prepaid) ->
|
||||
createPrepaid 'subscription', 1, 0, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
subscribeUser user1, null, prepaid.code, ->
|
||||
loginNewUser (user2) ->
|
||||
|
@ -714,7 +722,7 @@ describe 'Subscriptions', ->
|
|||
user1.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user1.isAdmin()).toEqual(true)
|
||||
createPrepaid 'subscription', 2, (err, res, prepaid) ->
|
||||
createPrepaid 'subscription', 2, 0, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
subscribeUser user1, null, prepaid.code, ->
|
||||
loginNewUser (user2) ->
|
||||
|
@ -730,7 +738,7 @@ describe 'Subscriptions', ->
|
|||
user1.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user1.isAdmin()).toEqual(true)
|
||||
createPrepaid 'subscription', 1, (err, res, prepaid) ->
|
||||
createPrepaid 'subscription', 1, 0, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
subscribeUser user1, null, prepaid.code, ->
|
||||
Prepaid.findById prepaid._id, (err, prepaid) ->
|
||||
|
@ -746,7 +754,7 @@ describe 'Subscriptions', ->
|
|||
user1.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user1.isAdmin()).toEqual(true)
|
||||
createPrepaid 'subscription', 2, (err, res, prepaid) ->
|
||||
createPrepaid 'subscription', 2, 0, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
Prepaid.findById prepaid._id, (err, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
|
@ -795,8 +803,13 @@ describe 'Subscriptions', ->
|
|||
createNewUser (user2) ->
|
||||
loginNewUser (user1) ->
|
||||
subscribeRecipients user1, [user2], token, (updatedUser) ->
|
||||
customerID = updatedUser.stripe.customerID
|
||||
subscriptionID = updatedUser.stripe.recipients[0].subscriptionID
|
||||
expect(updatedUser).not.toBeNull()
|
||||
return done() unless updatedUser
|
||||
customerID = updatedUser.stripe?.customerID
|
||||
expect(customerID).toBeDefined()
|
||||
subscriptionID = updatedUser.stripe?.recipients[0]?.subscriptionID
|
||||
expect(subscriptionID).toBeDefined()
|
||||
return done() unless customerID and subscriptionID
|
||||
loginUser user2, (user2) ->
|
||||
request.del {uri: "#{userURL}/#{user2.id}"}, (err, res) ->
|
||||
expect(err).toBeNull()
|
||||
|
@ -987,7 +1000,7 @@ describe 'Subscriptions', ->
|
|||
user2.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user2.isAdmin()).toEqual(true)
|
||||
createPrepaid 'subscription', 1, (err, res, prepaid) ->
|
||||
createPrepaid 'subscription', 1, 0, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
requestBody = user2.toObject()
|
||||
requestBody.stripe =
|
||||
|
@ -1022,8 +1035,11 @@ describe 'Subscriptions', ->
|
|||
createNewUser (user2) ->
|
||||
loginNewUser (user1) ->
|
||||
subscribeRecipients user1, [user2, user3], token, (updatedUser) ->
|
||||
customerID = updatedUser.stripe.customerID
|
||||
subscriptionID = updatedUser.stripe.sponsorSubscriptionID
|
||||
customerID = updatedUser?.stripe?.customerID
|
||||
subscriptionID = updatedUser?.stripe?.sponsorSubscriptionID
|
||||
expect(customerID).toBeDefined()
|
||||
expect(subscriptionID).toBeDefined()
|
||||
return done() unless customerID and subscriptionID
|
||||
|
||||
# Find Stripe sponsor subscription
|
||||
stripe.customers.retrieveSubscription customerID, subscriptionID, (err, subscription) ->
|
||||
|
@ -1041,6 +1057,7 @@ describe 'Subscriptions', ->
|
|||
expect(err).toBeNull()
|
||||
|
||||
# Should have 2 cancelled recipient subs with cancel_at_period_end = true
|
||||
# TODO: is this correct, or do we terminate recipient subs immediately now?
|
||||
User.findById user1.id, (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
stripeInfo = user1.get('stripe')
|
||||
|
@ -1159,7 +1176,7 @@ describe 'Subscriptions', ->
|
|||
user1.save (err, user1) ->
|
||||
expect(err).toBeNull()
|
||||
expect(user1.isAdmin()).toEqual(true)
|
||||
createPrepaid 'subscription', 1, (err, res, prepaid) ->
|
||||
createPrepaid 'subscription', 1, 0, (err, res, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
subscribeUser user1, null, prepaid.code, ->
|
||||
stripe.tokens.create {
|
||||
|
@ -1233,7 +1250,7 @@ describe 'Subscriptions', ->
|
|||
stripe.customers.retrieveSubscription stripeInfo.customerID, stripeInfo.sponsorSubscriptionID, (err, subscription) ->
|
||||
expect(err).toBeNull()
|
||||
expect(subscription).not.toBeNull()
|
||||
expect(subscription.quantity).toEqual(getSubscribedQuantity(1))
|
||||
expect(subscription?.quantity).toEqual(getSubscribedQuantity(1))
|
||||
|
||||
# Unsubscribe recipient1
|
||||
unsubscribeRecipient user1, recipients.get(1), ->
|
||||
|
@ -1245,6 +1262,7 @@ describe 'Subscriptions', ->
|
|||
stripe.customers.retrieveSubscription stripeInfo.customerID, stripeInfo.sponsorSubscriptionID, (err, subscription) ->
|
||||
expect(err).toBeNull()
|
||||
expect(subscription).not.toBeNull()
|
||||
return done() unless subscription
|
||||
expect(subscription.quantity).toEqual(0)
|
||||
done()
|
||||
|
||||
|
@ -1274,13 +1292,16 @@ describe 'Subscriptions', ->
|
|||
unsubscribeRecipient user1, recipients.get(0), ->
|
||||
User.findById user1.id, (err, user1) ->
|
||||
stripeInfo = user1.get('stripe')
|
||||
expect(stripeInfo.customerID).toBeDefined()
|
||||
expect(stripeInfo.sponsorSubscriptionID).toBeDefined()
|
||||
return done() unless stripeInfo.customerID and stripeInfo.sponsorSubscriptionID
|
||||
expect(stripeInfo.recipients.length).toEqual(recipientCount - 1)
|
||||
verifyNotSponsoring user1.id, recipients.get(0).id, ->
|
||||
verifyNotRecipient recipients.get(0).id, ->
|
||||
stripe.customers.retrieveSubscription stripeInfo.customerID, stripeInfo.sponsorSubscriptionID, (err, subscription) ->
|
||||
expect(err).toBeNull()
|
||||
expect(subscription).not.toBeNull()
|
||||
expect(subscription.quantity).toEqual(getSubscribedQuantity(recipientCount - 1))
|
||||
expect(subscription?.quantity).toEqual(getSubscribedQuantity(recipientCount - 1))
|
||||
|
||||
# Unsubscribe second recipient
|
||||
unsubscribeRecipient user1, recipients.get(1), ->
|
||||
|
@ -1292,7 +1313,7 @@ describe 'Subscriptions', ->
|
|||
stripe.customers.retrieveSubscription stripeInfo.customerID, stripeInfo.sponsorSubscriptionID, (err, subscription) ->
|
||||
expect(err).toBeNull()
|
||||
expect(subscription).not.toBeNull()
|
||||
expect(subscription.quantity).toEqual(getSubscribedQuantity(recipientCount - 2))
|
||||
expect(subscription?.quantity).toEqual(getSubscribedQuantity(recipientCount - 2))
|
||||
|
||||
# Unsubscribe self
|
||||
User.findById user1.id, (err, user1) ->
|
||||
|
@ -1312,7 +1333,7 @@ describe 'Subscriptions', ->
|
|||
stripe.customers.retrieveSubscription stripeInfo.customerID, stripeInfo.sponsorSubscriptionID, (err, subscription) ->
|
||||
expect(err).toBeNull()
|
||||
expect(subscription).not.toBeNull()
|
||||
expect(subscription.quantity).toEqual(getSubscribedQuantity(recipientCount - 3))
|
||||
expect(subscription?.quantity).toEqual(getSubscribedQuantity(recipientCount - 3))
|
||||
done()
|
||||
|
||||
xit 'Unsubscribed user1 subscribes 13 users, unsubcribes 2', (done) ->
|
||||
|
|
Loading…
Reference in a new issue