mumuki-domain 8.2.0 → 8.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +2 -0
- data/app/models/chapter.rb +3 -0
- data/app/models/concerns/with_timed_enablement.rb +11 -0
- data/app/models/exam.rb +4 -8
- data/app/models/exam_authorization_request.rb +19 -0
- data/app/models/exam_registration.rb +38 -0
- data/app/models/exam_registration/authorization_criterion.rb +61 -0
- data/app/models/exercise.rb +5 -0
- data/app/models/guide.rb +5 -1
- data/app/models/notification.rb +5 -0
- data/app/models/organization.rb +1 -1
- data/app/models/topic.rb +8 -0
- data/app/models/user.rb +5 -0
- data/app/models/with_stats.rb +1 -0
- data/db/migrate/20210114200545_create_exam_registrations.rb +14 -0
- data/db/migrate/20210118180941_create_exam_authorization_request.rb +13 -0
- data/db/migrate/20210118194904_create_notification.rb +13 -0
- data/db/migrate/20210119160440_add_prevent_manual_evaluation_content_to_organizations.rb +5 -0
- data/db/migrate/20210119190204_create_exam_registration_exam_join_table.rb +8 -0
- data/lib/mumuki/domain/factories.rb +2 -0
- data/lib/mumuki/domain/factories/exam_authorization_request_factory.rb +6 -0
- data/lib/mumuki/domain/factories/exam_registration_factory.rb +8 -0
- data/lib/mumuki/domain/helpers/organization.rb +4 -0
- data/lib/mumuki/domain/version.rb +1 -1
- metadata +14 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 05e92b25906e2bdad81e9af37f88d03423ce78e18e60e911883e1fd9933056d4
|
|
4
|
+
data.tar.gz: 3fc2d20e7199cd604ba3462a5755084ed1ed9bbcf4b434d71bd3ed340677d650
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8b75c52aeec6f2403888816619740882acf061c684d09f71fd52094c9cc2b13561203433b13eaca1499a4d7c6f7046e596d3e01d95ac0e02e983bf1107fc2923
|
|
7
|
+
data.tar.gz: 56ed033125bb4eea0d39ba693dca8e142532846159dea3e68329f3b79984ac201a3852ec6019c9428f2696d1e900583c09cd55f8b80c38215fe02ebefd014ed0
|
data/Rakefile
CHANGED
data/app/models/chapter.rb
CHANGED
|
@@ -13,6 +13,9 @@ class Chapter < ApplicationRecord
|
|
|
13
13
|
|
|
14
14
|
has_many :exercises, through: :topic
|
|
15
15
|
|
|
16
|
+
delegate :monolesson?, :monolesson, :first_lesson, to: :topic
|
|
17
|
+
|
|
18
|
+
delegate :next_exercise, :stats_for, to: :monolesson, allow_nil: true
|
|
16
19
|
|
|
17
20
|
def used_in?(organization)
|
|
18
21
|
organization.book == self.book
|
data/app/models/exam.rb
CHANGED
|
@@ -3,13 +3,17 @@ class Exam < ApplicationRecord
|
|
|
3
3
|
include GuideContainer
|
|
4
4
|
include FriendlyName
|
|
5
5
|
include TerminalNavigation
|
|
6
|
+
include WithTimedEnablement
|
|
6
7
|
|
|
7
8
|
belongs_to :organization
|
|
8
9
|
belongs_to :course
|
|
9
10
|
|
|
10
11
|
has_many :authorizations, class_name: 'ExamAuthorization', dependent: :destroy
|
|
12
|
+
has_many :authorization_requests, class_name: 'ExamAuthorizationRequest', dependent: :destroy
|
|
11
13
|
has_many :users, through: :authorizations
|
|
12
14
|
|
|
15
|
+
has_and_belongs_to_many :exam_registrations
|
|
16
|
+
|
|
13
17
|
enum passing_criterion_type: [:none, :percentage, :passed_exercises], _prefix: :passing_criterion
|
|
14
18
|
|
|
15
19
|
validates_presence_of :start_time, :end_time
|
|
@@ -27,14 +31,6 @@ class Exam < ApplicationRecord
|
|
|
27
31
|
organization == self.organization
|
|
28
32
|
end
|
|
29
33
|
|
|
30
|
-
def enabled?
|
|
31
|
-
enabled_range.cover? DateTime.current
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def enabled_range
|
|
35
|
-
start_time..end_time
|
|
36
|
-
end
|
|
37
|
-
|
|
38
34
|
def enabled_for?(user)
|
|
39
35
|
enabled_range_for(user).cover? DateTime.current
|
|
40
36
|
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class ExamAuthorizationRequest < ApplicationRecord
|
|
2
|
+
belongs_to :exam
|
|
3
|
+
belongs_to :user
|
|
4
|
+
belongs_to :organization
|
|
5
|
+
|
|
6
|
+
enum status: %i(pending approved rejected)
|
|
7
|
+
|
|
8
|
+
after_update :notify_user!
|
|
9
|
+
|
|
10
|
+
def try_authorize!
|
|
11
|
+
exam.authorize! user if approved?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def notify_user!
|
|
17
|
+
Notification.create! organization: organization, user: user, target: self if saved_change_to_status?
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
class ExamRegistration < ApplicationRecord
|
|
2
|
+
include WithTimedEnablement
|
|
3
|
+
|
|
4
|
+
belongs_to :organization
|
|
5
|
+
has_and_belongs_to_many :exams
|
|
6
|
+
has_many :authorization_requests, class_name: 'ExamAuthorizationRequest', through: :exams
|
|
7
|
+
|
|
8
|
+
enum authorization_criterion_type: %i(none passed_exercises), _prefix: :authorization_criterion
|
|
9
|
+
|
|
10
|
+
before_save :ensure_valid_authorization_criterion!
|
|
11
|
+
|
|
12
|
+
delegate :meets_authorization_criteria?, :process_request!, to: :authorization_criterion
|
|
13
|
+
|
|
14
|
+
def authorization_criterion
|
|
15
|
+
@authorization_criterion ||= ExamRegistration::AuthorizationCriterion.parse(authorization_criterion_type, authorization_criterion_value)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def ensure_valid_authorization_criterion!
|
|
19
|
+
authorization_criterion.ensure_valid!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def start!(users)
|
|
23
|
+
users.each &method(:notify_user!)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def process_requests!
|
|
27
|
+
authorization_requests.each do |it|
|
|
28
|
+
process_request! it
|
|
29
|
+
it.try_authorize!
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def notify_user!(user)
|
|
36
|
+
Notification.create! organization: organization, user: user, target: self
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
class ExamRegistration::AuthorizationCriterion
|
|
2
|
+
attr_reader :value
|
|
3
|
+
|
|
4
|
+
def initialize(value)
|
|
5
|
+
@value = value
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def type
|
|
9
|
+
self.class.name.demodulize.underscore
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def as_json
|
|
13
|
+
{ type: type, value: value }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def ensure_valid!
|
|
17
|
+
raise "Invalid criterion value #{value} for #{type}" unless valid?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def process_request!(authorization_request)
|
|
21
|
+
authorization_request.update! status: authorization_status_for(authorization_request)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def authorization_status_for(authorization_request)
|
|
25
|
+
meets_authorization_criteria?(authorization_request) ? :approved : :rejected
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.parse(type, value)
|
|
29
|
+
parse_criterion_type(type, value)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.parse_criterion_type(type, value)
|
|
33
|
+
"ExamRegistration::AuthorizationCriterion::#{type.camelize}".constantize.new(value)
|
|
34
|
+
rescue
|
|
35
|
+
raise "Invalid criterion type #{type}"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class ExamRegistration::AuthorizationCriterion::None < ExamRegistration::AuthorizationCriterion
|
|
40
|
+
def initialize(_)
|
|
41
|
+
@value = nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def valid?
|
|
45
|
+
!value
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def meets_authorization_criteria?(_authorization_request)
|
|
49
|
+
true
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class ExamRegistration::AuthorizationCriterion::PassedExercises < ExamRegistration::AuthorizationCriterion
|
|
54
|
+
def valid?
|
|
55
|
+
value.positive?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def meets_authorization_criteria?(authorization_request)
|
|
59
|
+
authorization_request.user.passed_submissions_count_in(authorization_request.organization) >= value
|
|
60
|
+
end
|
|
61
|
+
end
|
data/app/models/exercise.rb
CHANGED
|
@@ -28,6 +28,10 @@ class Exercise < ApplicationRecord
|
|
|
28
28
|
|
|
29
29
|
defaults { self.submissions_count = 0 }
|
|
30
30
|
|
|
31
|
+
def self.default_scope
|
|
32
|
+
where(manual_evaluation: false) if Organization.safe_current&.prevent_manual_evaluation_content
|
|
33
|
+
end
|
|
34
|
+
|
|
31
35
|
alias_method :progress_for, :assignment_for
|
|
32
36
|
|
|
33
37
|
serialize :choices, Array
|
|
@@ -38,6 +42,7 @@ class Exercise < ApplicationRecord
|
|
|
38
42
|
|
|
39
43
|
randomize(*RANDOMIZED_FIELDS)
|
|
40
44
|
delegate :timed?, to: :navigable_parent
|
|
45
|
+
delegate :stats_for, to: :guide
|
|
41
46
|
|
|
42
47
|
def console?
|
|
43
48
|
queriable?
|
data/app/models/guide.rb
CHANGED
data/app/models/organization.rb
CHANGED
data/app/models/topic.rb
CHANGED
|
@@ -35,6 +35,14 @@ class Topic < Content
|
|
|
35
35
|
Chapter.where(topic: self).map(&:book).each(&:reindex_usages!)
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
def monolesson
|
|
39
|
+
@monolesson ||= lessons.to_a.single
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def monolesson?
|
|
43
|
+
monolesson.present?
|
|
44
|
+
end
|
|
45
|
+
|
|
38
46
|
## Forking
|
|
39
47
|
|
|
40
48
|
def fork_children_into!(dup, organization, syncer)
|
data/app/models/user.rb
CHANGED
|
@@ -12,6 +12,7 @@ class User < ApplicationRecord
|
|
|
12
12
|
serialize :permissions, Mumukit::Auth::Permissions
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
has_many :notifications
|
|
15
16
|
has_many :assignments, foreign_key: :submitter_id
|
|
16
17
|
has_many :messages, -> { order(created_at: :desc) }, through: :assignments
|
|
17
18
|
|
|
@@ -49,6 +50,10 @@ class User < ApplicationRecord
|
|
|
49
50
|
last_guide.try(:lesson)
|
|
50
51
|
end
|
|
51
52
|
|
|
53
|
+
def passed_submissions_count_in(organization)
|
|
54
|
+
assignments.where(top_submission_status: Mumuki::Domain::Status::Submission::Passed.to_i, organization: organization).count
|
|
55
|
+
end
|
|
56
|
+
|
|
52
57
|
def submissions_count
|
|
53
58
|
assignments.pluck(:submissions_count).sum
|
|
54
59
|
end
|
data/app/models/with_stats.rb
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class CreateExamRegistrations < ActiveRecord::Migration[5.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :exam_registrations do |t|
|
|
4
|
+
t.string :description
|
|
5
|
+
t.datetime :start_time, null: false
|
|
6
|
+
t.datetime :end_time, null: false
|
|
7
|
+
t.integer :authorization_criterion_type, default: 0
|
|
8
|
+
t.integer :authorization_criterion_value
|
|
9
|
+
t.references :organization, index: true
|
|
10
|
+
|
|
11
|
+
t.timestamps
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class CreateExamAuthorizationRequest < ActiveRecord::Migration[5.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :exam_authorization_requests do |t|
|
|
4
|
+
t.integer :status, default: 0
|
|
5
|
+
t.references :exam, index: true
|
|
6
|
+
t.references :exam_registration, index: true
|
|
7
|
+
t.references :user, index: true
|
|
8
|
+
t.references :organization, index: true
|
|
9
|
+
|
|
10
|
+
t.timestamps
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class CreateNotification < ActiveRecord::Migration[5.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :notifications do |t|
|
|
4
|
+
t.integer :priority, default: 100
|
|
5
|
+
t.boolean :read, default: false
|
|
6
|
+
t.references :target, polymorphic: true
|
|
7
|
+
t.references :user, index: true
|
|
8
|
+
t.references :organization, index: true
|
|
9
|
+
|
|
10
|
+
t.timestamps
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -7,6 +7,8 @@ require_relative './factories/complement_factory'
|
|
|
7
7
|
require_relative './factories/course_factory'
|
|
8
8
|
require_relative './factories/discussion_factory'
|
|
9
9
|
require_relative './factories/exam_factory'
|
|
10
|
+
require_relative './factories/exam_authorization_request_factory'
|
|
11
|
+
require_relative './factories/exam_registration_factory'
|
|
10
12
|
require_relative './factories/exercise_factory'
|
|
11
13
|
require_relative './factories/guide_factory'
|
|
12
14
|
require_relative './factories/invitation_factory'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mumuki-domain
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.
|
|
4
|
+
version: 8.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Franco Leonardo Bulgarelli
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-01-
|
|
11
|
+
date: 2021-01-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -297,6 +297,7 @@ files:
|
|
|
297
297
|
- app/models/concerns/with_slug.rb
|
|
298
298
|
- app/models/concerns/with_target_audience.rb
|
|
299
299
|
- app/models/concerns/with_terms_acceptance.rb
|
|
300
|
+
- app/models/concerns/with_timed_enablement.rb
|
|
300
301
|
- app/models/concerns/with_usages.rb
|
|
301
302
|
- app/models/concerns/with_user_navigation.rb
|
|
302
303
|
- app/models/content.rb
|
|
@@ -306,6 +307,9 @@ files:
|
|
|
306
307
|
- app/models/exam.rb
|
|
307
308
|
- app/models/exam/passing_criterion.rb
|
|
308
309
|
- app/models/exam_authorization.rb
|
|
310
|
+
- app/models/exam_authorization_request.rb
|
|
311
|
+
- app/models/exam_registration.rb
|
|
312
|
+
- app/models/exam_registration/authorization_criterion.rb
|
|
309
313
|
- app/models/exercise.rb
|
|
310
314
|
- app/models/exercise/challenge.rb
|
|
311
315
|
- app/models/exercise/interactive.rb
|
|
@@ -320,6 +324,7 @@ files:
|
|
|
320
324
|
- app/models/lesson.rb
|
|
321
325
|
- app/models/medal.rb
|
|
322
326
|
- app/models/message.rb
|
|
327
|
+
- app/models/notification.rb
|
|
323
328
|
- app/models/organization.rb
|
|
324
329
|
- app/models/progress.rb
|
|
325
330
|
- app/models/stats.rb
|
|
@@ -637,6 +642,11 @@ files:
|
|
|
637
642
|
- db/migrate/20201027134205_add_immersible_to_organization.rb
|
|
638
643
|
- db/migrate/20201027152806_create_terms.rb
|
|
639
644
|
- db/migrate/20201130163114_add_banned_from_forum_to_users.rb
|
|
645
|
+
- db/migrate/20210114200545_create_exam_registrations.rb
|
|
646
|
+
- db/migrate/20210118180941_create_exam_authorization_request.rb
|
|
647
|
+
- db/migrate/20210118194904_create_notification.rb
|
|
648
|
+
- db/migrate/20210119160440_add_prevent_manual_evaluation_content_to_organizations.rb
|
|
649
|
+
- db/migrate/20210119190204_create_exam_registration_exam_join_table.rb
|
|
640
650
|
- lib/mumuki/domain.rb
|
|
641
651
|
- lib/mumuki/domain/area.rb
|
|
642
652
|
- lib/mumuki/domain/engine.rb
|
|
@@ -669,7 +679,9 @@ files:
|
|
|
669
679
|
- lib/mumuki/domain/factories/complement_factory.rb
|
|
670
680
|
- lib/mumuki/domain/factories/course_factory.rb
|
|
671
681
|
- lib/mumuki/domain/factories/discussion_factory.rb
|
|
682
|
+
- lib/mumuki/domain/factories/exam_authorization_request_factory.rb
|
|
672
683
|
- lib/mumuki/domain/factories/exam_factory.rb
|
|
684
|
+
- lib/mumuki/domain/factories/exam_registration_factory.rb
|
|
673
685
|
- lib/mumuki/domain/factories/exercise_factory.rb
|
|
674
686
|
- lib/mumuki/domain/factories/guide_factory.rb
|
|
675
687
|
- lib/mumuki/domain/factories/invitation_factory.rb
|