From 40428e83976b4cb4c9d4845db3d4dfad38264f93 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Gaya?= <sebastien.gaya@gmail.com>
Date: Thu, 6 Jan 2022 17:57:36 +0100
Subject: [PATCH] create role

---
 .../program/role/people_controller.rb         | 38 +++++++++++++++++++
 app/models/education/program/role.rb          |  2 +
 app/models/education/program/role/person.rb   | 37 ++++++++++++++++++
 .../program/role/people/_list.html.erb        | 30 +++++++++++++++
 .../program/role/people/new.html.erb          | 20 ++++++++++
 .../education/program/roles/_list.html.erb    |  2 +
 .../education/program/roles/show.html.erb     | 11 ++++++
 .../education/program/teachers/_form.html.erb |  4 +-
 config/locales/education/en.yml               |  5 +++
 config/locales/education/fr.yml               |  5 +++
 config/routes/admin/education.rb              |  4 +-
 ...25_create_education_program_role_people.rb | 11 ++++++
 db/schema.rb                                  | 14 ++++++-
 .../education/program/role/people.yml         | 32 ++++++++++++++++
 .../education/program/role/person_test.rb     | 28 ++++++++++++++
 15 files changed, 239 insertions(+), 4 deletions(-)
 create mode 100644 app/controllers/admin/education/program/role/people_controller.rb
 create mode 100644 app/models/education/program/role/person.rb
 create mode 100644 app/views/admin/education/program/role/people/_list.html.erb
 create mode 100644 app/views/admin/education/program/role/people/new.html.erb
 create mode 100644 db/migrate/20220106134525_create_education_program_role_people.rb
 create mode 100644 test/fixtures/education/program/role/people.yml
 create mode 100644 test/models/education/program/role/person_test.rb

diff --git a/app/controllers/admin/education/program/role/people_controller.rb b/app/controllers/admin/education/program/role/people_controller.rb
new file mode 100644
index 000000000..88a4ac3c3
--- /dev/null
+++ b/app/controllers/admin/education/program/role/people_controller.rb
@@ -0,0 +1,38 @@
+class Admin::Education::Program::Role::PeopleController < Admin::Education::Program::ApplicationController
+  load_and_authorize_resource :role, class: Education::Program::Role, through: :program
+  load_and_authorize_resource class: Education::Program::Role::Person, through: :role
+
+  def new
+    breadcrumb
+  end
+
+  def create
+    if @person.save
+      redirect_to admin_education_program_role_path(@role), notice: t('admin.successfully_created_html', model: @person.to_s)
+    else
+      breadcrumb
+      render :new, status: :unprocessable_entity
+    end
+  end
+
+  def destroy
+    @person.destroy
+    redirect_to admin_education_program_role_path(@role), notice: t('admin.successfully_destroyed_html', model: @person.to_s)
+  end
+
+  protected
+
+  def breadcrumb
+    super
+    add_breadcrumb Education::Program::Role.model_name.human(count: 2)
+    breadcrumb_for @role
+    add_breadcrumb Education::Program::Role::Person.model_name.human(count: 2)
+    breadcrumb_for @person
+  end
+
+  def person_params
+    params.require(:education_program_role_person)
+          .permit(:person_id)
+          .merge(role_id: @role.id)
+  end
+end
diff --git a/app/models/education/program/role.rb b/app/models/education/program/role.rb
index 5a0365f34..8edd5ae2a 100644
--- a/app/models/education/program/role.rb
+++ b/app/models/education/program/role.rb
@@ -25,6 +25,8 @@ class Education::Program::Role < ApplicationRecord
 
   belongs_to :university
   belongs_to :program, class_name: 'Education::Program'
+  has_many :people, class_name: 'Education::Program::Role::Person'
+  has_many :university_people, through: :people, source: :person
 
   def to_s
     "#{title}"
