closes EVAL-1333
flag=grade_calc_ignore_unposted_anonymous
Test Plan:
1. Enable the 'Ignore Unposted Anonymous Assignments in Grade
Calculation' release flag. Create an anonymous assignment and
grade some students.
2. Before posting the assignment, export the gradebook. Verify:
- The CSV includes a column for the anonymous assignment.
- The CSV totals (assignment group and final grade) exclude the
scores for the anonymous assignment in their calculations.
3. Disable the 'Ignore Unposted Anonymous Assignments in Grade
Calculation' release flag.
4. Re-export the gradebook. Verify:
- The CSV includes a column for the anonymous assignment.
- The CSV totals (assignment group and final grade) include the
scores for the anonymous assignment in their calculations.
5. Post the assignment to students. Then export the gradebook again and
verify the exported CSV includes a column for the anonymous
assigment the totals include the scores for the anonymous
assignment.
6. Re-enable the 'Ignore Unposted Anonymous Assignments in Grade
Calculation' release flag and re-export the Gradebook. Verify the
exported CSV includes a column for the anonymous assigment the
totals include the scores for the anonymous assignment.
Change-Id: If83237344ee16c9f6621c5d58cfb49e2da099f7b
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/254081
Product-Review: Syed Hussain <shussain@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
QA-Review: Gary Mei <gmei@instructure.com>
Reviewed-by: Gary Mei <gmei@instructure.com>
Reviewed-by: Adrian Packel <apackel@instructure.com>
This catches expected exceptions from the GradeCalculator and
DueDateCacher, logs them, and then signals to delayed jobs to retry.
test plan:
- specs pass
Change-Id: I7851c1df59c43facd621c7aab7fbc29fd6ff6fd9
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/254962
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Syed Hussain <shussain@instructure.com>
Reviewed-by: Spencer Olson <solson@instructure.com>
QA-Review: Keith Garner <kgarner@instructure.com>
Product-Review: Keith Garner <kgarner@instructure.com>
closes EVAL-1272
flag=grade_calc_ignore_unposted_anonymous
Test Plan:
1. Enable the 'Ignore Unposted Anonymous Assignments in Grade
Calculation' release flag. Create an anonymous assignment and
grade some students.
2. Before posting the assignment, enter a rails console and check the
unposted_* scores for the students. Verify:
- The unposted_* scores do not include the submission score from the
anonymous unposted assignment.
3. Disable the 'Ignore Unposted Anonymous Assignments in Grade
Calculation' release flag.
4. Enter a rails console again and check the unposted_* scores for the
students. Verify:
- The unposted_* scores include the submission score from the
anonymous unposted assignment.
5. Post the assignment to students. Then enter a rails console again and
verify the unposted_* scores for the students include the submission
score from the anonymous (now posted) assignment.
6. Re-enable the 'Ignore Unposted Anonymous Assignments in Grade
Calculation' release flag. Verify the unposted_* scores for the
students include the submission score from the anonymous (now posted)
assignment.
Change-Id: Ibb42b9f3164c08e3bc2a21fc02736760f58af51a
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/251786
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Product-Review: Syed Hussain <shussain@instructure.com>
Reviewed-by: Adrian Packel <apackel@instructure.com>
Reviewed-by: Gary Mei <gmei@instructure.com>
QA-Review: Kai Bjorkman <kbjorkman@instructure.com>
fixes FOO-1201
Change-Id: I96d43545cf165bec3603430acab0ef47fe9f20c4
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/254170
Reviewed-by: Simon Williams <simon@instructure.com>
QA-Review: Simon Williams <simon@instructure.com>
Product-Review: Simon Williams <simon@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Switching to postgres 12 exposed some float addition that was resulting
in long precision. It looks like 9.5 was hiding that helpfully, but the
behavior isn't guaranteed and somewhere from 9.5 to 12 had changes in
that regard.
fixes EVAL-1104
flag=none
Test Plan
- Have postgres12.
- Have 2 assignments worth 1000 points each.
- Give a grade of 142.7 and a grade of 99.6.
- Verify in a console that there isn't floating point weirdness for the
user's scores.
Change-Id: Ic2c85a12909a3c99d7a58351ca9b4f0df4ff656e
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/245252
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Keith Garner <kgarner@instructure.com>
Reviewed-by: Syed Hussain <shussain@instructure.com>
Reviewed-by: Kai Bjorkman <kbjorkman@instructure.com>
QA-Review: Kai Bjorkman <kbjorkman@instructure.com>
Product-Review: Syed Hussain <shussain@instructure.com>
closes TALLY-704
flag=none
Test Plan:
1. Create a brand-new course and add some students.
2. Verify that all scores associated with the course have a
root_account_id set:
c = Course.find(<id>)
scores = Score.where(enrollment: c.all_enrollments)
scores.pluck(:root_account_id) # should all be set (not null)
Change-Id: I549d82c40a2057cc1fdcff604b5e5e7a9285f0ac
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/239417
Reviewed-by: Gary Mei <gmei@instructure.com>
Reviewed-by: Adrian Packel <apackel@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
QA-Review: Syed Hussain <shussain@instructure.com>
Product-Review: Syed Hussain <shussain@instructure.com>
This caches the averages for the teacher's grade as part of the score
statistics generator. This rewrite removes the need for a course-level
cache busting as it was only used
closes TALLY-851
flag=none
test plan:
- Have a few courses with a few assignments and a few students
- As a teacher, grade the students
- As a teacher, go to /grades
- Ensure values for all the teacher's courses appear
- Ensure the values are correct (i.e. the average of each courses
current scores for all active and invited enrollments)
Change-Id: Ieeb5ddb734d8bc21f40196014d062b9ba5935ebd
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/234109
Reviewed-by: Jeremy Neander <jneander@instructure.com>
Reviewed-by: Adrian Packel <apackel@instructure.com>
QA-Review: Robin Kuss <rkuss@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Product-Review: Keith Garner <kgarner@instructure.com>
We invalidate the course cache by touching the course too often. This
can cause issues in the database at scale. This patchset only touches
the course once after all the calculator work is done.
closes TALLY-849
test plan:
- specs pass
Change-Id: Id006b9618ab89c003bd2d4b354247036dca9ce09
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/234082
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
Reviewed-by: Spencer Olson <solson@instructure.com>
QA-Review: Keith Garner <kgarner@instructure.com>
Product-Review: Keith Garner <kgarner@instructure.com>
closes TALLY-792
flag=grade_calculator_performance_improvements
Fixes N+1s around observers, observer alerts, and observer alert
thresholds.
Test Plan:
1. Enable the 'Grade Calculator Performance Improvements' release
flag at /accounts/site_admin/settings
2. Smoke test to make sure observers receive 'course_grade_high'
and 'course_grade_low' alerts when an observee gets graded and the
grade is above or below the set threshold, respectively.
3. Disable the 'Grade Calculator Performance Improvements' release
flag at /accounts/site_admin/settings. Repeat step 2.
Change-Id: Ie9c3139006fed9eeec9af0aababad87bb6adb8df
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/232210
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Gary Mei <gmei@instructure.com>
Reviewed-by: Keith Garner <kgarner@instructure.com>
QA-Review: Robin Kuss <rkuss@instructure.com>
Product-Review: Spencer Olson <solson@instructure.com>
Fires any time a student's course grade has changed.
Dig needs this event.
This also updates ObserverAlerts to only make one alert per
student+course in the case that the student is enrolled in multiple
sections of the same course. (Checked with mobile team to make sure
this is OK).
It also moves creating the alerts until after calculate_hidden_scores.
This shouldn't matter because the hidden (unposted) scores don't affect
the ObserverAlerts which only care about current_score. (Really we
could ignore the observer alert code if @ignore_muted is true
but I didn't want to change too much. Likewise, @ignore_muted
and @emit_live_event should be synonymous but I wanted to be explicit
and not rely on that always being the case.)
This also reloads scores all at once instead of individually, which
means less SQL queries and simplifies the code (especially since
reloading an object undoes the preloading of the enrollment).
refs PLAT-5189
flag=none
Test plan:
- Add `puts JSON.pretty_generate(event)` to
gems/live_events/lib/live_events/client.rb:103 (#post_event) to see
events locally
- watch for live events when going through various workflows which
change course grades and make sure only one event per course+student is
emitted
1. change an assignment grade for a student enrolled in multiple
sections -- only one event should be triggered
2. group assignments
3. a call to compute_and_save_scores where
@update_all_grading_period_scores is true (we start grading a
course/student and this kicks off scoring of all grading period
scores)
4. a call to compute_and_save_scores where @update_course_score is
true (we start by scoring a grading period and this starts scoring the
related student/course)
5. any thing else we can think of. grade_calculator experts or other
product experts may be able to suggest other scenarios.
- test these scenarios out with the "observer alerts" in the Canvas
Parent mobile app to make sure these events still work right.
Change-Id: I1d6d530149962a97890656566e26bc32dbb4c190
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/219208
Tested-by: Jenkins
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Product-Review: Oxana Jurosevic
Reviewed-by: Matt Sessions <msessions@instructure.com>
Reviewed-by: Xander Moffatt <xmoffatt@instructure.com>
Reviewed-by: Spencer Olson <solson@instructure.com>
QA-Review: Tucker Mcknight <tmcknight@instructure.com>
According to sentry removing the transaction made the deadlock problem worse. Reverting until a new approach can be had.
test plan:
- grade calculator specs pass
This reverts commit 8aacb717cc.
Change-Id: I7899641b6e6f8430fa343bf9f1bd4ef6fe9822ea
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/215436
Tested-by: Jenkins
QA-Review: Keith Garner <kgarner@instructure.com>
Product-Review: Keith Garner <kgarner@instructure.com>
Reviewed-by: Nick Pitrak <npitrak@instructure.com>
Removes a database transaction in the grade calculator that is scoped
around too much work. The transaction was originally added before
postgres's upsert capability for two statements. Over time, more and
more work was added leading to deadlocks in production.
test plan:
- spec pass
Change-Id: Ia95035be6934b148f8d836bf4419f978a0b45918
Reviewed-on: https://gerrit.instructure.com/212873
Reviewed-by: Spencer Olson <solson@instructure.com>
Reviewed-by: Derek Bender <djbender@instructure.com>
Tested-by: Jenkins
QA-Review: Keith Garner <kgarner@instructure.com>
Product-Review: Keith Garner <kgarner@instructure.com>
When the grade calculator attempts to apply drop rules, don't
automatically exempt muted assignments (or unposted submissions in the
case of Post Policies) from being dropped. Continue treating them as 0
points (if computing final score) or ignoring them altogether (if
computing posted score), but generally allow them to be dropped. This
fixes a calculation issue that could occur for an assignment group with
drop rules: muted/unposted submissions that should have been dropped
completely were still included (but treated as 0 points), with the
result that the group's points_possible value was higher than could ever
have been attained given the drop rules in place.
fixes GRADE-2356
Test plan:
- Have a course with New Gradebook and Post Policies enabled
- Set up an assignment group
- Add 2 assignments worth 10 points each
- Set a drop rule to drop the lowest assignment
- Open Gradebook
- Grade a student on the first assignment but not the second
- Export to CSV
- The "final score" column should reflect just the one graded
assignment and should not treat the ungraded assignment as 0
- Repeat this setup in an Old Gradebook course
- Mute the second assignment (to make it "unposted")
- Export to CSV
- The "final score" column should be the same as above
Change-Id: I91903d481fcbedf60180e5dcabe96106308586e9
Reviewed-on: https://gerrit.instructure.com/205856
Product-Review: Keith Garner <kgarner@instructure.com>
Tested-by: Jenkins
Reviewed-by: Keith Garner <kgarner@instructure.com>
Reviewed-by: Gary Mei <gmei@instructure.com>
QA-Review: Derek Bender <djbender@instructure.com>
- A variable named "submission" was actually a hash containing (among
other things) a submission and an assignment, so checking
submission.posted? was not okay
- Moreover, the submission that said submission-hash contained could
have been set to nil if the submission had not yet been posted (or, in
the pre-post-policies world, the assignment was muted). This wasn't an
issue before, but became one since with post policies we check
individual submissions.
fixes GRADE-2268
Test plan:
- Specs pass
- Enable post policies/new gradebook
- Have a course with assignment groups and a drop rule (at least one
"drop highest" or "drop lowest")
- Assign some grades
- Grade calculator should not cause an error
Change-Id: I3a94e7ee4808cc6f38f247b6ee9652ddf6e7f6d0
Reviewed-on: https://gerrit.instructure.com/199187
Tested-by: Jenkins
Reviewed-by: Keith Garner <kgarner@instructure.com>
QA-Review: Adrian Packel <apackel@instructure.com>
Product-Review: Keith Garner <kgarner@instructure.com>
Convert post policies from a garden-variety feature flag into a global
setting and remove the old feature flag. Add some helper methods to
handle enabling and disabling, and have everywhere in the code that
references the feature use the new helper methods instead. Also, have
the activation of post policies for a given course depend on whether new
gradebook is active for that course.
closes GRADE-1974
Test plan:
Note that the Post Policies feature flag no longer exists, and instead
there's a setting you'll need to turn on. You can do so in the console
using:
> PostPolicy.enable_feature!
To disable it:
> PostPolicy.disabled_feature!
Note that, even when enabled, it should only apply to courses that have
new gradebook turned on.
- With the new setting ENABLED:
- Courses with new gradebook behave as though post policies is enabled
- Do a bit of smoke testing to see if stuff like posting/hiding and
changing assignment posting policies hasn't broken
- Courses with old gradebook do not
- For example, calling a mutation like postAssignmentGrades on an OG
course should return an error indicating the feature isn't enabled
- With the new setting DISABLED:
- Courses with new gradebook behave as though post policies is
disabled (e.g., old-style muting is active)
- Calling a mutation, as described above, should return an error
Change-Id: I5e223d2c4ca4202cce0641f316ecaa505a66298c
Reviewed-on: https://gerrit.instructure.com/196062
Tested-by: Jenkins
Reviewed-by: Keith Garner <kgarner@instructure.com>
Reviewed-by: Gary Mei <gmei@instructure.com>
QA-Review: Derek Bender <djbender@instructure.com>
Product-Review: Keith Garner <kgarner@instructure.com>
When Post Policies is enabled, the submission details page will check
that the submission is posted. Otherwise, it checks if the assignment
is muted.
closes GRADE-1995
Test Plan
- Enable Post Policies.
- Create an assignment graded with a rubric.
- Grade a submission via the rubric.
- Leave comments on the submission as the teacher.
- Leave comments on the submission as the student.
- Hide the submission.
- As a teacher, verify that you can see the rubric assessment and all
comments.
- As the student, verify that you can see a blank rubric assessment
and only the student's own comments.
- Post submissions. As both the teacher and student, verify that you
can see all comments, rubric assessment, and the grade.
- Verify that when Post Policies is off, the assignment muted state
is what determines the above, rather than the submission's posted
state.
Change-Id: Id1662f43c24250a0ed6750a1f83f81ff5952ad95
Reviewed-on: https://gerrit.instructure.com/196253
Tested-by: Jenkins
Reviewed-by: Keith Garner <kgarner@instructure.com>
Reviewed-by: Adrian Packel <apackel@instructure.com>
QA-Review: Gary Mei <gmei@instructure.com>
Product-Review: Jonathan Fenton <jfenton@instructure.com>
This fixes a very specific corner case in the grade calculator. When
drop rules eliminated all pointed assignments in the drop highest
phase and ended up with only unpointed assignments being considered in
the dropped lowest phase the grade calculator would error out as it
attempted to subtract from nil. Since we can't do the drop math that
is expected in this phase, the grade calculator will act similar to
dropping for all unpointed assignments.
fixes GRADE-2209
test plan:
- (For this test plan you'll need to look at the canvas logs)
- Create an course with a student
- In the default assignment group, create three assignments, 2 of
which are 0 points possible and 1 with some number of points
possible.
- Adjust the assignment group drop rules to drop one highest
and one lowest
- Score the assignments
- Confirm in the logs that none of the runs of the grade calculator
crashed with the error "undefined method `+' for nil:NilClass"
- Confirm the course score for the student is nil
Change-Id: I10ac06d5b99b5c328b0b509902268af57bfc0c37
Reviewed-on: https://gerrit.instructure.com/193580
Reviewed-by: Jeremy Neander <jneander@instructure.com>
Reviewed-by: Adrian Packel <apackel@instructure.com>
QA-Review: Adrian Packel <apackel@instructure.com>
Tested-by: Jenkins
Product-Review: Keith Garner <kgarner@instructure.com>
ff83302bb0 stopped populating the cache with assignment stat
data, however, the code to invalidate the cache remained just burning
time. This removes the function to invalidate the cache and the code
that calls it.
test plan:
- specs pass
- Confirm grade calculator and student grades page still function.
Change-Id: I5bcd29359addfd9d46f161c74d2e433417914a4f
Reviewed-on: https://gerrit.instructure.com/193869
Reviewed-by: Adrian Packel <apackel@instructure.com>
Tested-by: Jenkins
QA-Review: Keith Garner <kgarner@instructure.com>
Product-Review: Keith Garner <kgarner@instructure.com>
If post policies is enabled, have the grade calculator, rather than
ignoring all submissions for muted assignments, ignore submissions that
have not been posted. Also make sure we recalculate grades when
posting/hiding submissions.
closes GRADE-36
Test plan:
- Enable post policies
- Create some assignments, make at least one manually-posted
- Assign some scores
- When you post or hide submissions, the Score objects associated
with the students/enrollments should be updated
- The computed_ values should not reflect unposted submissions
- The unposted_ values should reflect them
- In a course with post policies disabled
- Make sure muting/unmuting assignments kicks off the grade
calculator (and it calculates as expected)
Change-Id: If08fbfa090cf0174f9f6ee306a3d5ecec81351fc
Reviewed-on: https://gerrit.instructure.com/192075
Tested-by: Jenkins
Reviewed-by: Jeremy Neander <jneander@instructure.com>
Reviewed-by: Gary Mei <gmei@instructure.com>
Reviewed-by: Keith Garner <kgarner@instructure.com>
QA-Review: James Butters <jbutters@instructure.com>
Product-Review: Keith Garner <kgarner@instructure.com>
Have the grade calculator update the scores and score_metadata tables
using a single INSERT ... ON CONFLICT DO UPDATE statement rather than
consecutive UPDATE and INSERT statements. This will (we hope) prevent
separate invocations of the grade calculator from stepping on each
other's toes and interrupting calculations midway through due to
constraint errors.
fixes GRADE-2163
Test plan:
- Specs pass
- Set up a course with some assignment groups and grading periods
- Assign some grades
- Check that scores are being calculated properly and no errors
Change-Id: I894d5040f8a536c4b91d344dffd246fb0d9a6311
Reviewed-on: https://gerrit.instructure.com/192330
Tested-by: Jenkins
Reviewed-by: Keith Garner <kgarner@instructure.com>
QA-Review: Derek Bender <djbender@instructure.com>
Product-Review: Keith Garner <kgarner@instructure.com>
closes GRADE-1512
test plan:
* Smoke test some grade calculations?
Change-Id: Ia26fe7fcb137dd1f5bc07bb77babf3694a268b70
Reviewed-on: https://gerrit.instructure.com/172851
Tested-by: Jenkins
Reviewed-by: Gary Mei <gmei@instructure.com>
Reviewed-by: Keith Garner <kgarner@instructure.com>
QA-Review: James Butters <jbutters@instructure.com>
Product-Review: Keith Garner <kgarner@instructure.com>
Refs MBL-10851
Test Plan:
- Create a student and 2 courses and enroll the student in both
- Create a user and make them an observer in only one course for
the student
- Setup thresholds for assignment_grade, course_grade, and
assignment_missing
- Go to the course the observer is not in and grade the student
above/below the assignment_grade threshold
- This should also trigger the course_grade threshold
- Go to the course and create an assignment that is due in a minute
or two
- Wait at least 5 minutes
- No assignment_missing alert should be created
Change-Id: If05db61a198ada8c2cfce9049d595fb633483882
Reviewed-on: https://gerrit.instructure.com/156852
Tested-by: Jenkins
QA-Review: Kausty Saxena <ksaxena@instructure.com>
Reviewed-by: Layne Moseley <lmoseley@instructure.com>
Product-Review: Matthew Sessions <msessions@instructure.com>
Refs MBL-10742
Test Plan:
- Create a threshold for each type for an observer-student
pairing
- Generate an alert for each threshold type
- The title should match the ticket
- Threshold Types:
- course_grade_low
- course_grade_high
- assignment_grade_low
- assignment_grade_high
- assignment_missing
- course_announcement
- institution_announcement
- For assignment grade thresholds have multiple
assignments that have different display grade as
types and ensure it puts the correct grade in the
alert title
Change-Id: Ia971e707c8da73b09066c5f23a742fe60a64be8f
Reviewed-on: https://gerrit.instructure.com/155341
Tested-by: Jenkins
Reviewed-by: Layne Moseley <lmoseley@instructure.com>
QA-Review: Layne Moseley <lmoseley@instructure.com>
Product-Review: Matthew Sessions <msessions@instructure.com>
Refs MBL-10479
Test Plan:
- Create a course with a student and observer
that are linked
- Create an assignment
- Create a threshold for 'course_grade_low'
- Grade the assignment higher than the threshold
- You shouldnt have an ObserverAlert
- Grade the assignment lower than the threshold
- You should have an ObserverAlert
- Create a threshold for
- Grade the assignment lower than the threshold
- You shouldnt have an ObserverAlert
- Grade the assignment higher than the threshold
- You should have an ObserverAlert
Change-Id: I2149080b52396de45eba61e3164a1c099fbed466
Reviewed-on: https://gerrit.instructure.com/150364
Tested-by: Jenkins
Reviewed-by: Cameron Sutter <csutter@instructure.com>
Product-Review: Cameron Sutter <csutter@instructure.com>
QA-Review: Cameron Sutter <csutter@instructure.com>
Convert values to bigdecimal before computing to avoid rounding issues
in certain edge cases.
closes GRADE-1187
Test Plan:
- specs pass
Change-Id: If5140e24c28647350170f559ffe6f231ed1a6a30
Reviewed-on: https://gerrit.instructure.com/151674
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
Product-Review: Spencer Olson <solson@instructure.com>
QA-Review: Spencer Olson <solson@instructure.com>
The grade calculator can have multiple runs per course if the course
has more than 100 students in it or if single students were being
graded closely together. This patchset invokes the
AssignmentScoreStatisticsGenerator as a singleton from the grade
calculator to avoid running the same calculation multiple times
concurrently.
fixes GRADE-1105
test plan:
* Create a course with a few students and one 100 point assignment
* Grade all students with an assortment of points
* Visit the grade summary page for any student
* Verify that the assignment stats are correct:
- minimum score
- maximum score
- mean score
- number of scores
Change-Id: I29b907117a2a2384d871f7dc33050a50344bcc3c
Reviewed-on: https://gerrit.instructure.com/148176
Tested-by: Jenkins
Reviewed-by: Shahbaz Javeed <sjaveed@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: Adrian Packel <apackel@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
closes GRADE-990
test plan:
* Create a course with a few students and one 100 point assignment
* Grade all students with an assortment of points
* Visit the grade summary page for any student
* Verify that the assignment stats are correct:
- minimum score
- maximum score
- mean score
- number of scores
Change-Id: I1f666b607d8b4570eba8868a8de84c4aa41823c9
Reviewed-on: https://gerrit.instructure.com/144900
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Tested-by: Jenkins
Reviewed-by: Adrian Packel <apackel@instructure.com>
QA-Review: Indira Pai <ipai@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
Change-Id: I93bfcc9407e169e575d96c6d23c8020de07f639b
Reviewed-on: https://gerrit.instructure.com/142581
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Tested-by: Jenkins
Product-Review: James Williams <jamesw@instructure.com>
QA-Review: James Williams <jamesw@instructure.com>
closes GRADE-819
The specific case was to unassign a graded student from an assignment by
removing "Everyone" and adding all students except one to the
assignment. Then remove all students and assign "Everyone" to the
assignment. This should make the previously unassigned student's grades
stale.
test plan:
* Configure delayed jobs to use 6 simultaneously running workers
by editing config/delayed_jobs.yml to look like this:
default:
workers:
- queue: canvas_queue
workers: 6
Notice the line that says "workers: 6"
* Restart the jobs container so all six new workers are started
* Create a published course with one assignment worth 150 points
and two students enrolled
* For the remainder of these steps, let's assume unique identifer
for the course is "course_id" and the unique identifier for
the student is "student_id"
* Go to the Gradebook and grade the first student at 125 points
and wait for their score to be updated in the gradebook.
* Verify the score in the Gradebook is 83.33%
* In a separate tab, visit the following URL, making sure to
replace course_id with the actual course id and student_id
with the actual student id:
/api/v1/courses/course_id/enrollments?user_id=student_id
* Verify that you see the student's current_score as 83.33
* Repeat the following steps multiple times to ensure the
problem does not manifest itself:
- Modify the assignment: unassign it from the first student
and only assign it to the second student only
- Go to the gradebook and verify the cells for the first student
are not editable any more
- Go back to the API URL above and verify the student's
current_score now says null
- Modify the assignment: re-assign it to "Everyone"
- Go to the gradebook and verify the cells for the first student
are now editable again
- Go back to the API URL above and verify the student's
current_score now says 83.33 again. If it ever says null
at this point, there is a problem.
Change-Id: Ifaaf0609dfe5081697c1939db1b4a4e0a3e05bad
Reviewed-on: https://gerrit.instructure.com/141049
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Reviewed-by: Derek Bender <djbender@instructure.com>
Tested-by: Jenkins
Product-Review: Keith T. Garner <kgarner@instructure.com>
QA-Review: Keith T. Garner <kgarner@instructure.com>
closes GRADE-8
test plan:
Store points and points_possible for all Scores
closes GRADE-8
test plan:
** Setup
* Create a course in a term with two grading periods GP1 and GP2
* Weight the grading periods as: GP1: 30%, GP2: 70%
* Create four assignment groups AG1, AG2, AG3 and AG4
- Ensure the assignment groups have a rule to drop the 1 lowest
score
* Weight the assignment groups as: AG1: 15%, AG2: 20%, AG3: 25%, AG4: 40%
* Create three assignments in AG1, AG1-1, AG1-2, AG1-3
- Ensure they're all due in GP1
- Ensure they have the following points possible:
AG1-1: 5, AG1-2: 10, AG1-3: 15
- Mute AG1-1
* Create three assignments in AG2, AG2-1, AG2-2, AG2-3
- Ensure they're all due in GP1
- Ensure they have the following points possible:
AG2-1: 5, AG2-2: 10, AG2-3: 15
- Mute AG2-2
* Create three assignments in AG3, AG3-1, AG3-2, AG3-3
- Ensure they're all due in GP2
- Ensure they have the following points possible:
AG3-1: 5, AG3-2: 10, AG3-3: 15
- Mute AG3-3
* Create three assignments in AG4, AG4-1, AG4-2, AG4-3
- Ensure they're all due in GP2
- Ensure they have the following points possible:
AG4-1: 5, AG4-2: 10, AG4-3: 15
- Mute AG4-1
* Enroll one student in this course
* Go to the Gradebook and ensure you're viewing all grading periods
* Assign the following grades to the student:
AG1-1: 3
AG1-2: 8
AG1-3: 5
AG2-1: 4
AG2-2: 6
AG2-3: 10
AG3-1: 2
AG3-2: 9
AG3-3: 14
AG4-1: 1
AG4-2: 7
AG4-3: 12
** Validating Assignment Group Scores
* Assuming your newly created course's id is course_id, run the
following command from the Rails console:
Score.where(enrollment: Course.find(course_id).enrollments).
where.not(assignment_group_id: nil).order(assignment_group_id: :asc).
pluck(:current_points)
* Verify that this returns [8.0, 4.0, 9.0, 12.0]
* Run the following command from the Rails console:
Score.where(enrollment: Course.find(course_id).enrollments).
where.not(assignment_group_id: nil).order(assignment_group_id: :asc).
pluck(:final_points)
* Verify that this returns [8.0, 10.0, 9.0, 12.0]
* Run the following command from the Rails console:
Score.where(enrollment: Course.find(course_id).enrollments).
where.not(assignment_group_id: nil).order(assignment_group_id: :asc).
pluck(:unposted_current_points)
* Verify that this returns [11.0, 14.0, 23.0, 19.0]
* Run the following command from the Rails console:
Score.where(enrollment: Course.find(course_id).enrollments).
where.not(assignment_group_id: nil).order(assignment_group_id: :asc).
pluck(:unposted_final_points)
* Verify that this returns [11.0, 14.0, 23.0, 19.0]
** Validating Grading Period Scores
* Run the following command from the Rails console:
Score.where(enrollment: Course.find(course_id).enrollments).
where.not(grading_period_id: nil).order(grading_period_id: :asc).
pluck(:current_points)
* Verify that this returns [80.0, 83.85]
* Run the following command from the Rails console:
Score.where(enrollment: Course.find(course_id).enrollments).
where.not(grading_period_id: nil).order(grading_period_id: :asc).
pluck(:final_points)
* Verify that this returns [45.71, 50.77]
* Run the following command from the Rails console:
Score.where(enrollment: Course.find(course_id).enrollments).
where.not(grading_period_id: nil).order(grading_period_id: :asc).
pluck(:unposted_current_points)
* Verify that this returns [71.43, 82.15]
* Run the following command from the Rails console:
Score.where(enrollment: Course.find(course_id).enrollments).
where.not(grading_period_id: nil).order(grading_period_id: :asc).
pluck(:unposted_final_points)
* Verify that this returns [71.43, 82.15]
** Validating Total Scores
* Run the following command from the Rails console:
Score.where(enrollment: Course.find(course_id).enrollments).
where(course_score: true).pluck(:current_points)
* Verify that this returns [82.7]
* Run the following command from the Rails console:
Score.where(enrollment: Course.find(course_id).enrollments).
where(course_score: true).pluck(:final_points)
* Verify that this returns [49.25]
* Run the following command from the Rails console:
Score.where(enrollment: Course.find(course_id).enrollments).
where(course_score: true).pluck(:unposted_current_points)
* Verify that this returns [82.7]
* Run the following command from the Rails console:
Score.where(enrollment: Course.find(course_id).enrollments).
where(course_score: true).pluck(:unposted_final_points)
* Verify that this returns [49.25]
Change-Id: I6a107f09bc43d6e82eab4e3476313380f3e5d819
Reviewed-on: https://gerrit.instructure.com/137257
Reviewed-by: Derek Bender <djbender@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Tested-by: Jenkins
QA-Review: Indira Pai <ipai@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
Fixes calculation of dropped assignments so that muted assignments are
never considered for dropping when computing posted score. In addition,
prevents score metadata for unposted grades from overwriting score
metadata for posted grades.
closes GRADE-763
Test Plan:
* Prerequisites: Have a course with at least one student and one
teacher.
1. Create two assignments in a course with the same point value and
place them in the same assignment group.
2. Set up a grading rule to drop the lowest 1 score.
3. Mute one of the assignments.
4. Have the teacher enter a score of zero for the muted assignment.
5. Have the teacher enter a positive score for the second assignment.
6. Check the teacher interaction report and verify there is
no page error.
Change-Id: I5015ef73bb40bb0a45a21f166fa6b9ff146002da
Reviewed-on: https://gerrit.instructure.com/137538
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Tested-by: Jenkins
QA-Review: Indira Pai <ipai@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
closes GRADE-721
test plan:
* Create a course with two sections, I and II
* Enroll three students in Section I: A, B and C
* Ensure C is enrolled in both Section I and Section II
* Create a 10 point assignment in the default "Assignments" assignment
group and ensure it is assigned to everyone in all sections
* Grade all three students
* Conclude Student C's enrollment in Section I
* Create two more 10 point assignments in the default "Assignments"
assignment group
* Configure the "Assignments" assignment group to drop 1 lowest score
* Grade the students on the two new assignments
* Export the Gradebook and verify it works
* Conclude Student C's enrollment in Section II
* Create two more 10 point assignments in the default "Assignments"
assignment group
* Grade the remaining two students on the two new assignments
* Export the Gradebook and verify it works
Change-Id: I4cafcd1328effdf3a57341978eb494376f680634
Reviewed-on: https://gerrit.instructure.com/135634
Reviewed-by: Spencer Olson <solson@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
Tested-by: Jenkins
QA-Review: Anju Reddy <areddy@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
This updates the grade calculator with a new switch:
only_update_course_gp_metadata. When set to true will only update
ScoreMetadata data for the current score calculations for course and
grading period scores
closes GRADE-711
test plan:
- Have a course with a student, two assignment groups, and an
assignment in each group
- In the rails console:
- examine the scores for the student for that course and note
the updated_at for the course score and the assignment group
scores.
- execute: GradeCalculator.new(@student.id, @course,
only_update_course_gp_metadata: true).compute_and_save_scores
- examine the scores for the student for that course and note that
the updated_at for the course score is unchanged and the
assignment group scores have been updated
- examine the course score's associated ScoreMetadata, note
that updated_at for ScoreMetadata has changed
Change-Id: I81c9302f3dfe50b87c3a87ccef8ec98b677ff6e1
Reviewed-on: https://gerrit.instructure.com/135291
Reviewed-by: Jeremy Neander <jneander@instructure.com>
Reviewed-by: Shahbaz Javeed <sjaveed@instructure.com>
QA-Review: Shahbaz Javeed <sjaveed@instructure.com>
Tested-by: Jenkins
Product-Review: Keith T. Garner <kgarner@instructure.com>
When calculating final scores for a course with grading period
periods, a student with no cached scores would cause the grade
calculator to error out. This patchset fixes the error condition and
changes the grading period to only consider grading period
score objects what have an active workflow state.
fixes GRADE-663
test plan:
- Have a course in a term with weighted grading period
- Add a student to the course
- Confirm no entries in the scores table. If you find entries in the
scores table, destroy them via the rails console
- As a teacher, in the new gradebook, export the gradebook
- Observe it completes without error
Change-Id: I1f6679ba1cc1d9e96cf535ed3d7ed68dc67a4e3c
Reviewed-on: https://gerrit.instructure.com/132854
Tested-by: Jenkins
Reviewed-by: Derek Bender <djbender@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: Indira Pai <ipai@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
Fixes a bug where the grade calculator does not create a course
score for an enrollment if the enrollment has an assignment group
score.
refs GRADE-634
Test Plan:
1. Create a course with at least one assignment group.
2. Enroll a student in the course.
3. Enter a rails console and delete the 'course score' for the
enrollment:
course = Course.find(<course_id>)
enrollment = course.student_enrollments.where(user_id: <student_id>)
score = enrollment.find_score(course_score: true)
score.destroy_permanently!
4. Run the Grade Calculator for the student:
GradeCalculator.new(<student_id>, course).compute_and_save_scores
5. Verify the course score has been created:
enrollment.reload.find_score(course_score: true)
# => should return a Score
Change-Id: Ifef8eb24b90e95d35ef2bb17031a53dca3268fdb
Reviewed-on: https://gerrit.instructure.com/132409
Reviewed-by: Derek Bender <djbender@instructure.com>
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Tested-by: Jenkins
QA-Review: Anju Reddy <areddy@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
fixes GRADE-326
test plan:
* Create a course with a student and assignment group
* Add 2 assignments with 10 points possible to the assignment group
* Create a drop rule to drop the lowest assignment from the group
* Score the student 5 and 10 on the assignment
* In rails console:
e = Enrollment.where(user_id: <student_id>, course_id: <course_id>)
score = e.first.find_score
details = score.score_metadata.calculation_details
score.current_score should be 10, and details should look like
{
current: {
dropped: [first submission id]
}, final: {
dropped: [first submission id]
}
}
Change-Id: Iba4173ce52f52f6acd474860d190d1d4c4d3c253
Reviewed-on: https://gerrit.instructure.com/129213
Tested-by: Jenkins
Reviewed-by: Spencer Olson <solson@instructure.com>
Reviewed-by: Shahbaz Javeed <sjaveed@instructure.com>
QA-Review: Spencer Olson <solson@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
This removes the environmental variable guard that was blocking the
grade calculator from storing assignment group totals in the scores
table.
closes GRADE-198
test plan:
- Have a course with:
o some students
o weighted assignment groups
o weighted grading periods
o ungraded assignments
o quizzes
o late and missing policies
- As a teacher grade a bunch of the above
- Using the rails console, verify that assignment group grades
recorded in the scores table match those calculated by the front
end
Change-Id: I05f8dd0e115e7ed83d3dbfe07513679bac2b88bb
Reviewed-on: https://gerrit.instructure.com/129705
Reviewed-by: Rob Orton <rob@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
Tested-by: Jenkins
Reviewed-by: Derek Bender <djbender@instructure.com>
QA-Review: KC Naegle <knaegle@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
fixes GRADE-9
Test plan:
* Create a course with a student and 2 assignments
* Mute one of the assignments
* Grade both assignments
* Verify that student sees the unmuted current score
* Verify that teacher sees current score that includes both assignments
* In rails console:
e = Enrollment.where(user_id: <student id>, course_id: <course id>)
score = e.find_score(course_score: true)
score.current_score should match the student view score
score.unposted_current_score should match the teacher view score
Change-Id: I995ec26fdef8b10e3e981d7b467edcb989230943
Reviewed-on: https://gerrit.instructure.com/127467
Reviewed-by: Jeremy Neander <jneander@instructure.com>
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
QA-Review: KC Naegle <knaegle@instructure.com>
Product-Review: Neil Gupta <ngupta@instructure.com>
closes GRADE-19
Test Plan:
1. Using the master branch prior to this commit:
a. Seed a course with all of the following:
- weighted assignment groups
- weighted grading periods
- ungraded assignments
- quizzes
- late and missing policies
b. Record all data displayed in the gradebook
2. Using the code in this commit:
a. Verify GRADEBOOK_COURSE_SCORE_POPULATED is
not set in your environment
b. Run database migrations
c. Repeat steps in (1a)
d. Verify that results are identical to (1b)
3. Using the code in this commit:
a. Set GRADEBOOK_COURSE_SCORE_POPULATED="true"
in your environment
b. Repeat steps in (1a)
c. Verify that results are identical to (1b)
d. (Dev-QA only)
Verify that assignment group grades recorded in the
scores table match those calculated by the front end
4. (Dev-QA only)
run scores_spec and grade_calculator_spec tests
with GRADEBOOK_COURSE_SCORE_POPULATED="true"
5. (Dev-QA only)
After running grade calculations with the new migrations
in place, revert those migrations and verify that all
scores created for assignment groups are deleted
Change-Id: Ie5e06eb5ad7c0d3958a686e7f0b054e6585be37d
Reviewed-on: https://gerrit.instructure.com/123085
Reviewed-by: Rob Orton <rob@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: Spencer Olson <solson@instructure.com>
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
When calculating grades for weighted grading periods, the grade
calculator would throw an error if it was passed users that were
A) not enrolled in the course, or B) had deleted enrollments in the
course.
closes GRADE-249
Test Plan:
1. Verify grade calculation for weighted grading periods gracefully
handles users with deleted enrollments and users enrolled in other
courses.
Change-Id: I584276fbdd7cf7637dd04adceab43d4077a4926c
Reviewed-on: https://gerrit.instructure.com/124869
Reviewed-by: Rob Orton <rob@instructure.com>
Tested-by: Jenkins
QA-Review: KC Naegle <knaegle@instructure.com>
Product-Review: Gentry Beckmann <gbeckmann@instructure.com>
fixes CNVS-38794
test plan
- specs should pass
Change-Id: Iff6b6933d5d2fc7d2372a5032822ed32b04b5c51
Reviewed-on: https://gerrit.instructure.com/123636
Tested-by: Jenkins
Reviewed-by: Neil Gupta <ngupta@instructure.com>
Product-Review: Rob Orton <rob@instructure.com>
QA-Review: Rob Orton <rob@instructure.com>
Change-Id: Ieef3d3447cfa2b22c9c9f6662688a40ae48a726c
Reviewed-on: https://gerrit.instructure.com/119730
Tested-by: Jenkins
Reviewed-by: Cody Cutrer <cody@instructure.com>
Product-Review: James Williams <jamesw@instructure.com>
QA-Review: James Williams <jamesw@instructure.com>
This patchset combined two queries for course side stats into one to
be slightly kinder to the database for large classes and caches the
results in redis. The cache is invalided when the backend grade
calculator is run.
This also changes a call to EffectiveDueDates in grade summary to
switch from getting dates for everyone when we only care about one
student to doing a more targeted lookup using the newer more accurate
cached due dates off Submission.
fixes CNVS-38025
test plan:
- Create a course with a number of students and assignments.
- Grade the students.
- Visit the grade summary page for one student.
- Observe that the assignment stats are correct.
Change-Id: I57c0f2912abc33a4af6c73fd4da4bfcf021bcf64
Reviewed-on: https://gerrit.instructure.com/118179
Tested-by: Jenkins
Reviewed-by: Shahbaz Javeed <sjaveed@instructure.com>
Reviewed-by: Neil Gupta <ngupta@instructure.com>
QA-Review: Anju Reddy <areddy@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
Fixes CNVS-37088
Test plan:
* Create a course
* Enroll 2 students
* Create an assignment with a due date
* Grade student 1
* From rails console, run grade calculator for a single student
GradeCalculator.new(user1_id, course)
* From console, run effective due dates for a single student
EffectiveDueDates.for_course(course, assignment).filter_students_to(user1_id).to_hash
It should return a hash with only user 1's due date
Change-Id: Ibd509153558b2674775566b1f8ccd444a4aed1ce
Reviewed-on: https://gerrit.instructure.com/112839
Tested-by: Jenkins
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
Reviewed-by: Spencer Olson <solson@instructure.com>
QA-Review: Matt Taylor <mtaylor@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>