Add search feature for gestionnaire backoffice
This commit is contained in:
parent
3effa5e9fd
commit
9f34d20475
9 changed files with 235 additions and 24 deletions
32
app/assets/stylesheets/backoffice.scss
Normal file
32
app/assets/stylesheets/backoffice.scss
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#backoffice_search {
|
||||||
|
.table {
|
||||||
|
tr th {
|
||||||
|
border-top: none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
li {
|
||||||
|
margin-top: 11px;
|
||||||
|
a {
|
||||||
|
height: 45px;
|
||||||
|
h5 {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#search {
|
||||||
|
margin-top: 0;
|
||||||
|
a {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
height: 56px;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
padding: 11px 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,18 @@ class Backoffice::DossiersController < ApplicationController
|
||||||
total_dossiers_per_state
|
total_dossiers_per_state
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def search
|
||||||
|
@search_terms = params[:search_terms]
|
||||||
|
|
||||||
|
@dossiers_search, @dossier = Dossier.search(current_gestionnaire, @search_terms)
|
||||||
|
@dossiers_search = @dossiers_search.decorate unless @dossiers_search.empty?
|
||||||
|
@dossier = @dossier.decorate unless @dossier.nil?
|
||||||
|
|
||||||
|
total_dossiers_per_state
|
||||||
|
rescue RuntimeError
|
||||||
|
@dossiers_search = []
|
||||||
|
end
|
||||||
|
|
||||||
def valid
|
def valid
|
||||||
initialize_instance_params params[:dossier_id]
|
initialize_instance_params params[:dossier_id]
|
||||||
|
|
||||||
|
|
|
@ -128,27 +128,43 @@ class Dossier < ActiveRecord::Base
|
||||||
Dossier.joins(:procedure).where("state='closed' AND dossiers.procedure_id = procedures.id AND procedures.administrateur_id = #{current_gestionnaire.administrateur_id}").order('updated_at ASC')
|
Dossier.joins(:procedure).where("state='closed' AND dossiers.procedure_id = procedures.id AND procedures.administrateur_id = #{current_gestionnaire.administrateur_id}").order('updated_at ASC')
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.search terms
|
def self.search current_gestionnaire, terms
|
||||||
return if terms.blank?
|
return [], nil if terms.blank?
|
||||||
|
|
||||||
dossiers = Dossier.arel_table
|
dossiers = Dossier.arel_table
|
||||||
users = User.arel_table
|
users = User.arel_table
|
||||||
etablissements = Etablissement.arel_table
|
etablissements = Etablissement.arel_table
|
||||||
entreprises = Entreprise.arel_table
|
entreprises = Entreprise.arel_table
|
||||||
|
|
||||||
composed_scope = self.joins('LEFT OUTER JOIN users ON users.id = dossiers.user_id')
|
composed_scope = self.joins('LEFT OUTER JOIN users ON users.id = dossiers.user_id')
|
||||||
.joins('LEFT OUTER JOIN entreprises ON entreprises.dossier_id = dossiers.id')
|
.joins('LEFT OUTER JOIN entreprises ON entreprises.dossier_id = dossiers.id')
|
||||||
.joins('LEFT OUTER JOIN etablissements ON etablissements.dossier_id = dossiers.id')
|
.joins('LEFT OUTER JOIN etablissements ON etablissements.dossier_id = dossiers.id')
|
||||||
|
|
||||||
terms.split.each do |word|
|
terms.split.each do |word|
|
||||||
query_string = "%#{word}%"
|
query_string = "%#{word}%"
|
||||||
query_string_start_with = "#{word}%"
|
query_string_start_with = "#{word}%"
|
||||||
|
|
||||||
composed_scope = composed_scope.where(
|
composed_scope = composed_scope.where(
|
||||||
dossiers[:nom_projet].matches(query_string).or\
|
dossiers[:nom_projet].matches(query_string).or\
|
||||||
users[:email].matches(query_string).or\
|
users[:email].matches(query_string).or\
|
||||||
dossiers[:id].eq(word).or\
|
etablissements[:siret].matches(query_string_start_with).or\
|
||||||
etablissements[:siret].matches(query_string_start_with).or\
|
entreprises[:raison_sociale].matches(query_string))
|
||||||
entreprises[:raison_sociale].matches(query_string)
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
composed_scope
|
|
||||||
|
#TODO refactor
|
||||||
|
composed_scope = composed_scope.where(
|
||||||
|
dossiers[:id].eq_any(current_gestionnaire.dossiers.ids).and\
|
||||||
|
dossiers[:state].does_not_match('draft'))
|
||||||
|
|
||||||
|
begin
|
||||||
|
if Float(terms) && terms.to_i <= 2147483647 && current_gestionnaire.dossiers.ids.include?(terms.to_i)
|
||||||
|
dossier = Dossier.where("state != 'draft'").find(terms.to_i)
|
||||||
|
end
|
||||||
|
rescue ArgumentError, ActiveRecord::RecordNotFound
|
||||||
|
dossier = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return composed_scope, dossier
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -4,15 +4,22 @@
|
||||||
%ul.nav.nav-tabs
|
%ul.nav.nav-tabs
|
||||||
%li{class: "#{'active' unless @dossiers_a_traiter.nil? }"}
|
%li{class: "#{'active' unless @dossiers_a_traiter.nil? }"}
|
||||||
%a{:href => "#{url_for :backoffice_dossiers_a_traiter}"}
|
%a{:href => "#{url_for :backoffice_dossiers_a_traiter}"}
|
||||||
%strong.text-danger
|
%h5.text-danger
|
||||||
= "À traiter (#{@dossiers_a_traiter_total})"
|
= "À traiter (#{@dossiers_a_traiter_total})"
|
||||||
%li{class: "#{'active' unless @dossiers_en_attente.nil? }"}
|
%li{class: "#{'active' unless @dossiers_en_attente.nil? }"}
|
||||||
%a{:href => "#{url_for :backoffice_dossiers_en_attente}"}
|
%a{:href => "#{url_for :backoffice_dossiers_en_attente}"}
|
||||||
%strong.text-info
|
%h5.text-info
|
||||||
="En attente (#{@dossiers_en_attente_total})"
|
="En attente (#{@dossiers_en_attente_total})"
|
||||||
%li{class: "#{'active' unless @dossiers_termine.nil? }"}
|
%li{class: "#{'active' unless @dossiers_termine.nil? }"}
|
||||||
%a{:href => "#{url_for :backoffice_dossiers_termine}"}
|
%a{:href => "#{url_for :backoffice_dossiers_termine}"}
|
||||||
%strong.text-success
|
%h5.text-success
|
||||||
= "Terminé (#{@dossiers_termine_total})"
|
= "Terminé (#{@dossiers_termine_total})"
|
||||||
|
%li#search{class: "#{'active' unless @dossiers_search.nil?}", style:'float:right'}
|
||||||
|
%a
|
||||||
|
= form_tag(backoffice_dossiers_search_url, method: :post) do
|
||||||
|
.input-group{style:'width: 300px'}
|
||||||
|
= text_field_tag('search_terms', "#{@search_terms unless @search_terms.nil? }", id: 'search_terms', placeholder: "Rechercher un dossier ...", class:'form-control')
|
||||||
|
%span.input-group-btn
|
||||||
|
= button_tag('', id:'search_button', class:'btn btn-default') do
|
||||||
|
%i.fa.fa-search
|
||||||
%br
|
%br
|
47
app/views/backoffice/dossiers/search.html.haml
Normal file
47
app/views/backoffice/dossiers/search.html.haml
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#backoffice_search
|
||||||
|
= render partial: 'onglets'
|
||||||
|
|
||||||
|
- unless @dossier.nil?
|
||||||
|
%table.table{style:'background-color: rgba(248, 248, 255, 0.8)'}
|
||||||
|
%tr
|
||||||
|
%th{colspan:2}
|
||||||
|
%h4
|
||||||
|
= "Dossier N°#{@dossier.id}"
|
||||||
|
%tr
|
||||||
|
%td.col-md-2.col-lg-1
|
||||||
|
= @dossier.id
|
||||||
|
%td.col-md-4.col-lg-3
|
||||||
|
= link_to(@dossier.nom_projet, "/backoffice/dossiers/#{@dossier.id}")
|
||||||
|
%td.col-md-2.col-lg-3
|
||||||
|
= @dossier.entreprise.raison_sociale
|
||||||
|
%td.col-md-4.col-lg-2
|
||||||
|
= @dossier.user.email
|
||||||
|
%td.col-md-2.col-lg-2
|
||||||
|
= @dossier.etablissement.siret
|
||||||
|
%td.col-md-1.col-lg-1
|
||||||
|
= @dossier.state_fr
|
||||||
|
%br
|
||||||
|
|
||||||
|
- if @dossiers_search.empty? && @dossier.nil?
|
||||||
|
%div{style: 'text-align:center'}
|
||||||
|
%h4 Aucun dossier trouvé
|
||||||
|
|
||||||
|
- elsif !@dossiers_search.empty?
|
||||||
|
%table.table
|
||||||
|
%tr
|
||||||
|
%th.col-md-2.col-lg-1 ID dossier
|
||||||
|
%th.col-md-4.col-lg-3 Dossier
|
||||||
|
%th.col-md-2.col-lg-3 Raison Sociale
|
||||||
|
%th.col-md-4.col-lg-2 Email contact
|
||||||
|
%th.col-md-2.col-lg-2 SIRET
|
||||||
|
%th.col-md-1.col-lg-1 État
|
||||||
|
|
||||||
|
- @dossiers_search.each do |dossier|
|
||||||
|
%tr
|
||||||
|
%td= dossier.id
|
||||||
|
%td
|
||||||
|
= link_to(dossier.nom_projet, "/backoffice/dossiers/#{dossier.id}")
|
||||||
|
%td= dossier.entreprise.raison_sociale
|
||||||
|
%td= dossier.user.email
|
||||||
|
%td= dossier.etablissement.siret
|
||||||
|
%td= dossier.state_fr
|
|
@ -54,6 +54,7 @@ Rails.application.routes.draw do
|
||||||
get 'dossiers/a_traiter' => 'dossiers#a_traiter'
|
get 'dossiers/a_traiter' => 'dossiers#a_traiter'
|
||||||
get 'dossiers/en_attente' => 'dossiers#en_attente'
|
get 'dossiers/en_attente' => 'dossiers#en_attente'
|
||||||
get 'dossiers/termine' => 'dossiers#termine'
|
get 'dossiers/termine' => 'dossiers#termine'
|
||||||
|
post 'dossiers/search' => 'dossiers#search'
|
||||||
|
|
||||||
resources :dossiers do
|
resources :dossiers do
|
||||||
post 'valid' => 'dossiers#valid'
|
post 'valid' => 'dossiers#valid'
|
||||||
|
|
|
@ -68,6 +68,18 @@ describe Backoffice::DossiersController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'POST #search' do
|
||||||
|
before do
|
||||||
|
sign_in gestionnaire
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
post :search, search_terms: 'test'
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
describe 'POST #valid' do
|
describe 'POST #valid' do
|
||||||
before do
|
before do
|
||||||
dossier.initiated!
|
dossier.initiated!
|
||||||
|
|
58
spec/features/backoffice/search_file_spec.rb
Normal file
58
spec/features/backoffice/search_file_spec.rb
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
feature 'search file on gestionnaire backoffice' do
|
||||||
|
let(:administrateur) { create(:administrateur) }
|
||||||
|
let(:gestionnaire) { create(:gestionnaire, administrateur: administrateur) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
login_as gestionnaire, scope: :gestionnaire
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when gestionnaire is logged in' do
|
||||||
|
context 'when he click on search button' do
|
||||||
|
let(:terms) { '' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
visit backoffice_dossiers_a_traiter_url
|
||||||
|
page.find_by_id(:search_terms).set terms
|
||||||
|
page.find_by_id(:search_button).click
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(page).to have_css('#backoffice_search') }
|
||||||
|
|
||||||
|
context 'when terms input is empty' do
|
||||||
|
it { expect(page).to have_content('Aucun dossier trouvé') }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when terms input is informed' do
|
||||||
|
let(:terms) { 'test' }
|
||||||
|
|
||||||
|
it 'terms stay in input after search' do
|
||||||
|
expect(page.find_by_id('search_terms').value).to eq(terms)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when terms input does not return result' do
|
||||||
|
it { expect(page).to have_content('Aucun dossier trouvé') }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when terms input does return result' do
|
||||||
|
let!(:procedure) { create(:procedure, administrateur: administrateur) }
|
||||||
|
let!(:dossier) { create(:dossier, :with_entreprise, :with_user, procedure: procedure, state: 'initiated') }
|
||||||
|
let!(:dossier_2) { create(:dossier, :with_user, procedure: procedure, state: 'initiated', nom_projet: 'Projet de test') }
|
||||||
|
|
||||||
|
let(:terms) { dossier.nom_projet }
|
||||||
|
|
||||||
|
it { expect(page).not_to have_content('Projet de test') }
|
||||||
|
|
||||||
|
it { expect(page).to have_content(dossier.nom_projet) }
|
||||||
|
|
||||||
|
context "when terms is a file's id" do
|
||||||
|
let(:terms) { dossier.id }
|
||||||
|
|
||||||
|
it { expect(page).to have_content("Dossier N°#{dossier.id}") }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -419,11 +419,24 @@ describe Dossier do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.search' do
|
describe '.search' do
|
||||||
subject { described_class.search(terms) }
|
subject { liste_dossiers }
|
||||||
|
|
||||||
let!(:dossier_1) { create(:dossier, nom_projet: 'Projet de test', user: create(:user, email: 'contact@test.com')) }
|
let(:liste_dossiers) { described_class.search(gestionnaire_1, terms)[0] }
|
||||||
let!(:dossier_2) { create(:dossier, nom_projet: 'Lili et Marcel', user: create(:user, email: 'plop@gmail.com')) }
|
let(:dossier) { described_class.search(gestionnaire_1, terms)[1] }
|
||||||
let!(:dossier_3) { create(:dossier, nom_projet: 'Construction projet marcel', user: create(:user, email: 'peace@clap.fr')) }
|
|
||||||
|
let(:administrateur_1) { create(:administrateur) }
|
||||||
|
let(:administrateur_2) { create(:administrateur) }
|
||||||
|
|
||||||
|
let(:gestionnaire_1) { create(:gestionnaire, administrateur: administrateur_1) }
|
||||||
|
let(:gestionnaire_2) { create(:gestionnaire, administrateur: administrateur_2) }
|
||||||
|
|
||||||
|
let(:procedure_1) { create(:procedure, administrateur: administrateur_1) }
|
||||||
|
let(:procedure_2) { create(:procedure, administrateur: administrateur_2) }
|
||||||
|
|
||||||
|
let!(:dossier_0) { create(:dossier, nom_projet: 'je suis un brouillon', state: 'draft', procedure: procedure_1, user: create(:user, email: 'brouillon@clap.fr')) }
|
||||||
|
let!(:dossier_1) { create(:dossier, nom_projet: 'Projet de test', state: 'initiated', procedure: procedure_1, user: create(:user, email: 'contact@test.com')) }
|
||||||
|
let!(:dossier_2) { create(:dossier, nom_projet: 'Lili et Marcel', state: 'initiated', procedure: procedure_1, user: create(:user, email: 'plop@gmail.com')) }
|
||||||
|
let!(:dossier_3) { create(:dossier, nom_projet: 'Construction projet marcel', state: 'initiated', procedure: procedure_2, user: create(:user, email: 'peace@clap.fr')) }
|
||||||
|
|
||||||
let!(:etablissement_1) { create(:etablissement, entreprise: create(:entreprise, raison_sociale: 'OCTO Academy', dossier: dossier_1), dossier: dossier_1, siret: '41636169600051') }
|
let!(:etablissement_1) { create(:etablissement, entreprise: create(:entreprise, raison_sociale: 'OCTO Academy', dossier: dossier_1), dossier: dossier_1, siret: '41636169600051') }
|
||||||
let!(:etablissement_2) { create(:etablissement, entreprise: create(:entreprise, raison_sociale: 'Plop octo', dossier: dossier_2), dossier: dossier_2, siret: '41816602300012') }
|
let!(:etablissement_2) { create(:etablissement, entreprise: create(:entreprise, raison_sociale: 'Plop octo', dossier: dossier_2), dossier: dossier_2, siret: '41816602300012') }
|
||||||
|
@ -432,42 +445,55 @@ describe Dossier do
|
||||||
describe 'search is empty' do
|
describe 'search is empty' do
|
||||||
let(:terms) { '' }
|
let(:terms) { '' }
|
||||||
|
|
||||||
it { expect(subject).to eq(nil) }
|
it { expect(subject.size).to eq(0) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'search draft file' do
|
||||||
|
let(:terms) { 'brouillon' }
|
||||||
|
|
||||||
|
it { expect(subject.size).to eq(0) }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'search on file title' do
|
describe 'search on file title' do
|
||||||
let(:terms) { 'Marcel' }
|
let(:terms) { 'Marcel' }
|
||||||
|
|
||||||
it { expect(subject.size).to eq(2) }
|
it { expect(subject.size).to eq(1) }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'search on contact email' do
|
describe 'search on contact email' do
|
||||||
let(:terms) { 'clap' }
|
let(:terms) { 'clap' }
|
||||||
|
|
||||||
it { expect(subject.size).to eq(1) }
|
it { expect(subject.size).to eq(0) }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'search on ID dossier' do
|
describe 'search on ID dossier' do
|
||||||
let(:terms) { "#{dossier_2.id}" }
|
let(:terms) { "#{dossier_2.id}" }
|
||||||
|
|
||||||
it { expect(subject.size).to eq(1) }
|
it { expect(dossier.id).to eq(dossier_2.id) }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'search on SIRET' do
|
describe 'search on SIRET' do
|
||||||
|
context 'when is part of SIRET' do
|
||||||
|
let(:terms) { '4181' }
|
||||||
|
|
||||||
let(:terms) { '4181' }
|
it { expect(subject.size).to eq(1) }
|
||||||
|
end
|
||||||
|
|
||||||
it { expect(subject.size).to eq(2) }
|
context 'when is a complet SIRET' do
|
||||||
|
let(:terms) { '41816602300012' }
|
||||||
|
|
||||||
|
it { expect(subject.size).to eq(1) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'search on raison social' do
|
describe 'search on raison social' do
|
||||||
let(:terms) { 'OCTO' }
|
let(:terms) { 'OCTO' }
|
||||||
|
|
||||||
it { expect(subject.size).to eq(3) }
|
it { expect(subject.size).to eq(2) }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'search on multiple fields' do
|
describe 'search on multiple fields' do
|
||||||
let(:terms) { 'octo peace' }
|
let(:terms) { 'octo test' }
|
||||||
|
|
||||||
it { expect(subject.size).to eq(1) }
|
it { expect(subject.size).to eq(1) }
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue