From 9b68e9140961871a3b50dd82062c612c6157cf21 Mon Sep 17 00:00:00 2001 From: Matt Lott Date: Sun, 10 Jul 2016 17:55:07 -0700 Subject: [PATCH] :bug:Fix analytics dashboard coursePrepaid use --- app/templates/admin/analytics.jade | 46 ++---- app/views/admin/AnalyticsView.coffee | 84 ++++++----- .../mongodb/insertAnalyticsActiveClasses.js | 140 +++++++++++------- .../mongodb/insertAnalyticsActiveUsers.js | 50 +++++-- 4 files changed, 188 insertions(+), 132 deletions(-) diff --git a/app/templates/admin/analytics.jade b/app/templates/admin/analytics.jade index 51dc0c100..f5f7a1d4e 100644 --- a/app/templates/admin/analytics.jade +++ b/app/templates/admin/analytics.jade @@ -18,7 +18,7 @@ block content .col-md-5.big-stat.classroom-active-users div.description Classroom Monthly Active Users if view.activeUsers.length > 0 - - var classroomBigMAU = 0; + - var classroomBigMAU = 0; each count, event in view.activeUsers[0].events if event.indexOf('MAU classroom') >= 0 - classroomBigMAU += count; @@ -26,24 +26,24 @@ block content .col-md-5.big-stat.campaign-active-users div.description Campaign Monthly Active Users if view.activeUsers.length > 0 - - var campaignBigMAU = 0; + - var campaignBigMAU = 0; each count, event in view.activeUsers[0].events if event.indexOf('MAU campaign') >= 0 - campaignBigMAU += count; div.count= campaignBigMAU ul.nav.nav-tabs - li.active + li.active a(data-target="#tab_kpis", data-toggle="tab") KPIs - li + li a(data-target="#tab_active_classes", data-toggle="tab") Active Classes - li + li a(data-target="#tab_revenue", data-toggle="tab") Revenue - li + li a(data-target="#tab_classroom", data-toggle="tab") Classroom - li + li a(data-target="#tab_campaign", data-toggle="tab") Campaign - li + li a(data-target="#tab_campaign_vs_classroom", data-toggle="tab") Campaign vs Classroom .tab-content @@ -165,7 +165,7 @@ block content .small Paid teacher: at least one paid student in course instance .small Trial teacher: at least one trial student in course instance, and no paid students .small Free teacher: no paid students, no trial students - .small Paid status takes precedent over furthest course, so teacher furthest course is furthest course of highest paid status student + .small Paid status takes precedent over furthest course, so teacher furthest course is furthest course of highest paid status student if view.courseDistributionsRecent table.table.table-striped.table-condensed tr @@ -267,9 +267,9 @@ block content h1 Active Users if view.activeUsers.length > 0 - var eventNames = []; - each count, event in view.activeUsers[0].events + each event in view.activeUserEventNames if event.indexOf('classroom') >= 0 - - eventNames.push(event) + - eventNames.push(event); - eventNames.sort(function (a, b) {return a.localeCompare(b);}); table.table.table-striped.table-condensed tr @@ -293,7 +293,7 @@ block content each day in view.enrollmentDays tr td= day - if view.dayEnrollmentsMap[day] + if view.dayEnrollmentsMap[day] td= view.dayEnrollmentsMap[day].paidIssued || 0 td= view.dayEnrollmentsMap[day].paidRedeemed || 0 td= view.dayEnrollmentsMap[day].trialIssued || 0 @@ -322,9 +322,9 @@ block content h1 Active Users if view.activeUsers.length > 0 - var eventNames = []; - each count, event in view.activeUsers[0].events + each event in view.activeUserEventNames if event.indexOf('campaign') >= 0 - - eventNames.push(event) + - eventNames.push(event); - eventNames.sort(function (a, b) {return a.localeCompare(b);}); table.table.table-striped.table-condensed tr @@ -346,27 +346,13 @@ block content h1 Active Users if view.activeUsers.length > 0 - - var eventNames = []; - each count, event in view.activeUsers[0].events - - eventNames.push(event) - - eventNames.sort(function (a, b) { - - if (a.indexOf('campaign') == b.indexOf('campaign') || a.indexOf('classroom') == b.indexOf('classroom')) { - - return a.localeCompare(b); - - } - - else if (a.indexOf('campaign') > b.indexOf('campaign')) { - - return 1; - - } - - else { - - return -1; - - } - - }); table.table.table-striped.table-condensed tr th(style='min-width:85px;') Day - each eventName in eventNames + each eventName in view.activeUserEventNames th= eventName each activeUser in view.activeUsers tr td= activeUser.day - each eventName in eventNames + each eventName in view.activeUserEventNames td= activeUser.events[eventName] || 0 diff --git a/app/views/admin/AnalyticsView.coffee b/app/views/admin/AnalyticsView.coffee index f23c0e58a..591a174a5 100644 --- a/app/views/admin/AnalyticsView.coffee +++ b/app/views/admin/AnalyticsView.coffee @@ -73,6 +73,7 @@ module.exports = class AnalyticsView extends RootView # Add campaign/classroom DAU 30-day averages and daily totals campaignDauTotals = [] classroomDauTotals = [] + eventMap = {} for entry in @activeUsers day = entry.day campaignDauTotal = 0 @@ -82,18 +83,31 @@ module.exports = class AnalyticsView extends RootView campaignDauTotal += count else if event.indexOf('DAU classroom') >= 0 classroomDauTotal += count + eventMap[event] = true; entry.events['DAU campaign total'] = campaignDauTotal + eventMap['DAU campaign total'] = true; campaignDauTotals.unshift(campaignDauTotal) campaignDauTotals.pop() while campaignDauTotals.length > 30 if campaignDauTotals.length is 30 entry.events['DAU campaign 30-day average'] = Math.round(_.reduce(campaignDauTotals, (a, b) -> a + b) / 30) + eventMap['DAU campaign 30-day average'] = true; entry.events['DAU classroom total'] = classroomDauTotal + eventMap['DAU classroom total'] = true; classroomDauTotals.unshift(classroomDauTotal) classroomDauTotals.pop() while classroomDauTotals.length > 30 if classroomDauTotals.length is 30 entry.events['DAU classroom 30-day average'] = Math.round(_.reduce(classroomDauTotals, (a, b) -> a + b) / 30) + eventMap['DAU classroom 30-day average'] = true; @activeUsers.sort (a, b) -> b.day.localeCompare(a.day) + @activeUserEventNames = Object.keys(eventMap) + @activeUserEventNames.sort (a, b) -> + if a.indexOf('campaign') is b.indexOf('campaign') or a.indexOf('classroom') is b.indexOf('classroom') + a.localeCompare(b) + else if a.indexOf('campaign') > b.indexOf('campaign') + 1 + else + -1 @updateAllKPIChartData() @updateActiveUsersChartData() @@ -134,13 +148,13 @@ module.exports = class AnalyticsView extends RootView return unless @revenue.length > 0 # Add monthly recurring revenue values - + # For each daily group, add up monthly values walking forward through time, and add to revenue groups monthlyDailyGroupMap = {} dailyGroupIndexMap = {} for group, i in @revenueGroups monthlyDailyGroupMap[group.replace('DRR', 'MRR')] = group - dailyGroupIndexMap[group] = i + dailyGroupIndexMap[group] = i for monthlyGroup, dailyGroup of monthlyDailyGroupMap monthlyValues = [] for i in [@revenue.length-1..0] @@ -183,7 +197,7 @@ module.exports = class AnalyticsView extends RootView @supermodel.addRequestResource({ url: '/db/prepaid/-/courses' method: 'POST' - data: {project: {maxRedeemers: 1, properties: 1, redeemers: 1}} + data: {project: {endDate: 1, maxRedeemers: 1, properties: 1, redeemers: 1}} success: (prepaids) => paidDayMaxMap = {} paidDayRedeemedMap = {} @@ -201,14 +215,13 @@ module.exports = class AnalyticsView extends RootView redeemDay = redeemer.date.substring(0, 10) trialDayRedeemedMap[redeemDay] ?= 0 trialDayRedeemedMap[redeemDay]++ - else + else if not prepaid.endDate? or new Date(prepaid.endDate) > new Date() paidDayMaxMap[day] ?= 0 paidDayMaxMap[day] += prepaid.maxRedeemers for redeemer in prepaid.redeemers redeemDay = redeemer.date.substring(0, 10) paidDayRedeemedMap[redeemDay] ?= 0 paidDayRedeemedMap[redeemDay]++ - @dayEnrollmentsMap = {} @paidCourseTotalEnrollments = [] for day, count of paidDayMaxMap @@ -218,7 +231,7 @@ module.exports = class AnalyticsView extends RootView @paidCourseTotalEnrollments.sort (a, b) -> a.day.localeCompare(b.day) @paidCourseRedeemedEnrollments = [] for day, count of paidDayRedeemedMap - @paidCourseRedeemedEnrollments.push({day: day, count: count}) + @paidCourseRedeemedEnrollments.push({day: day, count: count}) @dayEnrollmentsMap[day] ?= {paidIssued: 0, paidRedeemed: 0, trialIssued: 0, trialRedeemed: 0} @dayEnrollmentsMap[day].paidRedeemed += count @paidCourseRedeemedEnrollments.sort (a, b) -> a.day.localeCompare(b.day) @@ -239,7 +252,7 @@ module.exports = class AnalyticsView extends RootView }, 0).load() @courses = new CocoCollection([], { url: "/db/course", model: Course}) - @courses.comparator = "_id" + @courses.comparator = "_id" @listenToOnce @courses, 'sync', @onCoursesSync @supermodel.loadCollection(@courses) @@ -276,7 +289,7 @@ module.exports = class AnalyticsView extends RootView studentFurthestCourseMap = {} studentPaidStatusMap = {} for courseInstance in data.courseInstances - continue if utils.objectIdToDate(courseInstance._id) < startDate + continue if utils.objectIdToDate(courseInstance._id) < startDate courseID = courseInstance.courseID teacherID = courseInstance.ownerID for studentID in courseInstance.members @@ -306,7 +319,7 @@ module.exports = class AnalyticsView extends RootView # Paid teacher: at least one paid student # Trial teacher: at least one trial student in course instance, and no paid students # Free teacher: no paid students, no trial students - # Teacher furthest course is furthest course of highest paid status student + # Teacher furthest course is furthest course of highest paid status student teacherFurthestCourseMap = {} teacherPaidStatusMap = {} for teacher, students of teacherStudentsMap @@ -368,14 +381,17 @@ module.exports = class AnalyticsView extends RootView # Trim points preceding days if points.length and days.length and points[0].day.localeCompare(days[0]) < 0 - for point, i in points - if point.day.localeCompare(days[0]) >= 0 - points.splice(0, i) - break + if points[points.length - 1].day.localeCompare(days[0]) < 0 + points = [] + else + for point, i in points + if point.day.localeCompare(days[0]) >= 0 + points.splice(0, i) + break # Ensure points for each day for day, i in days - if points.length <= i or points[i].day isnt day + if points.length <= i or points[i]?.day isnt day prevY = if i > 0 then points[i - 1].y else 0.0 points.splice i, 0, day: day @@ -534,7 +550,7 @@ module.exports = class AnalyticsView extends RootView day = entry.day for event, count of entry.events eventDataMap[event] ?= [] - eventDataMap[event].push + eventDataMap[event].push day: entry.day value: count @@ -550,7 +566,7 @@ module.exports = class AnalyticsView extends RootView lines.push points: points description: event - lineColor: @lineColors[colorIndex++ % @lineColors.length] + lineColor: @lineColors[colorIndex++ % @lineColors.length] strokeWidth: 1 min: 0 showYScale: showYScale @@ -577,7 +593,7 @@ module.exports = class AnalyticsView extends RootView day = entry.day for event, count of entry.events eventDataMap[event] ?= [] - eventDataMap[event].push + eventDataMap[event].push day: entry.day value: count @@ -591,7 +607,7 @@ module.exports = class AnalyticsView extends RootView @campaignVsClassroomMonthlyActiveUsersRecentChartLines.push points: points description: event - lineColor: @lineColors[colorIndex++ % @lineColors.length] + lineColor: @lineColors[colorIndex++ % @lineColors.length] strokeWidth: 1 min: 0 showYScale: true @@ -601,7 +617,7 @@ module.exports = class AnalyticsView extends RootView @campaignVsClassroomMonthlyActiveUsersRecentChartLines.push points: points description: event - lineColor: @lineColors[colorIndex++ % @lineColors.length] + lineColor: @lineColors[colorIndex++ % @lineColors.length] strokeWidth: 1 min: 0 showYScale: false @@ -619,7 +635,7 @@ module.exports = class AnalyticsView extends RootView @campaignVsClassroomMonthlyActiveUsersChartLines.push points: points description: event - lineColor: @lineColors[colorIndex++ % @lineColors.length] + lineColor: @lineColors[colorIndex++ % @lineColors.length] strokeWidth: 1 min: 0 showYScale: true @@ -629,7 +645,7 @@ module.exports = class AnalyticsView extends RootView @campaignVsClassroomMonthlyActiveUsersChartLines.push points: points description: event - lineColor: @lineColors[colorIndex++ % @lineColors.length] + lineColor: @lineColors[colorIndex++ % @lineColors.length] strokeWidth: 1 min: 0 showYScale: false @@ -648,16 +664,14 @@ module.exports = class AnalyticsView extends RootView dailyMax = 0 data = [] - total = 0 for entry in @paidCourseTotalEnrollments - total += entry.count data.push day: entry.day - value: total + value: entry.count points = @createLineChartPoints(days, data) @enrollmentsChartLines.push points: points - description: 'Total paid enrollments issued' + description: 'Paid enrollments issued' lineColor: @lineColors[colorIndex++ % @lineColors.length] strokeWidth: 1 min: 0 @@ -666,16 +680,14 @@ module.exports = class AnalyticsView extends RootView dailyMax = _.max([dailyMax, _.max(points, 'y').y]) data = [] - total = 0 for entry in @paidCourseRedeemedEnrollments - total += entry.count data.push day: entry.day - value: total + value: entry.count points = @createLineChartPoints(days, data) @enrollmentsChartLines.push points: points - description: 'Total paid enrollments redeemed' + description: 'Paid enrollments redeemed' lineColor: @lineColors[colorIndex++ % @lineColors.length] strokeWidth: 1 min: 0 @@ -684,16 +696,14 @@ module.exports = class AnalyticsView extends RootView dailyMax = _.max([dailyMax, _.max(points, 'y').y]) data = [] - total = 0 for entry in @trialCourseTotalEnrollments - total += entry.count data.push day: entry.day - value: total - points = @createLineChartPoints(days, data) + value: entry.count + points = @createLineChartPoints(days, data, true) @enrollmentsChartLines.push points: points - description: 'Total trial enrollments issued' + description: 'Trial enrollments issued' lineColor: @lineColors[colorIndex++ % @lineColors.length] strokeWidth: 1 min: 0 @@ -702,16 +712,14 @@ module.exports = class AnalyticsView extends RootView dailyMax = _.max([dailyMax, _.max(points, 'y').y]) data = [] - total = 0 for entry in @trialCourseRedeemedEnrollments - total += entry.count data.push day: entry.day - value: total + value: entry.count points = @createLineChartPoints(days, data) @enrollmentsChartLines.push points: points - description: 'Total trial enrollments redeemed' + description: 'Trial enrollments redeemed' lineColor: @lineColors[colorIndex++ % @lineColors.length] strokeWidth: 1 min: 0 diff --git a/scripts/analytics/mongodb/insertAnalyticsActiveClasses.js b/scripts/analytics/mongodb/insertAnalyticsActiveClasses.js index b26e89af1..9599ffd94 100644 --- a/scripts/analytics/mongodb/insertAnalyticsActiveClasses.js +++ b/scripts/analytics/mongodb/insertAnalyticsActiveClasses.js @@ -6,51 +6,49 @@ // Usage: // mongo
:/