mumuki-domain 8.1.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/assignment.rb +7 -2
- data/app/models/chapter.rb +3 -0
- data/app/models/concerns/with_expectations.rb +3 -7
- data/app/models/concerns/with_randomizations.rb +1 -2
- 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 +8 -5
- data/app/models/exercise/challenge.rb +4 -2
- data/app/models/exercise/problem.rb +5 -10
- data/app/models/guide.rb +5 -1
- data/app/models/indicator.rb +35 -0
- data/app/models/notification.rb +5 -0
- data/app/models/organization.rb +1 -1
- data/app/models/progress.rb +35 -0
- data/app/models/topic.rb +8 -0
- data/app/models/user.rb +6 -1
- data/app/models/with_stats.rb +1 -0
- data/db/migrate/20201130163114_add_banned_from_forum_to_users.rb +5 -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.rb +1 -0
- data/lib/mumuki/domain/extensions.rb +2 -0
- data/lib/mumuki/domain/extensions/array.rb +2 -4
- data/lib/mumuki/domain/extensions/hash.rb +4 -0
- data/lib/mumuki/domain/extensions/nil.rb +17 -0
- data/lib/mumuki/domain/extensions/string.rb +2 -9
- data/lib/mumuki/domain/extensions/symbol.rb +5 -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/locales/activerecord/en.yml +1 -1
- data/lib/mumuki/domain/locales/activerecord/es-CL.yml +1 -1
- data/lib/mumuki/domain/locales/activerecord/es.yml +1 -1
- data/lib/mumuki/domain/locales/activerecord/pt.yml +1 -1
- data/lib/mumuki/domain/progress_transfer.rb +8 -0
- data/lib/mumuki/domain/progress_transfer/base.rb +44 -0
- data/lib/mumuki/domain/progress_transfer/copy.rb +9 -0
- data/lib/mumuki/domain/progress_transfer/move.rb +14 -0
- data/lib/mumuki/domain/status/submission/manual_evaluation_pending.rb +1 -1
- data/lib/mumuki/domain/status/submission/submission.rb +4 -0
- data/lib/mumuki/domain/version.rb +1 -1
- metadata +22 -3
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/assignment.rb
CHANGED
@@ -23,6 +23,8 @@ class Assignment < Progress
|
|
23
23
|
|
24
24
|
delegate :completed?, :solved?, to: :submission_status
|
25
25
|
|
26
|
+
delegate :content_available_in?, to: :parent
|
27
|
+
|
26
28
|
alias_attribute :status, :submission_status
|
27
29
|
alias_attribute :attempts_count, :attemps_count
|
28
30
|
|
@@ -126,7 +128,7 @@ class Assignment < Progress
|
|
126
128
|
end
|
127
129
|
|
128
130
|
def content=(content)
|
129
|
-
|
131
|
+
if exercise.solvable?
|
130
132
|
self.solution = exercise.single_choice? ? exercise.choice_index_for(content) : content
|
131
133
|
end
|
132
134
|
end
|
@@ -263,6 +265,10 @@ class Assignment < Progress
|
|
263
265
|
|
264
266
|
private
|
265
267
|
|
268
|
+
def duplicates_key
|
269
|
+
{ exercise: exercise, submitter: submitter }
|
270
|
+
end
|
271
|
+
|
266
272
|
def update_submissions_count!
|
267
273
|
self.class.connection.execute(
|
268
274
|
"update public.exercises
|
@@ -278,5 +284,4 @@ class Assignment < Progress
|
|
278
284
|
def update_last_submission!
|
279
285
|
submitter.update!(last_submission_date: DateTime.current, last_exercise: exercise)
|
280
286
|
end
|
281
|
-
|
282
287
|
end
|
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
|
@@ -18,16 +18,12 @@ module WithExpectations
|
|
18
18
|
self[:expectations] = expectations.map(&:stringify_keys)
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def raw_expectations
|
22
22
|
self[:expectations]
|
23
23
|
end
|
24
24
|
|
25
|
-
def own_custom_expectations
|
26
|
-
self[:custom_expectations]
|
27
|
-
end
|
28
|
-
|
29
25
|
def ensure_expectations_format
|
30
|
-
errors.add :
|
31
|
-
:invalid_format unless
|
26
|
+
errors.add :raw_expectations,
|
27
|
+
:invalid_format unless raw_expectations.to_a.all? { |it| Mulang::Expectation.valid? it }
|
32
28
|
end
|
33
29
|
end
|
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
@@ -1,5 +1,5 @@
|
|
1
1
|
class Exercise < ApplicationRecord
|
2
|
-
RANDOMIZED_FIELDS = [:default_content, :description, :extra, :hint, :test]
|
2
|
+
RANDOMIZED_FIELDS = [:default_content, :description, :extra, :hint, :test, :expectations, :custom_expectations]
|
3
3
|
BASIC_RESOURCE_FIELDS = %i(
|
4
4
|
name layout editor corollary teacher_info manual_evaluation locale
|
5
5
|
choices assistance_rules randomizations tag_list extra_visible goal
|
@@ -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?
|
@@ -135,8 +140,6 @@ class Exercise < ApplicationRecord
|
|
135
140
|
language_resource_h = language.to_embedded_resource_h if language != guide.language
|
136
141
|
as_json(only: BASIC_RESOURCE_FIELDS)
|
137
142
|
.merge(id: bibliotheca_id, language: language_resource_h, type: type.underscore)
|
138
|
-
.merge(expectations: self[:expectations])
|
139
|
-
.merge(custom_expectations: self[:custom_expectations])
|
140
143
|
.merge(settings: self[:settings])
|
141
144
|
.merge(RANDOMIZED_FIELDS.map { |it| [it, self[it]] }.to_h)
|
142
145
|
.symbolize_keys
|
@@ -239,8 +242,8 @@ class Exercise < ApplicationRecord
|
|
239
242
|
guide.pending_exercises(user)
|
240
243
|
end
|
241
244
|
|
242
|
-
def
|
243
|
-
is_a?
|
245
|
+
def solvable?
|
246
|
+
is_a? ::Problem
|
244
247
|
end
|
245
248
|
|
246
249
|
private
|
@@ -21,20 +21,15 @@ class Problem < QueriableChallenge
|
|
21
21
|
self.expectations = []
|
22
22
|
end
|
23
23
|
|
24
|
+
alias_method :own_expectations, :expectations
|
25
|
+
alias_method :own_custom_expectations, :custom_expectations
|
26
|
+
|
24
27
|
def expectations
|
25
|
-
own_expectations +
|
28
|
+
own_expectations + guide.expectations
|
26
29
|
end
|
27
30
|
|
28
31
|
def custom_expectations
|
29
|
-
"#{own_custom_expectations}\n#{
|
30
|
-
end
|
31
|
-
|
32
|
-
def guide_expectations
|
33
|
-
guide.expectations
|
34
|
-
end
|
35
|
-
|
36
|
-
def guide_custom_expectations
|
37
|
-
guide.custom_expectations
|
32
|
+
"#{own_custom_expectations}\n#{guide.custom_expectations}"
|
38
33
|
end
|
39
34
|
|
40
35
|
def evaluation_criteria?
|
data/app/models/guide.rb
CHANGED
data/app/models/indicator.rb
CHANGED
@@ -66,8 +66,43 @@ class Indicator < Progress
|
|
66
66
|
where(content: content, organization: organization).delete_all
|
67
67
|
end
|
68
68
|
|
69
|
+
def _move_to!(organization)
|
70
|
+
move_children_to!(organization)
|
71
|
+
super
|
72
|
+
end
|
73
|
+
|
74
|
+
def _copy_to!(organization)
|
75
|
+
progress_item = super
|
76
|
+
children.each { |it| it._copy_to! organization }
|
77
|
+
progress_item
|
78
|
+
end
|
79
|
+
|
80
|
+
def move_children_to!(organization)
|
81
|
+
children.update_all(organization_id: organization.id)
|
82
|
+
|
83
|
+
indicators.each { |it| it.move_children_to!(organization) }
|
84
|
+
end
|
85
|
+
|
86
|
+
def cascade_delete_children!
|
87
|
+
indicators.each(&:cascade_delete_children!)
|
88
|
+
children.delete_all(:delete_all)
|
89
|
+
end
|
90
|
+
|
91
|
+
def content_available_in?(organization)
|
92
|
+
content.usage_in_organization(organization).present?
|
93
|
+
end
|
94
|
+
|
95
|
+
def delete_duplicates_in!(organization)
|
96
|
+
duplicates_in(organization).each(&:cascade_delete_children!)
|
97
|
+
super
|
98
|
+
end
|
99
|
+
|
69
100
|
private
|
70
101
|
|
102
|
+
def duplicates_key
|
103
|
+
{ content: content, user: user }
|
104
|
+
end
|
105
|
+
|
71
106
|
def children
|
72
107
|
indicators.presence || assignments
|
73
108
|
end
|
data/app/models/organization.rb
CHANGED
data/app/models/progress.rb
CHANGED
@@ -12,4 +12,39 @@ class Progress < ApplicationRecord
|
|
12
12
|
def dirty_parent_by_submission!
|
13
13
|
parent&.dirty_by_submission!
|
14
14
|
end
|
15
|
+
|
16
|
+
def _copy_to!(organization)
|
17
|
+
dup.transfer_to!(organization)
|
18
|
+
end
|
19
|
+
|
20
|
+
def transfer_to!(organization)
|
21
|
+
update! organization: organization, parent: nil
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_method :_move_to!, :transfer_to!
|
26
|
+
|
27
|
+
%w(copy move).each do |transfer_type|
|
28
|
+
define_method "#{transfer_type}_to!" do |organization|
|
29
|
+
"Mumuki::Domain::ProgressTransfer::#{transfer_type.camelize}".constantize.new(self, organization).execute!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def guide_indicator?
|
34
|
+
is_a?(Indicator) && content_type == 'Guide'
|
35
|
+
end
|
36
|
+
|
37
|
+
def has_duplicates_in?(organization)
|
38
|
+
duplicates_in(organization).present?
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete_duplicates_in!(organization)
|
42
|
+
duplicates_in(organization).delete_all
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def duplicates_in(organization)
|
48
|
+
self.class.where(duplicates_key.merge(organization: organization)).where.not(id: id)
|
49
|
+
end
|
15
50
|
end
|
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
|
@@ -182,7 +187,7 @@ class User < ApplicationRecord
|
|
182
187
|
# This is true only when this organization has the forum enabled and the user
|
183
188
|
# has the discusser pseudo-permission and the discusser is trusted
|
184
189
|
def can_discuss_in?(organization)
|
185
|
-
organization.forum_enabled? && discusser_of?(organization) && trusted_as_discusser_in?(organization)
|
190
|
+
organization.forum_enabled? && discusser_of?(organization) && trusted_as_discusser_in?(organization) && !banned_from_forum?
|
186
191
|
end
|
187
192
|
|
188
193
|
def trusted_as_discusser_in?(organization)
|
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
|
data/lib/mumuki/domain.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require_relative './extensions/string'
|
2
|
+
require_relative './extensions/symbol'
|
2
3
|
require_relative './extensions/array'
|
3
4
|
require_relative './extensions/module'
|
4
5
|
require_relative './extensions/hash'
|
6
|
+
require_relative './extensions/nil'
|
5
7
|
require_relative './extensions/time'
|
@@ -59,15 +59,8 @@ class String
|
|
59
59
|
def sanitized
|
60
60
|
Mumukit::ContentType::Sanitizer.sanitize self
|
61
61
|
end
|
62
|
-
end
|
63
|
-
|
64
|
-
class NilClass
|
65
|
-
def affable
|
66
|
-
end
|
67
62
|
|
68
|
-
def
|
69
|
-
|
70
|
-
|
71
|
-
def sanitized
|
63
|
+
def randomize_with(randomizer, seed)
|
64
|
+
randomizer.randomize!(self, seed)
|
72
65
|
end
|
73
66
|
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'
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Mumuki::Domain::ProgressTransfer::Base
|
2
|
+
attr_reader *%i(source_organization destination_organization progress_item transferred_item)
|
3
|
+
|
4
|
+
delegate :user, to: :progress_item
|
5
|
+
|
6
|
+
def initialize(progress_item, destination_organization)
|
7
|
+
@progress_item = progress_item
|
8
|
+
@destination_organization = destination_organization
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute!
|
12
|
+
ActiveRecord::Base.transaction do
|
13
|
+
pre_transfer!
|
14
|
+
transfer!
|
15
|
+
post_transfer!
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def pre_transfer!
|
20
|
+
validate_transferrable!
|
21
|
+
@source_organization = progress_item.organization
|
22
|
+
progress_item.delete_duplicates_in!(destination_organization)
|
23
|
+
end
|
24
|
+
|
25
|
+
def transfer!
|
26
|
+
@transferred_item = do_transfer!
|
27
|
+
end
|
28
|
+
|
29
|
+
def post_transfer!
|
30
|
+
transferred_item.dirty_parent_by_submission!
|
31
|
+
notify_transfer!
|
32
|
+
transferred_item
|
33
|
+
end
|
34
|
+
|
35
|
+
def validate_transferrable!
|
36
|
+
raise "Transferred progress' content must be available in destination!" unless progress_item.content_available_in?(destination_organization)
|
37
|
+
raise 'User must be student in destination organization' unless user.student_of?(destination_organization)
|
38
|
+
raise 'Transfer only supported for guide indicators' unless progress_item.guide_indicator?
|
39
|
+
end
|
40
|
+
|
41
|
+
def notify_transfer!
|
42
|
+
Mumukit::Nuntius.notify! 'progress-transfers', { from: source_organization.name, to: destination_organization.name, item_type: transferred_item.class.to_s, item_id: transferred_item.id, transfer_type: transfer_type }
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Mumuki::Domain::ProgressTransfer::Move < Mumuki::Domain::ProgressTransfer::Base
|
2
|
+
def transfer_type
|
3
|
+
:move
|
4
|
+
end
|
5
|
+
|
6
|
+
def pre_transfer!
|
7
|
+
super
|
8
|
+
progress_item.dirty_parent_by_submission!
|
9
|
+
end
|
10
|
+
|
11
|
+
def do_transfer!
|
12
|
+
progress_item._move_to!(destination_organization)
|
13
|
+
end
|
14
|
+
end
|
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.1
|
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:
|
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
|
@@ -636,6 +641,12 @@ files:
|
|
636
641
|
- db/migrate/20201026225312_add_organization_wins_page_flag.rb
|
637
642
|
- db/migrate/20201027134205_add_immersible_to_organization.rb
|
638
643
|
- db/migrate/20201027152806_create_terms.rb
|
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
|
639
650
|
- lib/mumuki/domain.rb
|
640
651
|
- lib/mumuki/domain/area.rb
|
641
652
|
- lib/mumuki/domain/engine.rb
|
@@ -655,7 +666,9 @@ files:
|
|
655
666
|
- lib/mumuki/domain/extensions/array.rb
|
656
667
|
- lib/mumuki/domain/extensions/hash.rb
|
657
668
|
- lib/mumuki/domain/extensions/module.rb
|
669
|
+
- lib/mumuki/domain/extensions/nil.rb
|
658
670
|
- lib/mumuki/domain/extensions/string.rb
|
671
|
+
- lib/mumuki/domain/extensions/symbol.rb
|
659
672
|
- lib/mumuki/domain/extensions/time.rb
|
660
673
|
- lib/mumuki/domain/factories.rb
|
661
674
|
- lib/mumuki/domain/factories/api_client_factory.rb
|
@@ -666,7 +679,9 @@ files:
|
|
666
679
|
- lib/mumuki/domain/factories/complement_factory.rb
|
667
680
|
- lib/mumuki/domain/factories/course_factory.rb
|
668
681
|
- lib/mumuki/domain/factories/discussion_factory.rb
|
682
|
+
- lib/mumuki/domain/factories/exam_authorization_request_factory.rb
|
669
683
|
- lib/mumuki/domain/factories/exam_factory.rb
|
684
|
+
- lib/mumuki/domain/factories/exam_registration_factory.rb
|
670
685
|
- lib/mumuki/domain/factories/exercise_factory.rb
|
671
686
|
- lib/mumuki/domain/factories/guide_factory.rb
|
672
687
|
- lib/mumuki/domain/factories/invitation_factory.rb
|
@@ -701,6 +716,10 @@ files:
|
|
701
716
|
- lib/mumuki/domain/organization/profile.rb
|
702
717
|
- lib/mumuki/domain/organization/settings.rb
|
703
718
|
- lib/mumuki/domain/organization/theme.rb
|
719
|
+
- lib/mumuki/domain/progress_transfer.rb
|
720
|
+
- lib/mumuki/domain/progress_transfer/base.rb
|
721
|
+
- lib/mumuki/domain/progress_transfer/copy.rb
|
722
|
+
- lib/mumuki/domain/progress_transfer/move.rb
|
704
723
|
- lib/mumuki/domain/seed.rb
|
705
724
|
- lib/mumuki/domain/status.rb
|
706
725
|
- lib/mumuki/domain/status/discussion/closed.rb
|
@@ -756,7 +775,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
756
775
|
- !ruby/object:Gem::Version
|
757
776
|
version: '0'
|
758
777
|
requirements: []
|
759
|
-
rubygems_version: 3.0.
|
778
|
+
rubygems_version: 3.0.3
|
760
779
|
signing_key:
|
761
780
|
specification_version: 4
|
762
781
|
summary: Mumuki Platform's Domain Model
|