diff --git a/src/controllers/payments.js b/src/controllers/payments.js index 7956a7db8c..86b45bcbdf 100644 --- a/src/controllers/payments.js +++ b/src/controllers/payments.js @@ -44,7 +44,8 @@ function createSubscription(user, data) { customerId: data.customerId, dateUpdated: new Date, gemsBought: 0, - paymentMethod: data.paymentMethod + paymentMethod: data.paymentMethod, + dateTerminated: null }) .defaults({ // allow non-override if a plan was previously used dateCreated: new Date, @@ -56,9 +57,15 @@ function createSubscription(user, data) { ga.transaction(data.customerId, 5).item(5, 1, data.paymentMethod.toLowerCase() + '-subscription', data.paymentMethod + " > Stripe").send(); } +/** + * Sets their subscription to be cancelled later + */ function cancelSubscription(user, data){ - _.merge(user.purchased.plan, {planId:null, customerId:null, paymentMethod:null}); - user.markModified('purchased.plan'); + var du = user.purchased.plan.dateUpdated, now = moment(); + user.purchased.plan.dateTerminated = + moment( now.format('MM') + '/' + moment(du).format('DD') + '/' + now.format('YYYY') ) + .add('month',1) + .toDate(); ga.event('unsubscribe', 'Stripe').send(); } @@ -69,6 +76,12 @@ function buyGems(user, data) { ga.transaction(data.customerId, 5).item(5, 1, data.paymentMethod.toLowerCase() + "-checkout", "Gems > " + data.paymentMethod).send(); } +// Expose some functions for tests +if (nconf.get('NODE_ENV')==='testing') { + api.cancelSubscription = cancelSubscription; + api.createSubscription = createSubscription; +} + /* Setup Stripe response when posting payment */ diff --git a/src/models/user.js b/src/models/user.js index 3f5b02cc54..4e019af4aa 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -89,6 +89,7 @@ var UserSchema = new Schema({ paymentMethod: String, //enum: ['Paypal','Stripe', '']} customerId: String, dateCreated: Date, + dateTerminated: Date, dateUpdated: Date, gemsBought: {type: Number, 'default': 0}, mysteryItems: {type: Array, 'default': []} diff --git a/test/api.mocha.js b/test/api.mocha.js index 935e9f0ca1..fc98b60f8a 100644 --- a/test/api.mocha.js +++ b/test/api.mocha.js @@ -27,6 +27,7 @@ var Challenge = require('../src/models/challenge').model; var app = require('../src/server'); var shared = require('habitrpg-shared'); +var payments = require('../src/controllers/payments'); // ###### Helpers & Variables ###### var model, uuid, taskPath, @@ -118,6 +119,7 @@ describe('API', function () { }); }); + describe('Todos', function(){ it('Archives old todos',function(done){ request.post(baseURL + "/user/batch-update?_v=999") @@ -506,8 +508,7 @@ describe('API', function () { ],done); - // You see all these freaking })s? This is why I prefer coffeescript!! I keep hitting stupid errors - // where they're mis-matched and I'm counting )'s on my fingers for 10m just to fix them. Gaahhh.. + // See all these })s? This is why CoffeeScript is better. //}) }) }) @@ -517,5 +518,41 @@ describe('API', function () { }); }); + + describe('Subscriptions', function(){ + var user; + before(function(done){ + User.findOne({_id: _id}, function (err, _user) { + expect(err).to.not.be.ok(); + user = _user; + done(); + }); + }) + }) + + it('Handles unsubscription', function(done){ + var cron = function(){ + user.lastCron = moment().subtract('d',1); + user.fns.cron(); + } + expect(user.purchased.plan.customerId).to.not.be.ok(); + payments.createSubscription(user,{customerId:'123',paymentMethod:'Stripe'}); + expect(user.purchased.plan.customerId).to.be.ok(); + shared.wrap(user); + cron(); + expect(user.purchased.plan.customerId).to.be.ok(); + payments.cancelSubscription(user); + cron(); + expect(user.purchased.plan.customerId).to.be.ok(); + expect(user.purchased.plan.dateTerminated).to.be.ok(); + user.purchased.plan.dateTerminated = moment().subtract('d',2); + cron(); + expect(user.purchased.plan.customerId).to.not.be.ok(); + payments.createSubscription(user,{customerId:'123',paymentMethod:'Stripe'}); + expect(user.purchased.plan.dateTerminated).to.not.be.ok(); + done(); + }) + + }); }); diff --git a/views/options/settings.jade b/views/options/settings.jade index 832c08bb03..7e450ec533 100644 --- a/views/options/settings.jade +++ b/views/options/settings.jade @@ -193,16 +193,17 @@ script(id='partials/options.settings.subscription.html',type='text/ng-template') p small.muted Payment Methods: .btn.btn-primary(ng-click='showStripe(true)') Card - //-small.muted PayPal coming soon. - //a.btn.btn-warning(ng-click='paypalSubscribe()') PayPal + //a.btn.btn-warning(ng-click='paypalSubscribe()') PayPal a.btn.btn-warning(href='/paypal/subscribe?_id={{user._id}}&apiToken={{user.apiToken}}') PayPal div(ng-if='user.purchased.plan.customerId') - .well - p.lead - =env.t('subscribed') - |   - span.glyphicon.glyphicon-ok - div(ng-include="'partials/options.settings.subscription.perks.html'") - .btn.btn-sm.btn-danger(ng-click='cancelSubscription()')=env.t('cancelSub') - p - small.muted Unsubscribing removes subscriber perks (read more here). We're working on persisting subscriber perks through a canceled plan's billing cycle, but for now be sure to open your mystery box before unsubscribing! + p.alert.alert-warning(ng-if='user.purchased.plan.dateTerminated') + i.glyphicon.glyphicon-time + |   + =env.t('subCanceled') + | {{moment(user.purchased.plan.dateTerminated).format('MM/DD/YYYY')}} + p.lead + =env.t('subscribed') + |   + span.glyphicon.glyphicon-ok + div(ng-include="'partials/options.settings.subscription.perks.html'") + .btn.btn-sm.btn-danger(ng-if='!user.purchased.plan.dateTerminated', ng-click='cancelSubscription()')=env.t('cancelSub') \ No newline at end of file