From edbe67b999073716f5673edb5239ad6074b370e9 Mon Sep 17 00:00:00 2001
From: Arnaud Levy <contact@arnaudlevy.com>
Date: Thu, 17 Mar 2022 09:16:41 +0100
Subject: [PATCH] alumnus wip

---
 .../admin/university/people_controller.rb     |  3 +-
 .../university/person/alumni_controller.rb    | 17 ++--
 app/models/concerns/importable.rb             | 36 +++++++++
 .../university/person/alumnus/import.rb       | 62 +++++++++++----
 .../organization/imports/new.html.erb         |  2 +-
 .../admin/university/people/_form.html.erb    |  3 +-
 .../university/person/alumni/_list.html.erb   | 18 ++++-
 .../university/person/alumni/show.html.erb    |  1 +
 .../person/alumnus/imports/new.html.erb       | 77 ++++++++++++++++++-
 .../person/alumnus/imports/show.html.erb      | 17 ++--
 config/locales/university/fr.yml              |  4 +-
 11 files changed, 194 insertions(+), 46 deletions(-)
 create mode 100644 app/models/concerns/importable.rb
 create mode 100644 app/views/admin/university/person/alumni/show.html.erb

diff --git a/app/controllers/admin/university/people_controller.rb b/app/controllers/admin/university/people_controller.rb
index 8babe56ea..febdd9829 100644
--- a/app/controllers/admin/university/people_controller.rb
+++ b/app/controllers/admin/university/people_controller.rb
@@ -64,7 +64,8 @@ class Admin::University::PeopleController < Admin::University::ApplicationContro
       :slug, :first_name, :last_name, :email, :phone, :description,
       :biography,  :picture, :picture_delete, :picture_infos,
       :habilitation, :tenure, :url, :linkedin, :twitter,
-      :is_researcher, :is_teacher, :is_administration, :user_id
+      :is_researcher, :is_teacher, :is_administration, :is_alumnus,
+      :user_id
     ).merge(university_id: current_university.id)
   end
 end
diff --git a/app/controllers/admin/university/person/alumni_controller.rb b/app/controllers/admin/university/person/alumni_controller.rb
index 93d4438b7..f86a16f46 100644
--- a/app/controllers/admin/university/person/alumni_controller.rb
+++ b/app/controllers/admin/university/person/alumni_controller.rb
@@ -1,12 +1,12 @@
 class Admin::University::Person::AlumniController < Admin::University::ApplicationController
-  before_action :load_alumnus, only: [:show, :edit, :update]
-
+  load_and_authorize_resource class: University::Person::Alumnus,
+                              through: :current_university,
+                              through_association: :people
   def index
-    @alumni = current_university.people
-                                .alumni
-                                .accessible_by(current_ability)
-                                .ordered
-                                .page(params[:page])
+    @alumni = @alumni.alumni
+                     .accessible_by(current_ability)
+                     .ordered
+                     .page(params[:page])
     breadcrumb
   end
 
@@ -39,9 +39,6 @@ class Admin::University::Person::AlumniController < Admin::University::Applicati
     breadcrumb_for  @alumnus
   end
 
-  def load_alumnus
-  end
-
   def alumnus_params
     params.require(:university_person_alumnus)
           .permit()
diff --git a/app/models/concerns/importable.rb b/app/models/concerns/importable.rb
new file mode 100644
index 000000000..6bc569eef
--- /dev/null
+++ b/app/models/concerns/importable.rb
@@ -0,0 +1,36 @@
+module Importable
+  extend ActiveSupport::Concern
+
+  included do
+    belongs_to :user
+
+    has_one_attached :file
+
+    after_save :parse_async
+  end
+
+  def lines
+    csv.count
+  rescue
+    'NA'
+  end
+
+  def to_s
+    "#{user}, #{I18n.l created_at}"
+  end
+
+  protected
+
+  def parse_async
+    parse
+  end
+  handle_asynchronously :parse_async, queue: 'default'
+
+  def parse
+    raise NotImplementedError
+  end
+
+  def csv
+    @csv ||= CSV.parse file.blob.download, headers: true
+  end
+end
diff --git a/app/models/university/person/alumnus/import.rb b/app/models/university/person/alumnus/import.rb
index 94fcd55e8..6b31c5dfe 100644
--- a/app/models/university/person/alumnus/import.rb
+++ b/app/models/university/person/alumnus/import.rb
@@ -1,28 +1,58 @@
 class University::Person::Alumnus::Import < ApplicationRecord
   include WithUniversity
-
-  belongs_to :user
-
-  has_one_attached :file
-
-  after_save :parse
+  include Importable
 
   def self.table_name
     'university_person_alumnus_imports'
   end
 
-  def lines
-    csv.count
-  rescue
-    'NA'
-  end
-
-  def to_s
-    "#{user}, #{I18n.l created_at}"
-  end
-
   protected
 
   def parse
