Add on gestionnaire dossier view the private form

This commit is contained in:
Xavier J 2016-08-08 12:52:30 +02:00
parent ddb64878c8
commit 480431ea01
28 changed files with 320 additions and 88 deletions

View file

@ -184,7 +184,7 @@ div.pagination {
.alert.alert-success.move_up, .alert.alert-success.move_up,
.alert.alert-danger.siret{ .alert.alert-danger.siret{
position: absolute; position: fixed;
top: 0px; top: 0px;
left: 0; left: 0;
height: 52px; height: 52px;

View file

@ -14,6 +14,7 @@ class Backoffice::DossiersController < ApplicationController
def show def show
create_dossier_facade params[:id] create_dossier_facade params[:id]
@champs = @facade.champs_private unless @facade.nil?
end end
def search def search

View file

@ -0,0 +1,19 @@
class Backoffice::PrivateFormulairesController < ApplicationController
before_action :authenticate_gestionnaire!
def update
dossier = current_gestionnaire.dossiers.find(params[:dossier_id])
unless params[:champs].nil?
champs_service_errors = ChampsService.save_formulaire dossier.champs_private, params
if champs_service_errors.empty?
flash[:notice] = "Formulaire enregistré"
else
flash[:alert] = (champs_service_errors.inject('') { |acc, error| acc+= error[:message]+'<br>' }).html_safe
end
end
render 'backoffice/dossiers/formulaire_private', formats: :js
end
end

View file

@ -43,24 +43,12 @@ class Users::DescriptionController < UsersController
end end
unless params[:champs].nil? unless params[:champs].nil?
@dossier.champs.each do |champ| champs_service_errors = ChampsService.save_formulaire @dossier.champs, params
champ.value = params[:champs]["'#{champ.id}'"]
if champ.type_champ == 'datetime' unless champs_service_errors.empty?
champ.value = params[:champs]["'#{champ.id}'"]+ flash.now.alert = (champs_service_errors.inject('') {|acc, error| acc+= error[:message]+'<br>' }).html_safe
' ' +
params[:time_hour]["'#{champ.id}'"] +
':' +
params[:time_minute]["'#{champ.id}'"]
end
if champ.mandatory? && (champ.value.nil? || champ.value.blank?)
flash.now.alert = "Le champ #{champ.libelle} doit être rempli."
return render 'show' return render 'show'
end end
champ.save
end
end end
unless (errors_upload = PiecesJustificativesService.upload!(@dossier, current_user, params)).empty? unless (errors_upload = PiecesJustificativesService.upload!(@dossier, current_user, params)).empty?

View file

@ -46,6 +46,10 @@ class DossierFacades
@dossier.invites @dossier.invites
end end
def champs_private
@dossier.ordered_champs_private
end
def commentaires_files def commentaires_files
PieceJustificative.where(dossier_id: @dossier.id, type_de_piece_justificative_id: nil) PieceJustificative.where(dossier_id: @dossier.id, type_de_piece_justificative_id: nil)
end end

View file

@ -0,0 +1,3 @@
class ChampPrivate < Champ
end

View file

@ -0,0 +1,3 @@
class ChampPublic < Champ
end

View file

@ -13,7 +13,8 @@ class Dossier < ActiveRecord::Base
has_many :cerfa, dependent: :destroy has_many :cerfa, dependent: :destroy
has_many :pieces_justificatives, dependent: :destroy has_many :pieces_justificatives, dependent: :destroy
has_many :champs, dependent: :destroy has_many :champs, class_name: 'ChampPublic', dependent: :destroy
has_many :champs_private, class_name: 'ChampPrivate', dependent: :destroy
has_many :quartier_prioritaires, dependent: :destroy has_many :quartier_prioritaires, dependent: :destroy
has_many :cadastres, dependent: :destroy has_many :cadastres, dependent: :destroy
has_many :commentaires, dependent: :destroy has_many :commentaires, dependent: :destroy
@ -47,7 +48,11 @@ class Dossier < ActiveRecord::Base
def build_default_champs def build_default_champs
procedure.types_de_champ.each do |type_de_champ| procedure.types_de_champ.each do |type_de_champ|
Champ.create(type_de_champ_id: type_de_champ.id, dossier_id: id) ChampPublic.create(type_de_champ_id: type_de_champ.id, dossier_id: id)
end
procedure.types_de_champ_private.each do |type_de_champ|
ChampPrivate.create(type_de_champ_id: type_de_champ.id, dossier_id: id)
end end
end end
@ -55,6 +60,10 @@ class Dossier < ActiveRecord::Base
champs.joins(', types_de_champ').where("champs.type_de_champ_id = types_de_champ.id AND types_de_champ.procedure_id = #{procedure.id}").order('order_place') champs.joins(', types_de_champ').where("champs.type_de_champ_id = types_de_champ.id AND types_de_champ.procedure_id = #{procedure.id}").order('order_place')
end end
def ordered_champs_private
champs_private.joins(', types_de_champ').where("champs.type_de_champ_id = types_de_champ.id AND types_de_champ.procedure_id = #{procedure.id}").order('order_place')
end
def ordered_commentaires def ordered_commentaires
commentaires.order(created_at: :desc) commentaires.order(created_at: :desc)
end end

View file

@ -0,0 +1,5 @@
class ChampPrivateSerializer < ActiveModel::Serializer
attributes :value
has_one :type_de_champ
end

View file

@ -0,0 +1,5 @@
class ChampPublicSerializer < ActiveModel::Serializer
attributes :value
has_one :type_de_champ
end

View file

@ -1,5 +0,0 @@
class ChampSerializer < ActiveModel::Serializer
attributes :value
has_one :type_de_champ
end

View file

@ -12,6 +12,7 @@ class DossierSerializer < ActiveModel::Serializer
has_many :cerfa has_many :cerfa
has_many :commentaires has_many :commentaires
has_many :champs has_many :champs
has_many :champs_private
has_many :pieces_justificatives has_many :pieces_justificatives
has_many :types_de_piece_justificative has_many :types_de_piece_justificative
end end

View file

@ -0,0 +1,25 @@
class ChampsService
def self.save_formulaire champs, params
errors = Array.new
champs.each do |champ|
champ.value = params[:champs]["'#{champ.id}'"]
if champ.type_champ == 'datetime'
champ.value = params[:champs]["'#{champ.id}'"]+
' ' +
params[:time_hour]["'#{champ.id}'"] +
':' +
params[:time_minute]["'#{champ.id}'"]
end
if champ.mandatory? && (champ.value.nil? || champ.value.blank?)
errors.push({message: "Le champ #{champ.libelle} doit être rempli."})
end
champ.save
end
errors
end
end

View file

@ -12,6 +12,7 @@
%h4 Description %h4 Description
= ff.text_area :description, class: 'form-control description', placeholder: 'Description' = ff.text_area :description, class: 'form-control description', placeholder: 'Description'
- unless ff.object.object.class == TypeDeChampPrivate
.form-group.mandatory .form-group.mandatory
%h4 Obligatoire ? %h4 Obligatoire ?
.center .center

View file

@ -0,0 +1,4 @@
<% flash.each do |type, message| %>
$("#flash_message").html("<div class=\"alert alert-success move_up\" style=\"display: block:\"> <%= message.html_safe %></div>").children().fadeOut(5000)
<% end %>
<% flash.clear %>

View file

@ -27,6 +27,9 @@
%li{role: "presentation"} %li{role: "presentation"}
%a{href: "#followers", 'aria-controls' => "followers", role: "tab", 'data-toggle' => "tab"} %a{href: "#followers", 'aria-controls' => "followers", role: "tab", 'data-toggle' => "tab"}
Abonnés Abonnés
%li{role: "presentation"}
%a{href: "#champs_private", 'aria-controls' => "champs_private", role: "tab", 'data-toggle' => "tab"}
Formulaire
%div{class: "tab-content"} %div{class: "tab-content"}
%div{role: "tabpanel", class: "tab-pane fade in active", id:"commentaires"} %div{role: "tabpanel", class: "tab-pane fade in active", id:"commentaires"}
@ -39,6 +42,12 @@
= render partial: '/dossiers/invites' = render partial: '/dossiers/invites'
%div{role: "tabpanel", class: "tab-pane fade", id:"followers"} %div{role: "tabpanel", class: "tab-pane fade", id:"followers"}
= render partial: 'followers' = render partial: 'followers'
%div{role: "tabpanel", class: "tab-pane fade", id:"champs_private"}
%h3 Formulaire privé
- unless @champs.nil?
= form_for @facade.dossier, url: {controller: 'backoffice/private_formulaires', action: :update, dossier_id: @facade.dossier.id}, remote: true do
= render partial: '/users/description/champs'
%br
= submit_tag :Enregistrer, {class: 'btn btn-success', style: 'float: right'}
%br %br
%br %br

View file

@ -145,6 +145,7 @@ Rails.application.routes.draw do
get 'filtres' => 'procedure_filter#index' get 'filtres' => 'procedure_filter#index'
patch 'filtres/update' => 'procedure_filter#update' patch 'filtres/update' => 'procedure_filter#update'
resource :private_formulaire
namespace :preference_list_dossier do namespace :preference_list_dossier do
post 'add' post 'add'

View file

@ -0,0 +1,25 @@
class AddTypeAttrInChampTable < ActiveRecord::Migration
class TypeDeChamp < ActiveRecord::Base
has_many :champs
end
class Champ < ActiveRecord::Base
belongs_to :type_de_champ
end
def up
add_column :champs, :type, :string
Champ.all.each do |champ|
type = 'ChampPublic' if champ.type_de_champ.class == TypeDeChampPublic
type = 'ChampPrivate' if champ.type_de_champ.class == TypeDeChampPrivate
champ.update_attribute(:type, type)
end
end
def down
remove_column :champs, :type
end
end

View file

@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160803081304) do ActiveRecord::Schema.define(version: 20160804130638) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -99,6 +99,7 @@ ActiveRecord::Schema.define(version: 20160803081304) do
t.string "value" t.string "value"
t.integer "type_de_champ_id" t.integer "type_de_champ_id"
t.integer "dossier_id" t.integer "dossier_id"
t.string "type"
end end
create_table "commentaires", force: :cascade do |t| create_table "commentaires", force: :cascade do |t|

View file

@ -2,7 +2,7 @@ require 'spec_helper'
describe API::V1::DossiersController do describe API::V1::DossiersController do
let(:admin) { create(:administrateur) } let(:admin) { create(:administrateur) }
let(:procedure) { create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ, administrateur: admin, cerfa_flag: true) } let(:procedure) { create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ, :with_type_de_champ_private, administrateur: admin, cerfa_flag: true) }
let(:wrong_procedure) { create(:procedure) } let(:wrong_procedure) { create(:procedure) }
it { expect(described_class).to be < APIController } it { expect(described_class).to be < APIController }
@ -115,7 +115,7 @@ describe API::V1::DossiersController do
let!(:dossier) { Timecop.freeze(date_creation) { create(:dossier, :with_entreprise, procedure: procedure) } } let!(:dossier) { Timecop.freeze(date_creation) { create(:dossier, :with_entreprise, procedure: procedure) } }
let(:dossier_id) { dossier.id } let(:dossier_id) { dossier.id }
let(:body) { JSON.parse(retour.body, symbolize_names: true) } let(:body) { JSON.parse(retour.body, symbolize_names: true) }
let(:field_list) { [:id, :created_at, :updated_at, :archived, :mandataire_social, :total_commentaire, :entreprise, :etablissement, :cerfa, :types_de_piece_justificative, :pieces_justificatives, :champs, :commentaires, :state] } let(:field_list) { [:id, :created_at, :updated_at, :archived, :mandataire_social, :total_commentaire, :entreprise, :etablissement, :cerfa, :types_de_piece_justificative, :pieces_justificatives, :champs, :champs_private, :commentaires, :state] }
subject { body[:dossier] } subject { body[:dossier] }
it 'return REST code 200', :show_in_doc do it 'return REST code 200', :show_in_doc do
@ -235,6 +235,37 @@ describe API::V1::DossiersController do
end end
end end
describe 'champs_private' do
let(:field_list) { [
:url] }
subject { super()[:champs_private] }
it { expect(subject.length).to eq 1 }
describe 'first champs' do
subject { super().first }
it { expect(subject.keys.include?(:value)).to be_truthy }
it { expect(subject.keys.include?(:type_de_champ)).to be_truthy }
describe 'type de champ' do
let(:field_list) { [
:id,
:libelle,
:description,
:order_place,
:type] }
subject { super()[:type_de_champ] }
it { expect(subject.keys.include?(:id)).to be_truthy }
it { expect(subject[:libelle]).to eq('Description') }
it { expect(subject[:description]).to eq('description de votre projet') }
it { expect(subject.keys.include?(:order_place)).to be_truthy }
it { expect(subject[:type_champ]).to eq('text') }
end
end
end
describe 'commentaires' do describe 'commentaires' do
let!(:commentaire) { create :commentaire, body: 'plop', created_at: '2016-03-14 14:00:00', email: 'plop@plip.com', dossier: dossier } let!(:commentaire) { create :commentaire, body: 'plop', created_at: '2016-03-14 14:00:00', email: 'plop@plip.com', dossier: dossier }
let!(:commentaire_2) { create :commentaire, body: 'plip', created_at: '2016-03-14 15:00:00', email: 'plip@plap.com', dossier: dossier } let!(:commentaire_2) { create :commentaire, body: 'plip', created_at: '2016-03-14 15:00:00', email: 'plip@plap.com', dossier: dossier }