diff --git a/app/models/education/program/role/person.rb b/app/models/education/program/role/person.rb
new file mode 100644
index 000000000..f61f1d20f
--- /dev/null
+++ b/app/models/education/program/role/person.rb
@@ -0,0 +1,37 @@
+# == Schema Information
+#
+# Table name: education_program_role_people
+#
+#  id         :uuid             not null, primary key
+#  position   :integer
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#  person_id  :uuid             not null
+#  role_id    :uuid             not null
+#
+# Indexes
+#
+#  index_education_program_role_people_on_person_id  (person_id)
+#  index_education_program_role_people_on_role_id    (role_id)
+#
+# Foreign Keys
+#
+#  fk_rails_...  (person_id => university_people.id)
+#  fk_rails_...  (role_id => education_program_roles.id)
+#
+class Education::Program::Role::Person < ApplicationRecord
+  include WithPosition
+
+  belongs_to :person, class_name: 'University::Person'
+  belongs_to :role, class_name: 'Education::Program::Role'
+
+  def to_s
+    person.to_s
+  end
+
+  protected
+
+  def last_ordered_element
+    role.people.ordered.last
+  end
+end
diff --git a/app/views/admin/education/program/role/people/_list.html.erb b/app/views/admin/education/program/role/people/_list.html.erb
new file mode 100644
index 000000000..cee21001a
--- /dev/null
+++ b/app/views/admin/education/program/role/people/_list.html.erb
@@ -0,0 +1,30 @@
+<% if people.any? %>
+  <table class="table">
+    <thead>
+      <tr>
+        <th><%= Education::Program::Role::Person.model_name.human %></th>
+        <th></th>
+      </tr>
+    </thead>
+    <tbody>
+      <% people.each do |person| %>
+        <tr>
+          <td>
+            <%= link_to_if  can?(:read, person.person),
+                            person.person,
+                            admin_university_person_path(person.person) %>
+          </td>
+          <td class="text-end pe-0">
+            <div class="btn-group" role="group">
+              <%= link_to t('delete'),
+                          admin_education_program_role_person_path(person, { role_id: @role.id }),
+                          method: :delete,
+                          data: { confirm: t('please_confirm') },
+                          class: button_classes_danger %>
+            </div>
+          </td>
+        </tr>
+      <% end %>
+    </tbody>
+  </table>
+<% end %>
diff --git a/app/views/admin/education/program/role/people/new.html.erb b/app/views/admin/education/program/role/people/new.html.erb
new file mode 100644
index 000000000..402d1727d
--- /dev/null
+++ b/app/views/admin/education/program/role/people/new.html.erb
@@ -0,0 +1,20 @@
+<% content_for :title, Education::Program::Role::Person.model_name.human %>
+
+<%= simple_form_for [:admin, @person] do |f| %>
+  <div class="row">
+    <div class="col-md-8">
+      <div class="card flex-fill w-100">
+        <div class="card-header">
+          <h5 class="card-title mb-0"><%= t('admin.infos') %></h5>
+        </div>
+        <div class="card-body">
+          <% used_person_ids = @role.people.where.not(id: @person.id).pluck(:person_id) %>
+          <%= f.association :person, collection: current_university.people.where.not(id: used_person_ids).ordered %>
+        </div>
+      </div>
+    </div>
+  </div>
+  <% content_for :action_bar_right do %>
+    <%= submit f %>
+  <% end %>
+<% end %>
diff --git a/app/views/admin/education/program/roles/_list.html.erb b/app/views/admin/education/program/roles/_list.html.erb
index b3a3b5fee..7b92d9d1f 100644
--- a/app/views/admin/education/program/roles/_list.html.erb
+++ b/app/views/admin/education/program/roles/_list.html.erb
@@ -2,6 +2,7 @@
   <thead>
     <tr>
       <th><%= Education::Program::Role.model_name.human %></th>
+      <th><%= Education::Program::Role.human_attribute_name('people') %></th>
       <th></th>
     </tr>
   </thead>
@@ -13,6 +14,7 @@
                           role,
                           admin_education_program_role_path(role, { program_id: @program.id }) %>
         </td>
+        <td><%= role.people.includes(:person).ordered.map { |person| person.person.to_s }.to_sentence %></td>
         <td class="text-end pe-0">
           <div class="btn-group" role="group">
             <%= link_to t('edit'),
