From 79e8f3457497c173b3e9d0955832c3266e25860f Mon Sep 17 00:00:00 2001
From: Arnaud Levy <contact@arnaudlevy.com>
Date: Sun, 15 May 2022 08:17:54 +0200
Subject: [PATCH] Diplomas #382

---
 .../admin/application_controller.rb           |  7 ---
 .../admin/education/diplomas_controller.rb    | 63 +++++++++++++++++++
 .../admin/education/programs_controller.rb    |  6 +-
 app/models/ability.rb                         |  2 +
 app/models/education/diploma.rb               | 51 +++++++++++++++
 app/models/education/program.rb               |  6 ++
 app/models/university/with_education.rb       |  5 ++
 .../admin/education/cohorts/_form.html.erb    |  1 -
 .../admin/education/cohorts/new.html.erb      |  6 +-
 .../admin/education/diplomas/_form.html.erb   | 20 ++++++
 .../admin/education/diplomas/_list.html.erb   | 27 ++++++++
 .../admin/education/diplomas/edit.html.erb    |  3 +
 .../admin/education/diplomas/index.html.erb   |  7 +++
 .../admin/education/diplomas/new.html.erb     |  3 +
 .../admin/education/diplomas/show.html.erb    | 27 ++++++++
 .../admin/education/diplomas/static.html.erb  |  6 ++
 .../admin/education/programs/_form.html.erb   | 11 +++-
 .../admin/education/programs/show.html.erb    | 24 +++++--
 config/admin_navigation.rb                    |  7 ++-
 config/locales/education/en.yml               | 22 +++++++
 config/locales/education/fr.yml               | 22 +++++++
 config/routes/admin/education.rb              |  1 +
 ...0220515052429_create_education_diplomas.rb | 14 +++++
 ...48_add_short_name_to_education_programs.rb |  5 ++
 db/schema.rb                                  | 36 ++++++++++-
 test/fixtures/education/diplomas.yml          | 33 ++++++++++
 test/models/education/diploma_test.rb         | 28 +++++++++
 27 files changed, 417 insertions(+), 26 deletions(-)
 create mode 100644 app/controllers/admin/education/diplomas_controller.rb
 create mode 100644 app/models/education/diploma.rb
 create mode 100644 app/views/admin/education/diplomas/_form.html.erb
 create mode 100644 app/views/admin/education/diplomas/_list.html.erb
 create mode 100644 app/views/admin/education/diplomas/edit.html.erb
 create mode 100644 app/views/admin/education/diplomas/index.html.erb
 create mode 100644 app/views/admin/education/diplomas/new.html.erb
 create mode 100644 app/views/admin/education/diplomas/show.html.erb
 create mode 100644 app/views/admin/education/diplomas/static.html.erb
 create mode 100644 db/migrate/20220515052429_create_education_diplomas.rb
 create mode 100644 db/migrate/20220515060948_add_short_name_to_education_programs.rb
 create mode 100644 test/fixtures/education/diplomas.yml
 create mode 100644 test/models/education/diploma_test.rb

diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb
index 084644e1d..3934d2576 100644
--- a/app/controllers/admin/application_controller.rb
+++ b/app/controllers/admin/application_controller.rb
@@ -3,8 +3,6 @@ class Admin::ApplicationController < ApplicationController
 
   before_action :load_filters, only: :index
 
-  around_action :switch_locale
-
   protected
 
   def breadcrumb
@@ -23,11 +21,6 @@ class Admin::ApplicationController < ApplicationController
                       : add_breadcrumb(t('create'))
   end
 
-  def switch_locale(&action)
-    locale = LocaleService.locale(current_user, request.env['HTTP_ACCEPT_LANGUAGE'])
-    I18n.with_locale(locale, &action)
-  end
-
   def load_filters
     @filters = []
     filter_class_name = "::Filters::#{self.class.to_s.gsub('Controller', '')}"
