mumuki-domain 8.2.0 → 8.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|