diff --git a/services/web/app/coffee/Features/Referal/ReferalAllocator.coffee b/services/web/app/coffee/Features/Referal/ReferalAllocator.coffee index e19735e3f6..43349b9b1e 100644 --- a/services/web/app/coffee/Features/Referal/ReferalAllocator.coffee +++ b/services/web/app/coffee/Features/Referal/ReferalAllocator.coffee @@ -1,3 +1,4 @@ +_ = require("underscore") logger = require('logger-sharelatex') User = require('../../models/User').User SubscriptionLocator = require "../Subscription/SubscriptionLocator" @@ -28,6 +29,8 @@ module.exports = ReferalAllocator = else callback() + + assignBonus: (user_id, callback = (error) ->) -> SubscriptionLocator.getUsersSubscription user_id, (error, subscription) -> return callback(error) if error? @@ -43,13 +46,40 @@ module.exports = ReferalAllocator = logger.log user_id: user_id, refered_user_count: user.refered_user_count, - bonus_features: Settings.bonus_features[user.refered_user_count], "assigning bonus" - if user.refered_user_count? and Settings.bonus_features[user.refered_user_count]? - User.update query, { $set: features: Settings.bonus_features[user.refered_user_count] }, callback + if user.refered_user_count? and user.refered_user_count > 0 + newFeatures = ReferalAllocator._calculateBonuses(user) + User.update query, { $set: features: newFeatures }, callback + else callback() else callback() - + _calculateBonuses : (user)-> + bonusLevel = ReferalAllocator._getBonusLevel(user) + + newFeatures = {} + _.each Settings.bonus_features["#{bonusLevel}"], (bonusLevel, key)-> + currentLevel = user?.features?[key] + if _.isBoolean(currentLevel) and currentLevel == false + newFeatures[key] = bonusLevel + + if _.isNumber(currentLevel) + if currentLevel == -1 + return + bonusIsGreaterThanCurrent = currentLevel < bonusLevel + if bonusIsGreaterThanCurrent or bonusLevel == -1 + newFeatures[key] = bonusLevel + + return newFeatures + + + _getBonusLevel: (user)-> + highestBonusLevel = 0 + _.each _.keys(Settings.bonus_features), (level)-> + levelIsLessThanUser = level <= user.refered_user_count + levelIsMoreThanCurrentHighest = level >= highestBonusLevel + if levelIsLessThanUser and levelIsMoreThanCurrentHighest + highestBonusLevel = level + return highestBonusLevel diff --git a/services/web/test/UnitTests/coffee/Referal/ReferalAllocatorTests.coffee b/services/web/test/UnitTests/coffee/Referal/ReferalAllocatorTests.coffee index 8ccc0019aa..28592f70bf 100644 --- a/services/web/test/UnitTests/coffee/Referal/ReferalAllocatorTests.coffee +++ b/services/web/test/UnitTests/coffee/Referal/ReferalAllocatorTests.coffee @@ -83,7 +83,12 @@ describe 'Referal allocator', -> collaborators: 3 dropbox: false versioning: false - @User.findOne = sinon.stub().callsArgWith 1, null, { refered_user_count: @refered_user_count } + stubbedUser = { + refered_user_count: @refered_user_count, + features:{collaborators:1, dropbox:false, versioning:false} + } + + @User.findOne = sinon.stub().callsArgWith 1, null,stubbedUser @User.update = sinon.stub().callsArgWith 2, null @SubscriptionLocator.getUsersSubscription = sinon.stub().callsArgWith 1, null, null @ReferalAllocator.assignBonus @user_id, @callback @@ -114,13 +119,22 @@ describe 'Referal allocator', -> describe "when user does not have a recurlySubscription_id", -> beforeEach -> - @refered_user_count = 3 + @refered_user_count = 4 @Settings.bonus_features = + "2": + collaborators: 2 + dropbox: false + versioning: false + "5": + collaborators: 5 + dropbox: true + versioning: false "3": collaborators: 3 dropbox: false versioning: false - @User.findOne = sinon.stub().callsArgWith 1, null, { refered_user_count: @refered_user_count } + stubbedUser = { refered_user_count: @refered_user_count, features:{collaborators:1, dropbox:false, versioning:false} } + @User.findOne = sinon.stub().callsArgWith 1, null, stubbedUser @User.update = sinon.stub().callsArgWith 2, null @SubscriptionLocator.getUsersSubscription = sinon.stub().callsArgWith 1, null, {} @ReferalAllocator.assignBonus @user_id, @callback @@ -135,25 +149,56 @@ describe 'Referal allocator', -> .calledWith(_id: @user_id) .should.equal true - it "should update the user to bonus features", -> + it "should update the user to bonus features with the closest level", -> @User.update .calledWith({ _id: @user_id }, { $set: features: - @Settings.bonus_features[@refered_user_count.toString()] + @Settings.bonus_features["3"] }) .should.equal true it "should call the callback", -> @callback.called.should.equal true - describe "when the user is not at a bonus level", -> + describe "when the user has better features already", -> + beforeEach -> @refered_user_count = 3 + @stubbedUser = + refered_user_count:4 + features: + collaborators:3 + dropbox:false + versioning:false @Settings.bonus_features = "4": + collaborators: 10 + dropbox: true + versioning: false + + @User.findOne = sinon.stub().callsArgWith 1, null, @stubbedUser + @User.update = sinon.stub().callsArgWith 2, null + @SubscriptionLocator.getUsersSubscription = sinon.stub().callsArgWith 1, null,null + + it "should not set in in mongo when the feature is better", (done)-> + @ReferalAllocator.assignBonus @user_id, => + @User.update.calledWith({_id: @user_id }, {$set: features:{dropbox:true, versioning:false, collaborators:10} }).should.equal true + done() + + it "should not overright if the user has -1 users", (done)-> + @stubbedUser.features.collaborators = -1 + @ReferalAllocator.assignBonus @user_id, => + @User.update.calledWith({_id: @user_id }, {$set: features:{dropbox:true, versioning:false} }).should.equal true + done() + + describe "when the user is not at a bonus level", -> + beforeEach -> + @refered_user_count = 0 + @Settings.bonus_features = + "1": collaborators: 3 dropbox: false versioning: false