diff --git a/app/controllers/admin/education/diplomas_controller.rb b/app/controllers/admin/education/diplomas_controller.rb
new file mode 100644
index 000000000..4fe3bd48b
--- /dev/null
+++ b/app/controllers/admin/education/diplomas_controller.rb
@@ -0,0 +1,63 @@
+class Admin::Education::DiplomasController < Admin::Education::ApplicationController
+  load_and_authorize_resource class: Education::Diploma,
+                              through: :current_university
+
+  def index
+    breadcrumb
+  end
+
+  def show
+    @programs = @diploma.programs.ordered.page params[:page]
+    breadcrumb
+  end
+
+  def new
+    breadcrumb
+  end
+
+  def edit
+    breadcrumb
+    add_breadcrumb t('edit')
+  end
+
+  def create
+    @diploma.university = current_university
+    if @diploma.save_and_sync
+      redirect_to [:admin, @diploma],
+                  notice: t('admin.successfully_created_html', model: @diploma.to_s)
+    else
+      breadcrumb
+      render :new, status: :unprocessable_entity
+    end
+  end
+
+  def update
+    if @diploma.update_and_sync(diploma_params)
+      redirect_to [:admin, @diploma],
+                  notice: t('admin.successfully_updated_html', model: @diploma.to_s)
+    else
+      breadcrumb
+      add_breadcrumb t('edit')
+      render :edit, status: :unprocessable_entity
+    end
+  end
+
+  def destroy
+    @diploma.destroy_and_sync
+    redirect_to admin_education_diplomas_url,
+                notice: t('admin.successfully_destroyed_html', model: @diploma.to_s)
+  end
+
+  private
+
+  def breadcrumb
+    super
+    add_breadcrumb Education::Diploma.model_name.human(count: 2), admin_education_diplomas_path
+    breadcrumb_for @diploma
+  end
+
+  def diploma_params
+    params.require(:education_diploma)
+          .permit(:name, :short_name, :level)
+  end
+end
diff --git a/app/controllers/admin/education/programs_controller.rb b/app/controllers/admin/education/programs_controller.rb
index 3d509c808..f1b7476b4 100644
--- a/app/controllers/admin/education/programs_controller.rb
+++ b/app/controllers/admin/education/programs_controller.rb
@@ -97,11 +97,11 @@ class Admin::Education::ProgramsController < Admin::Education::ApplicationContro
 
   def program_params
     params.require(:education_program).permit(
-      :name, :slug, :level, :capacity, :ects, :continuing, :description, :published,
+      :name, :short_name, :slug, :level, :capacity, :ects, :continuing, :description, :published,
       :featured_image, :featured_image_delete, :featured_image_infos, :featured_image_alt, :featured_image_credit,
       :prerequisites, :objectives, :duration, :presentation, :registration, :pedagogy, :content,
-      :evaluation, :accessibility, :pricing, :contacts, :opportunities, :results, :other, :main_information,
-      :parent_id, school_ids: [],
+      :evaluation, :accessibility, :pricing, :contacts, :opportunities, :results, :other,  :main_information,
+      :parent_id, :diploma_id, school_ids: [], 
       university_person_involvements_attributes: [:id, :person_id, :description, :position, :_destroy]
     )
   end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 687a45581..293322880 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -20,6 +20,7 @@ class Ability
     can :read, Communication::Website::Imported::Website, university_id: @user.university_id
     can :read, Communication::Website::Imported::Page, university_id: @user.university_id
     can :read, Communication::Website::Imported::Post, university_id: @user.university_id
+    can :read, Education::Diploma, university_id: @user.university_id
     can :read, Education::Program, university_id: @user.university_id
     can :read, Education::School, university_id: @user.university_id
     can :read, Research::Journal, university_id: @user.university_id
@@ -100,6 +101,7 @@ class Ability
     can :manage, Education::AcademicYear, university_id: @user.university_id
     can :manage, Education::Cohort, university_id: @user.university_id
     can :manage, Education::School, university_id: @user.university_id
+    can :manage, Education::Diploma, university_id: @user.university_id
     can :manage, Education::Program, university_id: @user.university_id
     can :manage, :all_programs # needed to prevent program_manager to access specific global screens
     can :manage, Research::Journal, university_id: @user.university_id
