From f42f34c96fc479d38578116cb2b4b1f79a691baa Mon Sep 17 00:00:00 2001 From: Matt Lott Date: Sun, 23 Aug 2015 20:54:39 -0700 Subject: [PATCH 1/3] :bug:Fix subs dashboard 30 day churn --- app/templates/admin/analytics-subscriptions.jade | 2 +- app/views/admin/AnalyticsSubscriptionsView.coffee | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/templates/admin/analytics-subscriptions.jade b/app/templates/admin/analytics-subscriptions.jade index 3ed6ca864..7d98aa993 100644 --- a/app/templates/admin/analytics-subscriptions.jade +++ b/app/templates/admin/analytics-subscriptions.jade @@ -24,7 +24,7 @@ block content div.description 30 Day Total Growth div.count #{monthlyGrowth.toFixed(1)}% .col-md-5.big-stat.churn-count - div.description Monthly Churn (cancelled / total) + div.description 30 Day Churn (cancelled / total) div.count #{monthlyChurn.toFixed(1)}% each graph in analytics.graphs diff --git a/app/views/admin/AnalyticsSubscriptionsView.coffee b/app/views/admin/AnalyticsSubscriptionsView.coffee index 3ad0e16f1..571cac432 100644 --- a/app/views/admin/AnalyticsSubscriptionsView.coffee +++ b/app/views/admin/AnalyticsSubscriptionsView.coffee @@ -33,7 +33,6 @@ module.exports = class AnalyticsSubscriptionsView extends RootView context.subscriberCancelled = _.find context.subscribers, (subscriber) -> subscriber.cancel context.subscriberSponsored = _.find context.subscribers, (subscriber) -> subscriber.user?.stripe?.sponsorID context.total = @total ? 0 - context.cancelled = @cancellations?.length ? @cancelled ? 0 context.monthlyChurn = @monthlyChurn ? 0.0 context.monthlyGrowth = @monthlyGrowth ? 0.0 context.outstandingCancels = @outstandingCancels ? [] @@ -52,7 +51,6 @@ module.exports = class AnalyticsSubscriptionsView extends RootView @analytics = graphs: [] @subs = [] @total = 0 - @cancelled = 0 @monthlyChurn = 0.0 @monthlyGrowth = 0.0 @refreshDataState = 'Fetching dashboard data...' @@ -258,14 +256,15 @@ module.exports = class AnalyticsSubscriptionsView extends RootView ended: subDayMap[day]['end'] or 0 @subs.sort (a, b) -> a.day.localeCompare(b.day) + cancelledThisMonth = 0 totalLastMonth = 0 for sub, i in @subs @total += sub.started @total -= sub.ended - @cancelled += sub.cancelled sub.total = @total + cancelledThisMonth += sub.cancelled if @subs.length - i < 31 totalLastMonth = @total if @subs.length - i is 31 - @monthlyChurn = @cancelled / totalLastMonth * 100.0 if totalLastMonth > 0 + @monthlyChurn = cancelledThisMonth / totalLastMonth * 100.0 if totalLastMonth > 0 if @subs.length > 30 and @subs[@subs.length - 31].total > 0 startMonthTotal = @subs[@subs.length - 31].total endMonthTotal = @subs[@subs.length - 1].total From 7d419c1615e5d374c22789b875c6cc74bd7554e6 Mon Sep 17 00:00:00 2001 From: Matt Lott Date: Mon, 24 Aug 2015 06:11:11 -0700 Subject: [PATCH 2/3] Courses UI: add screenshot to landing page course blocks --- app/styles/courses/mock1/courses.sass | 4 ++++ app/templates/courses/mock1/courses.jade | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/app/styles/courses/mock1/courses.sass b/app/styles/courses/mock1/courses.sass index 41d6f2f17..c3efb70b1 100644 --- a/app/styles/courses/mock1/courses.sass +++ b/app/styles/courses/mock1/courses.sass @@ -5,6 +5,10 @@ .code-input width: 100% + + .course-image + width: 100% + .course-panel margin: 20px diff --git a/app/templates/courses/mock1/courses.jade b/app/templates/courses/mock1/courses.jade index 6d0f40aff..ea02d713f 100644 --- a/app/templates/courses/mock1/courses.jade +++ b/app/templates/courses/mock1/courses.jade @@ -95,6 +95,10 @@ mixin course-block(course, courseID) strong #{course.unlocked ? '[ enrolled ]' : ''} .panel-body .container-fluid + .row + .col-md-12 + p + img.course-image(src="#{course.image}") .row.button-row .col-md-6 strong Topics From 9c492a2d4bfcd0b997450cf7884704851162f69e Mon Sep 17 00:00:00 2001 From: Matt Lott Date: Mon, 24 Aug 2015 10:54:06 -0700 Subject: [PATCH 3/3] :bug:Increment gems for year sale purchase --- server/lib/stripe_utils.coffee | 1 + server/payments/subscription_handler.coffee | 9 +++++++++ test/server/functional/subscription.spec.coffee | 2 ++ 3 files changed, 12 insertions(+) diff --git a/server/lib/stripe_utils.coffee b/server/lib/stripe_utils.coffee index 3f789c778..90fcede1a 100644 --- a/server/lib/stripe_utils.coffee +++ b/server/lib/stripe_utils.coffee @@ -28,6 +28,7 @@ module.exports = service: 'stripe' amount: parseInt(stripeCharge.amount) payment.set 'description', stripeCharge.metadata.description if stripeCharge.metadata.description + payment.set 'gems', parseInt(stripeCharge.metadata.gems) if stripeCharge.metadata.gems payment.set 'stripe', customerID: stripeCharge.customer timestamp: parseInt(stripeCharge.metadata.timestamp) diff --git a/server/payments/subscription_handler.coffee b/server/payments/subscription_handler.coffee index 7f96821bd..11c6bc70f 100644 --- a/server/payments/subscription_handler.coffee +++ b/server/payments/subscription_handler.coffee @@ -127,6 +127,7 @@ class SubscriptionHandler extends Handler metadata = type: req.body.type userID: req.user._id + '' + gems: subscriptions.basic.gems * 12 timestamp: parseInt(req.body.stripe?.timestamp) description: req.body.description @@ -146,6 +147,14 @@ class SubscriptionHandler extends Handler stripeInfo = _.cloneDeep(req.user.get('stripe') ? {}) stripeInfo.free = endDate.toISOString().substring(0, 10) req.user.set('stripe', stripeInfo) + + # Add year's worth of gems to User + purchased = _.clone(req.user.get('purchased')) + purchased ?= {} + purchased.gems ?= 0 + purchased.gems += parseInt(charge.metadata.gems) + req.user.set('purchased', purchased) + req.user.save (err, user) => if err @logSubscriptionError(req.user, "User save error: #{JSON.stringify(err)}") diff --git a/test/server/functional/subscription.spec.coffee b/test/server/functional/subscription.spec.coffee index 037be1da9..a51200e2e 100644 --- a/test/server/functional/subscription.spec.coffee +++ b/test/server/functional/subscription.spec.coffee @@ -1394,7 +1394,9 @@ describe 'Subscriptions', -> endDate.setUTCFullYear(endDate.getUTCFullYear() + 1) expect(stripeInfo.free).toEqual(endDate.toISOString().substring(0, 10)) expect(stripeInfo.customerID).toBeDefined() + expect(user1.get('purchased')?.gems).toEqual(3500*12) Payment.findOne 'stripe.customerID': stripeInfo.customerID, (err, payment) -> expect(err).toBeNull() expect(payment).toBeDefined() + expect(payment.get('gems')).toEqual(3500*12) done()