View file

@ -0,0 +1,28 @@
require 'spec_helper'
describe Backoffice::PrivateFormulairesController, type: :controller do
let(:gestionnaire) { create :gestionnaire }
let(:dossier) { create :dossier }
let(:dossier_champs_first) { 'plop' }
before do
create :assign_to, procedure_id: dossier.procedure.id, gestionnaire_id: gestionnaire.id
sign_in gestionnaire
end
describe '#PATCH update' do
subject { patch :update, dossier_id: dossier.id,
champs: {
"'#{dossier.champs_private.first.id}'" => dossier_champs_first
} }
before do
subject
end
it { expect(response.status).to eq 200 }
it { expect(Dossier.find(dossier.id).champs_private.first.value).to eq dossier_champs_first }
it { expect(flash[:notice]).to be_present }
end
end

View file

@ -5,7 +5,7 @@ FactoryGirl.define do
before(:create) do |dossier, _evaluator| before(:create) do |dossier, _evaluator|
unless dossier.procedure unless dossier.procedure
procedure = create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ) procedure = create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ, :with_type_de_champ_private)
dossier.procedure = procedure dossier.procedure = procedure
end end
end end

View file

@ -0,0 +1,7 @@
require 'spec_helper'
describe ChampPrivate do
require 'models/champ_shared_example.rb'
it_should_behave_like "champ_spec"
end