diff --git a/app/models/education/diploma.rb b/app/models/education/diploma.rb
new file mode 100644
index 000000000..8f6763d8e
--- /dev/null
+++ b/app/models/education/diploma.rb
@@ -0,0 +1,51 @@
+# == Schema Information
+#
+# Table name: education_diplomas
+#
+#  id            :uuid             not null, primary key
+#  level         :integer          default("not_applicable")
+#  name          :string
+#  short_name    :string
+#  slug          :string
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  university_id :uuid             not null, indexed
+#
+# Indexes
+#
+#  index_education_diplomas_on_university_id  (university_id)
+#
+# Foreign Keys
+#
+#  fk_rails_6cb2e9fa90  (university_id => universities.id)
+#
+class Education::Diploma < ApplicationRecord
+  include WithUniversity
+  include WithGit
+  include WithSlug
+
+  has_many :programs
+
+  scope :ordered, -> { order(:level, :name) }
+
+  enum level: {
+    not_applicable: 0,
+    primary: 40,
+    secondary: 60,
+    high: 80,
+    first_year: 100,
+    second_year: 200,
+    third_year: 300,
+    fourth_year: 500,
+    master: 500,
+    doctor: 800
+  }
+
+  def git_path(website)
+    "content/diplomas/#{slug}/_index.html"
+  end
+
+  def to_s
+    "#{name}"
+  end
+end
diff --git a/app/models/education/program.rb b/app/models/education/program.rb
index bb68ea144..33e76c866 100644
--- a/app/models/education/program.rb
+++ b/app/models/education/program.rb
@@ -29,14 +29,17 @@
 #  published             :boolean          default(FALSE)
 #  registration          :text
 #  results               :text
+#  short_name            :string
 #  slug                  :string
 #  created_at            :datetime         not null
 #  updated_at            :datetime         not null
+#  diploma_id            :uuid             indexed
 #  parent_id             :uuid             indexed
 #  university_id         :uuid             not null, indexed
 #
 # Indexes
 #
+#  index_education_programs_on_diploma_id     (diploma_id)
 #  index_education_programs_on_parent_id      (parent_id)
 #  index_education_programs_on_university_id  (university_id)
 #
@@ -84,6 +87,9 @@ class Education::Program < ApplicationRecord
              class_name: 'Education::Program',
              foreign_key: :parent_id,
              dependent: :destroy
+  belongs_to :diploma,
+             class_name: 'Education::Diploma',
+             optional: true
   has_many   :university_roles,
              class_name: 'University::Role',
              as: :target,
diff --git a/app/models/university/with_education.rb b/app/models/university/with_education.rb
index 95b2d605b..d6852f624 100644
--- a/app/models/university/with_education.rb
+++ b/app/models/university/with_education.rb
@@ -7,6 +7,11 @@ module University::WithEducation
               dependent: :destroy
     alias_attribute :cohorts, :education_cohorts
 
+    has_many  :education_diplomas,
+              class_name: 'Education::Diploma',
+              dependent: :destroy
+    alias_attribute :diplomas, :education_diplomas
+
     has_many  :education_programs,
               class_name: 'Education::Program',
               dependent: :destroy
diff --git a/app/views/admin/education/cohorts/_form.html.erb b/app/views/admin/education/cohorts/_form.html.erb
index c2ed9f568..17a5811a7 100644
--- a/app/views/admin/education/cohorts/_form.html.erb
+++ b/app/views/admin/education/cohorts/_form.html.erb
@@ -1,4 +1,3 @@
-
 <%= simple_form_for(@education_cohort) do |f| %>
   <%= f.error_notification %>
   <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
diff --git a/app/views/admin/education/cohorts/new.html.erb b/app/views/admin/education/cohorts/new.html.erb
index 7ac730f56..bb0dcdab4 100644
--- a/app/views/admin/education/cohorts/new.html.erb
+++ b/app/views/admin/education/cohorts/new.html.erb
@@ -1,5 +1,3 @@
-<h1>New Education Cohort</h1>
+<% content_for :title, Education::Cohort.model_name.human %>
 