diff --git a/app/views/admin/education/program/roles/show.html.erb b/app/views/admin/education/program/roles/show.html.erb
index e6d4117f3..051d0859a 100644
--- a/app/views/admin/education/program/roles/show.html.erb
+++ b/app/views/admin/education/program/roles/show.html.erb
@@ -12,6 +12,17 @@
       </div>
     </div>
   </div>
+  <div class="col-md-8">
+    <div class="card flex-fill w-100">
+      <div class="card-header">
+        <h2 class="card-title mb-0 h5"><%= Education::Program::Role.human_attribute_name('people') %></h2>
+      </div>
+      <div class="card-body">
+        <p><%= link_to t('create'), new_admin_education_program_role_person_path(role_id: @role.id), class: 'btn btn-primary' %></p>
+        <%= render 'admin/education/program/role/people/list', people: @role.people.includes(:person).ordered %>
+      </div>
+    </div>
+  </div>
 </div>
 
 <% content_for :action_bar_right do %>
diff --git a/app/views/admin/education/program/teachers/_form.html.erb b/app/views/admin/education/program/teachers/_form.html.erb
index e8c8b9067..503032b23 100644
--- a/app/views/admin/education/program/teachers/_form.html.erb
+++ b/app/views/admin/education/program/teachers/_form.html.erb
@@ -6,8 +6,8 @@
     <div class="card-body">
       <div class="row">
         <div class="col-md-6">
-          <% teacher_ids = @program.teachers.where.not(id: teacher.id).pluck(:person_id) %>
-          <%= f.association :person, collection: current_university.people.teachers.where.not(id: teacher_ids).ordered %>
+          <% used_teacher_ids = @program.teachers.where.not(id: teacher.id).pluck(:person_id) %>
+          <%= f.association :person, collection: current_university.people.teachers.where.not(id: used_teacher_ids).ordered %>
         </div>
         <div class="col-md-6">
           <%= f.input :description, as: :string %>
diff --git a/config/locales/education/en.yml b/config/locales/education/en.yml
index a5e6d3c66..1cb84dcbc 100644
--- a/config/locales/education/en.yml
+++ b/config/locales/education/en.yml
@@ -10,6 +10,9 @@ en:
       education/program/role:
         one: Role
         other: Roles
+      education/program/role/person:
+        one: Person
+        other: People
       education/program/teacher:
         one: Teacher
         other: Teachers
@@ -45,6 +48,8 @@ en:
       education/program/role:
         people: People
         title: Title
+      education/program/role/person:
+        person: Person
       education/program/teacher:
         description: Description
         person: Person
diff --git a/config/locales/education/fr.yml b/config/locales/education/fr.yml
index c087f4a27..755c0845c 100644
--- a/config/locales/education/fr.yml
+++ b/config/locales/education/fr.yml
@@ -10,6 +10,9 @@ fr:
       education/program/role:
         one: Rôle
         other: Rôles
+      education/program/role/person:
+        one: Personne
+        other: Personnes
       education/program/teacher:
         one: Enseignant·e
         other: Enseignants·es
@@ -47,6 +50,8 @@ fr:
       education/program/role:
         people: Personnes
         title: Titre
+      education/program/role/person:
+        person: Personne
       education/program/teacher:
         description: Description
         person: Personne
diff --git a/config/routes/admin/education.rb b/config/routes/admin/education.rb
index 75ca3697e..fa8099527 100644
--- a/config/routes/admin/education.rb
+++ b/config/routes/admin/education.rb
@@ -2,7 +2,9 @@ namespace :education do
   resources :teachers, only: [:index, :show]
   resources :schools
   resources :programs do
-    resources :roles, controller: 'program/roles', except: :index
+    resources :roles, controller: 'program/roles', except: :index do
+      resources :people, controller: 'program/role/people', except: [:index, :show, :edit, :update]
+    end
     resources :teachers, controller: 'program/teachers', except: [:index, :show]
     collection do
       post :reorder
