diff options
Diffstat (limited to 'server/lib/api/subscription.js')
| -rw-r--r-- | server/lib/api/subscription.js | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js new file mode 100644 index 0000000..c1e2d33 --- /dev/null +++ b/server/lib/api/subscription.js @@ -0,0 +1,206 @@ +/* jshint node: true */ + +var _ = require('lodash'), + util = require('../util'), + upload = require('../upload'), + config = require('../../../config.json'), + User = require('../schemas/User'), + Project = require('../schemas/Project'), + Layout = require('../schemas/Layout'), + Plan = require('../schemas/Plan'); + Subscription = require('../schemas/Subscription'); +// Recurly = require('node-recurly'), +// recurly = new Recurly(require('../webhook/recurly-config')); + +var plan_levels = { + free: 0, + basic: 1, + pro: 2, + custom: 3, +} + +var subscription = module.exports = { + middleware: { + ensureSubscription: function(req, res, next){ + Subscription.findOne({ user_id: req.user._id }, function(err, data){ + if (err) { return next() } + req.subscription = data + next() + }) + }, + ensurePlans: function(req, res, next){ + Plan.find({}).sort({ 'level': 1 }).exec(function (err, plans) { + res.locals.plans = (plans || []) + next() + }) + }, + }, + + // synchronise an account with recurly.. + // useful when testing locally (where webhooks cannot be received) + // parses the XML from the subscription API into something usable + sync: function(req, res){ + var subscriber = req.subscription || new Subscription () + var user = req.user + recurly.subscriptions.listByAccount(req.user._id, function(recurlyRes){ + var data = recurlyRes.data + if (recurlyRes.description !== 200) { + res.json({ error: "no account" }) + return + } + var subscriptions = data.subscriptions.subscription.length ? data.subscriptions.subscription : [data.subscriptions.subscription] + var is_active = subscriptions.some(function(subscription_data){ + if (subscription_data.state == "active") { + set_active(subscription_data) + return true + } + return false + }) + if (! is_active) { + set_cancelled() + } + }) + function set_cancelled(){ + user.plan_type = "free" + user.plan_level = plan_levels["free"] + + return subscriber.remove(function(){ + user.save(function(){ + res.json({ error: "account cancelled" }) + }) + }) + } + function set_active(data){ + var plan = data.plan.plan_code.split("-") + var plan_type = plan[0] + var plan_period = plan[1] + + user.plan_type = plan_type + user.plan_level = plan_levels[plan_type] + + subscriber.uuid = data.uuid + subscriber.user_id = user._id + subscriber.plan_type = plan_type + subscriber.plan_period = plan_period + subscriber.plan_level = plan_levels[plan_type] + + var add_ons = data.subscription_add_ons.subscription_add_on + if (add_ons) { + if (add_ons.add_on_code) { + add_ons = [ add_ons ] + } + // TODO: handle multiple add-ons.. presumably this will work + add_ons.forEach(function(add_on){ + var add_on_type = add_on.add_on_code.split("-")[1] + if (add_on_type == "basic") { + subscriber.basic_layouts = parseInt( add_on.quantity._ ) + } + if (add_on_type == "pro") { + subscriber.pro_layouts = parseInt( add_on.quantity._ ) + } + }) + } + else { + subscriber.basic_layouts = 0 + subscriber.pro_layouts = 0 + } + subscriber.save(function(){ + user.save(function(){ + res.json({ + subscription: subscriber, + plans: res.locals.plans + }) + }) + }) + } + }, + + show: function(req, res){ + if (req.subscription) { + res.json({ + subscription: req.subscription, + plans: res.locals.plans + }) + } + else { + res.json({ + error: "no subscription", + plans: res.locals.plans, + }) + } + }, + + update: function(req, res){ + if (! req.subscription ) { + return res.json({ error: "no subscription" }) + } + if (! (req.body.plan_type in plan_levels)) { + return res.json({ error: "bad input" }) + } + var subscriber = req.subscription + var user = req.user + + var plan_type = req.body.plan_type + var basic_layouts = Math.max(0, parseInt(req.body.basic_layouts || 0, 10)) + var pro_layouts = Math.max(0, parseInt(req.body.pro_layouts || 0, 10)) + if (plan_type != "pro") { pro_layouts = 0 } + + if (plan_type == subscription.plan_type + && basic_layouts == subscriber.basic_layouts + && pro_layouts == subscriber.pro_layouts) { + return res.json(subscriber) + } + + var data = { subscription_add_ons: [] } + data.plan_code = plan_type + "-monthly" + + if (plan_levels[plan_type] > 0 && basic_layouts > 0) { + data.subscription_add_ons.push({ add_on_code: "extra-basic-layout", quantity: basic_layouts }) + } + + if (plan_type == "pro" && pro_layouts > 0) { + data.subscription_add_ons.push({ add_on_code: "extra-pro-layout", quantity: pro_layouts }) + } + + // data.plan_code + // data.subscription_add_ons = [] + // add_on.add_on_code + // add_on.quantity + console.log(data) + recurly.subscriptions.update(subscriber.uuid, data, function(err, data){ + console.log("got response from RECURLY ...") + if (err) { + console.log("error updating recurly subscription", err) + return res.json({ error: err }) + } + subscriber.plan_type = plan_type + subscriber.basic_layouts = basic_layouts + subscriber.pro_layouts = pro_layouts + subscriber.save(function(){ + user.plan_level = plan_levels[plan_type] + user.plan_type = plan_type + user.save(function(){ + return res.json(subscriber) + }) + }) + }) + }, + + destroy: function(req, res){ + if (! req.subscription ) { + return res.json({ error: "no subscription" }) + } + var subscriber = req.subscription + + recurly.subscriptions.terminate(subscriber.uuid, "partial", function(err, data){ + subscriber.remove(function(){ + req.user.plan_code = 0 + req.user.plan_type = "free" + req.user.save(function(){ + res.json({ status: "OK" }) + }) + }) + }) + }, + +}; |