-<%= render 'form', education_cohort: @education_cohort %>
-
-<%= link_to 'Back', education_cohorts_path %>
+<%= render 'form', cohort: @cohort %>
diff --git a/app/views/admin/education/diplomas/_form.html.erb b/app/views/admin/education/diplomas/_form.html.erb
new file mode 100644
index 000000000..04f3a2d6e
--- /dev/null
+++ b/app/views/admin/education/diplomas/_form.html.erb
@@ -0,0 +1,20 @@
+<%= simple_form_for [:admin, diploma] do |f| %>
+  <%= f.error_notification %>
+  <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
+
+  <div class="row">
+    <div class="col-lg-6">
+      <%= f.input :name %>
+    </div>
+    <div class="col-lg-3">
+      <%= f.input :short_name %>
+    </div>
+    <div class="col-lg-3">
+      <%= f.input :level, include_blank: false %>
+    </div>
+  </div>
+
+  <% content_for :action_bar_right do %>
+    <%= submit f %>
+  <% end %>
+<% end %>
diff --git a/app/views/admin/education/diplomas/_list.html.erb b/app/views/admin/education/diplomas/_list.html.erb
new file mode 100644
index 000000000..e7adc544e
--- /dev/null
+++ b/app/views/admin/education/diplomas/_list.html.erb
@@ -0,0 +1,27 @@
+<table class="<%= table_classes %>">
+  <thead>
+    <tr>
+      <th><%= Education::Diploma.human_attribute_name('name') %></th>
+      <th><%= Education::Diploma.human_attribute_name('short_name') %></th>
+      <th><%= Education::Diploma.human_attribute_name('level') %></th>
+      <th><%= Education::Diploma.human_attribute_name('programs') %></th>
+      <th></th>
+    </tr>
+  </thead>
+  <tbody>
+    <% diplomas.ordered.each do |diploma| %>
+      <tr>
+        <td><%= link_to diploma, [:admin, diploma] %></td>
+        <td><%= diploma.short_name %></td>
+        <td><%= diploma.level_i18n %></td>
+        <td><%= diploma.programs.count %></td>
+        <td class="text-end">
+          <div class="btn-group" role="group">
+            <%= edit_link diploma %>
+            <%= destroy_link diploma %>
+          </div>
+        </td>
+      </tr>
+    <% end %>
+  </tbody>
+</table>
diff --git a/app/views/admin/education/diplomas/edit.html.erb b/app/views/admin/education/diplomas/edit.html.erb
new file mode 100644
index 000000000..49c3650d8
--- /dev/null
+++ b/app/views/admin/education/diplomas/edit.html.erb
@@ -0,0 +1,3 @@
+<% content_for :title, @diploma %>
+
+<%= render 'form', diploma: @diploma %>
diff --git a/app/views/admin/education/diplomas/index.html.erb b/app/views/admin/education/diplomas/index.html.erb
new file mode 100644
index 000000000..98c19f66f
--- /dev/null
+++ b/app/views/admin/education/diplomas/index.html.erb
@@ -0,0 +1,7 @@
+<% content_for :title, Education::Diploma.model_name.human(count: 2) %>
+
+<%= render 'admin/education/diplomas/list', diplomas: @diplomas %>
+
+<% content_for :action_bar_right do %>
+  <%= create_link Education::Diploma %>
+<% end %>
diff --git a/app/views/admin/education/diplomas/new.html.erb b/app/views/admin/education/diplomas/new.html.erb
new file mode 100644
index 000000000..2542f8abe
--- /dev/null
+++ b/app/views/admin/education/diplomas/new.html.erb
@@ -0,0 +1,3 @@
+<% content_for :title, Education::Diploma.model_name.human %>
+
+<%= render 'form', diploma: @diploma %>
diff --git a/app/views/admin/education/diplomas/show.html.erb b/app/views/admin/education/diplomas/show.html.erb
new file mode 100644
index 000000000..7fad666fb
--- /dev/null
+++ b/app/views/admin/education/diplomas/show.html.erb
@@ -0,0 +1,27 @@
+<% content_for :title, @diploma %>
+
+<div class="row">
+  <div class="col-lg-6">
+    <p>
+      <strong><%= Education::Diploma.human_attribute_name('short_name') %></strong>
+      <%= @diploma.short_name %>
+    </p>
+  </div>
+  <div class="col-lg-6">
+    <p>
+      <strong><%= Education::Diploma.human_attribute_name('level') %></strong>
+      <%= @diploma.level_i18n %>
+    </p>
+  </div>
+</div>
+
+
+<%= render 'admin/education/programs/list', programs: @programs %>
+
+<% content_for :action_bar_left do %>
+  <%= destroy_link @diploma %>
+<% end %>
+
+<% content_for :action_bar_right do %>
+  <%= edit_link @diploma %>
+<% end %>
diff --git a/app/views/admin/education/diplomas/static.html.erb b/app/views/admin/education/diplomas/static.html.erb
new file mode 100644
index 000000000..e0ca041da
--- /dev/null
+++ b/app/views/admin/education/diplomas/static.html.erb
@@ -0,0 +1,6 @@
+---
+title: >
+  <%= @about.name %>
+short_name: >
+  <%= @about.short_name %>
+---
diff --git a/app/views/admin/education/programs/_form.html.erb b/app/views/admin/education/programs/_form.html.erb
index 22b08099d..4fbc4ae85 100644
--- a/app/views/admin/education/programs/_form.html.erb
+++ b/app/views/admin/education/programs/_form.html.erb
@@ -29,9 +29,18 @@
     </div>
     <div class="col-md-9">
       <%= render 'admin/education/programs/forms/part', part: :essential do %>