+    csv.each do |row|
+      # program
+      # year
+      # first_name
+      # last_name
+      # gender
+      # birth
+      # mail
+      # photo
+      # url
+      # phonepro
+      # phoneperso
+      # mobile
+      # address
+      # zipcode
+      # city
+      # country
+      # status
+      # socialtwitter
+      # sociallinkedin
+      row['program'] = '23279cab-8bc1-4c75-bcd8-1fccaa03ad55' #TMP local fix
+      program = university.education_programs
+                          .find_by(id: row['program'])
+      next if program.nil?
+      year = university.academic_years
+                       .where(year: row['year'])
+                       .first_or_create
+      if row['mail'].blank?
+        person = university.people
+                           .where(first_name: row['first_name'], last_name: row['last_name'])
+                           .first_or_create
+      else
+        person = university.people
+                           .where(email: row['mail'])
+                           .first_or_create
+        person.first_name = row['first_name']
+        person.last_name = row['last_name']
+      end
+      # TODO all fields
+      person.is_alumnus = true
+      person.url = row['url']
+      person.slug = person.to_s.parameterize
+      person.save
+      # byebug
+    end
   end
 end
diff --git a/app/views/admin/university/organization/imports/new.html.erb b/app/views/admin/university/organization/imports/new.html.erb
index d69bc7b28..fcf325f6f 100644
--- a/app/views/admin/university/organization/imports/new.html.erb
+++ b/app/views/admin/university/organization/imports/new.html.erb
@@ -5,8 +5,8 @@
     <p>
       Les données doivent être au format csv, comme l'exemple suivant.<br>
       La première ligne doit être dédiée aux entêtes.<br>
+      Les noms des entêtes sont obligatoires et doivent être respectés strictement.<br>
       Le champ name est obligatoire.<br>
-      Les noms des entêtes sont indicatifs, l'import est basé sur la position des champs.<br>
       Les caractères doivent être encodés en UTF-8.<br>
       Les valeurs possibles pour kind sont : company, non_profit, government.
     </p>
diff --git a/app/views/admin/university/people/_form.html.erb b/app/views/admin/university/people/_form.html.erb
index 21eb1486a..f2a1bd72a 100644
--- a/app/views/admin/university/people/_form.html.erb
+++ b/app/views/admin/university/people/_form.html.erb
@@ -51,9 +51,10 @@
             <div class="col-md-6">
               <%= f.input :is_teacher %>
               <%= f.input :is_administration %>
-              <%= f.input :tenure %>
+              <%= f.input :is_alumnus %>
             </div>
             <div class="col-md-6">
+              <%= f.input :tenure %>
               <%= f.input :is_researcher %>
               <%= f.input :habilitation %>
             </div>
diff --git a/app/views/admin/university/person/alumni/_list.html.erb b/app/views/admin/university/person/alumni/_list.html.erb
index 8af5512e6..0d3945bd5 100644
--- a/app/views/admin/university/person/alumni/_list.html.erb
+++ b/app/views/admin/university/person/alumni/_list.html.erb
@@ -3,13 +3,27 @@
     <tr>
       <th><%= University::Person.human_attribute_name('last_name') %></th>
       <th><%= University::Person.human_attribute_name('first_name') %></th>
+      <th></th>
     </tr>
   </thead>
   <tbody>
     <% alumni.each do |alumnus| %>
+      <% path = admin_university_person_alumnus_path(alumnus) %>
       <tr>
-        <td><%= link_to alumnus.last_name, admin_university_alumnus_path(alumnus) %></td>
-        <td><%= link_to alumnus.first_name, admin_university_alumnus_path(alumnus) %></td>
+        <td><%= link_to alumnus.last_name, path %></td>
+        <td><%= link_to alumnus.first_name, path %></td>
+        <td class="text-end">
+          <div class="btn-group" role="group">
+            <%= link_to t('edit'),
+                      edit_admin_university_person_alumnus_path(alumnus),
+                      class: button_classes if can?(:update, alumnus) %>
+            <%= link_to t('delete'),
+                      path,
+                      method: :delete,
+                      data: { confirm: t('please_confirm') },
+                      class: button_classes_danger if can?(:destroy, alumnus) %>
+          </div>
+        </td>
       </tr>
     <% end %>
   </tbody>
diff --git a/app/views/admin/university/person/alumni/show.html.erb b/app/views/admin/university/person/alumni/show.html.erb
new file mode 100644
index 000000000..a82ea88ff
--- /dev/null
+++ b/app/views/admin/university/person/alumni/show.html.erb
@@ -0,0 +1 @@
+<% content_for :title, @alumnus %>
diff --git a/app/views/admin/university/person/alumnus/imports/new.html.erb b/app/views/admin/university/person/alumnus/imports/new.html.erb
index 89b51d4e8..e63db9d06 100644
--- a/app/views/admin/university/person/alumnus/imports/new.html.erb
+++ b/app/views/admin/university/person/alumnus/imports/new.html.erb
@@ -5,9 +5,10 @@
     <p>
       Les données doivent être au format csv, comme l'exemple suivant.<br>
       La première ligne doit être dédiée aux entêtes.<br>
