Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

Commit

Permalink
Merge pull request #55 from barbaraliau/0406-credits-debits
Browse files Browse the repository at this point in the history
Compatible with new bridge-gui
  • Loading branch information
Dylan Lott committed Apr 20, 2017
2 parents 5dc9857 + de7b13a commit 3bd248d
Show file tree
Hide file tree
Showing 9 changed files with 1,060 additions and 1,153 deletions.
5 changes: 3 additions & 2 deletions lib/server/routefactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ module.exports = function RouteFactory(options) {
return ([
require('./routes/credits'),
require('./routes/debits'),
require('./routes/users'),
require('./routes/graphql'),
require('./routes/referrals')
require('./routes/referrals'),
require('./routes/marketing'),
require('./routes/payment-processors')
]).map(function(Router) {
return Router({
config: options.config,
Expand Down
179 changes: 108 additions & 71 deletions lib/server/routes/credits.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ const inherits = require('util').inherits;
const middleware = require('storj-service-middleware');
const rawbody = middleware.rawbody;
const log = require('../../logger');
const authenticate = middleware.authenticate;
const { CREDIT_TYPES, PROMO_CODE, PROMO_EXPIRES, PROMO_AMOUNT } = require('storj-service-storage-models/lib/constants');
const {
CREDIT_TYPES,
PROMO_CODE,
PROMO_EXPIRES,
PROMO_AMOUNT
} = require('storj-service-storage-models/lib/constants');
const stripe = require('../vendor/stripe');
const errors = require('storj-service-error-types');
const Promise = require('bluebird');
Expand All @@ -25,46 +29,12 @@ function CreditsRouter(options) {
}
Router.apply(this, arguments);
this.models = options.storage.models;
this.authenticate = middleware.authenticate(options.storage);
Object.assign(this, helperFactory(this.models));
}

inherits(CreditsRouter, Router);


CreditsRouter.prototype.handleReferralSignup = function(req, res) {
const self = this;
const Marketing = self.models.Marketing;

console.log('HIT: handleReferralSignup', req.body);

Marketing.isValidReferralLink(req.body.referralLink)
.then((marketing) => {
console.log('VALID MARKETING DOC: ', marketing)
marketing._id = marketing.id;

self._getReferral(req.body, marketing)
.then((referral) => {
self._issueReferralSignupCredit(req.body, referral)
.then((credit) => self._convertReferralRecipient(referral, credit))
.then((referral) => res.status(200).send(referral))
})
})
.catch((err) => {
if (err.message === 'Invalid referral link') {
return self.handleRegularSignup(req, res);
}
res.status(500).send(err);
});
};

CreditsRouter.prototype.handleRegularSignup = function(req, res) {
console.log('HIT: handleRegularSignup for', req.body);
const self = this;
self._issueRegularSignupCredit(req.body)
.then((credit) => res.status(200).send(credit))
.catch((err) => res.status(500).send(err));
};

CreditsRouter.prototype.handleSignups = function (req, res) {
console.log('handlingSignup: ', req.body);

Expand All @@ -75,38 +45,60 @@ CreditsRouter.prototype.handleSignups = function (req, res) {
console.log('Error creating signup marketing: ', err);
return res.status(500).send(err);
}

console.log('CREATED MARKETING DOC: ', marketing);
if (req.body.referralLink) {
return self.handleReferralSignup(req, res);
}

return self.handleRegularSignup(req, res);
return res.status(200).send('Success');
})
}

CreditsRouter.prototype._issueRegularSignupCredit = function(data) {
const Credit = this.models.Credit;
/**
* Handles sign ups with referral links. Validates referral link, issues
* sign up credit, and tracks that the referral recipient has been converted
* @param {string} req.body.email - new user's email
* @param {string} req.body.referralLink - referral link from location.query
*/
CreditsRouter.prototype.handleReferralSignup = function(req, res) {
const self = this;
const Marketing = self.models.Marketing;

return new Promise((resolve, reject) => {
const newCredit = new Credit({
user: data.email,
type: CREDIT_TYPES.AUTO,
promo_code: PROMO_CODE.NEW_SIGNUP,
promo_amount: PROMO_AMOUNT.NEW_SIGNUP,
promo_expires: PROMO_EXPIRES.NEW_SIGNUP
});
console.log('HIT: handleReferralSignup', req.body);

newCredit
.save()
.then((credit) => {
return resolve(credit);
Marketing.isValidReferralLink(req.body.referralLink).then((marketing) => {
console.log('VALID MARKETING DOC: ', marketing)
marketing._id = marketing.id;
self._noDuplicateCredit(req.body)
.then(() => self._getReferral(req.body, marketing))
.then((referral) => {
self._issueReferralSignupCredit(req.body, referral)
.then((credit) => self._convertReferralRecipient(referral, credit))
// TODO: Send back amount of credit created so user knows it worked
// res.status(200).send({ creditAmount: credit.promo_amount,
// referralLink: referral.link })
.then((referral) => res.status(200).send('Success'))
.catch((err) => res.status(err.status).send(err));
})
.catch((err) => {
return reject(err);
});
.catch((err) => res.status(err.status).send(err))
})
.catch((err) => {
if (err.message === 'Invalid referral link') {
return res.status(200).send('Sign up successful, invalid referral link');
}
return res.status(err.status).send(err);
});
};

/**
* Used by `handleReferralSignup` to retrieve the referral doc related to the
* referral link passed in. If the referral doc exists, then the referral type
* has been previously generated and is of type 'email' (meaning some user sent
* an email to this new user previously). If the referral doc does not exist,
* then no referral email was sent prior to sign up, and type is of 'link'
* @param {Object} data - req.body containing email and referralLink
* @param {Object} marketing - marketing document belong to referral sender
*/
CreditsRouter.prototype._getReferral = function(data, marketing) {
const Referral = this.models.Referral;
console.log('data', data, 'marketing', marketing)
Expand All @@ -118,18 +110,53 @@ CreditsRouter.prototype._getReferral = function(data, marketing) {
})
.then((referral) => {
if (referral) {
console.log('GOT EXISTING REFERRAL: ', referral);
return resolve(referral);
}
console.log('CREATING NEW REFERRAL...');
Referral
.create(marketing, data.email, 'link')
.then((referral) => {
console.log('NEW REFERRAL CREATED: ', referral)
return resolve(referral)
})
.catch((err) => reject(errors.InternalError(err)));
})
.catch((err) => reject(errors.InternalError(err)))
});
};

/**
* Verfies that there is only one referral.recipient type of credit. A user can
* receive as many referral.sender credits, but can only ever be the recipient
* of ONE referral.recipient credit, since you can only sign up once per user
*/
CreditsRouter.prototype._noDuplicateCredit = function(data) {
const Credit = this.models.Credit;
console.log('Checking for duplicate credits');

return new Promise((resolve, reject) => {
Credit.find({
user: data.email,
promo_code: PROMO_CODE.REFERRAL_RECIPIENT
}).then((credits) => {
if (!credits.length) {
console.log('no dups. CM');
return resolve(true);
}
console.log('dup credits. do not pass go');
return reject(new errors.BadRequestError(
'Duplicate referral recipient credit'
));
})
.catch((err) => reject(new errors.InternalError(err.message)));
});
};
/**
* Issues a referral recipient sign up credit
* @param {Object} data - req.body with email and referralLink props
* @param {Object} referral - referral doc
*/
CreditsRouter.prototype._issueReferralSignupCredit = function(data, referral) {
const Credit = this.models.Credit;

Expand Down Expand Up @@ -157,17 +184,13 @@ CreditsRouter.prototype._issueReferralSignupCredit = function(data, referral) {
};

/**
* anonymous function - description
* Dates when a referral recipient was converted.
*
* @param {type} credit description
* @param {type} marketing refers to sender marketing document, NOT recipient
* @param {type} data description
* @return {type} description
* @param {object} referral - instance of referral doc
* @param {object} credit - referral recipient credit doc
*/
CreditsRouter.prototype._convertReferralRecipient = function(referral, credit) {

console.log('_convertReferralRecipient')
const Referral = this.models.Referral;

return new Promise((resolve, reject) => {
referral.convert_recipient_signup(credit)
Expand Down Expand Up @@ -333,15 +356,30 @@ CreditsRouter.prototype.handleConfirmCredit = function(req, res) {
}
};

CreditsRouter.prototype.getReferralSenderCreditsByDate = function(req, res, next) {
const Credit = this.models.credit;
CreditsRouter.prototype.getCredits = function(req, res, next) {
console.log('body', req.body, 'params', req.params, 'query', req.query);
const Credit = this.models.Credit;

if (!req.query.startDate && !req.query.endDate) {
return Credit.find({ user: req.user.id })
.then((credits) => {
const creditObjects = credits.map(credit => credit.toObject());
res.status(200).send(creditObjects);
})
.catch((err) => next(new errors.InternalError(err.message)));
}

Credit.find({
created: { $gte: req.periodStart, $lt: req.periodEnd }
user: req.user.id,
created: {
$gte: req.query.startDate,
$lt: req.query.endDate
}
}, function(err, credits) {
if (err) {
return next(new errors.InternalError(err.message));
}
res.status(200).send(credits.map(credit => credit.toObject()))
res.status(200).send(credits.map(credit => credit.toObject()));
})
};

Expand All @@ -363,10 +401,9 @@ CreditsRouter.prototype._definitions = function() {
this.checkType(/^invoice.payment_(succeeded|failed)$/),
this.handleConfirmCredit
],
['GET',
'/credits/referral/:periodStart/:periodEnd',
authenticate,
this.getReferralSenderCreditsByDate
['GET', '/credits',
this.authenticate,
this.getCredits
],
[
'POST', '/credits/signups',
Expand Down
41 changes: 38 additions & 3 deletions lib/server/routes/debits.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const moment = require('moment');
const inherits = require('util').inherits;
const Router = require('./index');
const middleware = require('storj-service-middleware');
const authenticate = middleware.authenticate;
const errors = require('storj-service-error-types');

// TODO: duplicated from service-storge-models `PaymentProcessor`

Expand All @@ -16,7 +16,7 @@ function DebitsRouter(options) {
Router.apply(this, arguments);

this.models = options.storage.models;
this._verify = authenticate(this.storage);
this.authenticate = middleware.authenticate(options.storage);
}

inherits(DebitsRouter, Router);
Expand Down Expand Up @@ -94,6 +94,34 @@ DebitsRouter.prototype.createDebit = function(req, res) {
})
};


DebitsRouter.prototype.getDebits = function(req, res, next) {
console.log('DEBITS: body', req.body, 'params', req.params, 'query', req.query);
const Debit = this.models.Debit;

if (!req.query.startDate && !req.query.endDate) {
return Debit.find({ user: req.user.id })
.then((debits) => {
const debitObjects = debits.map((debit) => debit.toObject());
res.status(200).send(debitObjects);
})
.catch((err) => next(new errors.InternalError(err.message)));
}

Debit.find({
user: req.user.id,
created: {
$gte: req.query.startDate,
$lt: req.query.endDate
}
}, function(err, debits) {
if (err) {
return next(new errors.InternalError(err.message));
}
res.status(200).send(debits.map(debit => debit.toObject()));
})
};

DebitsRouter.prototype._getBillingPeriodFor = function(referenceMoment = moment.utc(),
billingDate = moment.utc().date()){
const endOfBillingMonth = moment
Expand Down Expand Up @@ -123,7 +151,14 @@ DebitsRouter.prototype._getBillingPeriodFor = function(referenceMoment = moment.
*/
DebitsRouter.prototype._definitions = function() {
return [
['POST', '/debits', this._verify, this.createDebit]
['POST', '/debits',
this.authenticate,
this.createDebit
],
['GET', '/debits',
this.authenticate,
this.getDebits
]
];
};

Expand Down
Loading

0 comments on commit 3bd248d

Please sign in to comment.