-        <%= f.input :name %>
+        <div class="row">
+          <div class="col-lg-9">
+            <%= f.input :name %>
+          </div>
+          <div class="col-lg-3">
+            <%= f.input :short_name %>
+          </div>
+        </div>
         <div class="row">
           <div class="col-lg-6">
+            <%= f.association :diploma,
+                              collection: current_university.diplomas.ordered %>
             <%= f.input :level, include_blank: false %>
             <%= f.input :ects %>
             <%= render 'admin/education/programs/forms/input_with_inheritance',
diff --git a/app/views/admin/education/programs/show.html.erb b/app/views/admin/education/programs/show.html.erb
index a494e6e81..76b867045 100644
--- a/app/views/admin/education/programs/show.html.erb
+++ b/app/views/admin/education/programs/show.html.erb
@@ -28,20 +28,34 @@
   <div class="col-md-9">
     <%= render 'admin/education/programs/forms/part',
                 part: :essential,
-                collapsed: true do %>
-      <h3 class="h5"><%= Education::Program.human_attribute_name('name') %></h3>
-      <%= @program.name %>
+                collapsed: false do %>
       <div class="row">
         <div class="col-lg-6">
-          <h3 class="h5 mt-4"><%= Education::Program.human_attribute_name('level') %></h3>
+          <h3 class="h5">
+            <%= Education::Program.human_attribute_name('name') %>
+          </h3>
+          <p><%= @program.name %></p>
+          <h3 class="h5 mt-4">
+            <%= Education::Program.human_attribute_name('diploma') %>
+          </h3>
+          <p><%= link_to @program.diploma, [:admin, @program.diploma] if @program.diploma %></p>
+          <h3 class="h5 mt-4">
+            <%= Education::Program.human_attribute_name('level') %>
+          </h3>
           <p><%= @program.level_i18n %></p>
-          <h3 class="h5 mt-4"><%= Education::Program.human_attribute_name('ects') %></h3>
+          <h3 class="h5 mt-4">
+            <%= Education::Program.human_attribute_name('ects') %>
+          </h3>
           <p><%= @program.ects %></p>
           <%= render 'admin/application/property/text',
                       object: @program,
                       property: :duration %>
         </div>
         <div class="col-lg-6">
