Add prepaids to payments

Closes #3402
This commit is contained in:
Matt Lott 2016-02-17 05:34:12 -08:00
parent 37fbd8ca21
commit cb29d7068b
6 changed files with 50 additions and 43 deletions

View file

@ -10,6 +10,7 @@ PaymentSchema = c.object({title: 'Payment', required: []}, {
gems: { type: 'integer', description: 'The number of gems acquired.' }
productID: { enum: ['gems_5', 'gems_10', 'gems_20', 'custom']}
description: { type: 'string' }
prepaidID: c.objectId()
ios: c.object({title: 'iOS IAP Data'}, {
transactionID: { type: 'string' }

View file

@ -37,7 +37,7 @@ module.exports = class PrepaidView extends RootView
@codes = new CocoCollection([], { url: '/db/user/'+me.id+'/prepaid_codes', model: Prepaid })
@codes.on 'sync', (code) => @render?()
@supermodel.loadCollection(@codes, 'prepaid', {cache: false})
@supermodel.loadCollection(@codes, {cache: false})
@ppc = utils.getQueryVariable('_ppc') ? ''
unless _.isEmpty(@ppc)
@ -45,7 +45,7 @@ module.exports = class PrepaidView extends RootView
@loadPrepaid(@ppc)
@products = new Products()
@supermodel.loadCollection(@products, 'products')
@supermodel.loadCollection(@products)
onLoaded: ->
@prepaidProduct = @products.findWhere { name: 'prepaid_subscription' }
@ -190,7 +190,7 @@ module.exports = class PrepaidView extends RootView
@renderSelectors('#codes-panel')
@statusMessage "Finalizing purchase...", "information"
@supermodel.addRequestResource('purchase_prepaid', options, 0).load()
@supermodel.addRequestResource(options, 0).load()
loadPrepaid: (ppc) ->
return unless ppc

View file

@ -21,7 +21,7 @@ module.exports =
return done(err)
done(err, charge)
createPayment: (user, stripeCharge, done) ->
createPayment: (user, stripeCharge, extraProps, done) ->
payment = new Payment
purchaser: user._id
recipient: user._id
@ -34,6 +34,7 @@ module.exports =
customerID: stripeCharge.customer
timestamp: parseInt(stripeCharge.metadata.timestamp)
chargeID: stripeCharge.id
payment.set(prop, val) for prop, val of extraProps
validation = PaymentHandler.validateDocumentInput(payment.toObject())
if validation.valid is false
@logError(user, 'Invalid stripe payment object.')

View file

@ -156,7 +156,7 @@ class SubscriptionHandler extends Handler
@logSubscriptionError(req.user, "Purchase year sale create charge: #{JSON.stringify(err)}")
return @sendDatabaseError(res, err)
StripeUtils.createPayment req.user, charge, (err, payment) =>
StripeUtils.createPayment req.user, charge, {}, (err, payment) =>
if err
@logSubscriptionError(req.user, "Purchase year sale create payment: #{JSON.stringify(err)}")
return @sendDatabaseError(res, err)
@ -200,7 +200,7 @@ class SubscriptionHandler extends Handler
@logSubscriptionError(req.user, "Redeem Prepaid Code find: #{JSON.stringify(err)}")
return @sendDatabaseError(res, err)
unless prepaid
@logSubscriptionError(req.user, "Could not find prepaid code #{req.body.ppc}")
@logSubscriptionError(req.user, "Could not find prepaid code #{req.body.ppc?.toString()}")
return @sendNotFoundError(res, "Prepaid not found")
oldRedeemers = prepaid.get('redeemers') ? []

View file

@ -202,13 +202,18 @@ PrepaidHandler = class PrepaidHandler extends Handler
@logError(user, "createCharge error: #{JSON.stringify(err)}")
return done(err)
StripeUtils.createPayment user, charge, (err, payment) =>
@createPrepaid user, type, maxRedeemers, {}, (err, prepaid) =>
if err
@logError(user, "createPayment error: #{JSON.stringify(err)}")
@logError(user, "createPrepaid error: #{JSON.stringify(err)}")
return done(err)
msg = "Prepaid code purchased: #{type} seats=#{maxRedeemers} #{user.get('email')}"
hipchat.sendHipChatMessage msg, ['tower']
@createPrepaid(user, type, maxRedeemers, {}, done)
StripeUtils.createPayment user, charge, {prepaidID: prepaid._id}, (err, payment) =>
if err
@logError(user, "createPayment error: #{JSON.stringify(err)}")
return done(err)
msg = "Prepaid code purchased: #{type} seats=#{maxRedeemers} #{user.get('email')}"
hipchat.sendHipChatMessage msg, ['tower']
done(null, prepaid)
purchasePrepaidTerminalSubscription: (user, description, maxRedeemers, months, timestamp, token, product, done) ->
type = 'terminal_subscription'
@ -234,27 +239,18 @@ PrepaidHandler = class PrepaidHandler extends Handler
@logError(user, "createCharge error: #{JSON.stringify(err)}")
return done(err)
StripeUtils.createPayment user, charge, (err, payment) =>
@createPrepaid user, type, maxRedeemers, {months: months}, (err, prepaid) =>
if err
@logError(user, "createPayment error: #{JSON.stringify(err)}")
@logError(user, "createPrepaid error: #{JSON.stringify(err)}")
return done(err)
Prepaid.generateNewCode (code) =>
return done('Database error.') unless code
prepaid = new Prepaid
creator: user._id
type: type
code: code
maxRedeemers: parseInt(maxRedeemers)
redeemers: []
properties:
months: months
prepaid.save (err) =>
return done(err) if err
msg = "Prepaid code purchased: #{type} users=#{maxRedeemers} months=#{months} #{user.get('email')}"
hipchat.sendHipChatMessage msg, ['tower']
return done(null, prepaid)
StripeUtils.createPayment user, charge, {prepaidID: prepaid._id}, (err, payment) =>
if err
@logError(user, "createPayment error: #{JSON.stringify(err)}")
return done(err)
msg = "Prepaid code purchased: #{type} users=#{maxRedeemers} months=#{months} #{user.get('email')}"
hipchat.sendHipChatMessage msg, ['tower']
done(null, prepaid)
get: (req, res) ->
if creator = req.query.creator

View file

@ -20,7 +20,12 @@ describe '/db/prepaid', ->
expect(prepaid.type).toEqual('course')
expect(prepaid.maxRedeemers).toBeGreaterThan(0)
expect(prepaid.code).toMatch(/^\w{8}$/)
done()
return done() if user.isAdmin()
Payment.findOne {prepaidID: new ObjectId(prepaid._id)}, (err, payment) ->
expect(err).toBeNull()
expect(payment).not.toBeNull()
expect(payment?.get('purchaser')).toEqual(user._id)
done()
verifySubscriptionPrepaid = (user, prepaid, done) ->
expect(prepaid.creator).toEqual(user.id)
@ -28,13 +33,18 @@ describe '/db/prepaid', ->
expect(prepaid.maxRedeemers).toBeGreaterThan(0)
expect(prepaid.code).toMatch(/^\w{8}$/)
expect(prepaid.properties?.couponID).toEqual('free')
done()
return done() if user.isAdmin()
Payment.findOne {prepaidID: new ObjectId(prepaid._id)}, (err, payment) ->
expect(err).toBeNull()
expect(payment).not.toBeNull()
expect(payment?.get('purchaser')).toEqual(user._id)
done()
it 'Clear database', (done) ->
clearModels [Course, CourseInstance, Payment, Prepaid, User], (err) ->
throw err if err
done()
describe 'POST /db/prepaid/<id>/redeemers', ->
it 'adds a given user to the redeemers property', (done) ->
@ -60,7 +70,7 @@ describe '/db/prepaid', ->
User.findById otherUser.id, (err, user) ->
expect(user.get('coursePrepaidID').equals(prepaid.get('_id'))).toBe(true)
done()
it 'does not allow more redeemers than maxRedeemers', (done) ->
loginNewUser (user1) ->
prepaid = new Prepaid({
@ -97,7 +107,7 @@ describe '/db/prepaid', ->
request.post {uri: url, json: redeemer }, (err, res, body) ->
expect(res.statusCode).toBe(403)
done()
it 'is idempotent across prepaids collection', (done) ->
loginNewUser (user1) ->
otherUser = new User({
@ -279,7 +289,7 @@ describe '/db/prepaid', ->
request.post {uri: url, json: redeemer }, (err, res, body) ->
expect(res.statusCode).toBe(403)
done()
it 'Clear database', (done) ->
clearModels [Course, CourseInstance, Payment, Prepaid, User], (err) ->
throw err if err
@ -392,7 +402,7 @@ describe '/db/prepaid', ->
describe 'Purchase course', ->
afterEach nockUtils.teardownNock
it 'Standard user purchases a prepaid for 0 seats', (done) ->
nockUtils.setupNock 'db-prepaid-purchase-course-test-1.json', (err, nockDone) ->
stripe.tokens.create {
@ -404,7 +414,7 @@ describe '/db/prepaid', ->
expect(res.statusCode).toBe(422)
nockDone()
done()
it 'Standard user purchases a prepaid for 1 seat', (done) ->
nockUtils.setupNock 'db-prepaid-purchase-course-test-2.json', (err, nockDone) ->
stripe.tokens.create {
@ -430,7 +440,7 @@ describe '/db/prepaid', ->
verifyCoursePrepaid user1, prepaid, ->
nockDone()
done()
describe 'Purchase terminal_subscription', ->
afterEach nockUtils.teardownNock
@ -624,7 +634,7 @@ describe '/db/prepaid', ->
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()
@ -635,7 +645,7 @@ describe '/db/prepaid', ->
else
expect(stripeSubscriptionPeriodEndDate).toBeDefined()
return done()
subscribeWithPrepaid joeCode, (err, res, result) =>
expect(err).toBeNull()
expect(res.statusCode).toEqual(200)
@ -690,7 +700,6 @@ describe '/db/prepaid', ->
expect(res.statusCode).toEqual(403)
done()
it 'Can fetch a list of purchased and redeemed prepaid codes', (done) ->
nockUtils.setupNock 'db-sub-redeem-test-2.json', (err, nockDone) ->
stripe.tokens.create {
@ -735,12 +744,12 @@ describe '/db/prepaid', ->
return fnDone(null, {status: "ok", msg: "Redeemed " + retry})
else
return fnDone(null, {status: 'error', msg: "Redeem attempt Error #{result} (#{userX.id})" + retry })
redeemPrepaidFn = (code, testnum) =>
(fnDone) =>
loginNewUser (user1) =>
doRedeem(user1, code, testnum, 0, fnDone)
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->