View file

@ -0,0 +1,7 @@
require 'spec_helper'
describe ChampPublic do
require 'models/champ_shared_example.rb'
it_should_behave_like "champ_spec"
end

View file

@ -0,0 +1,38 @@
shared_examples 'champ_spec' do
describe 'database columns' do
it { is_expected.to have_db_column(:value) }
end
describe 'associations' do
it { is_expected.to belong_to(:dossier) }
it { is_expected.to belong_to(:type_de_champ) }
end
describe 'delegation' do
it { is_expected.to delegate_method(:libelle).to(:type_de_champ) }
it { is_expected.to delegate_method(:type_champ).to(:type_de_champ) }
it { is_expected.to delegate_method(:order_place).to(:type_de_champ) }
end
describe 'data_provide' do
let(:champ) { create :champ }
subject { champ.data_provide }
context 'when type_champ is datetime' do
before do
champ.type_de_champ = create :type_de_champ_public, type_champ: 'datetime'
end
it { is_expected.to eq 'datepicker' }
end
context 'when type_champ is address' do
before do
champ.type_de_champ = create :type_de_champ_public, type_champ: 'address'
end
it { is_expected.to eq 'typeahead' }
end
end
end

View file

@ -1,40 +1,7 @@
require 'spec_helper' require 'spec_helper'
describe Champ do describe Champ do
describe 'database columns' do require 'models/champ_shared_example.rb'
it { is_expected.to have_db_column(:value) }
end
describe 'associations' do it_should_behave_like "champ_spec"
it { is_expected.to belong_to(:dossier) }
it { is_expected.to belong_to(:type_de_champ) }
end
describe 'delegation' do
it { is_expected.to delegate_method(:libelle).to(:type_de_champ) }
it { is_expected.to delegate_method(:type_champ).to(:type_de_champ) }
it { is_expected.to delegate_method(:order_place).to(:type_de_champ) }
end
describe 'data_provide' do
let(:champ) { create :champ }
subject { champ.data_provide }
context 'when type_champ is datetime' do
before do
champ.type_de_champ = create :type_de_champ_public, type_champ: 'datetime'
end
it { is_expected.to eq 'datepicker' }
end
context 'when type_champ is address' do
before do
champ.type_de_champ = create :type_de_champ_public, type_champ: 'address'
end
it { is_expected.to eq 'typeahead' }
end
end
end end