+          <h3 class="h5">
+            <%= Education::Program.human_attribute_name('short_name') %>
+          </h3>
+          <p><%= @program.short_name %></p>
           <h3 class="h5 mt-4">
             <%= Education::Program.human_attribute_name('capacity') %>
           </h3>
diff --git a/config/admin_navigation.rb b/config/admin_navigation.rb
index fa7f7f9f1..f0f93fb02 100644
--- a/config/admin_navigation.rb
+++ b/config/admin_navigation.rb
@@ -15,9 +15,10 @@ SimpleNavigation::Configuration.run do |navigation|
 
     if can?(:read, Education::Program)
       primary.item :education, Education.model_name.human, nil, { kind: :header }
-      primary.item :education, t('education.teachers', count: 2), admin_education_teachers_path, { icon: 'user-graduate' } if can?(:read, University::Person)
-      primary.item :education, Education::School.model_name.human(count: 2), admin_education_schools_path, { icon: 'university' } if can?(:read, Education::School)
-      primary.item :education_programs, Education::Program.model_name.human(count: 2), admin_education_programs_path, { icon: 'graduation-cap' } if can?(:read, Education::Program)
+      primary.item :education_teachers, t('education.teachers', count: 2), admin_education_teachers_path, { icon: 'user-graduate' } if can?(:read, University::Person)
+      primary.item :education_schools, Education::School.model_name.human(count: 2), admin_education_schools_path, { icon: 'university' } if can?(:read, Education::School)
+      primary.item :education_diplomas, Education::Diploma.model_name.human(count: 2), admin_education_diplomas_path, { icon: 'graduation-cap' } if can?(:read, Education::Diploma)
+      primary.item :education_programs, Education::Program.model_name.human(count: 2), admin_education_programs_path, { icon: 'chalkboard-teacher' } if can?(:read, Education::Program)
       primary.item :education, 'Ressources éducatives', nil, { icon: 'laptop' }
       primary.item :education, 'Feedbacks', nil, { icon: 'comments' }
     end
diff --git a/config/locales/education/en.yml b/config/locales/education/en.yml
index 26bd81afc..4cd54e4b7 100644
--- a/config/locales/education/en.yml
+++ b/config/locales/education/en.yml
@@ -10,6 +10,9 @@ en:
       education/cohort:
         one: Cohort
         other: Cohorts
+      education/diploma:
+        one: Diploma
+        other: Diplomas
       education/program:
         one: Program
         other: Programs
@@ -20,6 +23,11 @@ en:
       education/cohort:
         year: Year
         alumni: Alumni
+      education/diploma:
+        name: Name
+        short_name: Short name
+        level: Level
+        programs: Programs
       education/program:
         accessibility: Accessibilité
         capacity: Capacity
@@ -27,6 +35,7 @@ en:
         continuing: Formation continue
         description: Meta Description
         duration: Durée
+        diploma: Diploma
         ects: Crédits ECTS
         evaluation: Modalités d’évaluation
         featured_image: Featured image
@@ -45,6 +54,7 @@ en:
         registration: Modalités et délais d’accès
         roles: Roles
         schools: Schools with this formation
+        short_name: Short name
         teachers: Teachers
         team: Team
         content: Program's content
@@ -86,6 +96,18 @@ en:
       other: Teachers
   enums:
     education:
+      diploma:
+        level:
+          not_applicable: Not applicable
+          primary: Primary school
+          secondary: Secondary school
+          high: High School
+          first_year: 1 year
+          second_year: 2 years
+          third_year: Licence (3 years)
+          fourth_year: 4 years
+          master: Master (5 years)
+          doctor: Doctorate (8 years)
       program:
         level:
           bachelor: Licence / bachelor
diff --git a/config/locales/education/fr.yml b/config/locales/education/fr.yml
index 7a23cec22..ecd5a58b3 100644
--- a/config/locales/education/fr.yml
+++ b/config/locales/education/fr.yml
@@ -10,6 +10,9 @@ fr:
       education/cohort:
         one: Promotion
         other: Promotions
