Родитель
f0ecf3da85
Коммит
4d41645987
|
@ -413,3 +413,6 @@ pygit2==0.27.2 \
|
|||
webencodings==0.5.1 \
|
||||
--hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \
|
||||
--hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923
|
||||
premailer==3.2.0 \
|
||||
--hash=sha256:a344b2013f8e099962bdea3a433fbea8614006fbe2ef62cd89c653a2b33290ad \
|
||||
--hash=sha256:ca97cec6115fea6590b49558c55d891996f9eb4da6490c7b60c3a8af4c8c0735
|
||||
|
|
|
@ -46,6 +46,9 @@ HOME=/tmp
|
|||
30 11 * * * %(z_cron)s update_addon_average_daily_users
|
||||
00 12 * * * %(z_cron)s index_latest_stats
|
||||
|
||||
# Once per week
|
||||
1 9 * * 1 %(django)s review_reports
|
||||
|
||||
# Do not put crons below this line
|
||||
|
||||
MAILTO=root
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
from datetime import date, timedelta
|
||||
|
||||
import os
|
||||
import settings
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db import connection
|
||||
|
||||
import olympia.core.logger
|
||||
|
||||
from olympia.amo.utils import send_mail
|
||||
from olympia.constants.reviewers import (POST_REVIEW_WEIGHT_HIGHEST_RISK,
|
||||
POST_REVIEW_WEIGHT_HIGH_RISK,
|
||||
POST_REVIEW_WEIGHT_MEDIUM_RISK)
|
||||
|
||||
from premailer import transform
|
||||
|
||||
SQL_DIR = os.path.join(
|
||||
settings.ROOT,
|
||||
"src/olympia/reviewers/management/commands/review_reports_sql/")
|
||||
|
||||
REPORTS = {
|
||||
'addon': [('Weekly Add-on Reviews, 5 Reviews or More',
|
||||
os.path.join(SQL_DIR, 'addon/weekly.sql')),
|
||||
('Weekly Volunteer Contribution Ratio',
|
||||
os.path.join(SQL_DIR, 'addon/breakdown.sql')),
|
||||
('Weekly Add-on Reviews by Risk Profiles',
|
||||
os.path.join(SQL_DIR, 'addon/risk.sql')),
|
||||
('Quarterly contributions',
|
||||
os.path.join(SQL_DIR, 'addon/quarterly.sql'))],
|
||||
'content': [('Weekly Content Reviews, 10 Reviews or More',
|
||||
os.path.join(SQL_DIR, 'content/weekly.sql')),
|
||||
('Weekly Volunteer Contribution Ratio',
|
||||
os.path.join(SQL_DIR, 'content/breakdown.sql')),
|
||||
('Quarterly contributions',
|
||||
os.path.join(SQL_DIR, 'content/quarterly.sql'))]
|
||||
}
|
||||
|
||||
log = olympia.core.logger.getLogger('z.reviewers.review_report')
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Generate and send the review report'
|
||||
|
||||
def handle(self, *args, **options):
|
||||
log.info("Generating add-on reviews report...")
|
||||
|
||||
addon_report_data = self.fetch_report_data('addon')
|
||||
addon_report_html = self.generate_report_html('addon',
|
||||
addon_report_data)
|
||||
addon_report_subject = '%s %s-%s' % (
|
||||
'Weekly Add-on Reviews Report',
|
||||
self.week_begin, self.week_end)
|
||||
self.mail_report('addon-reviewers@mozilla.org',
|
||||
addon_report_subject,
|
||||
addon_report_html)
|
||||
|
||||
log.info("Generating content reviews report...")
|
||||
content_report_data = self.fetch_report_data('content')
|
||||
content_report_html = self.generate_report_html('content',
|
||||
content_report_data)
|
||||
content_report_subject = '%s %s-%s' % (
|
||||
'Weekly Add-on Content Reviews Report',
|
||||
self.week_begin, self.week_end)
|
||||
self.mail_report('addon-content-reviewers@mozilla.org',
|
||||
content_report_subject,
|
||||
content_report_html)
|
||||
|
||||
def fetch_report_data(self, group):
|
||||
today = date.today()
|
||||
with connection.cursor() as cursor:
|
||||
# Set variables that are being used in the review report,
|
||||
# as well as the email output.
|
||||
cursor.execute("""
|
||||
SET @WEEK_BEGIN=%s;
|
||||
SET @WEEK_END=%s;
|
||||
SET @QUARTER_BEGIN=%s;
|
||||
SET @RISK_HIGHEST=%s;
|
||||
SET @RISK_HIGH=%s;
|
||||
SET @RISK_MEDIUM=%s;
|
||||
""", [today - timedelta(days=today.weekday() + 7),
|
||||
today - timedelta(days=today.weekday() + 1),
|
||||
date(today.year, (today.month - 1) // 3 * 3 + 1, 1),
|
||||
POST_REVIEW_WEIGHT_HIGHEST_RISK,
|
||||
POST_REVIEW_WEIGHT_HIGH_RISK,
|
||||
POST_REVIEW_WEIGHT_MEDIUM_RISK])
|
||||
|
||||
# Read the beginning/end of the week
|
||||
# in order to put it in the email.
|
||||
cursor.execute('SELECT @WEEK_BEGIN, @WEEK_END;')
|
||||
data = cursor.fetchone()
|
||||
self.week_begin = data[0]
|
||||
self.week_end = data[1]
|
||||
|
||||
report_data = []
|
||||
|
||||
for header, query_file in REPORTS.get(group):
|
||||
with open(query_file) as report_query:
|
||||
query_string = report_query.read().replace('\n', ' ')
|
||||
cursor.execute(query_string)
|
||||
|
||||
table_header = []
|
||||
for descr in cursor.description:
|
||||
table_header.append(descr[0])
|
||||
table_content = cursor.fetchall()
|
||||
|
||||
report_data.append((header, table_header, table_content))
|
||||
|
||||
return report_data
|
||||
|
||||
def generate_report_html(self, group, report_data):
|
||||
# Pre-set email with style information and header
|
||||
all_html = """
|
||||
<style>
|
||||
h1 { margin: 0; padding: 0; }
|
||||
h2 { margin: 0; padding: 30px 0 10px 0; }
|
||||
th { text-align: left; }
|
||||
th, td { padding: 0 12px; }
|
||||
td { text-align: right; white-space: nowrap; }
|
||||
td:first-child { text-align: left; white-space: nowrap; }
|
||||
</style>
|
||||
<h1>Weekly Add-on %sReviews Report</h1>
|
||||
<h3>%s - %s</h3>
|
||||
""" % (('Content ' if group == 'content' else ''),
|
||||
self.week_begin, self.week_end)
|
||||
|
||||
# For each group, execute the individual SQL reports
|
||||
# and build the HTML email.
|
||||
|
||||
for section in report_data:
|
||||
all_html += '<h2>%s</h2>\n' % section[0]
|
||||
|
||||
table_html = '<table>\n'
|
||||
table_html += '<tr><th>' + '</th><th>'.join(
|
||||
[header for header in section[1]]) + '</th></tr>\n'
|
||||
for row in section[2]:
|
||||
table_html += '<tr><td>' + '</td><td>'.join(
|
||||
[entry for entry in row]) + '</td></tr>\n'
|
||||
table_html += '</table>\n'
|
||||
all_html += table_html
|
||||
|
||||
# Some email clients (e.g. GMail) require all styles to be inline.
|
||||
# 'transform' takes the file-wide styles defined above and transforms
|
||||
# them to be inline styles.
|
||||
return transform(all_html)
|
||||
|
||||
def mail_report(self, recipient, subject, content):
|
||||
log.info("Sending report '%s' to %s." % (subject, recipient))
|
||||
|
||||
send_mail(subject,
|
||||
content,
|
||||
from_email='nobody@mzilla.org',
|
||||
recipient_list=[recipient],
|
||||
html_message=content,
|
||||
reply_to=[recipient])
|
|
@ -0,0 +1,30 @@
|
|||
SELECT 'All Reviewers' AS `Group`,
|
||||
FORMAT(SUM(aa.weight), 0) AS `Total Risk`,
|
||||
FORMAT(AVG(aa.weight), 2) AS `Average Risk`,
|
||||
FORMAT(COUNT(*), 0) AS `Add-ons Reviewed`
|
||||
FROM editors_autoapprovalsummary aa
|
||||
JOIN reviewer_scores rs ON rs.version_id = aa.version_id
|
||||
WHERE DATE(rs.created) BETWEEN @WEEK_BEGIN AND @WEEK_END
|
||||
/* Filter out internal task user */
|
||||
AND user_id <> 4757633
|
||||
/* The type of review, see constants/reviewers.py */
|
||||
AND rs.note_key IN (10, 12, 20, 22, 30, 32, 50, 52, 102, 103, 104, 105)
|
||||
UNION ALL
|
||||
SELECT 'Volunteers' AS `Group`,
|
||||
FORMAT(SUM(aa.weight), 0) AS `Total Risk`,
|
||||
FORMAT(AVG(aa.weight), 2) AS `Average Risk`,
|
||||
FORMAT(COUNT(*), 0) AS `Add-ons Reviewed`
|
||||
FROM editors_autoapprovalsummary aa
|
||||
JOIN reviewer_scores rs ON rs.version_id = aa.version_id
|
||||
WHERE DATE(rs.created) BETWEEN @WEEK_BEGIN AND @WEEK_END
|
||||
/* Filter out internal task user */
|
||||
AND user_id <> 4757633
|
||||
/* The type of review, see constants/reviewers.py */
|
||||
AND rs.note_key IN (10, 12, 20, 22, 30, 32, 50, 52, 102, 103, 104, 105)
|
||||
AND rs.user_id NOT IN
|
||||
(SELECT user_id
|
||||
FROM groups_users
|
||||
WHERE group_id IN
|
||||
(SELECT id
|
||||
FROM groups
|
||||
WHERE name IN ('Staff', 'No Reviewer Incentives')));
|
|
@ -0,0 +1,19 @@
|
|||
SELECT u.display_name AS `Name`,
|
||||
IFNULL(FORMAT(SUM(rs.score), 0), 0) AS `Points`,
|
||||
FORMAT(COUNT(*), 0) AS `Add-ons Reviewed`
|
||||
FROM reviewer_scores rs
|
||||
JOIN users u ON u.id = rs.user_id
|
||||
WHERE DATE(rs.created) BETWEEN @QUARTER_BEGIN AND @WEEK_END
|
||||
/* Filter out internal task user */
|
||||
AND user_id <> 4757633
|
||||
/* The type of review, see constants/reviewers.py */
|
||||
AND rs.note_key IN (10, 12, 20, 22, 30, 32, 50, 52, 102, 103, 104, 105)
|
||||
AND rs.user_id NOT IN
|
||||
(SELECT user_id
|
||||
FROM groups_users
|
||||
WHERE group_id IN
|
||||
(SELECT id
|
||||
FROM groups
|
||||
WHERE name IN ('Staff', 'No Reviewer Incentives')))
|
||||
GROUP BY rs.user_id
|
||||
ORDER BY SUM(rs.score) DESC;
|
|
@ -0,0 +1,32 @@
|
|||
SELECT risk_category AS `Risk Category`,
|
||||
FORMAT(SUM(n), 0) AS `All Reviewers`,
|
||||
FORMAT(SUM(CASE WHEN `group_category` = 'volunteer' THEN n ELSE 0 END), 0) AS 'Volunteers'
|
||||
FROM
|
||||
(SELECT CASE
|
||||
WHEN weight > @RISK_HIGHEST THEN 'highest'
|
||||
WHEN weight > @RISK_HIGH THEN 'high'
|
||||
WHEN weight > @RISK_MEDIUM THEN 'medium'
|
||||
ELSE 'low'
|
||||
END AS risk_category,
|
||||
group_category,
|
||||
COUNT(*) AS n
|
||||
FROM editors_autoapprovalsummary aa
|
||||
JOIN
|
||||
(SELECT version_id,
|
||||
CASE WHEN user_id NOT IN
|
||||
(SELECT user_id
|
||||
FROM groups_users
|
||||
WHERE group_id IN
|
||||
(SELECT id
|
||||
FROM groups
|
||||
WHERE name IN ('Staff', 'No Reviewer Incentives'))) THEN 'volunteer' ELSE 'all' END AS `group_category`
|
||||
FROM reviewer_scores rs
|
||||
WHERE DATE(rs.created) BETWEEN @WEEK_BEGIN AND @WEEK_END
|
||||
/* Filter out internal task user */
|
||||
AND user_id <> 4757633
|
||||
/* The type of review, see constants/reviewers.py */
|
||||
AND rs.note_key IN (10, 12, 20, 22, 30, 32, 50, 52, 102, 103, 104, 105)) reviews ON reviews.version_id = aa.version_id
|
||||
GROUP BY risk_category,
|
||||
`group_category`) risk
|
||||
GROUP BY 1
|
||||
ORDER BY FIELD(risk_category,'highest','high','medium', 'low');
|
|
@ -0,0 +1,30 @@
|
|||
SELECT u.display_name AS `Name`,
|
||||
IF(
|
||||
(SELECT DISTINCT(user_id)
|
||||
FROM groups_users
|
||||
WHERE group_id IN
|
||||
(SELECT id
|
||||
FROM groups
|
||||
WHERE name IN ('Staff', 'No Reviewer Incentives'))
|
||||
AND user_id = rs.user_id), '*', '') AS `Staff`,
|
||||
FORMAT(SUM(aa.weight), 0) AS `Total Risk`,
|
||||
FORMAT(AVG(aa.weight), 2) AS `Average Risk`,
|
||||
IFNULL(IF(
|
||||
(SELECT DISTINCT(user_id)
|
||||
FROM groups_users
|
||||
WHERE group_id IN
|
||||
(SELECT id
|
||||
FROM groups
|
||||
WHERE name IN ('Staff', 'No Reviewer Incentives'))
|
||||
AND user_id = rs.user_id), '-', SUM(rs.score)), 0) AS `Points`,
|
||||
FORMAT(COUNT(*), 0) AS `Add-ons Reviewed`
|
||||
FROM editors_autoapprovalsummary aa
|
||||
JOIN reviewer_scores rs ON rs.version_id = aa.version_id
|
||||
JOIN users u ON u.id = rs.user_id
|
||||
WHERE DATE(rs.created) BETWEEN @WEEK_BEGIN AND @WEEK_END
|
||||
/* Filter out internal task user */
|
||||
AND user_id <> 4757633
|
||||
/* The type of review, see constants/reviewers.py */
|
||||
AND rs.note_key IN (10, 12, 20, 22, 30, 32, 50, 52, 102, 103, 104, 105)
|
||||
GROUP BY user_id HAVING `Add-ons Reviewed` >= 5
|
||||
ORDER BY SUM(aa.weight) DESC;
|
|
@ -0,0 +1,26 @@
|
|||
SELECT 'All Reviewers' AS `Group`,
|
||||
FORMAT(COUNT(*), 0) AS `Add-ons Reviewed`
|
||||
FROM editors_autoapprovalsummary aa
|
||||
JOIN reviewer_scores rs ON rs.version_id = aa.version_id
|
||||
WHERE DATE(rs.created) BETWEEN @WEEK_BEGIN AND @WEEK_END
|
||||
/* Filter out internal task user */
|
||||
AND user_id <> 4757633
|
||||
/* The type of review, see constants/reviewers.py */
|
||||
AND rs.note_key IN (101)
|
||||
UNION ALL
|
||||
SELECT 'Volunteers' AS `Group`,
|
||||
FORMAT(COUNT(*), 0) AS `Add-ons Reviewed`
|
||||
FROM editors_autoapprovalsummary aa
|
||||
JOIN reviewer_scores rs ON rs.version_id = aa.version_id
|
||||
WHERE DATE(rs.created) BETWEEN @WEEK_BEGIN AND @WEEK_END
|
||||
/* Filter out internal task user */
|
||||
AND user_id <> 4757633
|
||||
/* The type of review, see constants/reviewers.py */
|
||||
AND rs.note_key IN (101)
|
||||
AND rs.user_id NOT IN
|
||||
(SELECT user_id
|
||||
FROM groups_users
|
||||
WHERE group_id IN
|
||||
(SELECT id
|
||||
FROM groups
|
||||
WHERE name IN ('Staff', 'No Reviewer Incentives')));
|
|
@ -0,0 +1,19 @@
|
|||
SELECT u.display_name AS `Name`,
|
||||
IFNULL(FORMAT(SUM(rs.score), 0), 0) AS `Points`,
|
||||
FORMAT(COUNT(*), 0) AS `Add-ons Reviewed`
|
||||
FROM reviewer_scores rs
|
||||
JOIN users u ON u.id = rs.user_id
|
||||
WHERE DATE(rs.created) BETWEEN @QUARTER_BEGIN AND @WEEK_END
|
||||
/* Filter out internal task user */
|
||||
AND user_id <> 4757633
|
||||
/* The type of review, see constants/reviewers.py */
|
||||
AND rs.note_key IN (101)
|
||||
AND rs.user_id NOT IN
|
||||
(SELECT user_id
|
||||
FROM groups_users
|
||||
WHERE group_id IN
|
||||
(SELECT id
|
||||
FROM groups
|
||||
WHERE name IN ('Staff', 'No Reviewer Incentives')))
|
||||
GROUP BY rs.user_id
|
||||
ORDER BY SUM(rs.score) DESC;
|
|
@ -0,0 +1,28 @@
|
|||
SELECT u.display_name AS `Name`,
|
||||
IF(
|
||||
(SELECT DISTINCT(user_id)
|
||||
FROM groups_users
|
||||
WHERE group_id IN
|
||||
(SELECT id
|
||||
FROM groups
|
||||
WHERE name IN ('Staff', 'No Reviewer Incentives'))
|
||||
AND user_id = rs.user_id), '*', '') AS `Staff`,
|
||||
IFNULL(IF(
|
||||
(SELECT DISTINCT(user_id)
|
||||
FROM groups_users
|
||||
WHERE group_id IN
|
||||
(SELECT id
|
||||
FROM groups
|
||||
WHERE name IN ('Staff', 'No Reviewer Incentives'))
|
||||
AND user_id = rs.user_id), '-', SUM(rs.score)), 0) AS `Points`,
|
||||
FORMAT(COUNT(*), 0) AS `Add-ons Reviewed`
|
||||
FROM editors_autoapprovalsummary aa
|
||||
JOIN reviewer_scores rs ON rs.version_id = aa.version_id
|
||||
JOIN users u ON u.id = rs.user_id
|
||||
WHERE DATE(rs.created) BETWEEN @WEEK_BEGIN AND @WEEK_END
|
||||
/* Filter out internal task user */
|
||||
AND user_id <> 4757633
|
||||
/* The type of review, see constants/reviewers.py */
|
||||
AND rs.note_key IN (101)
|
||||
GROUP BY user_id HAVING `Add-ons Reviewed` >= 10
|
||||
ORDER BY `Add-ons Reviewed` DESC;
|
|
@ -0,0 +1,156 @@
|
|||
from datetime import date, timedelta
|
||||
from freezegun import freeze_time
|
||||
|
||||
from django.core import mail
|
||||
|
||||
from olympia import amo
|
||||
from olympia.amo.tests import TestCase, user_factory, addon_factory
|
||||
from olympia.reviewers.management.commands.review_reports import Command
|
||||
from olympia.reviewers.models import AutoApprovalSummary, ReviewerScore
|
||||
|
||||
|
||||
class TestReviewReports(TestCase):
|
||||
today = date.today()
|
||||
last_week_begin = today - timedelta(days=today.weekday() + 7)
|
||||
last_week_end = today - timedelta(days=today.weekday() + 1)
|
||||
this_quarter_begin = date(today.year, (today.month - 1) // 3 * 3 + 1, 1)
|
||||
|
||||
def create_and_review_addon(self, user, weight, verdict, content_review):
|
||||
addon = addon_factory()
|
||||
AutoApprovalSummary.objects.create(
|
||||
version=addon.current_version, verdict=verdict, weight=weight)
|
||||
ReviewerScore.award_points(
|
||||
user, addon, addon.status, version=addon.versions.all()[0],
|
||||
post_review=True, content_review=content_review)
|
||||
|
||||
def setUp(self):
|
||||
super(TestReviewReports, self).setUp()
|
||||
with freeze_time(self.last_week_begin):
|
||||
reviewer1 = user_factory(display_name='Volunteer A')
|
||||
reviewer2 = user_factory(display_name='Staff B')
|
||||
reviewer3 = user_factory(display_name='Volunteer Content C')
|
||||
reviewer4 = user_factory(display_name='Staff Content D')
|
||||
self.grant_permission(reviewer2, '', name='Staff')
|
||||
self.grant_permission(reviewer4, '', name='No Reviewer Incentives')
|
||||
|
||||
data = [
|
||||
(reviewer1, 178, amo.AUTO_APPROVED, False),
|
||||
(reviewer1, 95, amo.AUTO_APPROVED, False),
|
||||
(reviewer1, 123, amo.NOT_AUTO_APPROVED, False),
|
||||
(reviewer1, 328, amo.AUTO_APPROVED, False),
|
||||
(reviewer1, 450, amo.AUTO_APPROVED, False),
|
||||
(reviewer1, 999, amo.NOT_AUTO_APPROVED, False),
|
||||
(reviewer1, 131, amo.AUTO_APPROVED, False),
|
||||
(reviewer1, 74, amo.NOT_AUTO_APPROVED, False),
|
||||
(reviewer1, 15, amo.AUTO_APPROVED, False),
|
||||
|
||||
(reviewer2, 951, amo.NOT_AUTO_APPROVED, False),
|
||||
(reviewer2, 8421, amo.AUTO_APPROVED, False),
|
||||
(reviewer2, 281, amo.AUTO_APPROVED, False),
|
||||
(reviewer2, 54, amo.NOT_AUTO_APPROVED, False),
|
||||
(reviewer2, 91, amo.NOT_AUTO_APPROVED, False),
|
||||
(reviewer2, 192, amo.AUTO_APPROVED, False),
|
||||
(reviewer2, 222, amo.NOT_AUTO_APPROVED, False),
|
||||
|
||||
(reviewer3, 178, amo.AUTO_APPROVED, True),
|
||||
(reviewer3, 95, amo.AUTO_APPROVED, True),
|
||||
(reviewer3, 123, amo.NOT_AUTO_APPROVED, True),
|
||||
(reviewer3, 328, amo.AUTO_APPROVED, True),
|
||||
(reviewer3, 450, amo.AUTO_APPROVED, True),
|
||||
(reviewer3, 999, amo.NOT_AUTO_APPROVED, True),
|
||||
(reviewer3, 131, amo.AUTO_APPROVED, True),
|
||||
(reviewer3, 74, amo.NOT_AUTO_APPROVED, True),
|
||||
(reviewer3, 15, amo.AUTO_APPROVED, True),
|
||||
(reviewer3, 48, amo.AUTO_APPROVED, True),
|
||||
(reviewer3, 87, amo.NOT_AUTO_APPROVED, True),
|
||||
(reviewer3, 265, amo.AUTO_APPROVED, True),
|
||||
|
||||
(reviewer4, 951, amo.NOT_AUTO_APPROVED, True),
|
||||
(reviewer4, 8421, amo.AUTO_APPROVED, True),
|
||||
(reviewer4, 281, amo.AUTO_APPROVED, True),
|
||||
(reviewer4, 54, amo.NOT_AUTO_APPROVED, True),
|
||||
(reviewer4, 91, amo.NOT_AUTO_APPROVED, True),
|
||||
(reviewer4, 192, amo.AUTO_APPROVED, True),
|
||||
(reviewer4, 222, amo.NOT_AUTO_APPROVED, True),
|
||||
(reviewer4, 192, amo.AUTO_APPROVED, True),
|
||||
(reviewer4, 444, amo.NOT_AUTO_APPROVED, True),
|
||||
(reviewer4, 749, amo.AUTO_APPROVED, True),
|
||||
]
|
||||
for review_action in data:
|
||||
self.create_and_review_addon(review_action[0],
|
||||
review_action[1],
|
||||
review_action[2],
|
||||
review_action[3])
|
||||
|
||||
def test_report_addon_reviewer(self):
|
||||
command = Command()
|
||||
data = command.fetch_report_data('addon')
|
||||
assert data == [
|
||||
('Weekly Add-on Reviews, 5 Reviews or More',
|
||||
['Name', 'Staff', 'Total Risk', 'Average Risk', 'Points',
|
||||
'Add-ons Reviewed'],
|
||||
((u'Staff B', u'*', u'10,212', u'1,458.86', '-', u'7'),
|
||||
(u'Volunteer A', u'', u'2,393', u'265.89', '810', u'9'))),
|
||||
('Weekly Volunteer Contribution Ratio',
|
||||
['Group', 'Total Risk', 'Average Risk', 'Add-ons Reviewed'],
|
||||
((u'All Reviewers', u'12,605', u'787.81', u'16'),
|
||||
(u'Volunteers', u'2,393', u'265.89', u'9'))),
|
||||
('Weekly Add-on Reviews by Risk Profiles',
|
||||
['Risk Category', 'All Reviewers', 'Volunteers'],
|
||||
((u'highest', u'6', u'3'), (u'high', u'3', u'1'),
|
||||
(u'medium', u'4', u'3'), (u'low', u'3', u'2'))),
|
||||
('Quarterly contributions',
|
||||
['Name', 'Points', 'Add-ons Reviewed'],
|
||||
((u'Volunteer A', u'810', u'9'),))
|
||||
]
|
||||
|
||||
html = command.generate_report_html('addon', data)
|
||||
|
||||
assert 'Weekly Add-on Reviews Report' in html
|
||||
assert 'Volunteer A' in html
|
||||
assert 'Staff B' in html
|
||||
|
||||
to = 'addon-reviewers@mozilla.org'
|
||||
subject = '%s %s-%s' % (
|
||||
'Weekly Add-on Reviews Report',
|
||||
self.last_week_begin, self.last_week_end)
|
||||
command.mail_report(to, subject, html)
|
||||
|
||||
assert len(mail.outbox) == 1
|
||||
email = mail.outbox[0]
|
||||
assert to in email.to
|
||||
assert subject in email.subject
|
||||
|
||||
def test_report_content_reviewer(self):
|
||||
command = Command()
|
||||
data = command.fetch_report_data('content')
|
||||
|
||||
assert data == [
|
||||
('Weekly Content Reviews, 10 Reviews or More',
|
||||
['Name', 'Staff', 'Points', 'Add-ons Reviewed'],
|
||||
((u'Volunteer Content C', u'', '120', u'12'),
|
||||
(u'Staff Content D', u'*', '-', u'10'))),
|
||||
('Weekly Volunteer Contribution Ratio',
|
||||
['Group', 'Add-ons Reviewed'],
|
||||
((u'All Reviewers', u'22'), (u'Volunteers', u'12'))),
|
||||
('Quarterly contributions',
|
||||
['Name', 'Points', 'Add-ons Reviewed'],
|
||||
((u'Volunteer Content C', u'120', u'12'),))
|
||||
]
|
||||
|
||||
html = command.generate_report_html('content', data)
|
||||
|
||||
assert 'Weekly Add-on Content Reviews Report' in html
|
||||
assert 'Volunteer Content C' in html
|
||||
assert 'Staff Content D' in html
|
||||
|
||||
to = 'addon-content-reviewers@mozilla.org'
|
||||
subject = '%s %s-%s' % (
|
||||
'Weekly Add-on Content Reviews Report',
|
||||
self.last_week_begin, self.last_week_end)
|
||||
command.mail_report(to, subject, html)
|
||||
|
||||
assert len(mail.outbox) == 1
|
||||
email = mail.outbox[0]
|
||||
assert to in email.to
|
||||
assert subject in email.subject
|
Загрузка…
Ссылка в новой задаче