diff --git a/db/migrate/20220106134525_create_education_program_role_people.rb b/db/migrate/20220106134525_create_education_program_role_people.rb
new file mode 100644
index 000000000..a967cad41
--- /dev/null
+++ b/db/migrate/20220106134525_create_education_program_role_people.rb
@@ -0,0 +1,11 @@
+class CreateEducationProgramRolePeople < ActiveRecord::Migration[6.1]
+  def change
+    create_table :education_program_role_people, id: :uuid do |t|
+      t.integer :position
+      t.references :person, null: false, foreign_key: { to_table: :university_people }, type: :uuid
+      t.references :role, null: false, foreign_key: { to_table: :education_program_roles }, type: :uuid
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 4e15658bf..b8e59bfdb 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 2022_01_06_104521) do
+ActiveRecord::Schema.define(version: 2022_01_06_134525) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "pgcrypto"
@@ -347,6 +347,16 @@ ActiveRecord::Schema.define(version: 2022_01_06_104521) do
     t.index ["priority", "run_at"], name: "delayed_jobs_priority"
   end
 
+  create_table "education_program_role_people", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+    t.integer "position"
+    t.uuid "person_id", null: false
+    t.uuid "role_id", null: false
+    t.datetime "created_at", precision: 6, null: false
+    t.datetime "updated_at", precision: 6, null: false
+    t.index ["person_id"], name: "index_education_program_role_people_on_person_id"
+    t.index ["role_id"], name: "index_education_program_role_people_on_role_id"
+  end
+
   create_table "education_program_roles", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
     t.string "title"
     t.integer "position"
@@ -590,6 +600,8 @@ ActiveRecord::Schema.define(version: 2022_01_06_104521) do
   add_foreign_key "communication_website_posts", "universities"
   add_foreign_key "communication_website_posts", "university_people", column: "author_id"
   add_foreign_key "communication_websites", "universities"
+  add_foreign_key "education_program_role_people", "education_program_roles", column: "role_id"
+  add_foreign_key "education_program_role_people", "university_people", column: "person_id"
   add_foreign_key "education_program_roles", "education_programs", column: "program_id"
   add_foreign_key "education_program_roles", "universities"
   add_foreign_key "education_program_teachers", "education_programs", column: "program_id"
diff --git a/test/fixtures/education/program/role/people.yml b/test/fixtures/education/program/role/people.yml
new file mode 100644
index 000000000..dd8da3363
--- /dev/null
+++ b/test/fixtures/education/program/role/people.yml
@@ -0,0 +1,32 @@
+# == Schema Information
+#
+# Table name: education_program_role_people
+#
+#  id         :uuid             not null, primary key
+#  position   :integer
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#  person_id  :uuid             not null
+#  role_id    :uuid             not null
+#
+# Indexes
+#
+#  index_education_program_role_people_on_person_id  (person_id)
+#  index_education_program_role_people_on_role_id    (role_id)
+#
+# Foreign Keys
+#
+#  fk_rails_...  (person_id => university_people.id)
+#  fk_rails_...  (role_id => education_program_roles.id)
+#
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+  position: 1
+  person: one
+  role: one
+
+two:
+  position: 1
+  person: two
+  role: two
diff --git a/test/models/education/program/role/person_test.rb b/test/models/education/program/role/person_test.rb
new file mode 100644
index 000000000..a257dd899
--- /dev/null
+++ b/test/models/education/program/role/person_test.rb
@@ -0,0 +1,28 @@
+# == Schema Information
+#
+# Table name: education_program_role_people
+#
+#  id         :uuid             not null, primary key
+#  position   :integer
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#  person_id  :uuid             not null
+#  role_id    :uuid             not null
+#
+# Indexes
+#
+#  index_education_program_role_people_on_person_id  (person_id)
+#  index_education_program_role_people_on_role_id    (role_id)
+#
+# Foreign Keys
+#
+#  fk_rails_...  (person_id => university_people.id)
+#  fk_rails_...  (role_id => education_program_roles.id)
+#
+require "test_helper"
+
+class Education::Program::Role::PersonTest < ActiveSupport::TestCase
+  # test "the truth" do
+  #   assert true
+  # end
+end
-- 
GitLab