+      education/diploma:
+        one: Diplôme
+        other: Diplômes
       education/program:
         one: Formation
         other: Formations
@@ -20,6 +23,11 @@ fr:
       education/cohort:
         year: Année
         alumni: Alumni
+      education/diploma:
+        name: Nom
+        short_name: Nom abrégé
+        level: Niveau
+        programs: Formations
       education/program:
         accessibility: Accessibilité
         capacity: Capacité
@@ -27,6 +35,7 @@ fr:
         continuing: Formation continue
         description: Meta Description
         duration: Durée
+        diploma: Diplôme
         ects: Crédits ECTS
         evaluation: Modalités d’évaluation
         featured_image: Image à la une
@@ -45,6 +54,7 @@ fr:
         registration: Modalités et délais d’accès
         roles: Rôles
         schools: Écoles proposant cette formation
+        short_name: Nom abrégé
         teachers: Enseignants·es
         team: Équipe
         content: Contenus de la formation
@@ -104,6 +114,18 @@ fr:
       other: Enseignants·es
   enums:
     education:
+      diploma:
+        level:
+          not_applicable: Non applicable
+          primary: École primaire
+          secondary: Collège
+          high: Lycée
+          first_year: Bac + 1
+          second_year: Bac + 2
+          third_year: Licence (Bac + 3)
+          fourth_year: Bac + 4
+          master: Master (Bac + 5)
+          doctor: Doctorat (Bac + 8)
       program:
         level:
           bachelor: Licence / bachelor
diff --git a/config/routes/admin/education.rb b/config/routes/admin/education.rb
index 7926e252b..68586440f 100644
--- a/config/routes/admin/education.rb
+++ b/config/routes/admin/education.rb
@@ -34,4 +34,5 @@ namespace :education do
   end
   resources :academic_years
   resources :cohorts
+  resources :diplomas
 end
diff --git a/db/migrate/20220515052429_create_education_diplomas.rb b/db/migrate/20220515052429_create_education_diplomas.rb
new file mode 100644
index 000000000..4fa9a997a
--- /dev/null
+++ b/db/migrate/20220515052429_create_education_diplomas.rb
@@ -0,0 +1,14 @@
+class CreateEducationDiplomas < ActiveRecord::Migration[6.1]
+  def change
+    create_table :education_diplomas, id: :uuid do |t|
+      t.string :name
+      t.string :short_name
+      t.integer :level, default: 0
+      t.string :slug
+      t.references :university, null: false, foreign_key: true, type: :uuid
+
+      t.timestamps
+    end
+    add_reference :education_programs, :diploma, type: :uuid
+  end
+end
diff --git a/db/migrate/20220515060948_add_short_name_to_education_programs.rb b/db/migrate/20220515060948_add_short_name_to_education_programs.rb
new file mode 100644
index 000000000..433620850
--- /dev/null
+++ b/db/migrate/20220515060948_add_short_name_to_education_programs.rb
@@ -0,0 +1,5 @@
+class AddShortNameToEducationPrograms < ActiveRecord::Migration[6.1]
+  def change
+    add_column :education_programs, :short_name, :string
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 7b136e975..e91cd9d7e 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_05_05_131539) do
+ActiveRecord::Schema.define(version: 2022_05_15_060948) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "pgcrypto"
@@ -419,6 +419,17 @@ ActiveRecord::Schema.define(version: 2022_05_05_131539) do
     t.index ["university_person_id", "education_cohort_id"], name: "index_person_cohort"
   end
 
+  create_table "education_diplomas", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+    t.string "name"
+    t.string "short_name"
+    t.integer "level", default: 0
+    t.string "slug"
+    t.uuid "university_id", null: false
+    t.datetime "created_at", precision: 6, null: false
+    t.datetime "updated_at", precision: 6, null: false
+    t.index ["university_id"], name: "index_education_diplomas_on_university_id"
+  end
+
   create_table "education_programs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.string "name"
