Merge branch 'main' into feature/prefill_repetible
This commit is contained in:
parent
4b3d403d7e
commit
4876d583b6
33 changed files with 613 additions and 76 deletions
|
@ -12,7 +12,7 @@ module Types
|
||||||
|
|
||||||
global_id_field :id
|
global_id_field :id
|
||||||
field :source, GeoAreaSource, null: false
|
field :source, GeoAreaSource, null: false
|
||||||
field :geometry, Types::GeoJSON, null: false, method: :safe_geometry
|
field :geometry, Types::GeoJSON, null: false
|
||||||
field :description, String, null: true
|
field :description, String, null: true
|
||||||
|
|
||||||
definition_methods do
|
definition_methods do
|
||||||
|
|
11
app/jobs/migrations/normalize_geo_area_job.rb
Normal file
11
app/jobs/migrations/normalize_geo_area_job.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
class Migrations::NormalizeGeoAreaJob < ApplicationJob
|
||||||
|
def perform(ids)
|
||||||
|
GeoArea.where(id: ids).find_each do |geo_area|
|
||||||
|
geojson = RGeo::GeoJSON.decode(geo_area.geometry.to_json, geo_factory: RGeo::Geographic.simple_mercator_factory)
|
||||||
|
geometry = RGeo::GeoJSON.encode(geojson)
|
||||||
|
geo_area.update_column(:geometry, geometry)
|
||||||
|
rescue RGeo::Error::InvalidGeometry
|
||||||
|
geo_area.destroy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -64,21 +64,14 @@ class Champs::CarteChamp < Champ
|
||||||
end
|
end
|
||||||
|
|
||||||
def bounding_box
|
def bounding_box
|
||||||
factory = RGeo::Geographic.simple_mercator_factory
|
|
||||||
bounding_box = RGeo::Cartesian::BoundingBox.new(factory)
|
|
||||||
|
|
||||||
if geo_areas.present?
|
if geo_areas.present?
|
||||||
geo_areas.filter_map(&:rgeo_geometry).each do |geometry|
|
GeojsonService.bbox(type: 'FeatureCollection', features: geo_areas.map(&:to_feature))
|
||||||
bounding_box.add(geometry)
|
|
||||||
end
|
|
||||||
elsif dossier.present?
|
elsif dossier.present?
|
||||||
point = dossier.geo_position
|
point = dossier.geo_position
|
||||||
bounding_box.add(factory.point(point[:lon], point[:lat]))
|
GeojsonService.bbox(type: 'Feature', geometry: { type: 'Point', coordinates: [point[:lon], point[:lat]] })
|
||||||
else
|
else
|
||||||
bounding_box.add(factory.point(DEFAULT_LON, DEFAULT_LAT))
|
GeojsonService.bbox(type: 'Feature', geometry: { type: 'Point', coordinates: [DEFAULT_LON, DEFAULT_LAT] })
|
||||||
end
|
end
|
||||||
|
|
||||||
[bounding_box.max_point, bounding_box.min_point].compact.flat_map(&:coordinates)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_feature_collection
|
def to_feature_collection
|
||||||
|
|
|
@ -24,6 +24,10 @@ class Champs::EpciChamp < Champs::TextChamp
|
||||||
store_accessor :value_json, :code_departement
|
store_accessor :value_json, :code_departement
|
||||||
before_validation :on_departement_change
|
before_validation :on_departement_change
|
||||||
|
|
||||||
|
validate :code_departement_in_departement_codes, unless: -> { code_departement.nil? }
|
||||||
|
validate :external_id_in_departement_epci_codes, unless: -> { code_departement.nil? || external_id.nil? }
|
||||||
|
validate :value_in_departement_epci_names, unless: -> { code_departement.nil? || external_id.nil? || value.nil? }
|
||||||
|
|
||||||
def for_export
|
def for_export
|
||||||
[value, code, "#{code_departement} – #{departement_name}"]
|
[value, code, "#{code_departement} – #{departement_name}"]
|
||||||
end
|
end
|
||||||
|
@ -74,4 +78,22 @@ class Champs::EpciChamp < Champs::TextChamp
|
||||||
self.value = nil
|
self.value = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def code_departement_in_departement_codes
|
||||||
|
return if code_departement.in?(APIGeoService.departements.pluck(:code))
|
||||||
|
|
||||||
|
errors.add(:code_departement, :not_in_departement_codes)
|
||||||
|
end
|
||||||
|
|
||||||
|
def external_id_in_departement_epci_codes
|
||||||
|
return if external_id.in?(APIGeoService.epcis(code_departement).pluck(:code))
|
||||||
|
|
||||||
|
errors.add(:external_id, :not_in_departement_epci_codes)
|
||||||
|
end
|
||||||
|
|
||||||
|
def value_in_departement_epci_names
|
||||||
|
return if value.in?(APIGeoService.epcis(code_departement).pluck(:name))
|
||||||
|
|
||||||
|
errors.add(:value, :not_in_departement_epci_names)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1312,14 +1312,7 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def bounding_box
|
def bounding_box
|
||||||
factory = RGeo::Geographic.simple_mercator_factory
|
GeojsonService.bbox(type: 'FeatureCollection', features: geo_areas.map(&:to_feature))
|
||||||
bounding_box = RGeo::Cartesian::BoundingBox.new(factory)
|
|
||||||
|
|
||||||
geo_areas.filter_map(&:rgeo_geometry).each do |geometry|
|
|
||||||
bounding_box.add(geometry)
|
|
||||||
end
|
|
||||||
|
|
||||||
[bounding_box.max_point, bounding_box.min_point].compact.flat_map(&:coordinates)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def log_dossier_operation(author, operation, subject = nil)
|
def log_dossier_operation(author, operation, subject = nil)
|
||||||
|
|
|
@ -52,11 +52,12 @@ class GeoArea < ApplicationRecord
|
||||||
scope :cadastres, -> { where(source: sources.fetch(:cadastre)) }
|
scope :cadastres, -> { where(source: sources.fetch(:cadastre)) }
|
||||||
|
|
||||||
validates :geometry, geo_json: true, allow_blank: false
|
validates :geometry, geo_json: true, allow_blank: false
|
||||||
|
before_validation :normalize_geometry
|
||||||
|
|
||||||
def to_feature
|
def to_feature
|
||||||
{
|
{
|
||||||
type: 'Feature',
|
type: 'Feature',
|
||||||
geometry: safe_geometry,
|
geometry: geometry.deep_symbolize_keys,
|
||||||
properties: cadastre_properties.merge(
|
properties: cadastre_properties.merge(
|
||||||
source: source,
|
source: source,
|
||||||
area: area,
|
area: area,
|
||||||
|
@ -96,16 +97,6 @@ class GeoArea < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def safe_geometry
|
|
||||||
RGeo::GeoJSON.encode(rgeo_geometry)
|
|
||||||
end
|
|
||||||
|
|
||||||
def rgeo_geometry
|
|
||||||
RGeo::GeoJSON.decode(geometry.to_json, geo_factory: RGeo::Geographic.simple_mercator_factory)
|
|
||||||
rescue RGeo::Error::InvalidGeometry
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def area
|
def area
|
||||||
if polygon?
|
if polygon?
|
||||||
GeojsonService.area(geometry.deep_symbolize_keys).round(1)
|
GeojsonService.area(geometry.deep_symbolize_keys).round(1)
|
||||||
|
@ -120,7 +111,7 @@ class GeoArea < ApplicationRecord
|
||||||
|
|
||||||
def location
|
def location
|
||||||
if point?
|
if point?
|
||||||
Geo::Coord.new(*rgeo_geometry.coordinates.reverse).to_s
|
Geo::Coord.new(*geometry['coordinates'].reverse).to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -238,4 +229,21 @@ class GeoArea < ApplicationRecord
|
||||||
properties['id']
|
properties['id']
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def normalize_geometry
|
||||||
|
if geometry.present?
|
||||||
|
normalized_geometry = rgeo_geometry
|
||||||
|
if normalized_geometry.present?
|
||||||
|
self.geometry = RGeo::GeoJSON.encode(normalized_geometry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def rgeo_geometry
|
||||||
|
RGeo::GeoJSON.decode(geometry.to_json, geo_factory: RGeo::Geographic.simple_mercator_factory)
|
||||||
|
rescue RGeo::Error::InvalidGeometry
|
||||||
|
nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -45,17 +45,33 @@ class PrefillDescription < SimpleDelegator
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def prefilled_champs_for_link
|
|
||||||
prefilled_champs.map { |type_de_champ| ["champ_#{type_de_champ.to_typed_id}", type_de_champ.example_value] }.to_h
|
|
||||||
end
|
|
||||||
|
|
||||||
def prefilled_champs_for_query
|
|
||||||
prefilled_champs.map do |type_de_champ|
|
|
||||||
"\"champ_#{type_de_champ.to_typed_id}\": #{type_de_champ.formatted_example_value}"
|
|
||||||
end.join(', ')
|
|
||||||
end
|
|
||||||
|
|
||||||
def active_fillable_public_types_de_champ
|
def active_fillable_public_types_de_champ
|
||||||
active_revision.types_de_champ_public.fillable
|
active_revision.types_de_champ_public.fillable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def prefilled_champs_for_link
|
||||||
|
prefilled_champs_as_params.map(&:to_a).to_h
|
||||||
|
end
|
||||||
|
|
||||||
|
def prefilled_champs_for_query
|
||||||
|
prefilled_champs_as_params.map(&:to_s).join(', ')
|
||||||
|
end
|
||||||
|
|
||||||
|
def prefilled_champs_as_params
|
||||||
|
prefilled_champs.map { |type_de_champ| Param.new(type_de_champ.to_typed_id, type_de_champ.example_value) }
|
||||||
|
end
|
||||||
|
|
||||||
|
Param = Struct.new(:key, :value) do
|
||||||
|
def to_a
|
||||||
|
["champ_#{key}", value]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
if value.is_a?(Array)
|
||||||
|
"\"champ_#{key}\": #{value}"
|
||||||
|
else
|
||||||
|
"\"champ_#{key}\": \"#{value}\""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,7 +41,8 @@ class PrefillParams
|
||||||
TypeDeChamp.type_champs.fetch(:checkbox),
|
TypeDeChamp.type_champs.fetch(:checkbox),
|
||||||
TypeDeChamp.type_champs.fetch(:pays),
|
TypeDeChamp.type_champs.fetch(:pays),
|
||||||
TypeDeChamp.type_champs.fetch(:regions),
|
TypeDeChamp.type_champs.fetch(:regions),
|
||||||
TypeDeChamp.type_champs.fetch(:departements)
|
TypeDeChamp.type_champs.fetch(:departements),
|
||||||
|
TypeDeChamp.type_champs.fetch(:epci)
|
||||||
]
|
]
|
||||||
|
|
||||||
attr_reader :champ, :value
|
attr_reader :champ, :value
|
||||||
|
@ -55,12 +56,6 @@ class PrefillParams
|
||||||
champ.prefillable? && valid?
|
champ.prefillable? && valid?
|
||||||
end
|
end
|
||||||
|
|
||||||
def champ_attributes
|
|
||||||
TypesDeChamp::PrefillTypeDeChamp
|
|
||||||
.build(champ.type_de_champ)
|
|
||||||
.to_assignable_attributes(champ, value)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def valid?
|
def valid?
|
||||||
|
@ -69,5 +64,11 @@ class PrefillParams
|
||||||
champ.assign_attributes(champ_attributes)
|
champ.assign_attributes(champ_attributes)
|
||||||
champ.valid?(:prefill)
|
champ.valid?(:prefill)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def champ_attributes
|
||||||
|
TypesDeChamp::PrefillTypeDeChamp
|
||||||
|
.build(champ.type_de_champ)
|
||||||
|
.to_assignable_attributes(value)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -271,7 +271,8 @@ class TypeDeChamp < ApplicationRecord
|
||||||
TypeDeChamp.type_champs.fetch(:drop_down_list),
|
TypeDeChamp.type_champs.fetch(:drop_down_list),
|
||||||
TypeDeChamp.type_champs.fetch(:regions),
|
TypeDeChamp.type_champs.fetch(:regions),
|
||||||
TypeDeChamp.type_champs.fetch(:repetition),
|
TypeDeChamp.type_champs.fetch(:repetition),
|
||||||
TypeDeChamp.type_champs.fetch(:departements)
|
TypeDeChamp.type_champs.fetch(:departements),
|
||||||
|
TypeDeChamp.type_champs.fetch(:epci)
|
||||||
])
|
])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
25
app/models/types_de_champ/prefill_epci_type_de_champ.rb
Normal file
25
app/models/types_de_champ/prefill_epci_type_de_champ.rb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
class TypesDeChamp::PrefillEpciTypeDeChamp < TypesDeChamp::PrefillTypeDeChamp
|
||||||
|
def possible_values
|
||||||
|
departements.map do |departement|
|
||||||
|
"#{departement[:code]} (#{departement[:name]}) : https://geo.api.gouv.fr/epcis?codeDepartement=#{departement[:code]}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def example_value
|
||||||
|
departement_code = departements.pick(:code)
|
||||||
|
epci_code = APIGeoService.epcis(departement_code).pick(:code)
|
||||||
|
[departement_code, epci_code]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_assignable_attributes(champ, value)
|
||||||
|
return { id: champ.id, code_departement: nil, value: nil } if value.blank? || !value.is_a?(Array)
|
||||||
|
return { id: champ.id, code_departement: value.first, value: nil } if value.one?
|
||||||
|
{ id: champ.id, code_departement: value.first, value: value.second }
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def departements
|
||||||
|
@departements ||= APIGeoService.departements.sort_by { |departement| departement[:code] }
|
||||||
|
end
|
||||||
|
end
|
|
@ -13,8 +13,6 @@ class TypesDeChamp::PrefillRepetitionTypeDeChamp < TypesDeChamp::PrefillTypeDeCh
|
||||||
[row_values_format, row_values_format].map { |row| row.to_s.gsub("=>", ":") }
|
[row_values_format, row_values_format].map { |row| row.to_s.gsub("=>", ":") }
|
||||||
end
|
end
|
||||||
|
|
||||||
alias_method :formatted_example_value, :example_value
|
|
||||||
|
|
||||||
def to_assignable_attributes(champ, value)
|
def to_assignable_attributes(champ, value)
|
||||||
return [] unless value.is_a?(Array)
|
return [] unless value.is_a?(Array)
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ class TypesDeChamp::PrefillTypeDeChamp < SimpleDelegator
|
||||||
TypesDeChamp::PrefillRepetitionTypeDeChamp.new(type_de_champ)
|
TypesDeChamp::PrefillRepetitionTypeDeChamp.new(type_de_champ)
|
||||||
when TypeDeChamp.type_champs.fetch(:departements)
|
when TypeDeChamp.type_champs.fetch(:departements)
|
||||||
TypesDeChamp::PrefillDepartementTypeDeChamp.new(type_de_champ)
|
TypesDeChamp::PrefillDepartementTypeDeChamp.new(type_de_champ)
|
||||||
|
when TypeDeChamp.type_champs.fetch(:epci)
|
||||||
|
TypesDeChamp::PrefillEpciTypeDeChamp.new(type_de_champ)
|
||||||
else
|
else
|
||||||
new(type_de_champ)
|
new(type_de_champ)
|
||||||
end
|
end
|
||||||
|
@ -46,10 +48,6 @@ class TypesDeChamp::PrefillTypeDeChamp < SimpleDelegator
|
||||||
I18n.t("views.prefill_descriptions.edit.examples.#{type_champ}")
|
I18n.t("views.prefill_descriptions.edit.examples.#{type_champ}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def formatted_example_value
|
|
||||||
"\"#{example_value}\"" if example_value.present?
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_assignable_attributes(champ, value)
|
def to_assignable_attributes(champ, value)
|
||||||
{ id: champ.id, value: value }
|
{ id: champ.id, value: value }
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,7 +13,7 @@ class ChampSerializer < ActiveModel::Serializer
|
||||||
def value
|
def value
|
||||||
case object
|
case object
|
||||||
when GeoArea
|
when GeoArea
|
||||||
object.safe_geometry
|
object.geometry
|
||||||
else
|
else
|
||||||
object.for_api
|
object.for_api
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,7 +12,7 @@ class GeoAreaSerializer < ActiveModel::Serializer
|
||||||
attribute :code_arr, if: :include_cadastre?
|
attribute :code_arr, if: :include_cadastre?
|
||||||
|
|
||||||
def geometry
|
def geometry
|
||||||
object.safe_geometry
|
object.geometry
|
||||||
end
|
end
|
||||||
|
|
||||||
def include_cadastre?
|
def include_cadastre?
|
||||||
|
|
|
@ -45,6 +45,66 @@ class GeojsonService
|
||||||
radians * EQUATORIAL_RADIUS
|
radians * EQUATORIAL_RADIUS
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.bbox(geojson)
|
||||||
|
result = [-Float::INFINITY, -Float::INFINITY, Float::INFINITY, Float::INFINITY]
|
||||||
|
|
||||||
|
self.coord_each(geojson) do |coord|
|
||||||
|
if result[3] > coord[1]
|
||||||
|
result[3] = coord[1]
|
||||||
|
end
|
||||||
|
if result[2] > coord[0]
|
||||||
|
result[2] = coord[0]
|
||||||
|
end
|
||||||
|
if result[1] < coord[1]
|
||||||
|
result[1] = coord[1]
|
||||||
|
end
|
||||||
|
if result[0] < coord[0]
|
||||||
|
result[0] = coord[0]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.coord_each(geojson)
|
||||||
|
geometries = if geojson.fetch(:type) == "FeatureCollection"
|
||||||
|
geojson.fetch(:features).map { _1.fetch(:geometry) }
|
||||||
|
else
|
||||||
|
[geojson.fetch(:geometry)]
|
||||||
|
end.compact
|
||||||
|
|
||||||
|
geometries.each do |geometry|
|
||||||
|
geometries = if geometry.fetch(:type) == "GeometryCollection"
|
||||||
|
geometry.fetch(:geometries)
|
||||||
|
else
|
||||||
|
[geometry]
|
||||||
|
end.compact
|
||||||
|
|
||||||
|
geometries.each do |geometry|
|
||||||
|
case geometry.fetch(:type)
|
||||||
|
when "Point"
|
||||||
|
yield geometry.fetch(:coordinates).map(&:to_f)
|
||||||
|
when "LineString", "MultiPoint"
|
||||||
|
geometry.fetch(:coordinates).each { yield _1.map(&:to_f) }
|
||||||
|
when "Polygon", "MultiLineString"
|
||||||
|
geometry.fetch(:coordinates).each do |shapes|
|
||||||
|
shapes.each { yield _1.map(&:to_f) }
|
||||||
|
end
|
||||||
|
when "MultiPolygon"
|
||||||
|
geometry.fetch(:coordinates).each do |polygons|
|
||||||
|
polygons.each do |shapes|
|
||||||
|
shapes.each { yield _1.map(&:to_f) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
when "GeometryCollection"
|
||||||
|
geometry.fetch(:geometries).each do |geometry|
|
||||||
|
coord_each(geometry) { yield _1 }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def self.calculate_area(geom)
|
def self.calculate_area(geom)
|
||||||
total = 0
|
total = 0
|
||||||
case geom[:type]
|
case geom[:type]
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
- if show_detail
|
- if show_detail
|
||||||
%tr.procedure{ id: "procedure_detail_#{procedure.id}" }
|
%tr.procedure{ id: "procedure_detail_#{procedure.id}" }
|
||||||
%td.fr-highlight--beige-gris-galet{ colspan: '6' }
|
%td.fr-highlight--beige-gris-galet{ colspan: '7' }
|
||||||
.fr-container
|
.fr-container
|
||||||
.fr-grid-row
|
.fr-grid-row
|
||||||
.fr-col-6
|
.fr-col-6
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
= f.search_field 'libelle', size: 30, class: 'fr-input'
|
= f.search_field 'libelle', size: 30, class: 'fr-input'
|
||||||
.actions
|
.actions
|
||||||
.link.fr-mx-1w= link_to 'Voir les administrateurs', administrateurs_admin_procedures_path(@filter.params), class: 'fr-btn fr-btn--secondary'
|
.link.fr-mx-1w= link_to 'Voir les administrateurs', administrateurs_admin_procedures_path(@filter.params), class: 'fr-btn fr-btn--secondary'
|
||||||
.link.fr-mx-1w= link_to 'Exporter les résultats', all_admin_procedures_path(@filter.params.merge(format: :xlsx)), class: 'fr-btn fr-btn--secondary'
|
.link.fr-mx-1w{ "data-turbo": "false" }= link_to 'Exporter les résultats', all_admin_procedures_path(@filter.params.merge(format: :xlsx)), class: 'fr-btn fr-btn--secondary'
|
||||||
.fr-table.fr-table--bordered
|
.fr-table.fr-table--bordered
|
||||||
%table#all-demarches
|
%table#all-demarches
|
||||||
%caption
|
%caption
|
||||||
|
|
|
@ -128,14 +128,15 @@ en:
|
||||||
iban_html: An Iban number
|
iban_html: An Iban number
|
||||||
yes_no_html: '"true" for Yes, "false" pour No'
|
yes_no_html: '"true" for Yes, "false" pour No'
|
||||||
checkbox_html: '"true" to check, "false" to uncheck'
|
checkbox_html: '"true" to check, "false" to uncheck'
|
||||||
pays_html: An <a href="https://en.wikipedia.org/wiki/ISO_3166-2" target="_blank">ISO 3166-2 country code</a>
|
pays_html: An <a href="https://en.wikipedia.org/wiki/ISO_3166-2" target="_blank" rel="noopener noreferrer">ISO 3166-2 country code</a>
|
||||||
departements_html: A <a href="https://fr.wikipedia.org/wiki/Num%C3%A9rotation_des_d%C3%A9partements_fran%C3%A7ais" target="_blank">department number</a>
|
departements_html: A <a href="https://fr.wikipedia.org/wiki/Num%C3%A9rotation_des_d%C3%A9partements_fran%C3%A7ais" target="_blank">department number</a>
|
||||||
regions_html: An <a href="https://fr.wikipedia.org/wiki/R%C3%A9gion_fran%C3%A7aise" target="_blank">INSEE region code</a>
|
|
||||||
drop_down_list_html: A choice among those selected when the procedure was created
|
drop_down_list_html: A choice among those selected when the procedure was created
|
||||||
date_html: ISO8601 date
|
date_html: ISO8601 date
|
||||||
datetime_html: ISO8601 datetime
|
datetime_html: ISO8601 datetime
|
||||||
drop_down_list_other_html: Any value
|
drop_down_list_other_html: Any value
|
||||||
repetition_html: A array of hashes with possible values for each field of the repetition.
|
repetition_html: A array of hashes with possible values for each field of the repetition.
|
||||||
|
regions_html: An <a href="https://fr.wikipedia.org/wiki/R%C3%A9gion_fran%C3%A7aise" target="_blank" rel="noopener noreferrer">INSEE region code</a>
|
||||||
|
epci_html: An array of the department code and the <a href="https://geo.api.gouv.fr/epcis" target="_blank" rel="noopener noreferrer">EPCI one</a>.
|
||||||
examples:
|
examples:
|
||||||
title: Example
|
title: Example
|
||||||
text: Short text
|
text: Short text
|
||||||
|
@ -484,6 +485,14 @@ en:
|
||||||
not_in_departement_names: "must be a valid department name"
|
not_in_departement_names: "must be a valid department name"
|
||||||
external_id:
|
external_id:
|
||||||
not_in_departement_codes: "must be a valid department code"
|
not_in_departement_codes: "must be a valid department code"
|
||||||
|
"champs/epci_champ":
|
||||||
|
attributes:
|
||||||
|
code_departement:
|
||||||
|
not_in_departement_codes: "must be a valid department code"
|
||||||
|
external_id:
|
||||||
|
not_in_departement_epci_codes: "must be a valid EPCI code of the matching department"
|
||||||
|
value:
|
||||||
|
not_in_departement_epci_names: "must be a valid EPCI name of the matching department"
|
||||||
errors:
|
errors:
|
||||||
format: "Field « %{attribute} » %{message}"
|
format: "Field « %{attribute} » %{message}"
|
||||||
messages:
|
messages:
|
||||||
|
|
|
@ -119,14 +119,15 @@ fr:
|
||||||
iban_html: Un numéro Iban
|
iban_html: Un numéro Iban
|
||||||
yes_no_html: '"true" pour Oui, "false" pour Non'
|
yes_no_html: '"true" pour Oui, "false" pour Non'
|
||||||
checkbox_html: '"true" pour coché, "false" pour décoché'
|
checkbox_html: '"true" pour coché, "false" pour décoché'
|
||||||
pays_html: Un <a href="https://en.wikipedia.org/wiki/ISO_3166-2" target="_blank">code pays ISO 3166-2</a>
|
pays_html: Un <a href="https://en.wikipedia.org/wiki/ISO_3166-2" target="_blank" rel="noopener noreferrer">code pays ISO 3166-2</a>
|
||||||
departements_html: Un <a href="https://fr.wikipedia.org/wiki/Num%C3%A9rotation_des_d%C3%A9partements_fran%C3%A7ais" target="_blank">numéro de département</a>
|
departements_html: Un <a href="https://fr.wikipedia.org/wiki/Num%C3%A9rotation_des_d%C3%A9partements_fran%C3%A7ais" target="_blank">numéro de département</a>
|
||||||
regions_html: Un <a href="https://fr.wikipedia.org/wiki/R%C3%A9gion_fran%C3%A7aise" target="_blank">code INSEE de région</a>
|
|
||||||
drop_down_list_html: Un choix parmi ceux sélectionnés à la création de la procédure
|
drop_down_list_html: Un choix parmi ceux sélectionnés à la création de la procédure
|
||||||
datetime_html: Datetime au format ISO8601
|
datetime_html: Datetime au format ISO8601
|
||||||
date_html: Date au format ISO8601
|
date_html: Date au format ISO8601
|
||||||
drop_down_list_other_html: Toute valeur
|
drop_down_list_other_html: Toute valeur
|
||||||
repetition_html: Un tableau de dictionnaires avec les valeurs possibles pour chaque champ de la répétition.
|
repetition_html: Un tableau de dictionnaires avec les valeurs possibles pour chaque champ de la répétition.
|
||||||
|
regions_html: Un <a href="https://fr.wikipedia.org/wiki/R%C3%A9gion_fran%C3%A7aise" target="_blank" rel="noopener noreferrer">code INSEE de région</a>
|
||||||
|
epci_html: Un tableau contenant le code de département et <a href="https://geo.api.gouv.fr/epcis" target="_blank" rel="noopener noreferrer">celui de l'EPCI</a>.
|
||||||
examples:
|
examples:
|
||||||
title: Exemple
|
title: Exemple
|
||||||
text: Texte court
|
text: Texte court
|
||||||
|
@ -479,6 +480,14 @@ fr:
|
||||||
not_in_departement_names: "doit être un nom de département valide"
|
not_in_departement_names: "doit être un nom de département valide"
|
||||||
external_id:
|
external_id:
|
||||||
not_in_departement_codes: "doit être un code de département valide"
|
not_in_departement_codes: "doit être un code de département valide"
|
||||||
|
"champs/epci_champ":
|
||||||
|
attributes:
|
||||||
|
code_departement:
|
||||||
|
not_in_departement_codes: "doit être un code de département valide"
|
||||||
|
external_id:
|
||||||
|
not_in_departement_epci_codes: "doit être un code d'EPCI du département correspondant"
|
||||||
|
value:
|
||||||
|
not_in_departement_epci_names: "doit être un nom d'EPCI du département correspondant"
|
||||||
errors:
|
errors:
|
||||||
format: "Le champ « %{attribute} » %{message}"
|
format: "Le champ « %{attribute} » %{message}"
|
||||||
messages:
|
messages:
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
namespace :after_party do
|
||||||
|
desc 'Deployment task: normalize_geometries'
|
||||||
|
task normalize_geometries: :environment do
|
||||||
|
puts "Running deploy task 'normalize_geometries'"
|
||||||
|
|
||||||
|
progress = ProgressReport.new(GeoArea.count)
|
||||||
|
GeoArea.in_batches(of: 100) do |geo_areas|
|
||||||
|
ids = geo_areas.ids
|
||||||
|
Migrations::NormalizeGeoAreaJob.perform_later(ids)
|
||||||
|
progress.inc(ids.size)
|
||||||
|
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: AfterParty::TaskRecorder.new(__FILE__).timestamp
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,7 +1,7 @@
|
||||||
describe Champs::CarteChamp do
|
describe Champs::CarteChamp do
|
||||||
let(:champ) { Champs::CarteChamp.new(geo_areas: geo_areas, type_de_champ: create(:type_de_champ_carte)) }
|
let(:champ) { Champs::CarteChamp.new(geo_areas: geo_areas, type_de_champ: create(:type_de_champ_carte)) }
|
||||||
let(:value) { '' }
|
let(:value) { '' }
|
||||||
let(:coordinates) { [[2.3859214782714844, 48.87442541960633], [2.3850631713867183, 48.87273183590832], [2.3809432983398438, 48.87081237174292], [2.3859214782714844, 48.87442541960633]] }
|
let(:coordinates) { [[[2.3859214782714844, 48.87442541960633], [2.3850631713867183, 48.87273183590832], [2.3809432983398438, 48.87081237174292], [2.3859214782714844, 48.87442541960633]]] }
|
||||||
let(:geo_json) do
|
let(:geo_json) do
|
||||||
{
|
{
|
||||||
"type" => 'Polygon',
|
"type" => 'Polygon',
|
||||||
|
|
|
@ -6,9 +6,156 @@ describe Champs::EpciChamp, type: :model do
|
||||||
Rails.cache.clear
|
Rails.cache.clear
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:champ) { described_class.new }
|
describe 'validations' do
|
||||||
|
describe 'code_departement', vcr: { cassette_name: 'api_geo_departements' } do
|
||||||
|
subject { build(:champ_epci, code_departement: code_departement) }
|
||||||
|
|
||||||
|
context 'when nil' do
|
||||||
|
let(:code_departement) { nil }
|
||||||
|
|
||||||
|
it { is_expected.to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when empty' do
|
||||||
|
let(:code_departement) { '' }
|
||||||
|
|
||||||
|
it { is_expected.not_to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when included in the departement codes' do
|
||||||
|
let(:code_departement) { "01" }
|
||||||
|
|
||||||
|
it { is_expected.to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when not included in the departement codes' do
|
||||||
|
let(:code_departement) { "totoro" }
|
||||||
|
|
||||||
|
it { is_expected.not_to be_valid }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'external_id' do
|
||||||
|
let(:champ) { build(:champ_epci, code_departement: code_departement, external_id: nil) }
|
||||||
|
|
||||||
|
subject { champ }
|
||||||
|
|
||||||
|
before do
|
||||||
|
VCR.insert_cassette('api_geo_departements')
|
||||||
|
VCR.insert_cassette('api_geo_epcis')
|
||||||
|
|
||||||
|
champ.save!
|
||||||
|
champ.update_columns(external_id: external_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
VCR.eject_cassette('api_geo_departements')
|
||||||
|
VCR.eject_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when code_departement is nil' do
|
||||||
|
let(:code_departement) { nil }
|
||||||
|
let(:external_id) { nil }
|
||||||
|
|
||||||
|
it { is_expected.to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when code_departement is not nil and valid' do
|
||||||
|
let(:code_departement) { "01" }
|
||||||
|
|
||||||
|
context 'when external_id is nil' do
|
||||||
|
let(:external_id) { nil }
|
||||||
|
|
||||||
|
it { is_expected.to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when external_id is empty' do
|
||||||
|
let(:external_id) { '' }
|
||||||
|
|
||||||
|
it { is_expected.not_to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when external_id is included in the epci codes of the departement' do
|
||||||
|
let(:external_id) { '200042935' }
|
||||||
|
|
||||||
|
it { is_expected.to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when external_id is not included in the epci codes of the departement' do
|
||||||
|
let(:external_id) { 'totoro' }
|
||||||
|
|
||||||
|
it { is_expected.not_to be_valid }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'value' do
|
||||||
|
let(:champ) { build(:champ_epci, code_departement: code_departement, external_id: nil, value: nil) }
|
||||||
|
|
||||||
|
subject { champ }
|
||||||
|
|
||||||
|
before do
|
||||||
|
VCR.insert_cassette('api_geo_departements')
|
||||||
|
VCR.insert_cassette('api_geo_epcis')
|
||||||
|
|
||||||
|
champ.save!
|
||||||
|
champ.update_columns(external_id: external_id, value: value)
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
VCR.eject_cassette('api_geo_departements')
|
||||||
|
VCR.eject_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when code_departement is nil' do
|
||||||
|
let(:code_departement) { nil }
|
||||||
|
let(:external_id) { nil }
|
||||||
|
let(:value) { nil }
|
||||||
|
|
||||||
|
it { is_expected.to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when external_id is nil' do
|
||||||
|
let(:code_departement) { '01' }
|
||||||
|
let(:external_id) { nil }
|
||||||
|
let(:value) { nil }
|
||||||
|
|
||||||
|
it { is_expected.to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when code_departement and external_id are not nil and valid' do
|
||||||
|
let(:code_departement) { '01' }
|
||||||
|
let(:external_id) { '200042935' }
|
||||||
|
|
||||||
|
context 'when value is nil' do
|
||||||
|
let(:value) { nil }
|
||||||
|
|
||||||
|
it { is_expected.to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when value is empty' do
|
||||||
|
let(:value) { '' }
|
||||||
|
|
||||||
|
it { is_expected.not_to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when value is in departement epci names' do
|
||||||
|
let(:value) { 'CA Haut - Bugey Agglomération' }
|
||||||
|
|
||||||
|
it { is_expected.to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when value is not in departement epci names' do
|
||||||
|
let(:value) { 'totoro' }
|
||||||
|
|
||||||
|
it { is_expected.not_to be_valid }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'value', vcr: { cassette_name: 'api_geo_epcis' } do
|
describe 'value', vcr: { cassette_name: 'api_geo_epcis' } do
|
||||||
|
let(:champ) { described_class.new }
|
||||||
it 'with departement and code' do
|
it 'with departement and code' do
|
||||||
champ.code_departement = '01'
|
champ.code_departement = '01'
|
||||||
champ.value = '200042935'
|
champ.value = '200042935'
|
||||||
|
|
|
@ -1516,8 +1516,8 @@ describe Dossier do
|
||||||
{
|
{
|
||||||
type: 'Feature',
|
type: 'Feature',
|
||||||
geometry: {
|
geometry: {
|
||||||
'coordinates' => [[[2.428439855575562, 46.538476837725796], [2.4284291267395024, 46.53842148758162], [2.4282521009445195, 46.53841410755813], [2.42824137210846, 46.53847314771794], [2.428284287452698, 46.53847314771794], [2.428364753723145, 46.538487907747864], [2.4284291267395024, 46.538491597754714], [2.428439855575562, 46.538476837725796]]],
|
coordinates: [[[2.428439855575562, 46.538476837725796], [2.4284291267395024, 46.53842148758162], [2.4282521009445195, 46.53841410755813], [2.42824137210846, 46.53847314771794], [2.428284287452698, 46.53847314771794], [2.428364753723145, 46.538487907747864], [2.4284291267395024, 46.538491597754714], [2.428439855575562, 46.538476837725796]]],
|
||||||
'type' => 'Polygon'
|
type: 'Polygon'
|
||||||
},
|
},
|
||||||
properties: {
|
properties: {
|
||||||
area: 103.6,
|
area: 103.6,
|
||||||
|
|
|
@ -23,7 +23,7 @@ RSpec.describe GeoArea, type: :model do
|
||||||
it { expect(geo_area.location).to eq("46°32'19\"N 2°25'42\"E") }
|
it { expect(geo_area.location).to eq("46°32'19\"N 2°25'42\"E") }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#rgeo_geometry' do
|
describe '#geometry' do
|
||||||
let(:geo_area) { build(:geo_area, :polygon, champ: nil) }
|
let(:geo_area) { build(:geo_area, :polygon, champ: nil) }
|
||||||
let(:polygon) do
|
let(:polygon) do
|
||||||
{
|
{
|
||||||
|
@ -47,9 +47,9 @@ RSpec.describe GeoArea, type: :model do
|
||||||
|
|
||||||
context 'polygon_with_extra_coordinate' do
|
context 'polygon_with_extra_coordinate' do
|
||||||
let(:geo_area) { build(:geo_area, :polygon_with_extra_coordinate, champ: nil) }
|
let(:geo_area) { build(:geo_area, :polygon_with_extra_coordinate, champ: nil) }
|
||||||
|
before { geo_area.valid? }
|
||||||
|
|
||||||
it { expect(geo_area.geometry).not_to eq(polygon) }
|
it { expect(geo_area.geometry).to eq(polygon) }
|
||||||
it { expect(geo_area.safe_geometry).to eq(polygon) }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,34 @@ RSpec.describe PrefillDescription, type: :model do
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the type de champ can have multiple values' do
|
||||||
|
let(:type_de_champ) { TypesDeChamp::PrefillTypeDeChamp.build(create(:type_de_champ_epci, procedure: procedure)) }
|
||||||
|
|
||||||
|
let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(Rails).to receive(:cache).and_return(memory_store)
|
||||||
|
Rails.cache.clear
|
||||||
|
|
||||||
|
VCR.insert_cassette('api_geo_departements')
|
||||||
|
VCR.insert_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
VCR.eject_cassette('api_geo_departements')
|
||||||
|
VCR.eject_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'builds the URL with array parameter' do
|
||||||
|
expect(prefill_description.prefill_link).to eq(
|
||||||
|
commencer_url(
|
||||||
|
path: procedure.path,
|
||||||
|
"champ_#{type_de_champ.to_typed_id}": type_de_champ.example_value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#prefill_query', vcr: { cassette_name: 'api_geo_regions' } do
|
describe '#prefill_query', vcr: { cassette_name: 'api_geo_regions' } do
|
||||||
|
@ -121,10 +149,43 @@ RSpec.describe PrefillDescription, type: :model do
|
||||||
--data '{"champ_#{type_de_champ.to_typed_id}": "#{I18n.t("views.prefill_descriptions.edit.examples.#{type_de_champ.type_champ}")}", "champ_#{type_de_champ_repetition.to_typed_id}": #{TypesDeChamp::PrefillTypeDeChamp.build(type_de_champ_repetition).example_value}}'
|
--data '{"champ_#{type_de_champ.to_typed_id}": "#{I18n.t("views.prefill_descriptions.edit.examples.#{type_de_champ.type_champ}")}", "champ_#{type_de_champ_repetition.to_typed_id}": #{TypesDeChamp::PrefillTypeDeChamp.build(type_de_champ_repetition).example_value}}'
|
||||||
TEXT
|
TEXT
|
||||||
end
|
end
|
||||||
|
|
||||||
before { prefill_description.update(selected_type_de_champ_ids: [type_de_champ.id, type_de_champ_repetition.id]) }
|
before { prefill_description.update(selected_type_de_champ_ids: [type_de_champ.id, type_de_champ_repetition.id]) }
|
||||||
|
|
||||||
|
let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(Rails).to receive(:cache).and_return(memory_store)
|
||||||
|
Rails.cache.clear
|
||||||
|
|
||||||
|
VCR.insert_cassette('api_geo_departements')
|
||||||
|
VCR.insert_cassette('api_geo_epcis')
|
||||||
|
|
||||||
|
prefill_description.update(selected_type_de_champ_ids: [type_de_champ.id])
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
VCR.eject_cassette('api_geo_departements')
|
||||||
|
VCR.eject_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
it "builds the query to create a new prefilled dossier" do
|
it "builds the query to create a new prefilled dossier" do
|
||||||
expect(prefill_description.prefill_query).to eq(expected_query)
|
expect(prefill_description.prefill_query).to eq(expected_query)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the type de champ can have multiple values' do
|
||||||
|
let(:type_de_champ) { TypesDeChamp::PrefillTypeDeChamp.build(create(:type_de_champ_epci, procedure: procedure)) }
|
||||||
|
let(:expected_query) do
|
||||||
|
<<~TEXT
|
||||||
|
curl --request POST '#{api_public_v1_dossiers_url(procedure)}' \\
|
||||||
|
--header 'Content-Type: application/json' \\
|
||||||
|
--data '{"champ_#{type_de_champ.to_typed_id}": #{type_de_champ.example_value}}'
|
||||||
|
TEXT
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'builds the query with array parameter' do
|
||||||
|
expect(prefill_description.prefill_query).to eq(expected_query)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,6 +12,16 @@ RSpec.describe PrefillParams do
|
||||||
before do
|
before do
|
||||||
allow(Rails).to receive(:cache).and_return(memory_store)
|
allow(Rails).to receive(:cache).and_return(memory_store)
|
||||||
Rails.cache.clear
|
Rails.cache.clear
|
||||||
|
|
||||||
|
VCR.insert_cassette('api_geo_regions')
|
||||||
|
VCR.insert_cassette('api_geo_departements')
|
||||||
|
VCR.insert_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
VCR.eject_cassette('api_geo_regions')
|
||||||
|
VCR.eject_cassette('api_geo_departements')
|
||||||
|
VCR.eject_cassette('api_geo_epcis')
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the stable ids match the TypeDeChamp of the corresponding procedure" do
|
context "when the stable ids match the TypeDeChamp of the corresponding procedure" do
|
||||||
|
@ -76,7 +86,7 @@ RSpec.describe PrefillParams do
|
||||||
|
|
||||||
let(:params) { { "champ_#{type_de_champ.to_typed_id}" => value } }
|
let(:params) { { "champ_#{type_de_champ.to_typed_id}" => value } }
|
||||||
|
|
||||||
it "builds an array of hash(id, value) matching the given params" do
|
it "builds an array of hash matching the given params" do
|
||||||
expect(prefill_params_array).to match([{ id: champ.id }.merge(attributes(champ, value))])
|
expect(prefill_params_array).to match([{ id: champ.id }.merge(attributes(champ, value))])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -90,7 +100,7 @@ RSpec.describe PrefillParams do
|
||||||
|
|
||||||
let(:params) { { "champ_#{type_de_champ.to_typed_id}" => value } }
|
let(:params) { { "champ_#{type_de_champ.to_typed_id}" => value } }
|
||||||
|
|
||||||
it "builds an array of hash(id, value) matching the given params" do
|
it "builds an array of hash matching the given params" do
|
||||||
expect(prefill_params_array).to match([{ id: champ.id }.merge(attributes(champ, value))])
|
expect(prefill_params_array).to match([{ id: champ.id }.merge(attributes(champ, value))])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -127,6 +137,7 @@ RSpec.describe PrefillParams do
|
||||||
it_behaves_like "a champ public value that is authorized", :drop_down_list, "value"
|
it_behaves_like "a champ public value that is authorized", :drop_down_list, "value"
|
||||||
it_behaves_like "a champ public value that is authorized", :regions, "03"
|
it_behaves_like "a champ public value that is authorized", :regions, "03"
|
||||||
it_behaves_like "a champ public value that is authorized", :departements, "03"
|
it_behaves_like "a champ public value that is authorized", :departements, "03"
|
||||||
|
it_behaves_like "a champ public value that is authorized", :epci, ['01', '200042935']
|
||||||
|
|
||||||
context "when the public type de champ is authorized (repetition)" do
|
context "when the public type de champ is authorized (repetition)" do
|
||||||
let(:types_de_champ_public) { [{ type: :repetition, children: [{ type: :text }] }] }
|
let(:types_de_champ_public) { [{ type: :repetition, children: [{ type: :text }] }] }
|
||||||
|
@ -159,7 +170,8 @@ RSpec.describe PrefillParams do
|
||||||
it_behaves_like "a champ private value that is authorized", :checkbox, "false"
|
it_behaves_like "a champ private value that is authorized", :checkbox, "false"
|
||||||
it_behaves_like "a champ private value that is authorized", :drop_down_list, "value"
|
it_behaves_like "a champ private value that is authorized", :drop_down_list, "value"
|
||||||
it_behaves_like "a champ private value that is authorized", :regions, "93"
|
it_behaves_like "a champ private value that is authorized", :regions, "93"
|
||||||
it_behaves_like "a champ public value that is authorized", :departements, "03"
|
it_behaves_like "a champ private value that is authorized", :departements, "03"
|
||||||
|
it_behaves_like "a champ private value that is authorized", :epci, ['01', '200042935']
|
||||||
|
|
||||||
context "when the private type de champ is authorized (repetition)" do
|
context "when the private type de champ is authorized (repetition)" do
|
||||||
let(:types_de_champ_private) { [{ type: :repetition, children: [{ type: :text }] }] }
|
let(:types_de_champ_private) { [{ type: :repetition, children: [{ type: :text }] }] }
|
||||||
|
|
|
@ -252,6 +252,7 @@ describe TypeDeChamp do
|
||||||
it_behaves_like "a prefillable type de champ", :type_de_champ_regions
|
it_behaves_like "a prefillable type de champ", :type_de_champ_regions
|
||||||
it_behaves_like "a prefillable type de champ", :type_de_champ_repetition
|
it_behaves_like "a prefillable type de champ", :type_de_champ_repetition
|
||||||
it_behaves_like "a prefillable type de champ", :type_de_champ_departements
|
it_behaves_like "a prefillable type de champ", :type_de_champ_departements
|
||||||
|
it_behaves_like "a prefillable type de champ", :type_de_champ_epci
|
||||||
|
|
||||||
it_behaves_like "a non-prefillable type de champ", :type_de_champ_number
|
it_behaves_like "a non-prefillable type de champ", :type_de_champ_number
|
||||||
it_behaves_like "a non-prefillable type de champ", :type_de_champ_communes
|
it_behaves_like "a non-prefillable type de champ", :type_de_champ_communes
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe TypesDeChamp::PrefillEpciTypeDeChamp do
|
||||||
|
let(:type_de_champ) { build(:type_de_champ_epci) }
|
||||||
|
let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(Rails).to receive(:cache).and_return(memory_store)
|
||||||
|
Rails.cache.clear
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'ancestors' do
|
||||||
|
subject { described_class.new(type_de_champ) }
|
||||||
|
|
||||||
|
it { is_expected.to be_kind_of(TypesDeChamp::PrefillEpciTypeDeChamp) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#possible_values' do
|
||||||
|
let(:expected_values) do
|
||||||
|
departements.map { |departement| "#{departement[:code]} (#{departement[:name]}) : https://geo.api.gouv.fr/epcis?codeDepartement=#{departement[:code]}" }
|
||||||
|
end
|
||||||
|
subject(:possible_values) { described_class.new(type_de_champ).possible_values }
|
||||||
|
|
||||||
|
before do
|
||||||
|
VCR.insert_cassette('api_geo_departements')
|
||||||
|
VCR.insert_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
VCR.eject_cassette('api_geo_departements')
|
||||||
|
VCR.eject_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(possible_values).to match(expected_values) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#example_value' do
|
||||||
|
let(:departement_code) { departements.pick(:code) }
|
||||||
|
let(:epci_code) { APIGeoService.epcis(departement_code).pick(:code) }
|
||||||
|
subject(:example_value) { described_class.new(type_de_champ).example_value }
|
||||||
|
|
||||||
|
before do
|
||||||
|
VCR.insert_cassette('api_geo_departements')
|
||||||
|
VCR.insert_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
VCR.eject_cassette('api_geo_departements')
|
||||||
|
VCR.eject_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to eq([departement_code, epci_code]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#to_assignable_attributes' do
|
||||||
|
subject(:to_assignable_attributes) { described_class.build(type_de_champ).to_assignable_attributes(champ, value) }
|
||||||
|
|
||||||
|
context 'when the value is nil' do
|
||||||
|
let(:value) { nil }
|
||||||
|
it { is_expected.to match({ code_departement: nil, value: nil }) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the value is empty' do
|
||||||
|
let(:value) { '' }
|
||||||
|
it { is_expected.to match({ code_departement: nil, value: nil }) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the value is a string' do
|
||||||
|
let(:value) { 'hello' }
|
||||||
|
it { is_expected.to match({ code_departement: nil, value: nil }) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the value is an array of one element' do
|
||||||
|
let(:value) { ['01'] }
|
||||||
|
it { is_expected.to match({ code_departement: '01', value: nil }) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the value is an array of two elements' do
|
||||||
|
let(:value) { ['01', '200042935'] }
|
||||||
|
it { is_expected.to match({ code_departement: '01', value: '200042935' }) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the value is an array of three or more elements' do
|
||||||
|
let(:value) { ['01', '200042935', 'hello'] }
|
||||||
|
it { is_expected.to match({ code_departement: '01', value: '200042935' }) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def departements
|
||||||
|
APIGeoService.departements.sort_by { |departement| departement[:code] }
|
||||||
|
end
|
||||||
|
end
|
|
@ -37,6 +37,12 @@ RSpec.describe TypesDeChamp::PrefillTypeDeChamp, type: :model do
|
||||||
it { expect(built).to be_kind_of(TypesDeChamp::PrefillDepartementTypeDeChamp) }
|
it { expect(built).to be_kind_of(TypesDeChamp::PrefillDepartementTypeDeChamp) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the type de champ is a epci' do
|
||||||
|
let(:type_de_champ) { build(:type_de_champ_epci) }
|
||||||
|
|
||||||
|
it { expect(built).to be_kind_of(TypesDeChamp::PrefillEpciTypeDeChamp) }
|
||||||
|
end
|
||||||
|
|
||||||
context 'when any other type de champ' do
|
context 'when any other type de champ' do
|
||||||
let(:type_de_champ) { build(:type_de_champ_date) }
|
let(:type_de_champ) { build(:type_de_champ_date) }
|
||||||
|
|
||||||
|
|
|
@ -22,5 +22,6 @@ shared_examples "the user has got a prefilled dossier, owned by themselves" do
|
||||||
expect(page).to have_field(text_repetition_libelle, with: text_repetition_value)
|
expect(page).to have_field(text_repetition_libelle, with: text_repetition_value)
|
||||||
expect(page).to have_field(integer_repetition_libelle, with: integer_repetition_value)
|
expect(page).to have_field(integer_repetition_libelle, with: integer_repetition_value)
|
||||||
expect(page).to have_field(type_de_champ_datetime.libelle, with: datetime_value)
|
expect(page).to have_field(type_de_champ_datetime.libelle, with: datetime_value)
|
||||||
|
expect(page).to have_field(type_de_champ_epci.libelle, with: epci_value.last)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,7 +14,22 @@ describe 'As an administrateur I wanna clone a procedure', js: true do
|
||||||
published_at: Time.zone.now)
|
published_at: Time.zone.now)
|
||||||
login_as administrateur.user, scope: :user
|
login_as administrateur.user, scope: :user
|
||||||
end
|
end
|
||||||
|
context 'Visit all admin procedures' do
|
||||||
|
let(:download_dir) { Rails.root.join('tmp/capybara') }
|
||||||
|
let(:download_file_pattern) { download_dir.join('*.xlsx') }
|
||||||
|
|
||||||
|
scenario do
|
||||||
|
Dir[download_file_pattern].map { File.delete(_1) }
|
||||||
|
visit all_admin_procedures_path
|
||||||
|
|
||||||
|
click_on "Exporter les résultats"
|
||||||
|
Timeout.timeout(Capybara.default_max_wait_time,
|
||||||
|
Timeout::Error,
|
||||||
|
"File download timeout! can't download procedure/all.xlsx") do
|
||||||
|
sleep 0.1 until !Dir[download_file_pattern].empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
context 'Cloning a procedure owned by the current admin' do
|
context 'Cloning a procedure owned by the current admin' do
|
||||||
scenario do
|
scenario do
|
||||||
visit admin_procedures_path
|
visit admin_procedures_path
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
describe 'Prefilling a dossier (with a GET request):' do
|
describe 'Prefilling a dossier (with a GET request):' do
|
||||||
|
let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) }
|
||||||
|
|
||||||
let(:password) { 'my-s3cure-p4ssword' }
|
let(:password) { 'my-s3cure-p4ssword' }
|
||||||
|
|
||||||
let(:procedure) { create(:procedure, :published, opendata: true) }
|
let(:procedure) { create(:procedure, :published, opendata: true) }
|
||||||
|
@ -16,6 +18,21 @@ describe 'Prefilling a dossier (with a GET request):' do
|
||||||
let(:integer_repetition_libelle) { sub_type_de_champs_repetition.second.libelle }
|
let(:integer_repetition_libelle) { sub_type_de_champs_repetition.second.libelle }
|
||||||
let(:text_repetition_value) { "First repetition text" }
|
let(:text_repetition_value) { "First repetition text" }
|
||||||
let(:integer_repetition_value) { "42" }
|
let(:integer_repetition_value) { "42" }
|
||||||
|
let(:type_de_champ_epci) { create(:type_de_champ_epci, procedure: procedure) }
|
||||||
|
let(:epci_value) { ['01', '200029999'] }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(Rails).to receive(:cache).and_return(memory_store)
|
||||||
|
Rails.cache.clear
|
||||||
|
|
||||||
|
VCR.insert_cassette('api_geo_departements')
|
||||||
|
VCR.insert_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
VCR.eject_cassette('api_geo_departements')
|
||||||
|
VCR.eject_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
context 'when authenticated' do
|
context 'when authenticated' do
|
||||||
it_behaves_like "the user has got a prefilled dossier, owned by themselves" do
|
it_behaves_like "the user has got a prefilled dossier, owned by themselves" do
|
||||||
|
@ -35,7 +52,8 @@ describe 'Prefilling a dossier (with a GET request):' do
|
||||||
\"#{sub_type_de_champs_repetition.second.to_typed_id}\": \"#{integer_repetition_value}\"
|
\"#{sub_type_de_champs_repetition.second.to_typed_id}\": \"#{integer_repetition_value}\"
|
||||||
}"
|
}"
|
||||||
],
|
],
|
||||||
"champ_#{type_de_champ_datetime.to_typed_id}" => datetime_value
|
"champ_#{type_de_champ_datetime.to_typed_id}" => datetime_value,
|
||||||
|
"champ_#{type_de_champ_epci.to_typed_id}" => epci_value
|
||||||
)
|
)
|
||||||
|
|
||||||
click_on "Poursuivre mon dossier prérempli"
|
click_on "Poursuivre mon dossier prérempli"
|
||||||
|
@ -55,7 +73,8 @@ describe 'Prefilling a dossier (with a GET request):' do
|
||||||
\"#{sub_type_de_champs_repetition.second.to_typed_id}\": \"#{integer_repetition_value}\"
|
\"#{sub_type_de_champs_repetition.second.to_typed_id}\": \"#{integer_repetition_value}\"
|
||||||
}"
|
}"
|
||||||
],
|
],
|
||||||
"champ_#{type_de_champ_datetime.to_typed_id}" => datetime_value
|
"champ_#{type_de_champ_datetime.to_typed_id}" => datetime_value,
|
||||||
|
"champ_#{type_de_champ_epci.to_typed_id}" => epci_value
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
describe 'Prefilling a dossier (with a POST request):' do
|
describe 'Prefilling a dossier (with a POST request):' do
|
||||||
|
let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) }
|
||||||
|
|
||||||
let(:password) { 'my-s3cure-p4ssword' }
|
let(:password) { 'my-s3cure-p4ssword' }
|
||||||
|
|
||||||
let(:procedure) { create(:procedure, :published) }
|
let(:procedure) { create(:procedure, :published) }
|
||||||
|
@ -16,6 +18,21 @@ describe 'Prefilling a dossier (with a POST request):' do
|
||||||
let(:integer_repetition_libelle) { sub_type_de_champs_repetition.second.libelle }
|
let(:integer_repetition_libelle) { sub_type_de_champs_repetition.second.libelle }
|
||||||
let(:text_repetition_value) { "First repetition text" }
|
let(:text_repetition_value) { "First repetition text" }
|
||||||
let(:integer_repetition_value) { "42" }
|
let(:integer_repetition_value) { "42" }
|
||||||
|
let(:type_de_champ_epci) { create(:type_de_champ_epci, procedure: procedure) }
|
||||||
|
let(:epci_value) { ['01', '200029999'] }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(Rails).to receive(:cache).and_return(memory_store)
|
||||||
|
Rails.cache.clear
|
||||||
|
|
||||||
|
VCR.insert_cassette('api_geo_departements')
|
||||||
|
VCR.insert_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
VCR.eject_cassette('api_geo_departements')
|
||||||
|
VCR.eject_cassette('api_geo_epcis')
|
||||||
|
end
|
||||||
|
|
||||||
scenario "the user get the URL of a prefilled orphan brouillon dossier" do
|
scenario "the user get the URL of a prefilled orphan brouillon dossier" do
|
||||||
dossier_url = create_and_prefill_dossier_with_post_request
|
dossier_url = create_and_prefill_dossier_with_post_request
|
||||||
|
@ -110,7 +127,8 @@ describe 'Prefilling a dossier (with a POST request):' do
|
||||||
\"#{sub_type_de_champs_repetition.second.to_typed_id}\": \"#{integer_repetition_value}\"
|
\"#{sub_type_de_champs_repetition.second.to_typed_id}\": \"#{integer_repetition_value}\"
|
||||||
}"
|
}"
|
||||||
],
|
],
|
||||||
"champ_#{type_de_champ_datetime.to_typed_id}" => datetime_value
|
"champ_#{type_de_champ_datetime.to_typed_id}" => datetime_value,
|
||||||
|
"champ_#{type_de_champ_epci.to_typed_id}" => epci_value
|
||||||
}.to_json
|
}.to_json
|
||||||
JSON.parse(session.response.body)["dossier_url"].gsub("http://www.example.com", "")
|
JSON.parse(session.response.body)["dossier_url"].gsub("http://www.example.com", "")
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue