mumuki-domain 8.6.1 → 9.0.0
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/app/models/certificate.rb +29 -0
- data/app/models/certificate_program.rb +42 -0
- data/app/models/concerns/with_assignments.rb +2 -3
- data/app/models/concerns/with_assignments_batch.rb +2 -2
- data/app/models/concerns/with_generated_code.rb +19 -0
- data/app/models/concerns/with_notifications.rb +1 -1
- data/app/models/course.rb +5 -1
- data/app/models/invitation.rb +6 -10
- data/app/models/user.rb +26 -0
- data/db/migrate/20210119174504_create_certificate_programs.rb +13 -0
- data/db/migrate/20210119174835_create_certificates.rb +13 -0
- data/lib/mumuki/domain/factories.rb +2 -0
- data/lib/mumuki/domain/factories/certificate_factory.rb +8 -0
- data/lib/mumuki/domain/factories/certificate_program_factory.rb +7 -0
- data/lib/mumuki/domain/factories/organization_factory.rb +2 -1
- data/lib/mumuki/domain/helpers/course.rb +1 -1
- data/lib/mumuki/domain/version.rb +1 -1
- metadata +11 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 05b62ff1728ff0d8fd4a807ce4a8de4b7f70c532a6748c91af12db484582fad0
|
|
4
|
+
data.tar.gz: 25810325f5fa2fb294b0c189bd20f77e85e4722e2557d50b8a760df07edd56bf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f5795882f6b1ed8f8e7b4b66e3f85767c58f72eda7131aae3034a5abe48a27d27b2789e2f97e135f4713da0667769c58baec5ea2b9408ceacf012470439e3dbd
|
|
7
|
+
data.tar.gz: 34514f8787088f9c721fafae973af54a1163d27c00d47029bac4544e78c31d4e8726320ef9d3a81f453090e465c32cd5f10ebb25bad2b4ea9ab6f1227118f270
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
class Certificate < ApplicationRecord
|
|
2
|
+
include WithGeneratedCode
|
|
3
|
+
|
|
4
|
+
belongs_to :user
|
|
5
|
+
belongs_to :certificate_program
|
|
6
|
+
|
|
7
|
+
has_one :organization, through: :certificate_program
|
|
8
|
+
|
|
9
|
+
delegate :title, :description, :template_html_erb, :background_image_url, to: :certificate_program
|
|
10
|
+
|
|
11
|
+
def self.code_size
|
|
12
|
+
12
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def filename
|
|
16
|
+
"#{title.parameterize.underscore}.pdf"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def template_locals
|
|
20
|
+
{ user: user,
|
|
21
|
+
certificate_program: certificate_program,
|
|
22
|
+
organization: organization,
|
|
23
|
+
certificate: self }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def for_user?(user)
|
|
27
|
+
self.user == user
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class CertificateProgram < ApplicationRecord
|
|
2
|
+
belongs_to :organization
|
|
3
|
+
has_many :certificates
|
|
4
|
+
|
|
5
|
+
def friendly
|
|
6
|
+
title
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def template_html_erb
|
|
10
|
+
self[:template_html_erb] ||= <<HTML
|
|
11
|
+
<style>
|
|
12
|
+
.qr-code {
|
|
13
|
+
bottom: 5px;
|
|
14
|
+
right: 5px;
|
|
15
|
+
height: 15mm;
|
|
16
|
+
width: 15mm;
|
|
17
|
+
}
|
|
18
|
+
.name {
|
|
19
|
+
position: absolute;
|
|
20
|
+
width: 100%;
|
|
21
|
+
top: 380px;
|
|
22
|
+
text-align: center;
|
|
23
|
+
}
|
|
24
|
+
</style>
|
|
25
|
+
<!-- You can use interpolations like --
|
|
26
|
+
<%#= certificate.start_date %>
|
|
27
|
+
<%#= certificate.end_date %>
|
|
28
|
+
<%#= user.formal_first_name %>
|
|
29
|
+
<%#= user.formal_last_name %>
|
|
30
|
+
<%#= user.formal_full_name %>
|
|
31
|
+
<%#= certificate_program.title %>
|
|
32
|
+
<%#= certificate_program.description %>
|
|
33
|
+
<%#= organization.name %>
|
|
34
|
+
<%#= organization.display_name %>
|
|
35
|
+
-- -->
|
|
36
|
+
<section class="name">
|
|
37
|
+
<h1><%= user.formal_full_name %></h1>
|
|
38
|
+
</section>
|
|
39
|
+
HTML
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
@@ -19,9 +19,8 @@ module WithAssignments
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
# TODO: When the organization is used in this one, please change guide.pending_exercises
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
assignments.find_by(submitter: user)
|
|
22
|
+
def find_assignment_for(user, organization)
|
|
23
|
+
assignments.find_by(submitter: user, organization: organization)
|
|
25
24
|
end
|
|
26
25
|
|
|
27
26
|
def status_for(user)
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
module WithAssignmentsBatch
|
|
5
5
|
extend ActiveSupport::Concern
|
|
6
6
|
|
|
7
|
-
def find_assignments_for(user,
|
|
7
|
+
def find_assignments_for(user, organization = Organization.current, &block)
|
|
8
8
|
block = block_given? ? block : lambda { |it, _e| it }
|
|
9
9
|
|
|
10
10
|
return exercises.map { |it| block.call nil, it } unless user
|
|
11
11
|
|
|
12
12
|
pairs = exercises.map { |it| [it.id, [nil, it]] }.to_h
|
|
13
|
-
Assignment.where(submitter: user, exercise: exercises).each do |it|
|
|
13
|
+
Assignment.where(submitter: user, organization: organization, exercise: exercises).each do |it|
|
|
14
14
|
pairs[it.exercise_id][0] = it
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module WithGeneratedCode
|
|
2
|
+
extend ActiveSupport::Concern
|
|
3
|
+
|
|
4
|
+
included do
|
|
5
|
+
validates_uniqueness_of :code
|
|
6
|
+
|
|
7
|
+
defaults do
|
|
8
|
+
self.code ||= self.class.generate_code
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
required :code_size
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class_methods do
|
|
15
|
+
def generate_code
|
|
16
|
+
SecureRandom.urlsafe_base64 code_size
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/app/models/course.rb
CHANGED
|
@@ -3,7 +3,7 @@ class Course < ApplicationRecord
|
|
|
3
3
|
include Mumuki::Domain::Helpers::Course
|
|
4
4
|
include Mumuki::Domain::Area
|
|
5
5
|
|
|
6
|
-
validates_presence_of :slug, :
|
|
6
|
+
validates_presence_of :slug, :period, :code, :description, :organization_id
|
|
7
7
|
validates_uniqueness_of :slug
|
|
8
8
|
belongs_to :organization
|
|
9
9
|
|
|
@@ -35,6 +35,10 @@ class Course < ApplicationRecord
|
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
def canonical_code
|
|
39
|
+
"#{period}-#{code}".downcase
|
|
40
|
+
end
|
|
41
|
+
|
|
38
42
|
def closed?
|
|
39
43
|
current_invitation.blank? || current_invitation.expired?
|
|
40
44
|
end
|
data/app/models/invitation.rb
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
class Invitation < ApplicationRecord
|
|
2
|
-
include Mumuki::Domain::Syncable
|
|
2
|
+
include Mumuki::Domain::Syncable,
|
|
3
|
+
WithGeneratedCode
|
|
3
4
|
|
|
4
5
|
belongs_to :course
|
|
5
6
|
|
|
6
7
|
validate :ensure_not_expired, on: :create
|
|
7
|
-
validates_uniqueness_of :code
|
|
8
|
-
|
|
9
|
-
defaults do
|
|
10
|
-
self.code ||= self.class.generate_code
|
|
11
|
-
end
|
|
12
8
|
|
|
13
9
|
def ensure_not_expired
|
|
14
10
|
errors.add(:base, :invitation_expired) if expired?
|
|
@@ -51,12 +47,12 @@ class Invitation < ApplicationRecord
|
|
|
51
47
|
self
|
|
52
48
|
end
|
|
53
49
|
|
|
54
|
-
def self.generate_code
|
|
55
|
-
SecureRandom.urlsafe_base64 4
|
|
56
|
-
end
|
|
57
|
-
|
|
58
50
|
private
|
|
59
51
|
|
|
52
|
+
def self.code_size
|
|
53
|
+
4
|
|
54
|
+
end
|
|
55
|
+
|
|
60
56
|
def course_name
|
|
61
57
|
course.name
|
|
62
58
|
end
|
data/app/models/user.rb
CHANGED
|
@@ -35,6 +35,8 @@ class User < ApplicationRecord
|
|
|
35
35
|
|
|
36
36
|
has_many :exams, through: :exam_authorizations
|
|
37
37
|
|
|
38
|
+
has_many :certificates
|
|
39
|
+
|
|
38
40
|
enum gender: %i(female male other unspecified)
|
|
39
41
|
belongs_to :avatar, polymorphic: true, optional: true
|
|
40
42
|
|
|
@@ -52,6 +54,10 @@ class User < ApplicationRecord
|
|
|
52
54
|
last_guide.try(:lesson)
|
|
53
55
|
end
|
|
54
56
|
|
|
57
|
+
def messages_in_organization(organization = Organization.current)
|
|
58
|
+
messages.where('assignments.organization': organization)
|
|
59
|
+
end
|
|
60
|
+
|
|
55
61
|
def passed_submissions_count_in(organization)
|
|
56
62
|
assignments.where(top_submission_status: Mumuki::Domain::Status::Submission::Passed.to_i, organization: organization).count
|
|
57
63
|
end
|
|
@@ -275,6 +281,26 @@ class User < ApplicationRecord
|
|
|
275
281
|
end
|
|
276
282
|
end
|
|
277
283
|
|
|
284
|
+
def formal_first_name
|
|
285
|
+
verified_first_name || first_name
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def formal_last_name
|
|
289
|
+
verified_last_name || last_name
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def formal_full_name
|
|
293
|
+
"#{formal_first_name} #{formal_last_name}"
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def certificates_in_organization(organization = Organization.current)
|
|
297
|
+
certificates.where certificate_program: CertificateProgram.where(organization: organization)
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def certificated_in?(certificate_program)
|
|
301
|
+
certificates.where(certificate_program: certificate_program).exists?
|
|
302
|
+
end
|
|
303
|
+
|
|
278
304
|
private
|
|
279
305
|
|
|
280
306
|
def welcome_to_new_organizations!
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class CreateCertificatePrograms < ActiveRecord::Migration[5.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :certificate_programs do |t|
|
|
4
|
+
t.string :title
|
|
5
|
+
t.string :template_html_erb
|
|
6
|
+
t.text :description
|
|
7
|
+
t.string :background_image_url
|
|
8
|
+
t.references :organization, index: true
|
|
9
|
+
|
|
10
|
+
t.timestamps
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class CreateCertificates < ActiveRecord::Migration[5.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :certificates do |t|
|
|
4
|
+
t.references :user, index: true
|
|
5
|
+
t.references :certificate_program, index: true
|
|
6
|
+
t.datetime :start_date
|
|
7
|
+
t.datetime :end_date
|
|
8
|
+
t.string :code
|
|
9
|
+
|
|
10
|
+
t.timestamps
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -2,6 +2,8 @@ require_relative './factories/api_client_factory'
|
|
|
2
2
|
require_relative './factories/assignments_factory'
|
|
3
3
|
require_relative './factories/avatar_factory'
|
|
4
4
|
require_relative './factories/book_factory'
|
|
5
|
+
require_relative './factories/certificate_factory'
|
|
6
|
+
require_relative './factories/certificate_program_factory'
|
|
5
7
|
require_relative './factories/chapter_factory'
|
|
6
8
|
require_relative './factories/complement_factory'
|
|
7
9
|
require_relative './factories/course_factory'
|
|
@@ -29,7 +29,8 @@ FactoryBot.define do
|
|
|
29
29
|
book { create(:book, name: 'test', slug: 'mumuki/mumuki-the-book') }
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
factory :another_test_organization, parent: :test_organization
|
|
32
|
+
factory :another_test_organization, parent: :test_organization do
|
|
33
|
+
name { 'another-test' }
|
|
33
34
|
book { create(:book, name: 'another-test', slug: 'mumuki/mumuki-another-book') }
|
|
34
35
|
end
|
|
35
36
|
|
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:
|
|
4
|
+
version: 9.0.0
|
|
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-
|
|
11
|
+
date: 2021-03-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -128,14 +128,14 @@ dependencies:
|
|
|
128
128
|
requirements:
|
|
129
129
|
- - "~>"
|
|
130
130
|
- !ruby/object:Gem::Version
|
|
131
|
-
version: '
|
|
131
|
+
version: '7.0'
|
|
132
132
|
type: :runtime
|
|
133
133
|
prerelease: false
|
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
|
135
135
|
requirements:
|
|
136
136
|
- - "~>"
|
|
137
137
|
- !ruby/object:Gem::Version
|
|
138
|
-
version: '
|
|
138
|
+
version: '7.0'
|
|
139
139
|
- !ruby/object:Gem::Dependency
|
|
140
140
|
name: mumukit-sync
|
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -249,6 +249,8 @@ files:
|
|
|
249
249
|
- app/models/assignment.rb
|
|
250
250
|
- app/models/avatar.rb
|
|
251
251
|
- app/models/book.rb
|
|
252
|
+
- app/models/certificate.rb
|
|
253
|
+
- app/models/certificate_program.rb
|
|
252
254
|
- app/models/chapter.rb
|
|
253
255
|
- app/models/complement.rb
|
|
254
256
|
- app/models/concerns/assistable.rb
|
|
@@ -280,6 +282,7 @@ files:
|
|
|
280
282
|
- app/models/concerns/with_discussions.rb
|
|
281
283
|
- app/models/concerns/with_editor.rb
|
|
282
284
|
- app/models/concerns/with_expectations.rb
|
|
285
|
+
- app/models/concerns/with_generated_code.rb
|
|
283
286
|
- app/models/concerns/with_language.rb
|
|
284
287
|
- app/models/concerns/with_layout.rb
|
|
285
288
|
- app/models/concerns/with_locale.rb
|
|
@@ -651,6 +654,8 @@ files:
|
|
|
651
654
|
- db/migrate/20210118180941_create_exam_authorization_request.rb
|
|
652
655
|
- db/migrate/20210118194904_create_notification.rb
|
|
653
656
|
- db/migrate/20210119160440_add_prevent_manual_evaluation_content_to_organizations.rb
|
|
657
|
+
- db/migrate/20210119174504_create_certificate_programs.rb
|
|
658
|
+
- db/migrate/20210119174835_create_certificates.rb
|
|
654
659
|
- db/migrate/20210119190204_create_exam_registration_exam_join_table.rb
|
|
655
660
|
- lib/mumuki/domain.rb
|
|
656
661
|
- lib/mumuki/domain/area.rb
|
|
@@ -680,6 +685,8 @@ files:
|
|
|
680
685
|
- lib/mumuki/domain/factories/assignments_factory.rb
|
|
681
686
|
- lib/mumuki/domain/factories/avatar_factory.rb
|
|
682
687
|
- lib/mumuki/domain/factories/book_factory.rb
|
|
688
|
+
- lib/mumuki/domain/factories/certificate_factory.rb
|
|
689
|
+
- lib/mumuki/domain/factories/certificate_program_factory.rb
|
|
683
690
|
- lib/mumuki/domain/factories/chapter_factory.rb
|
|
684
691
|
- lib/mumuki/domain/factories/complement_factory.rb
|
|
685
692
|
- lib/mumuki/domain/factories/course_factory.rb
|