@@ -451,6 +462,9 @@ ActiveRecord::Schema.define(version: 2022_05_05_131539) do
     t.text "presentation"
     t.text "main_information"
     t.text "featured_image_credit"
+    t.uuid "diploma_id"
+    t.string "short_name"
+    t.index ["diploma_id"], name: "index_education_programs_on_diploma_id"
     t.index ["parent_id"], name: "index_education_programs_on_parent_id"
     t.index ["university_id"], name: "index_education_programs_on_university_id"
   end
@@ -490,6 +504,23 @@ ActiveRecord::Schema.define(version: 2022_05_05_131539) do
     t.index ["university_id"], name: "index_education_schools_on_university_id"
   end
 
+  create_table "external_organizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+    t.string "title"
+    t.text "description"
+    t.string "address"
+    t.string "zipcode"
+    t.string "city"
+    t.string "country"
+    t.string "website"
+    t.string "phone"
+    t.string "mail"
+    t.boolean "active"
+    t.string "sirene"
+    t.integer "kind"
+    t.datetime "created_at", precision: 6, null: false
+    t.datetime "updated_at", precision: 6, null: false
+  end
+
   create_table "languages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
     t.string "name"
     t.string "iso_code"
@@ -680,8 +711,8 @@ ActiveRecord::Schema.define(version: 2022_05_05_131539) do
     t.string "linkedin"
     t.boolean "is_alumnus", default: false
     t.text "description_short"
-    t.boolean "is_author"
     t.string "name"
+    t.boolean "is_author"
     t.index ["university_id"], name: "index_university_people_on_university_id"
     t.index ["user_id"], name: "index_university_people_on_user_id"
   end
@@ -826,6 +857,7 @@ ActiveRecord::Schema.define(version: 2022_05_05_131539) do
   add_foreign_key "education_cohorts", "education_academic_years", column: "academic_year_id"
   add_foreign_key "education_cohorts", "education_programs", column: "program_id"
   add_foreign_key "education_cohorts", "universities"
+  add_foreign_key "education_diplomas", "universities"
   add_foreign_key "education_programs", "education_programs", column: "parent_id"
   add_foreign_key "education_programs", "universities"
   add_foreign_key "education_schools", "universities"
diff --git a/test/fixtures/education/diplomas.yml b/test/fixtures/education/diplomas.yml
new file mode 100644
index 000000000..6b5998c34
--- /dev/null
+++ b/test/fixtures/education/diplomas.yml
@@ -0,0 +1,33 @@
+# == Schema Information
+#
+# Table name: education_diplomas
+#
+#  id            :uuid             not null, primary key
+#  level         :integer          default("not_applicable")
+#  name          :string
+#  short_name    :string
+#  slug          :string
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  university_id :uuid             not null, indexed
+#
+# Indexes
+#
+#  index_education_diplomas_on_university_id  (university_id)
+#
+# Foreign Keys
+#
+#  fk_rails_6cb2e9fa90  (university_id => universities.id)
+#
+
+one:
+  name: MyString
+  short_name: MyString
+  level: 1
+  slug: MyString
+
+two:
+  name: MyString
+  short_name: MyString
+  level: 1
+  slug: MyString
diff --git a/test/models/education/diploma_test.rb b/test/models/education/diploma_test.rb
new file mode 100644
index 000000000..543962814
--- /dev/null
+++ b/test/models/education/diploma_test.rb
@@ -0,0 +1,28 @@
+# == Schema Information
+#
+# Table name: education_diplomas
+#
+#  id            :uuid             not null, primary key
+#  level         :integer          default("not_applicable")
+#  name          :string
+#  short_name    :string
+#  slug          :string
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  university_id :uuid             not null, indexed
+#
+# Indexes
+#
+#  index_education_diplomas_on_university_id  (university_id)
+#
+# Foreign Keys
+#
+#  fk_rails_6cb2e9fa90  (university_id => universities.id)
+#
+require "test_helper"
+
+class Education::DiplomaTest < ActiveSupport::TestCase
+  # test "the truth" do
+  #   assert true
+  # end
+end
-- 
GitLab