commit
da692483cd
51 changed files with 524 additions and 123 deletions
1
Gemfile
1
Gemfile
|
@ -47,6 +47,7 @@ gem 'prawn' # PDF Generation
|
|||
gem 'prawn_rails'
|
||||
gem 'premailer-rails'
|
||||
gem 'puma' # Use Puma as the app server
|
||||
gem 'pundit'
|
||||
gem 'rack-mini-profiler'
|
||||
gem 'rails'
|
||||
gem 'rails-i18n' # Locales par défaut
|
||||
|
|
|
@ -431,6 +431,8 @@ GEM
|
|||
pry (~> 0.10)
|
||||
public_suffix (3.0.3)
|
||||
puma (3.12.0)
|
||||
pundit (2.0.1)
|
||||
activesupport (>= 3.0.0)
|
||||
rack (2.0.6)
|
||||
rack-mini-profiler (1.0.1)
|
||||
rack (>= 1.2.0)
|
||||
|
@ -749,6 +751,7 @@ DEPENDENCIES
|
|||
premailer-rails
|
||||
pry-byebug
|
||||
puma
|
||||
pundit
|
||||
rack-mini-profiler
|
||||
rails
|
||||
rails-controller-testing
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class ApplicationController < ActionController::Base
|
||||
include TrustedDeviceConcern
|
||||
include Pundit
|
||||
|
||||
MAINTENANCE_MESSAGE = 'Le site est actuellement en maintenance. Il sera à nouveau disponible dans un court instant.'
|
||||
|
||||
|
@ -41,12 +42,18 @@ class ApplicationController < ActionController::Base
|
|||
logged_user.present?
|
||||
end
|
||||
|
||||
def logged_user_ids
|
||||
logged_users.map(&:id)
|
||||
end
|
||||
|
||||
helper_method :logged_in?
|
||||
|
||||
def pundit_user
|
||||
if administrateur_signed_in?
|
||||
current_administrateur
|
||||
elsif gestionnaire_signed_in?
|
||||
current_gestionnaire
|
||||
else
|
||||
current_user
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def authenticate_logged_user!
|
||||
|
|
|
@ -14,15 +14,9 @@ class Champs::CarteController < ApplicationController
|
|||
end
|
||||
|
||||
@champ = if params[:champ_id].present?
|
||||
Champ
|
||||
.joins(:dossier)
|
||||
.where(dossiers: { user_id: logged_user_ids })
|
||||
.find(params[:champ_id])
|
||||
policy_scope(Champ).find(params[:champ_id])
|
||||
else
|
||||
TypeDeChamp
|
||||
.joins(:procedure)
|
||||
.where(procedures: { administrateur_id: logged_user_ids })
|
||||
.find(params[:type_de_champ_id]).champ.build
|
||||
policy_scope(TypeDeChamp).find(params[:type_de_champ_id]).champ.build
|
||||
end
|
||||
|
||||
geo_areas = []
|
||||
|
@ -61,11 +55,15 @@ class Champs::CarteController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
selection_utilisateur = ApiCartoService.generate_selection_utilisateur(coordinates)
|
||||
selection_utilisateur[:source] = GeoArea.sources.fetch(:selection_utilisateur)
|
||||
geo_areas << selection_utilisateur
|
||||
|
||||
@champ.geo_areas = geo_areas.map do |geo_area|
|
||||
GeoArea.new(geo_area)
|
||||
end
|
||||
|
||||
@champ.value = GeojsonService.to_json_polygon_for_selection_utilisateur(coordinates)
|
||||
@champ.value = coordinates.to_json
|
||||
end
|
||||
|
||||
if @champ.persisted?
|
||||
|
|
|
@ -2,10 +2,7 @@ class Champs::RepetitionController < ApplicationController
|
|||
before_action :authenticate_logged_user!
|
||||
|
||||
def show
|
||||
@champ = Champ
|
||||
.joins(:dossier)
|
||||
.where(dossiers: { user_id: logged_user_ids })
|
||||
.find(params[:champ_id])
|
||||
@champ = policy_scope(Champ).find(params[:champ_id])
|
||||
|
||||
@position = params[:position]
|
||||
row = (@champ.champs.empty? ? 0 : @champ.champs.last.row) + 1
|
||||
|
|
|
@ -109,8 +109,12 @@ module Gestionnaires
|
|||
if dossier.en_instruction?
|
||||
flash.notice = 'Le dossier est déjà en instruction.'
|
||||
else
|
||||
flash.notice = "Le dossier #{dossier.id} a été repassé en instruction."
|
||||
dossier.repasser_en_instruction!(current_gestionnaire)
|
||||
if dossier.accepte?
|
||||
flash.notice = 'Il n’est pas possible de repasser un dossier accepté en instruction.'
|
||||
else
|
||||
flash.notice = "Le dossier #{dossier.id} a été repassé en instruction."
|
||||
dossier.repasser_en_instruction!(current_gestionnaire)
|
||||
end
|
||||
end
|
||||
|
||||
render partial: 'state_button_refresh', locals: { dossier: dossier }
|
||||
|
|
|
@ -30,6 +30,16 @@ module Manager
|
|||
redirect_to manager_dossier_path(dossier)
|
||||
end
|
||||
|
||||
def repasser_en_instruction
|
||||
dossier = Dossier.find(params[:id])
|
||||
dossier.repasser_en_instruction(current_administration)
|
||||
|
||||
logger.info("Le dossier #{dossier.id} est repassé en instruction par #{current_administration.email}")
|
||||
flash[:notice] = "Le dossier #{dossier.id} est repassé en instruction."
|
||||
|
||||
redirect_to manager_dossier_path(dossier)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def unfiltered_list?
|
||||
|
|
|
@ -26,7 +26,7 @@ module ProcedureHelper
|
|||
if logo.blank?
|
||||
ActionController::Base.helpers.image_url("marianne.svg")
|
||||
else
|
||||
if Flipflop.remote_storage?
|
||||
if Rails.application.secrets.fog[:enabled]
|
||||
RemoteDownloader.new(logo.filename).url
|
||||
else
|
||||
LocalDownloader.new(logo.path, 'logo').url
|
||||
|
|
|
@ -68,9 +68,13 @@ const TypeDeChamp = sortableElement(
|
|||
<div className="flex justify-start delete">
|
||||
<button
|
||||
className="button small icon-only danger"
|
||||
onClick={() =>
|
||||
dispatch({ type: 'removeTypeDeChamp', params: { typeDeChamp } })
|
||||
}
|
||||
onClick={() => {
|
||||
if (confirm('Êtes vous sûr de vouloir supprimer ce champ ?'))
|
||||
dispatch({
|
||||
type: 'removeTypeDeChamp',
|
||||
params: { typeDeChamp }
|
||||
});
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon="trash" title="Supprimer" />
|
||||
</button>
|
||||
|
|
|
@ -3,7 +3,7 @@ class WeeklyOverviewJob < ApplicationJob
|
|||
|
||||
def perform(*args)
|
||||
# Feature flipped to avoid mails in staging due to unprocessed dossier
|
||||
if Flipflop.weekly_overview?
|
||||
if Rails.application.config.ds_weekly_overview
|
||||
Gestionnaire.all
|
||||
.map { |gestionnaire| [gestionnaire, gestionnaire.last_week_overview] }
|
||||
.reject { |_, overview| overview.nil? }
|
||||
|
|
|
@ -2,4 +2,13 @@ class Attestation < ApplicationRecord
|
|||
belongs_to :dossier
|
||||
|
||||
mount_uploader :pdf, AttestationUploader
|
||||
|
||||
def pdf_url
|
||||
if Rails.application.secrets.fog[:enabled]
|
||||
RemoteDownloader.new(pdf.path).url
|
||||
elsif pdf&.url
|
||||
# FIXME: this is horrible but used only in dev and will be removed after migration
|
||||
File.join(LOCAL_DOWNLOAD_URL, pdf.url)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,10 +5,11 @@ class Champ < ApplicationRecord
|
|||
has_many :commentaires
|
||||
has_one_attached :piece_justificative_file
|
||||
|
||||
# We declare champ specific relationships (Champs::CarteChamp and Champs::SiretChamp)
|
||||
# We declare champ specific relationships (Champs::CarteChamp, Champs::SiretChamp and Champs::RepetitionChamp)
|
||||
# here because otherwise we can't easily use includes in our queries.
|
||||
has_many :geo_areas, dependent: :destroy
|
||||
belongs_to :etablissement, dependent: :destroy
|
||||
has_many :champs, -> { ordered }, foreign_key: :parent_id, inverse_of: :parent, dependent: :destroy
|
||||
|
||||
delegate :libelle, :type_champ, :order_place, :mandatory?, :description, :drop_down_list, :exclude_from_export?, :exclude_from_view?, :repetition?, to: :type_de_champ
|
||||
|
||||
|
|
|
@ -19,6 +19,10 @@ class Champs::CarteChamp < Champ
|
|||
end
|
||||
end
|
||||
|
||||
def selection_utilisateur
|
||||
geo_areas.find(&:selection_utilisateur?)
|
||||
end
|
||||
|
||||
def cadastres?
|
||||
type_de_champ&.cadastres && type_de_champ.cadastres != '0'
|
||||
end
|
||||
|
@ -45,6 +49,49 @@ class Champs::CarteChamp < Champ
|
|||
|
||||
def geo_json
|
||||
@geo_json ||= begin
|
||||
geo_area = selection_utilisateur
|
||||
|
||||
if geo_area
|
||||
geo_area.geometry
|
||||
else
|
||||
geo_json_from_value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def selection_utilisateur_size
|
||||
if geo_json.present?
|
||||
geo_json['coordinates'].size
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
def to_render_data
|
||||
{
|
||||
position: position,
|
||||
selection: user_geo_area&.geometry,
|
||||
quartiersPrioritaires: quartiers_prioritaires? ? quartiers_prioritaires.as_json(except: :properties) : [],
|
||||
cadastres: cadastres? ? cadastres.as_json(except: :properties) : [],
|
||||
parcellesAgricoles: parcelles_agricoles? ? parcelles_agricoles.as_json(except: :properties) : []
|
||||
}
|
||||
end
|
||||
|
||||
def user_geo_area
|
||||
geo_area = selection_utilisateur
|
||||
|
||||
if geo_area.present?
|
||||
geo_area
|
||||
elsif geo_json_from_value.present?
|
||||
GeoArea.new(
|
||||
geometry: geo_json_from_value,
|
||||
source: GeoArea.sources.fetch(:selection_utilisateur)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def geo_json_from_value
|
||||
@geo_json_from_value ||= begin
|
||||
parsed_value = value.blank? ? nil : JSON.parse(value)
|
||||
# We used to store in the value column a json array with coordinates.
|
||||
if parsed_value.is_a?(Array)
|
||||
|
@ -62,34 +109,11 @@ class Champs::CarteChamp < Champ
|
|||
end
|
||||
end
|
||||
|
||||
def selection_utilisateur_size
|
||||
if geo_json.present?
|
||||
geo_json['coordinates'].size
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
def to_render_data
|
||||
{
|
||||
position: position,
|
||||
selection: geo_json,
|
||||
quartiersPrioritaires: quartiers_prioritaires? ? quartiers_prioritaires.as_json(except: :properties) : [],
|
||||
cadastres: cadastres? ? cadastres.as_json(except: :properties) : [],
|
||||
parcellesAgricoles: parcelles_agricoles? ? parcelles_agricoles.as_json(except: :properties) : []
|
||||
}
|
||||
end
|
||||
|
||||
def user_geo_area
|
||||
if geo_json.present?
|
||||
GeoArea.new(
|
||||
geometry: geo_json,
|
||||
source: GeoArea.sources.fetch(:selection_utilisateur)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def for_api
|
||||
geo_json&.to_json
|
||||
nil
|
||||
end
|
||||
|
||||
def for_export
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
class Champs::RepetitionChamp < Champ
|
||||
has_many :champs, -> { ordered }, foreign_key: :parent_id, inverse_of: :parent, dependent: :destroy
|
||||
|
||||
accepts_nested_attributes_for :champs, allow_destroy: true
|
||||
|
||||
def rows
|
||||
|
@ -21,11 +19,21 @@ class Champs::RepetitionChamp < Champ
|
|||
# The user cannot enter any information here so it doesn’t make much sense to search
|
||||
end
|
||||
|
||||
def rows_for_export
|
||||
rows.each.with_index(1).map do |champs, index|
|
||||
Champs::RepetitionChamp::Row.new(index: index, dossier_id: dossier_id.to_s, champs: champs)
|
||||
end
|
||||
end
|
||||
|
||||
class Row < Hashie::Dash
|
||||
property :index
|
||||
property :dossier_id
|
||||
property :champs
|
||||
|
||||
def read_attribute_for_serialization(attribute)
|
||||
self[attribute]
|
||||
end
|
||||
|
||||
def spreadsheet_columns
|
||||
[
|
||||
['Dossier ID', :dossier_id],
|
||||
|
|
|
@ -52,7 +52,7 @@ class Commentaire < ApplicationRecord
|
|||
if piece_jointe.virus_scanner.safe?
|
||||
Rails.application.routes.url_helpers.url_for(piece_jointe)
|
||||
end
|
||||
elsif Flipflop.remote_storage?
|
||||
elsif Rails.application.secrets.fog[:enabled]
|
||||
RemoteDownloader.new(file.path).url
|
||||
elsif file&.url
|
||||
# FIXME: this is horrible but used only in dev and will be removed after migration
|
||||
|
|
|
@ -86,6 +86,7 @@ class Dossier < ApplicationRecord
|
|||
event :repasser_en_instruction, after: :after_repasser_en_instruction do
|
||||
transitions from: :refuse, to: :en_instruction
|
||||
transitions from: :sans_suite, to: :en_instruction
|
||||
transitions from: :accepte, to: :en_instruction
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -108,7 +109,24 @@ class Dossier < ApplicationRecord
|
|||
scope :en_construction, -> { not_archived.state_en_construction }
|
||||
scope :en_instruction, -> { not_archived.state_en_instruction }
|
||||
scope :termine, -> { not_archived.state_termine }
|
||||
scope :downloadable_sorted, -> { state_not_brouillon.includes(:etablissement, :user, :individual, :followers_gestionnaires, :avis, champs: { etablissement: [:champ], type_de_champ: :drop_down_list }, champs_private: { etablissement: [:champ], type_de_champ: :drop_down_list }).order(en_construction_at: 'asc') }
|
||||
scope :downloadable_sorted, -> {
|
||||
state_not_brouillon
|
||||
.includes(
|
||||
:user,
|
||||
:individual,
|
||||
:followers_gestionnaires,
|
||||
:avis,
|
||||
etablissement: :champ,
|
||||
champs: {
|
||||
etablissement: :champ,
|
||||
type_de_champ: :drop_down_list
|
||||
},
|
||||
champs_private: {
|
||||
etablissement: :champ,
|
||||
type_de_champ: :drop_down_list
|
||||
}
|
||||
).order(en_construction_at: 'asc')
|
||||
}
|
||||
scope :en_cours, -> { not_archived.state_en_construction_ou_instruction }
|
||||
scope :without_followers, -> { left_outer_joins(:follows).where(follows: { id: nil }) }
|
||||
scope :followed_by, -> (gestionnaire) { joins(:follows).where(follows: { gestionnaire: gestionnaire }) }
|
||||
|
@ -120,14 +138,22 @@ class Dossier < ApplicationRecord
|
|||
champs: [
|
||||
:geo_areas,
|
||||
:etablissement,
|
||||
piece_justificative_file_attachment: :blob
|
||||
piece_justificative_file_attachment: :blob,
|
||||
champs: [
|
||||
piece_justificative_file_attachment: :blob
|
||||
]
|
||||
],
|
||||
champs_private: [
|
||||
:geo_areas,
|
||||
:etablissement,
|
||||
piece_justificative_file_attachment: :blob
|
||||
piece_justificative_file_attachment: :blob,
|
||||
champs: [
|
||||
piece_justificative_file_attachment: :blob
|
||||
]
|
||||
],
|
||||
avis: [],
|
||||
justificatif_motivation_attachment: :blob,
|
||||
attestation: [],
|
||||
avis: { piece_justificative_file_attachment: :blob },
|
||||
etablissement: [],
|
||||
individual: [],
|
||||
user: [])
|
||||
|
|
|
@ -120,6 +120,6 @@ class Etablissement < ApplicationRecord
|
|||
end
|
||||
|
||||
def libelle_for_export
|
||||
champ&.libelle
|
||||
champ&.libelle || 'Dossier'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,4 +30,8 @@ class GeoArea < ApplicationRecord
|
|||
scope :quartiers_prioritaires, -> { where(source: sources.fetch(:quartier_prioritaire)) }
|
||||
scope :cadastres, -> { where(source: sources.fetch(:cadastre)) }
|
||||
scope :parcelles_agricoles, -> { where(source: sources.fetch(:parcelle_agricole)) }
|
||||
|
||||
def selection_utilisateur?
|
||||
source == self.class.sources.fetch(:selection_utilisateur)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -225,6 +225,10 @@ class Gestionnaire < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def user
|
||||
User.find_by(email: email)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def annotations_hash(demande, annotations_privees, avis, messagerie)
|
||||
|
|
49
app/policies/application_policy.rb
Normal file
49
app/policies/application_policy.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
class ApplicationPolicy
|
||||
attr_reader :user, :record
|
||||
|
||||
def initialize(user, record)
|
||||
@user = user
|
||||
@record = record
|
||||
end
|
||||
|
||||
def index?
|
||||
false
|
||||
end
|
||||
|
||||
def show?
|
||||
false
|
||||
end
|
||||
|
||||
def create?
|
||||
false
|
||||
end
|
||||
|
||||
def new?
|
||||
create?
|
||||
end
|
||||
|
||||
def update?
|
||||
false
|
||||
end
|
||||
|
||||
def edit?
|
||||
update?
|
||||
end
|
||||
|
||||
def destroy?
|
||||
false
|
||||
end
|
||||
|
||||
class Scope
|
||||
attr_reader :user, :scope
|
||||
|
||||
def initialize(user, scope)
|
||||
@user = user
|
||||
@scope = scope
|
||||
end
|
||||
|
||||
def resolve
|
||||
scope.all
|
||||
end
|
||||
end
|
||||
end
|
24
app/policies/champ_policy.rb
Normal file
24
app/policies/champ_policy.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
class ChampPolicy < ApplicationPolicy
|
||||
class Scope < Scope
|
||||
def resolve
|
||||
if user.is_a?(User)
|
||||
scope
|
||||
.joins(:dossier)
|
||||
.where({ dossiers: { user_id: user.id } })
|
||||
elsif user.is_a?(Gestionnaire)
|
||||
scope_with_join = scope.joins(dossier: :follows)
|
||||
scope_with_left_join = scope.left_joins(dossier: :follows)
|
||||
|
||||
if user.user
|
||||
scope_with_left_join
|
||||
.where({ dossiers: { user_id: user.user.id } })
|
||||
.or(scope_with_left_join.where(dossiers: { follows: { gestionnaire_id: user.id } }))
|
||||
else
|
||||
scope_with_join.where(dossiers: { follows: { gestionnaire_id: user.id } })
|
||||
end
|
||||
else
|
||||
scope.none
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
13
app/policies/type_de_champ_policy.rb
Normal file
13
app/policies/type_de_champ_policy.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
class TypeDeChampPolicy < ApplicationPolicy
|
||||
class Scope < Scope
|
||||
def resolve
|
||||
if user.is_a?(Administrateur)
|
||||
scope
|
||||
.joins(procedure: [:administrateurs])
|
||||
.where({ administrateurs: { id: user.id } })
|
||||
else
|
||||
scope.none
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -8,6 +8,7 @@ class ChampSerializer < ActiveModel::Serializer
|
|||
has_many :geo_areas, if: :include_geo_areas?
|
||||
has_one :etablissement, if: :include_etablissement?
|
||||
has_one :entreprise, if: :include_etablissement?
|
||||
has_many :rows, serializer: RowSerializer, if: :include_rows?
|
||||
|
||||
def value
|
||||
case object
|
||||
|
@ -35,6 +36,10 @@ class ChampSerializer < ActiveModel::Serializer
|
|||
object.etablissement&.entreprise
|
||||
end
|
||||
|
||||
def rows
|
||||
object.rows_for_export
|
||||
end
|
||||
|
||||
def include_etablissement?
|
||||
object.is_a?(Champs::SiretChamp)
|
||||
end
|
||||
|
@ -43,6 +48,10 @@ class ChampSerializer < ActiveModel::Serializer
|
|||
object.is_a?(Champs::CarteChamp)
|
||||
end
|
||||
|
||||
def include_rows?
|
||||
object.is_a?(Champs::RepetitionChamp)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def legacy_type_de_champ
|
||||
|
|
|
@ -14,6 +14,9 @@ class DossierSerializer < ActiveModel::Serializer
|
|||
:motivation,
|
||||
:instructeurs
|
||||
|
||||
attribute :attestation, if: :include_attestation?
|
||||
attribute :justificatif_motivation, if: :include_justificatif_motivation?
|
||||
|
||||
has_one :individual
|
||||
has_one :entreprise
|
||||
has_one :etablissement
|
||||
|
@ -22,7 +25,6 @@ class DossierSerializer < ActiveModel::Serializer
|
|||
has_many :champs_private
|
||||
has_many :pieces_justificatives
|
||||
has_many :types_de_piece_justificative
|
||||
has_one :justificatif_motivation
|
||||
has_many :avis
|
||||
|
||||
has_many :champs, serializer: ChampSerializer
|
||||
|
@ -37,7 +39,9 @@ class DossierSerializer < ActiveModel::Serializer
|
|||
|
||||
if champ_carte.present?
|
||||
carto_champs = champ_carte.geo_areas.to_a
|
||||
carto_champs << champ_carte.user_geo_area
|
||||
if !carto_champs.find(&:selection_utilisateur?)
|
||||
carto_champs << champ_carte.user_geo_area
|
||||
end
|
||||
champs += carto_champs.compact
|
||||
end
|
||||
end
|
||||
|
@ -53,10 +57,12 @@ class DossierSerializer < ActiveModel::Serializer
|
|||
PiecesJustificativesService.serialize_champs_as_pjs(object)
|
||||
end
|
||||
|
||||
def attestation
|
||||
object.attestation.pdf_url
|
||||
end
|
||||
|
||||
def justificatif_motivation
|
||||
if object.justificatif_motivation.attached?
|
||||
Rails.application.routes.url_helpers.url_for(object.justificatif_motivation)
|
||||
end
|
||||
Rails.application.routes.url_helpers.url_for(object.justificatif_motivation)
|
||||
end
|
||||
|
||||
def types_de_piece_justificative
|
||||
|
@ -102,4 +108,12 @@ class DossierSerializer < ActiveModel::Serializer
|
|||
def processed_at
|
||||
object.processed_at&.in_time_zone('UTC')
|
||||
end
|
||||
|
||||
def include_attestation?
|
||||
object.accepte?
|
||||
end
|
||||
|
||||
def include_justificatif_motivation?
|
||||
object.justificatif_motivation.attached?
|
||||
end
|
||||
end
|
||||
|
|
5
app/serializers/row_serializer.rb
Normal file
5
app/serializers/row_serializer.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class RowSerializer < ActiveModel::Serializer
|
||||
has_many :champs, serializer: ChampSerializer
|
||||
|
||||
attribute :index, key: :id
|
||||
end
|
|
@ -22,4 +22,10 @@ class ApiCartoService
|
|||
).results
|
||||
end
|
||||
end
|
||||
|
||||
def self.generate_selection_utilisateur(coordinates)
|
||||
{
|
||||
geometry: JSON.parse(GeojsonService.to_json_polygon_for_selection_utilisateur(coordinates))
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -53,16 +53,14 @@ class ProcedureExportV2Service
|
|||
[dossier.champs, dossier.champs_private]
|
||||
.flatten
|
||||
.select { |champ| champ.is_a?(Champs::RepetitionChamp) }
|
||||
end
|
||||
end.group_by(&:libelle)
|
||||
end
|
||||
|
||||
def champs_repetables_options
|
||||
champs_repetables.map do |champ|
|
||||
champs_repetables.map do |libelle, champs|
|
||||
[
|
||||
champ.libelle,
|
||||
champ.rows.each_with_index.map do |champs, index|
|
||||
Champs::RepetitionChamp::Row.new(index: index + 1, dossier_id: champ.dossier_id.to_s, champs: champs)
|
||||
end
|
||||
libelle,
|
||||
champs.flat_map(&:rows_for_export)
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ class AttestationTemplateLogoUploader < BaseUploader
|
|||
end
|
||||
|
||||
# Choose what kind of storage to use for this uploader:
|
||||
if Flipflop.remote_storage?
|
||||
if Rails.application.secrets.fog[:enabled]
|
||||
storage :fog
|
||||
else
|
||||
storage :file
|
||||
|
@ -13,7 +13,7 @@ class AttestationTemplateLogoUploader < BaseUploader
|
|||
# Override the directory where uploaded files will be stored.
|
||||
# This is a sensible default for uploaders that are meant to be mounted:
|
||||
def store_dir
|
||||
if !Flipflop.remote_storage?
|
||||
if !Rails.application.secrets.fog[:enabled]
|
||||
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ class AttestationTemplateSignatureUploader < BaseUploader
|
|||
end
|
||||
|
||||
# Choose what kind of storage to use for this uploader:
|
||||
if Flipflop.remote_storage?
|
||||
if Rails.application.secrets.fog[:enabled]
|
||||
storage :fog
|
||||
else
|
||||
storage :file
|
||||
|
@ -13,7 +13,7 @@ class AttestationTemplateSignatureUploader < BaseUploader
|
|||
# Override the directory where uploaded files will be stored.
|
||||
# This is a sensible default for uploaders that are meant to be mounted:
|
||||
def store_dir
|
||||
if !Flipflop.remote_storage?
|
||||
if !Rails.application.secrets.fog[:enabled]
|
||||
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ class AttestationUploader < BaseUploader
|
|||
end
|
||||
|
||||
# Choose what kind of storage to use for this uploader:
|
||||
if Flipflop.remote_storage?
|
||||
if Rails.application.secrets.fog[:enabled]
|
||||
storage :fog
|
||||
else
|
||||
storage :file
|
||||
|
@ -13,7 +13,7 @@ class AttestationUploader < BaseUploader
|
|||
# Override the directory where uploaded files will be stored.
|
||||
# This is a sensible default for uploaders that are meant to be mounted:
|
||||
def store_dir
|
||||
if !Flipflop.remote_storage?
|
||||
if !Rails.application.secrets.fog[:enabled]
|
||||
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ class CommentaireFileUploader < BaseUploader
|
|||
Rails.root.join("public")
|
||||
end
|
||||
|
||||
if Flipflop.remote_storage?
|
||||
if Rails.application.secrets.fog[:enabled]
|
||||
storage :fog
|
||||
else
|
||||
storage :file
|
||||
|
|
|
@ -4,7 +4,7 @@ class ProcedureLogoUploader < BaseUploader
|
|||
end
|
||||
|
||||
# Choose what kind of storage to use for this uploader:
|
||||
if Flipflop.remote_storage?
|
||||
if Rails.application.secrets.fog[:enabled]
|
||||
storage :fog
|
||||
else
|
||||
storage :file
|
||||
|
@ -13,7 +13,7 @@ class ProcedureLogoUploader < BaseUploader
|
|||
# Override the directory where uploaded files will be stored.
|
||||
# This is a sensible default for uploaders that are meant to be mounted:
|
||||
def store_dir
|
||||
if !Flipflop.remote_storage?
|
||||
if !Rails.application.secrets.fog[:enabled]
|
||||
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
||||
end
|
||||
end
|
||||
|
@ -27,7 +27,7 @@ class ProcedureLogoUploader < BaseUploader
|
|||
def filename
|
||||
if file.present?
|
||||
if original_filename.present? || model.logo_secure_token
|
||||
if Flipflop.remote_storage?
|
||||
if Rails.application.secrets.fog[:enabled]
|
||||
filename = "#{model.class.to_s.underscore}-#{secure_token}.#{file.extension&.downcase}"
|
||||
else
|
||||
filename = "logo-#{secure_token}.#{file.extension&.downcase}"
|
||||
|
|
|
@ -28,6 +28,9 @@ as well as a link to its edit page.
|
|||
</h1>
|
||||
|
||||
<div>
|
||||
<% if dossier.accepte? %>
|
||||
<%= link_to 'Repasser en instruction', repasser_en_instruction_manager_dossier_path(dossier), method: :post, class: 'button', data: { confirm: "Confirmez vous le passage en instruction du dossier ?" } %>
|
||||
<% end %>
|
||||
<% if dossier.hidden_at.nil? %>
|
||||
<%= link_to 'Supprimer le dossier', hide_manager_dossier_path(dossier), method: :post, class: 'button', data: { confirm: "Confirmez vous la suppression du dossier ?" } %>
|
||||
<% end %>
|
||||
|
|
|
@ -39,5 +39,7 @@ module TPS
|
|||
# Make main application helpers available in administrate
|
||||
Administrate::ApplicationController.helper(TPS::Application.helpers)
|
||||
end
|
||||
|
||||
config.ds_weekly_overview = ENV['APP_NAME'] == 'tps'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,12 +29,8 @@ Flipflop.configure do
|
|||
end
|
||||
|
||||
group :production do
|
||||
feature :remote_storage,
|
||||
default: ENV['FOG_ENABLED'] == 'enabled'
|
||||
feature :insee_api_v3,
|
||||
default: true
|
||||
feature :weekly_overview,
|
||||
default: ENV['APP_NAME'] == 'tps'
|
||||
feature :pre_maintenance_mode
|
||||
feature :maintenance_mode
|
||||
end
|
||||
|
|
|
@ -16,6 +16,7 @@ Rails.application.routes.draw do
|
|||
|
||||
resources :dossiers, only: [:index, :show] do
|
||||
post 'hide', on: :member
|
||||
post 'repasser_en_instruction', on: :member
|
||||
end
|
||||
|
||||
resources :administrateurs, only: [:index, :show, :new, :create] do
|
||||
|
|
|
@ -34,6 +34,7 @@ defaults: &defaults
|
|||
pipedrive:
|
||||
key: <%= ENV['PIPEDRIVE_KEY'] %>
|
||||
fog:
|
||||
enabled: <%= ENV['FOG_ENABLED'] == 'enabled' %>
|
||||
openstack_tenant: <%= ENV['FOG_OPENSTACK_TENANT'] %>
|
||||
openstack_api_key: <%= ENV['FOG_OPENSTACK_API_KEY'] %>
|
||||
openstack_username: <%= ENV['FOG_OPENSTACK_USERNAME'] %>
|
||||
|
|
|
@ -513,6 +513,7 @@ ActiveRecord::Schema.define(version: 2019_07_17_151228) do
|
|||
t.boolean "durees_conservation_required", default: true
|
||||
t.string "path"
|
||||
t.string "declarative_with_state"
|
||||
t.text "monavis"
|
||||
t.text "monavis_embed"
|
||||
t.index ["declarative_with_state"], name: "index_procedures_on_declarative_with_state"
|
||||
t.index ["hidden_at"], name: "index_procedures_on_hidden_at"
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
namespace :after_party do
|
||||
desc 'Deployment task: migrate_geo_area_data'
|
||||
task migrate_geo_area_data: :environment do
|
||||
puts "Running deploy task 'migrate_geo_area_data'"
|
||||
|
||||
progress = ProgressReport.new(Champs::CarteChamp.count)
|
||||
|
||||
Champs::CarteChamp.includes(:geo_areas).find_each do |champ|
|
||||
geo_area = champ.geo_areas.find(&:selection_utilisateur?)
|
||||
geo_json = champ.geo_json_from_value
|
||||
|
||||
if geo_area.blank? && geo_json.present?
|
||||
GeoArea.create(
|
||||
champ: champ,
|
||||
geometry: geo_json,
|
||||
source: GeoArea.sources.fetch(:selection_utilisateur)
|
||||
)
|
||||
progress.inc
|
||||
end
|
||||
end
|
||||
|
||||
progress.finish
|
||||
|
||||
# Update task as completed. If you remove the line below, the task will
|
||||
# run with every deploy (or every time you call after_party:run).
|
||||
AfterParty::TaskRecord.create version: '20190731152733'
|
||||
end
|
||||
end
|
|
@ -154,10 +154,10 @@ describe API::V1::DossiersController do
|
|||
context 'when dossier exists and belongs to procedure' do
|
||||
let(:procedure_id) { procedure.id }
|
||||
let(:date_creation) { Time.zone.local(2008, 9, 1, 10, 5, 0) }
|
||||
let!(:dossier) { Timecop.freeze(date_creation) { create(:dossier, :with_entreprise, :en_construction, procedure: procedure, motivation: "Motivation") } }
|
||||
let!(:dossier) { Timecop.freeze(date_creation) { create(:dossier, :with_entreprise, :with_attestation, :accepte, procedure: procedure, motivation: "Motivation") } }
|
||||
let(:dossier_id) { dossier.id }
|
||||
let(:body) { JSON.parse(retour.body, symbolize_names: true) }
|
||||
let(:field_list) { [:id, :created_at, :updated_at, :archived, :individual, :entreprise, :etablissement, :cerfa, :types_de_piece_justificative, :pieces_justificatives, :champs, :champs_private, :commentaires, :state, :simplified_state, :initiated_at, :processed_at, :received_at, :motivation, :email, :instructeurs, :justificatif_motivation, :avis] }
|
||||
let(:field_list) { [:id, :created_at, :updated_at, :archived, :individual, :entreprise, :etablissement, :cerfa, :types_de_piece_justificative, :pieces_justificatives, :champs, :champs_private, :commentaires, :state, :simplified_state, :initiated_at, :processed_at, :received_at, :motivation, :email, :instructeurs, :attestation, :avis] }
|
||||
subject { body[:dossier] }
|
||||
|
||||
it 'return REST code 200', :show_in_doc do
|
||||
|
@ -165,7 +165,7 @@ describe API::V1::DossiersController do
|
|||
end
|
||||
|
||||
it { expect(subject[:id]).to eq(dossier.id) }
|
||||
it { expect(subject[:state]).to eq('initiated') }
|
||||
it { expect(subject[:state]).to eq('closed') }
|
||||
it { expect(subject[:created_at]).to eq('2008-09-01T08:05:00.000Z') }
|
||||
it { expect(subject[:updated_at]).to eq('2008-09-01T08:05:00.000Z') }
|
||||
it { expect(subject[:archived]).to eq(dossier.archived) }
|
||||
|
@ -235,6 +235,22 @@ describe API::V1::DossiersController do
|
|||
it { expect(subject[:type_champ]).to eq('text') }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'repetition' do
|
||||
let(:procedure) { create(:procedure, administrateur: admin) }
|
||||
let(:champ) { build(:champ_repetition) }
|
||||
let(:dossier) { create(:dossier, :en_construction, champs: [champ], procedure: procedure) }
|
||||
|
||||
subject { super().first[:rows] }
|
||||
|
||||
it 'should have rows' do
|
||||
expect(subject.size).to eq(2)
|
||||
expect(subject[0][:id]).to eq(1)
|
||||
expect(subject[0][:champs].size).to eq(2)
|
||||
expect(subject[0][:champs].map { |c| c[:value] }).to eq(['text', '42'])
|
||||
expect(subject[0][:champs].map { |c| c[:type_de_champ][:type_champ] }).to eq(['text', 'number'])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'champs_private' do
|
||||
|
|
|
@ -4,6 +4,8 @@ describe Gestionnaires::DossiersController, type: :controller do
|
|||
render_views
|
||||
|
||||
let(:gestionnaire) { create(:gestionnaire) }
|
||||
let(:administrateur) { create(:administrateur) }
|
||||
let(:administration) { create(:administration) }
|
||||
let(:gestionnaires) { [gestionnaire] }
|
||||
let(:procedure) { create(:procedure, :published, gestionnaires: gestionnaires) }
|
||||
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
|
||||
|
@ -153,9 +155,10 @@ describe Gestionnaires::DossiersController, type: :controller do
|
|||
|
||||
describe '#repasser_en_instruction' do
|
||||
let(:dossier) { create(:dossier, :refuse, procedure: procedure) }
|
||||
let(:current_user) { gestionnaire }
|
||||
|
||||
before do
|
||||
sign_in gestionnaire
|
||||
sign_in current_user
|
||||
post :repasser_en_instruction,
|
||||
params: { procedure_id: procedure.id, dossier_id: dossier.id },
|
||||
format: 'js'
|
||||
|
@ -173,6 +176,29 @@ describe Gestionnaires::DossiersController, type: :controller do
|
|||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the dossier is accepte' do
|
||||
let(:dossier) { create(:dossier, :accepte, procedure: procedure) }
|
||||
|
||||
it 'it is not possible to go back to en_instruction as gestionnaire' do
|
||||
expect(dossier.reload.state).to eq(Dossier.states.fetch(:accepte))
|
||||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
context 'as administrateur' do
|
||||
let (:current_user) { administrateur }
|
||||
it 'it is not possible to go back to en_instruction' do
|
||||
expect(dossier.reload.state).to eq(Dossier.states.fetch(:accepte))
|
||||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
end
|
||||
context 'as superadmin' do
|
||||
let (:current_user) { administration }
|
||||
it 'it is not possible to go back to en_instruction' do
|
||||
expect(dossier.reload.state).to eq(Dossier.states.fetch(:accepte))
|
||||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#terminer' do
|
||||
|
|
|
@ -11,4 +11,17 @@ describe Manager::DossiersController, type: :controller do
|
|||
|
||||
it { expect(dossier.hidden_at).not_to be_nil }
|
||||
end
|
||||
|
||||
describe '#repasser_en_instruction' do
|
||||
let(:administration) { create :administration }
|
||||
let!(:dossier) { create(:dossier, :accepte) }
|
||||
|
||||
before do
|
||||
sign_in administration
|
||||
post :repasser_en_instruction, params: { id: dossier.id }
|
||||
dossier.reload
|
||||
end
|
||||
|
||||
it { expect(dossier.en_instruction?).to be true }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,5 +9,9 @@ FactoryBot.define do
|
|||
nom { 'XYZ' }
|
||||
commune { 'Paris' }
|
||||
end
|
||||
|
||||
trait :selection_utilisateur do
|
||||
source { GeoArea.sources.fetch(:selection_utilisateur) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,7 +11,9 @@ feature 'As an administrateur I can edit types de champ', js: true do
|
|||
end
|
||||
|
||||
it "Add a new champ" do
|
||||
click_on 'Supprimer'
|
||||
page.accept_alert do
|
||||
click_on 'Supprimer'
|
||||
end
|
||||
|
||||
within '.buttons' do
|
||||
click_on 'Ajouter un champ'
|
||||
|
@ -48,7 +50,9 @@ feature 'As an administrateur I can edit types de champ', js: true do
|
|||
expect(page).to have_selector('#champ-3-libelle')
|
||||
|
||||
within '.type-de-champ[data-index="2"]' do
|
||||
click_on 'Supprimer'
|
||||
page.accept_alert do
|
||||
click_on 'Supprimer'
|
||||
end
|
||||
end
|
||||
|
||||
expect(page).not_to have_selector('#champ-3-libelle')
|
||||
|
@ -68,8 +72,9 @@ feature 'As an administrateur I can edit types de champ', js: true do
|
|||
blur
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
page.refresh
|
||||
|
||||
click_on 'Supprimer'
|
||||
page.accept_alert do
|
||||
click_on 'Supprimer'
|
||||
end
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
expect(page).to have_content('Supprimer', count: 1)
|
||||
page.refresh
|
||||
|
|
|
@ -8,7 +8,10 @@ RSpec.describe WeeklyOverviewJob, type: :job do
|
|||
|
||||
context 'if the feature is enabled' do
|
||||
before do
|
||||
Flipflop::FeatureSet.current.test!.switch!(:weekly_overview, true)
|
||||
Rails.application.config.ds_weekly_overview = true
|
||||
end
|
||||
after do
|
||||
Rails.application.config.ds_weekly_overview = false
|
||||
end
|
||||
|
||||
context 'with one gestionnaire with one overview' do
|
||||
|
@ -35,7 +38,6 @@ RSpec.describe WeeklyOverviewJob, type: :job do
|
|||
|
||||
context 'if the feature is disabled' do
|
||||
before do
|
||||
Flipflop::FeatureSet.current.test!.switch!(:weekly_overview, false)
|
||||
allow(Gestionnaire).to receive(:all)
|
||||
WeeklyOverviewJob.new.perform
|
||||
end
|
||||
|
|
|
@ -3,9 +3,9 @@ require 'spec_helper'
|
|||
describe Champs::CarteChamp do
|
||||
let(:champ) { Champs::CarteChamp.new(value: value) }
|
||||
let(:value) { '' }
|
||||
let(:geo_json) { GeojsonService.to_json_polygon_for_selection_utilisateur(coordinates) }
|
||||
let(:coordinates) { [[{ "lat" => 48.87442541960633, "lng" => 2.3859214782714844 }, { "lat" => 48.87273183590832, "lng" => 2.3850631713867183 }, { "lat" => 48.87081237174292, "lng" => 2.3809432983398438 }, { "lat" => 48.8712640169951, "lng" => 2.377510070800781 }, { "lat" => 48.87510283703279, "lng" => 2.3778533935546875 }, { "lat" => 48.87544154230615, "lng" => 2.382831573486328 }, { "lat" => 48.87442541960633, "lng" => 2.3859214782714844 }]] }
|
||||
let(:parsed_geo_json) { JSON.parse(geo_json) }
|
||||
let(:geo_json_as_string) { GeojsonService.to_json_polygon_for_selection_utilisateur(coordinates) }
|
||||
let(:geo_json) { JSON.parse(geo_json_as_string) }
|
||||
|
||||
describe '#to_render_data' do
|
||||
subject { champ.to_render_data }
|
||||
|
@ -47,15 +47,15 @@ describe Champs::CarteChamp do
|
|||
context 'when the value is coordinates' do
|
||||
let(:value) { coordinates.to_json }
|
||||
|
||||
let(:selection) { parsed_geo_json }
|
||||
let(:selection) { geo_json }
|
||||
|
||||
it { is_expected.to eq(render_data) }
|
||||
end
|
||||
|
||||
context 'when the value is geojson' do
|
||||
let(:value) { geo_json }
|
||||
let(:value) { geo_json.to_json }
|
||||
|
||||
let(:selection) { parsed_geo_json }
|
||||
let(:selection) { geo_json }
|
||||
|
||||
it { is_expected.to eq(render_data) }
|
||||
end
|
||||
|
@ -89,7 +89,7 @@ describe Champs::CarteChamp do
|
|||
end
|
||||
|
||||
context 'when the value is geojson' do
|
||||
let(:value) { geo_json }
|
||||
let(:value) { geo_json.to_json }
|
||||
|
||||
it { is_expected.to eq(1) }
|
||||
end
|
||||
|
|
56
spec/policies/champ_policy_spec.rb
Normal file
56
spec/policies/champ_policy_spec.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe ChampPolicy do
|
||||
let(:user) { create(:user) }
|
||||
let(:dossier) { create(:dossier, user: user) }
|
||||
let!(:champ) { create(:champ_text, dossier: dossier) }
|
||||
|
||||
let(:pundit_user) { user }
|
||||
subject { Pundit.policy_scope(pundit_user, Champ) }
|
||||
|
||||
context 'when the user has only user rights' do
|
||||
context 'cannot access champs for other dossiers' do
|
||||
let(:pundit_user) { create(:user) }
|
||||
|
||||
it { expect(subject.find_by(id: champ.id)).to eq(nil) }
|
||||
end
|
||||
|
||||
context 'can access champs for its own dossiers' do
|
||||
it {
|
||||
expect(subject.find(champ.id)).to eq(champ)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user has only gestionnaire rights' do
|
||||
context 'can access champs for dossiers it follows' do
|
||||
let(:dossier) { create(:dossier, :followed) }
|
||||
let(:pundit_user) { dossier.followers_gestionnaires.first }
|
||||
|
||||
it { expect(subject.find(champ.id)).to eq(champ) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user has user and gestionnaire rights' do
|
||||
let(:pundit_user) { dossier.followers_gestionnaires.first }
|
||||
let(:dossier) { create(:dossier, :followed) }
|
||||
|
||||
let(:user) { create(:user, email: pundit_user.email) }
|
||||
let(:dossier2) { create(:dossier, user: user) }
|
||||
let!(:champ_2) { create(:champ_text, dossier: dossier2) }
|
||||
|
||||
context 'can access champs for dossiers it follows' do
|
||||
it do
|
||||
expect(pundit_user.user).to eq(user)
|
||||
expect(subject.find(champ.id)).to eq(champ)
|
||||
end
|
||||
end
|
||||
|
||||
context 'can access champs for its own dossiers' do
|
||||
it do
|
||||
expect(pundit_user.user).to eq(user)
|
||||
expect(subject.find(champ_2.id)).to eq(champ_2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
23
spec/policies/type_de_champ_policy_spec.rb
Normal file
23
spec/policies/type_de_champ_policy_spec.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe TypeDeChampPolicy do
|
||||
let(:procedure) { create(:procedure) }
|
||||
let!(:type_de_champ) { create(:type_de_champ_text, procedure: procedure) }
|
||||
|
||||
let(:pundit_user) { create(:user) }
|
||||
subject { Pundit.policy_scope(pundit_user, TypeDeChamp) }
|
||||
|
||||
context 'when the user has only user rights' do
|
||||
it 'can not access' do
|
||||
expect(subject.find_by(id: type_de_champ.id)).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user has administrateur rights' do
|
||||
let(:pundit_user) { procedure.administrateurs.first }
|
||||
|
||||
it 'can access' do
|
||||
expect(subject.find(type_de_champ.id)).to eq(type_de_champ)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -26,9 +26,9 @@ describe ChampSerializer do
|
|||
context 'when type champ is carte' do
|
||||
let(:champ) { create(:champ_carte, value: value, geo_areas: [geo_area].compact) }
|
||||
let(:value) { nil }
|
||||
let(:geo_area) { create(:geo_area, geometry: parsed_geo_json) }
|
||||
let(:parsed_geo_json) { JSON.parse(geo_json) }
|
||||
let(:geo_json) { GeojsonService.to_json_polygon_for_selection_utilisateur(coordinates) }
|
||||
let(:geo_area) { create(:geo_area, geometry: geo_json) }
|
||||
let(:geo_json_as_string) { GeojsonService.to_json_polygon_for_selection_utilisateur(coordinates) }
|
||||
let(:geo_json) { JSON.parse(geo_json_as_string) }
|
||||
let(:coordinates) { [[{ "lat" => 48.87442541960633, "lng" => 2.3859214782714844 }, { "lat" => 48.87273183590832, "lng" => 2.3850631713867183 }, { "lat" => 48.87081237174292, "lng" => 2.3809432983398438 }, { "lat" => 48.8712640169951, "lng" => 2.377510070800781 }, { "lat" => 48.87510283703279, "lng" => 2.3778533935546875 }, { "lat" => 48.87544154230615, "lng" => 2.382831573486328 }, { "lat" => 48.87442541960633, "lng" => 2.3859214782714844 }]] }
|
||||
|
||||
let(:serialized_champ) {
|
||||
|
@ -49,10 +49,14 @@ describe ChampSerializer do
|
|||
let(:serialized_id) { -1 }
|
||||
let(:serialized_description) { "" }
|
||||
let(:serialized_order_place) { -1 }
|
||||
let(:serialized_value) { parsed_geo_json }
|
||||
let(:serialized_value) { geo_json }
|
||||
|
||||
context 'and geo_area is selection_utilisateur' do
|
||||
let(:geo_area) { create(:geo_area, :selection_utilisateur, geometry: geo_json) }
|
||||
|
||||
context 'value is empty' do
|
||||
let(:geo_area) { nil }
|
||||
|
||||
context 'when value is nil' do
|
||||
let(:value) { nil }
|
||||
|
||||
|
@ -85,7 +89,7 @@ describe ChampSerializer do
|
|||
end
|
||||
|
||||
context 'when value is geojson' do
|
||||
let(:value) { geo_json }
|
||||
let(:value) { geo_json.to_json }
|
||||
|
||||
it { expect(subject).to eq(serialized_champ) }
|
||||
end
|
||||
|
@ -105,7 +109,7 @@ describe ChampSerializer do
|
|||
let(:serialized_order_place) { champ.order_place }
|
||||
let(:serialized_libelle) { champ.libelle }
|
||||
let(:serialized_type_champ) { champ.type_champ }
|
||||
let(:serialized_value) { geo_json }
|
||||
let(:serialized_value) { nil }
|
||||
|
||||
context 'when value is coordinates' do
|
||||
let(:value) { coordinates.to_json }
|
||||
|
@ -114,7 +118,7 @@ describe ChampSerializer do
|
|||
end
|
||||
|
||||
context 'when value is geojson' do
|
||||
let(:value) { geo_json }
|
||||
let(:value) { geo_json.to_json }
|
||||
|
||||
it { expect(subject).to eq(serialized_champ) }
|
||||
end
|
||||
|
@ -147,7 +151,7 @@ describe ChampSerializer do
|
|||
it {
|
||||
expect(subject[:geo_areas].first).to include(
|
||||
source: GeoArea.sources.fetch(:cadastre),
|
||||
geometry: parsed_geo_json,
|
||||
geometry: geo_json,
|
||||
numero: '42',
|
||||
feuille: 'A11'
|
||||
)
|
||||
|
@ -165,13 +169,13 @@ describe ChampSerializer do
|
|||
end
|
||||
|
||||
context 'and geo_area is quartier_prioritaire' do
|
||||
let(:geo_area) { create(:geo_area, :quartier_prioritaire, geometry: parsed_geo_json) }
|
||||
let(:geo_area) { create(:geo_area, :quartier_prioritaire, geometry: geo_json) }
|
||||
|
||||
context 'new_api' do
|
||||
it {
|
||||
expect(subject[:geo_areas].first).to include(
|
||||
source: GeoArea.sources.fetch(:quartier_prioritaire),
|
||||
geometry: parsed_geo_json,
|
||||
geometry: geo_json,
|
||||
nom: 'XYZ',
|
||||
commune: 'Paris'
|
||||
)
|
||||
|
|
|
@ -93,6 +93,9 @@ describe ProcedureExportV2Service do
|
|||
context 'with etablissement' do
|
||||
let!(:dossier) { create(:dossier, :en_instruction, :with_all_champs, :with_entreprise, procedure: procedure) }
|
||||
|
||||
let(:dossier_etablissement) { etablissements_sheet.data[1] }
|
||||
let(:champ_etablissement) { etablissements_sheet.data[0] }
|
||||
|
||||
it 'should have headers' do
|
||||
expect(etablissements_sheet.headers).to eq([
|
||||
"Dossier ID",
|
||||
|
@ -132,6 +135,8 @@ describe ProcedureExportV2Service do
|
|||
|
||||
it 'should have data' do
|
||||
expect(etablissements_sheet.data.size).to eq(2)
|
||||
expect(dossier_etablissement[1]).to eq("Dossier")
|
||||
expect(champ_etablissement[1]).to eq("siret")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -155,8 +160,13 @@ describe ProcedureExportV2Service do
|
|||
end
|
||||
|
||||
context 'with repetitions' do
|
||||
let!(:dossier) { create(:dossier, :en_instruction, :with_all_champs, :for_individual, procedure: procedure) }
|
||||
let(:champ_repetition) { dossier.champs.find { |champ| champ.type_champ == 'repetition' } }
|
||||
let!(:dossiers) do
|
||||
[
|
||||
create(:dossier, :en_instruction, :with_all_champs, :for_individual, procedure: procedure),
|
||||
create(:dossier, :en_instruction, :with_all_champs, :for_individual, procedure: procedure)
|
||||
]
|
||||
end
|
||||
let(:champ_repetition) { dossiers.first.champs.find { |champ| champ.type_champ == 'repetition' } }
|
||||
|
||||
it 'should have sheets' do
|
||||
expect(subject.sheets.map(&:name)).to eq(['Dossiers', 'Etablissements', 'Avis', champ_repetition.libelle])
|
||||
|
@ -172,7 +182,7 @@ describe ProcedureExportV2Service do
|
|||
end
|
||||
|
||||
it 'should have data' do
|
||||
expect(repetition_sheet.data.size).to eq(2)
|
||||
expect(repetition_sheet.data.size).to eq(4)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -147,14 +147,6 @@ RSpec.configure do |config|
|
|||
Typhoeus::Expectation.clear
|
||||
|
||||
ActionMailer::Base.deliveries.clear
|
||||
|
||||
if Flipflop.remote_storage?
|
||||
VCR.use_cassette("ovh_storage_init") do
|
||||
CarrierWave.configure do |config|
|
||||
config.fog_credentials = { provider: 'OpenStack' }
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
RSpec::Matchers.define :have_same_attributes_as do |expected, options|
|
||||
|
|
Loading…
Reference in a new issue