View file

@ -92,12 +92,16 @@ describe Dossier do
end end
describe '#build_default_champs' do describe '#build_default_champs' do
context 'when dossier is linked to a procedure' do context 'when dossier is linked to a procedure with type_de_champ_public and private' do
let(:dossier) { create(:dossier, user: user) } let(:dossier) { create(:dossier, user: user) }
it 'build all champs needed' do it 'build all champs needed' do
expect(dossier.champs.count).to eq(1) expect(dossier.champs.count).to eq(1)
end end
it 'build all champs_private needed' do
expect(dossier.champs_private.count).to eq(1)
end
end end
end end
@ -604,7 +608,7 @@ describe Dossier do
subject { dossier.ordered_champs } subject { dossier.ordered_champs }
it { expect(Champ.where(dossier_id: 0).size).to eq 5 } it { expect(ChampPublic.where(dossier_id: 0).size).to eq 5 }
describe 'for dossier 1' do describe 'for dossier 1' do
let(:dossier) { dossier_1 } let(:dossier) { dossier_1 }
@ -626,6 +630,48 @@ describe Dossier do
end end
describe '#ordered_champs_private' do
let!(:procedure_1) { create :procedure }
let!(:procedure_2) { create :procedure }
let(:dossier_1) { Dossier.new(id: 0, procedure: procedure_1) }
let(:dossier_2) { Dossier.new(id: 0, procedure: procedure_2) }
before do
create :type_de_champ_private, libelle: 'type_1_1', order_place: 1, procedure: dossier_1.procedure
create :type_de_champ_private, libelle: 'type_1_2', order_place: 2, procedure: dossier_1.procedure
create :type_de_champ_private, libelle: 'type_2_1', order_place: 1, procedure: dossier_2.procedure
create :type_de_champ_private, libelle: 'type_2_2', order_place: 2, procedure: dossier_2.procedure
create :type_de_champ_private, libelle: 'type_2_3', order_place: 3, procedure: dossier_2.procedure
dossier_1.build_default_champs
dossier_2.build_default_champs
end
subject { dossier.ordered_champs_private }
it { expect(ChampPrivate.where(dossier_id: 0).size).to eq 5 }
describe 'for dossier 1' do
let(:dossier) { dossier_1 }
it { expect(subject.size).to eq 2 }
it { expect(subject.first.type_de_champ.libelle).to eq 'type_1_1' }
it { expect(subject.last.type_de_champ.libelle).to eq 'type_1_2' }
end
describe 'for dossier 2' do
let(:dossier) { dossier_2 }
it { expect(subject.size).to eq 3 }
it { expect(subject.first.type_de_champ.libelle).to eq 'type_2_1' }
it { expect(subject.second.type_de_champ.libelle).to eq 'type_2_2' }
it { expect(subject.last.type_de_champ.libelle).to eq 'type_2_3' }
end
end
describe '#total_follow' do describe '#total_follow' do
let(:dossier) { create(:dossier, :with_entreprise, user: user) } let(:dossier) { create(:dossier, :with_entreprise, user: user) }
let(:dossier2) { create(:dossier, :with_entreprise, user: user) } let(:dossier2) { create(:dossier, :with_entreprise, user: user) }

View file

@ -19,7 +19,7 @@ describe 'admin/types_de_champ/show.html.haml', type: :view do
end end
end end
describe 'arrow button' do describe 'elements presents or not' do
subject do subject do
procedure.reload procedure.reload
assign(:procedure, procedure) assign(:procedure, procedure)
@ -27,6 +27,14 @@ describe 'admin/types_de_champ/show.html.haml', type: :view do
render render
rendered rendered
end end
describe 'mandatory checkbox' do
it 'no mandatory checkbox are present' do
expect(subject).not_to have_css('.form-group.mandatory')
end
end
describe 'arrow button' do
context 'when there is no field in database' do context 'when there is no field in database' do
it { expect(subject).not_to have_css('.fa-chevron-down') } it { expect(subject).not_to have_css('.fa-chevron-down') }
it { expect(subject).not_to have_css('.fa-chevron-up') } it { expect(subject).not_to have_css('.fa-chevron-up') }
@ -48,3 +56,4 @@ describe 'admin/types_de_champ/show.html.haml', type: :view do
end end
end end
end end
end