-      Le champ name est obligatoire.<br>
-      Les noms des entêtes sont indicatifs, l'import est basé sur la position des champs.<br>
+      Les noms des entêtes sont obligatoires et doivent être respectés strictement.<br>
+      Les champs marqués d'une astérisque sont obligatoires.<br>
       Les caractères doivent être encodés en UTF-8.
+      Les valeurs pour gender peuvent être m (masculin), m (féminin) et n (non binaire).
     </p>
     <%= simple_form_for [:admin, @import] do |f| %>
       <%= f.input :file %>
@@ -24,6 +25,78 @@
           <th>program*</th>
           <td>c6b78fac-0a5f-4c44-ad22-4ee68ed382bb</td>
         </tr>
+        <tr>
+          <th>year*</th>
+          <td>2022</td>
+        </tr>
+        <tr>
+          <th>first_name*</th>
+          <td>Stéphane</td>
+        </tr>
+        <tr>
+          <th>last_name*</th>
+          <td>Dupond</td>
+        </tr>
+        <tr>
+          <th>gender</th>
+          <td>m</td>
+        </tr>
+        <tr>
+          <th>birth</th>
+          <td>2006-05-26</td>
+        </tr>
+        <tr>
+          <th>mail</th>
+          <td>jean.dupont@gmail.com</td>
+        </tr>
+        <tr>
+          <th>photo</th>
+          <td>https://www.example.com/photo.jpg</td>
+        </tr>
+        <tr>
+          <th>url</th>
+          <td>https://www.stephanedupond.fr</td>
+        </tr>
+        <tr>
+          <th>phonepro</th>
+          <td>+33 1 01 01 01 01</td>
+        </tr>
+        <tr>
+          <th>phoneperso</th>
+          <td>+33 1 01 01 01 01</td>
+        </tr>
+        <tr>
+          <th>mobile</th>
+          <td>+33 6 01 01 01 01</td>
+        </tr>
+        <tr>
+          <th>address</th>
+          <td>1 rue Jacques Ellul</td>
+        </tr>
+        <tr>
+          <th>zipcode</th>
+          <td>33000</td>
+        </tr>
+        <tr>
+          <th>city</th>
+          <td>Bordeaux</td>
+        </tr>
+        <tr>
+          <th>country</th>
+          <td>FR</td>
+        </tr>
+        <tr>
+          <th>status</th>
+          <td>Product Designer</td>
+        </tr>
+        <tr>
+          <th>socialtwitter</th>
+          <td>stephanedupond</td>
+        </tr>
+        <tr>
+          <th>sociallinkedin</th>
+          <td>https://www.linkedin.com/in/stephanedupond</td>
+        </tr>
       </tbody>
     </table>
   </div>
diff --git a/app/views/admin/university/person/alumnus/imports/show.html.erb b/app/views/admin/university/person/alumnus/imports/show.html.erb
index a5c23fddc..d3fec028c 100644
--- a/app/views/admin/university/person/alumnus/imports/show.html.erb
+++ b/app/views/admin/university/person/alumnus/imports/show.html.erb
@@ -1,14 +1,7 @@
-<p id="notice"><%= notice %></p>
+<% content_for :title, @import %>
 
-<p>
-  <strong>University:</strong>
-  <%= @university_person_alumnus_import.university_id %>
-</p>
+<p><%= @import.lines %> lines</p>
 
-<p>
-  <strong>User:</strong>
-  <%= @university_person_alumnus_import.user_id %>
-</p>
-
-<%= link_to 'Edit', edit_university_person_alumnus_import_path(@university_person_alumnus_import) %> |
-<%= link_to 'Back', university_person_alumnus_imports_path %>
+<%= link_to "#{@import.file.filename} (#{number_to_human_size @import.file.byte_size})",
+            url_for(@import.file),
+            class: button_classes %>
diff --git a/config/locales/university/fr.yml b/config/locales/university/fr.yml
index aa0fb6657..43b7cb906 100644
--- a/config/locales/university/fr.yml
+++ b/config/locales/university/fr.yml
@@ -29,6 +29,7 @@ fr:
         is_author: Auteur·rice
         is_researcher: Chercheur·se
         is_teacher: Enseignant·e
+        is_alumnus: Alumnus
         last_name: Nom de famille
         linkedin: LinkedIn (URL)
         name: Nom
@@ -86,8 +87,9 @@ fr:
         is_author: "Écrit des articles pour les sites."
         is_researcher: "Écrit des articles dans des revues scientifiques."
         is_teacher: "Enseigne dans des formations."
+        is_alumnus: "Étudie ou a étudié dans l'établissement."
         linkedin: "Exemple : https://www.linkedin.com/in/osuny"
-        tenure: "A différencier d'une personne vacataire."
+        tenure: "À différencier d'une personne vacataire."
         twitter: "Exemple : osuny"
   university:
     invoice_informations: Données de facturation
-- 
GitLab