Merge pull request #2898 from betagouv/dev

2018-10-23-02
This commit is contained in:
Paul Chavard 2018-10-23 18:54:28 +02:00 committed by GitHub
commit 2b65beea01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 495 additions and 102 deletions

View file

@ -46,6 +46,14 @@ class Champs::CarteController < ApplicationController
qp qp
end end
end end
if @champ.parcelles_agricoles?
parcelles_agricoles = ModuleApiCartoService.generate_rpg(geo_json)
geo_areas += parcelles_agricoles.map do |parcelle_agricole|
parcelle_agricole[:source] = GeoArea.sources.fetch(:parcelle_agricole)
parcelle_agricole
end
end
end end
@champ.geo_areas = geo_areas.map do |geo_area| @champ.geo_areas = geo_areas.map do |geo_area|

View file

@ -208,7 +208,15 @@ module NewGestionnaire
end end
def procedure_presentation def procedure_presentation
@procedure_presentation ||= current_gestionnaire.procedure_presentation_for_procedure_id(params[:procedure_id]) @procedure_presentation ||= get_procedure_presentation
end
def get_procedure_presentation
procedure_presentation, errors = current_gestionnaire.procedure_presentation_and_errors_for_procedure_id(params[:procedure_id])
if errors.present?
flash[:alert] = "Votre affichage a dû être réinitialisé en raison du problème suivant : " + errors.full_messages.join(', ')
end
procedure_presentation
end end
def displayed_fields_values def displayed_fields_values

View file

@ -10,7 +10,8 @@ module ChampHelper
position: champ.position, position: champ.position,
selection: champ.value.present? ? JSON.parse(champ.value) : [], selection: champ.value.present? ? JSON.parse(champ.value) : [],
quartiersPrioritaires: champ.quartiers_prioritaires? ? champ.quartiers_prioritaires : [], quartiersPrioritaires: champ.quartiers_prioritaires? ? champ.quartiers_prioritaires : [],
cadastres: champ.cadastres? ? champ.cadastres : [] cadastres: champ.cadastres? ? champ.cadastres : [],
parcellesAgricoles: champ.parcelles_agricoles? ? champ.parcelles_agricoles : []
}.to_json) }.to_json)
# rubocop:enable Rails/OutputSafety # rubocop:enable Rails/OutputSafety
end end

View file

@ -6,6 +6,7 @@ import {
geocodeAddress, geocodeAddress,
drawCadastre, drawCadastre,
drawQuartiersPrioritaires, drawQuartiersPrioritaires,
drawParcellesAgricoles,
drawUserSelection, drawUserSelection,
addFreeDrawEvents addFreeDrawEvents
} from '../../shared/carte'; } from '../../shared/carte';
@ -30,6 +31,7 @@ function diplayMap(element, data, initial = false) {
// draw external polygons // draw external polygons
drawCadastre(map, data, editable); drawCadastre(map, data, editable);
drawQuartiersPrioritaires(map, data, editable); drawQuartiersPrioritaires(map, data, editable);
drawParcellesAgricoles(map, data, editable);
// draw user polygon // draw user polygon
if (initial) { if (initial) {

View file

@ -57,6 +57,19 @@ export function drawQuartiersPrioritaires(
); );
} }
export function drawParcellesAgricoles(
map,
{ parcellesAgricoles },
editable = false
) {
drawLayer(
map,
parcellesAgricoles,
editable ? RPG_POLYGON_STYLE : noEditStyle(RPG_POLYGON_STYLE),
'parcellesAgricoles'
);
}
export function drawUserSelection(map, { selection }, editable = false) { export function drawUserSelection(map, { selection }, editable = false) {
let hasSelection = selection && selection.length > 0; let hasSelection = selection && selection.length > 0;
@ -170,6 +183,10 @@ const QP_POLYGON_STYLE = Object.assign({}, POLYGON_STYLE, {
fillColor: '#31708f' fillColor: '#31708f'
}); });
const RPG_POLYGON_STYLE = Object.assign({}, POLYGON_STYLE, {
fillColor: '#31708f'
});
delegate('click', '.carte.edit', event => { delegate('click', '.carte.edit', event => {
let element = event.target; let element = event.target;
let isPath = element.matches('.leaflet-container g path'); let isPath = element.matches('.leaflet-container g path');

View file

@ -1,23 +1,49 @@
class ApiGeo::API class ApiGeo::API
TIMEOUT = 15
def self.regions def self.regions
url = [API_GEO_URL, "regions"].join("/") url = [API_GEO_URL, "regions"].join("/")
call(url) call(url, { fields: :nom })
end end
def self.departements def self.departements
url = [API_GEO_URL, "departements"].join("/") url = [API_GEO_URL, "departements"].join("/")
call(url) call(url, { fields: :nom })
end end
def self.pays def self.pays
File.open('app/lib/api_geo/pays.json').read parse(File.open('app/lib/api_geo/pays.json').read)
end
def self.search_rpg(geojson)
url = [API_GEO_SANDBOX_URL, "rpg", "parcelles", "search"].join("/")
call(url, geojson, :post)
end end
private private
def self.call(url) def self.parse(body)
RestClient.get(url, params: { fields: :nom }) JSON.parse(body, symbolize_names: true)
rescue RestClient::ServiceUnavailable end
nil
def self.call(url, body, method = :get)
response = Typhoeus::Request.new(
url,
method: method,
params: method == :get ? body : nil,
body: method == :post ? body : nil,
timeout: TIMEOUT,
accept_encoding: 'gzip',
headers: {
'Accept' => 'application/json',
'Accept-Encoding' => 'gzip, deflate'
}.merge(method == :post ? { 'Content-Type' => 'application/json' } : {})
).run
if response.success?
parse(response.body)
else
nil
end
end end
end end

View file

@ -0,0 +1,24 @@
class ApiGeo::RPGAdapter
def initialize(coordinates)
@coordinates = GeojsonService.to_json_polygon_for_rpg(coordinates)
end
def data_source
@data_source ||= ApiGeo::API.search_rpg(@coordinates)
end
def results
data_source[:features].map do |feature|
feature[:properties]
.stringify_keys
.transform_keys(&:underscore)
.symbolize_keys
.slice(
:culture,
:code_culture,
:surface,
:bio
).merge({ geometry: feature[:geometry] })
end
end
end

View file

@ -3,7 +3,26 @@ class AssignTo < ApplicationRecord
belongs_to :gestionnaire belongs_to :gestionnaire
has_one :procedure_presentation, dependent: :destroy has_one :procedure_presentation, dependent: :destroy
def procedure_presentation_or_default def procedure_presentation_or_default_and_errors
self.procedure_presentation || build_procedure_presentation errors = reset_procedure_presentation_if_invalid
[procedure_presentation || build_procedure_presentation, errors]
end
private
def reset_procedure_presentation_if_invalid
if procedure_presentation&.invalid?
# This is a last defense against invalid `ProcedurePresentation`s persistently
# hindering instructeurs. Whenever this gets triggered, it means that there is
# a bug somewhere else that we need to fix.
errors = procedure_presentation.errors
Raven.capture_message(
"Destroying invalid ProcedurePresentation",
extra: { procedure_presentation: procedure_presentation.as_json }
)
self.procedure_presentation = nil
errors
end
end end
end end

View file

@ -15,6 +15,12 @@ class Champs::CarteChamp < Champ
end end
end end
def parcelles_agricoles
geo_areas.select do |area|
area.source == GeoArea.sources.fetch(:parcelle_agricole)
end
end
def cadastres? def cadastres?
type_de_champ&.cadastres && type_de_champ.cadastres != '0' type_de_champ&.cadastres && type_de_champ.cadastres != '0'
end end
@ -23,6 +29,10 @@ class Champs::CarteChamp < Champ
type_de_champ&.quartiers_prioritaires && type_de_champ.quartiers_prioritaires != '0' type_de_champ&.quartiers_prioritaires && type_de_champ.quartiers_prioritaires != '0'
end end
def parcelles_agricoles?
type_de_champ&.parcelles_agricoles && type_de_champ.parcelles_agricoles != '0'
end
def position def position
if dossier.present? if dossier.present?
dossier.geo_position dossier.geo_position

View file

@ -1,5 +1,5 @@
class Champs::DepartementChamp < Champs::TextChamp class Champs::DepartementChamp < Champs::TextChamp
def self.departements def self.departements
JSON.parse(ApiGeo::API.departements).map { |liste| "#{liste['code']} - #{liste['nom']}" }.push('99 - Étranger') ApiGeo::API.departements.map { |liste| "#{liste[:code]} - #{liste[:nom]}" }.push('99 - Étranger')
end end
end end

View file

@ -1,5 +1,5 @@
class Champs::PaysChamp < Champs::TextChamp class Champs::PaysChamp < Champs::TextChamp
def self.pays def self.pays
JSON.parse(ApiGeo::API.pays).pluck("nom") ApiGeo::API.pays.pluck(:nom)
end end
end end

View file

@ -1,5 +1,5 @@
class Champs::RegionChamp < Champs::TextChamp class Champs::RegionChamp < Champs::TextChamp
def self.regions def self.regions
JSON.parse(ApiGeo::API.regions).sort_by { |e| e['nom'] }.pluck("nom") ApiGeo::API.regions.sort_by { |e| e[:nom] }.pluck(:nom)
end end
end end

View file

@ -13,14 +13,20 @@ class GeoArea < ApplicationRecord
:code_arr, :code_arr,
:code, :code,
:nom, :nom,
:commune :commune,
:culture,
:code_culture,
:surface,
:bio
] ]
enum source: { enum source: {
quartier_prioritaire: 'quartier_prioritaire', quartier_prioritaire: 'quartier_prioritaire',
cadastre: 'cadastre' cadastre: 'cadastre',
parcelle_agricole: 'parcelle_agricole'
} }
scope :quartiers_prioritaires, -> { where(source: sources.fetch(:quartier_prioritaire)) } scope :quartiers_prioritaires, -> { where(source: sources.fetch(:quartier_prioritaire)) }
scope :cadastres, -> { where(source: sources.fetch(:cadastre)) } scope :cadastres, -> { where(source: sources.fetch(:cadastre)) }
scope :parcelles_agricoles, -> { where(source: sources.fetch(:parcelle_agricole)) }
end end

View file

@ -81,8 +81,8 @@ class Gestionnaire < ApplicationRecord
end end
end end
def procedure_presentation_for_procedure_id(procedure_id) def procedure_presentation_and_errors_for_procedure_id(procedure_id)
assign_to.find_by(procedure_id: procedure_id).procedure_presentation_or_default assign_to.find_by(procedure_id: procedure_id).procedure_presentation_or_default_and_errors
end end
def notifications_for_dossier(dossier) def notifications_for_dossier(dossier)

View file

@ -31,7 +31,7 @@ class TypeDeChamp < ApplicationRecord
belongs_to :procedure belongs_to :procedure
store :options, accessors: [:cadastres, :quartiers_prioritaires] store :options, accessors: [:cadastres, :quartiers_prioritaires, :parcelles_agricoles]
after_initialize :set_dynamic_type after_initialize :set_dynamic_type

View file

@ -1,16 +1,34 @@
class GeoAreaSerializer < ActiveModel::Serializer class GeoAreaSerializer < ActiveModel::Serializer
attributes :geometry, attributes :geometry, :source
:source,
:surface_intersection, attribute :surface_intersection, if: :include_cadastre?
:surface_parcelle, attribute :surface_parcelle, if: :include_cadastre?
:numero, attribute :numero, if: :include_cadastre?
:feuille, attribute :feuille, if: :include_cadastre?
:section, attribute :section, if: :include_cadastre?
:code_dep, attribute :code_dep, if: :include_cadastre?
:nom_com, attribute :nom_com, if: :include_cadastre?
:code_com, attribute :code_com, if: :include_cadastre?
:code_arr, attribute :code_arr, if: :include_cadastre?
:code,
:nom, attribute :code, if: :include_quartier_prioritaire?
:commune attribute :nom, if: :include_quartier_prioritaire?
attribute :commune, if: :include_quartier_prioritaire?
attribute :culture, if: :include_parcelle_agricole?
attribute :code_culture, if: :include_parcelle_agricole?
attribute :surface, if: :include_parcelle_agricole?
attribute :bio, if: :include_parcelle_agricole?
def include_cadastre?
object.source == GeoArea.sources.fetch(:cadastre)
end
def include_quartier_prioritaire?
object.source == GeoArea.sources.fetch(:quartier_prioritaire)
end
def include_parcelle_agricole?
object.source == GeoArea.sources.fetch(:parcelle_agricole)
end
end end

View file

@ -25,4 +25,15 @@ class GeojsonService
polygon.to_json polygon.to_json
end end
def self.to_json_polygon_for_rpg(coordinates)
polygon = {
polygonIntersects: {
type: "Polygon",
coordinates: [coordinates]
}
}
polygon.to_json
end
end end

View file

@ -38,4 +38,12 @@ class ModuleApiCartoService
).results ).results
end end
end end
def self.generate_rpg(coordinates)
coordinates.flat_map do |coordinate|
ApiGeo::RPGAdapter.new(
coordinate.map { |element| [element['lng'], element['lat']] }
).results
end
end
end end

View file

@ -16,6 +16,7 @@ class TypesDeChampService
:piece_justificative_template, :piece_justificative_template,
:quartiers_prioritaires, :quartiers_prioritaires,
:cadastres, :cadastres,
:parcelles_agricoles,
drop_down_list_attributes: [:value, :id] drop_down_list_attributes: [:value, :id]
]) ])

View file

@ -47,6 +47,10 @@
%label %label
= ff.check_box :cadastres = ff.check_box :cadastres
Cadastre Cadastre
%br
%label
= ff.check_box :parcelles_agricoles
Parcelles Agricoles
- hide_mandatory = (ff.object.object.private? || type_champ == TypeDeChamp.type_champs.fetch(:explication)) - hide_mandatory = (ff.object.object.private? || type_champ == TypeDeChamp.type_champs.fetch(:explication))
.form-group.mandatory{ style: hide_mandatory ? 'visibility: hidden;' : nil } .form-group.mandatory{ style: hide_mandatory ? 'visibility: hidden;' : nil }

View file

@ -25,3 +25,17 @@
%ul %ul
- champ.cadastres.each do |pc| - champ.cadastres.each do |pc|
%li Parcelle n° #{pc.numero} - Feuille #{pc.code_arr} #{pc.section} #{pc.feuille} %li Parcelle n° #{pc.numero} - Feuille #{pc.code_arr} #{pc.section} #{pc.feuille}
- if champ.parcelles_agricoles?
.areas-title Parcelles agricoles (RPG)
.areas
- if error.present?
.error Merci de dessiner une surface plus petite afin de récupérer les parcelles agricoles.
- elsif champ.value.blank?
Aucune zone tracée
- elsif champ.parcelles_agricoles.blank?
= t('errors.messages.parcelles_agricoles_empty', count: champ.zones.size)
- else
%ul
- champ.parcelles_agricoles.each do |pa|
%li Culture : #{pa.culture} - Surface : #{pa.surface} ha

View file

@ -0,0 +1 @@
Typhoeus::Config.user_agent = "demarches-simplifiees.fr"

View file

@ -3,6 +3,7 @@ API_ADRESSE_URL = "https://api-adresse.data.gouv.fr"
API_CARTO_URL = "https://apicarto.sgmap.fr" API_CARTO_URL = "https://apicarto.sgmap.fr"
API_ENTREPRISE_URL = "https://entreprise.api.gouv.fr/v2" API_ENTREPRISE_URL = "https://entreprise.api.gouv.fr/v2"
API_GEO_URL = "https://geo.api.gouv.fr" API_GEO_URL = "https://geo.api.gouv.fr"
API_GEO_SANDBOX_URL = "https://sandbox.geo.api.gouv.fr"
HELPSCOUT_API_URL = "https://api.helpscout.net/v2" HELPSCOUT_API_URL = "https://api.helpscout.net/v2"
PIPEDRIVE_API_URL = "https://api.pipedrive.com/v1" PIPEDRIVE_API_URL = "https://api.pipedrive.com/v1"

View file

@ -183,6 +183,9 @@ fr:
quartiers_prioritaires_empty: quartiers_prioritaires_empty:
one: "Aucun quartier prioritaire sur la zone séléctionnée" one: "Aucun quartier prioritaire sur la zone séléctionnée"
other: "Aucun quartier prioritaire sur les zones séléctionnées" other: "Aucun quartier prioritaire sur les zones séléctionnées"
parcelles_agricoles_empty:
one: "Aucune parcelle agricole sur la zone séléctionnée"
other: "Aucune parcelle agricole sur les zones séléctionnées"
date: date:
abbr_day_names: abbr_day_names:

View file

@ -36,7 +36,7 @@ describe Champs::CarteController, type: :controller do
context 'when coordinates are empty' do context 'when coordinates are empty' do
let(:selection) { [] } let(:selection) { [] }
it { expect(response.body).to include("DS.drawMapData(\".carte-1\", {\"position\":{\"lon\":\"2.428462\",\"lat\":\"46.538192\",\"zoom\":\"13\"},\"selection\":[],\"quartiersPrioritaires\":[],\"cadastres\":[]});") } it { expect(response.body).to include("DS.drawMapData(\".carte-1\", {\"position\":{\"lon\":\"2.428462\",\"lat\":\"46.538192\",\"zoom\":\"13\"},\"selection\":[],\"quartiersPrioritaires\":[],\"cadastres\":[],\"parcellesAgricoles\":[]});") }
end end
context 'when coordinates are informed' do context 'when coordinates are informed' do

View file

@ -3,5 +3,11 @@ FactoryBot.define do
source { GeoArea.sources.fetch(:cadastre) } source { GeoArea.sources.fetch(:cadastre) }
numero { '42' } numero { '42' }
feuille { 'A11' } feuille { 'A11' }
trait :quartier_prioritaire do
source { GeoArea.sources.fetch(:quartier_prioritaire) }
nom { 'XYZ' }
commune { 'Paris' }
end
end end
end end

View file

@ -7,21 +7,23 @@ http_interactions:
encoding: US-ASCII encoding: US-ASCII
string: '' string: ''
headers: headers:
User-Agent:
- demarches-simplifiees.fr
Accept: Accept:
- "*/*" - application/json
Accept-Encoding: Accept-Encoding:
- gzip, deflate - gzip, deflate
User-Agent: Expect:
- rest-client/2.0.0 (darwin15.6.0 x86_64) ruby/2.3.1p112 - ''
response: response:
status: status:
code: 200 code: 200
message: OK message: OK
headers: headers:
Server: Server:
- nginx - nginx/1.10.3 (Ubuntu)
Date: Date:
- Fri, 16 Dec 2016 09:25:41 GMT - Tue, 23 Oct 2018 13:11:36 GMT
Content-Type: Content-Type:
- application/json; charset=utf-8 - application/json; charset=utf-8
Transfer-Encoding: Transfer-Encoding:
@ -30,13 +32,12 @@ http_interactions:
- keep-alive - keep-alive
Vary: Vary:
- Accept-Encoding - Accept-Encoding
- Accept-Encoding
X-Powered-By: X-Powered-By:
- Express - Express
Access-Control-Allow-Origin: Access-Control-Allow-Origin:
- "*" - "*"
Etag: Etag:
- W/"cc1-lXUcIlpPmDfvrGONl0WWsQ" - W/"cc1-jlb3C7xpXUEaq56Wojrp9rAkoH8"
Strict-Transport-Security: Strict-Transport-Security:
- max-age=15552000 - max-age=15552000
Content-Encoding: Content-Encoding:
@ -44,27 +45,7 @@ http_interactions:
body: body:
encoding: ASCII-8BIT encoding: ASCII-8BIT
string: !binary |- string: !binary |-
H4sIAAAAAAAAA22Wy27bMBBFfyXwJpsKqF96dOfYrZsibow4MFAUXTARGxOQ W3sibm9tIjoiQWluIiwiY29kZSI6IjAxIn0seyJub20iOiJBaXNuZSIsImNvZGUiOiIwMiJ9LHsibm9tIjoiQWxsaWVyIiwiY29kZSI6IjAzIn0seyJub20iOiJBbHBlcy1kZS1IYXV0ZS1Qcm92ZW5jZSIsImNvZGUiOiIwNCJ9LHsibm9tIjoiSGF1dGVzLUFscGVzIiwiY29kZSI6IjA1In0seyJub20iOiJBbHBlcy1NYXJpdGltZXMiLCJjb2RlIjoiMDYifSx7Im5vbSI6IkFyZMOoY2hlIiwiY29kZSI6IjA3In0seyJub20iOiJBcmRlbm5lcyIsImNvZGUiOiIwOCJ9LHsibm9tIjoiQXJpw6hnZSIsImNvZGUiOiIwOSJ9LHsibm9tIjoiQXViZSIsImNvZGUiOiIxMCJ9LHsibm9tIjoiQXVkZSIsImNvZGUiOiIxMSJ9LHsibm9tIjoiQXZleXJvbiIsImNvZGUiOiIxMiJ9LHsibm9tIjoiQm91Y2hlcy1kdS1SaMO0bmUiLCJjb2RlIjoiMTMifSx7Im5vbSI6IkNhbHZhZG9zIiwiY29kZSI6IjE0In0seyJub20iOiJDYW50YWwiLCJjb2RlIjoiMTUifSx7Im5vbSI6IkNoYXJlbnRlIiwiY29kZSI6IjE2In0seyJub20iOiJDaGFyZW50ZS1NYXJpdGltZSIsImNvZGUiOiIxNyJ9LHsibm9tIjoiQ2hlciIsImNvZGUiOiIxOCJ9LHsibm9tIjoiQ29ycsOoemUiLCJjb2RlIjoiMTkifSx7Im5vbSI6IkPDtHRlLWQnT3IiLCJjb2RlIjoiMjEifSx7Im5vbSI6IkPDtHRlcy1kJ0FybW9yIiwiY29kZSI6IjIyIn0seyJub20iOiJDcmV1c2UiLCJjb2RlIjoiMjMifSx7Im5vbSI6IkRvcmRvZ25lIiwiY29kZSI6IjI0In0seyJub20iOiJEb3VicyIsImNvZGUiOiIyNSJ9LHsibm9tIjoiRHLDtG1lIiwiY29kZSI6IjI2In0seyJub20iOiJFdXJlIiwiY29kZSI6IjI3In0seyJub20iOiJFdXJlLWV0LUxvaXIiLCJjb2RlIjoiMjgifSx7Im5vbSI6IkZpbmlzdMOocmUiLCJjb2RlIjoiMjkifSx7Im5vbSI6IkNvcnNlLWR1LVN1ZCIsImNvZGUiOiIyQSJ9LHsibm9tIjoiSGF1dGUtQ29yc2UiLCJjb2RlIjoiMkIifSx7Im5vbSI6IkdhcmQiLCJjb2RlIjoiMzAifSx7Im5vbSI6IkhhdXRlLUdhcm9ubmUiLCJjb2RlIjoiMzEifSx7Im5vbSI6IkdlcnMiLCJjb2RlIjoiMzIifSx7Im5vbSI6Ikdpcm9uZGUiLCJjb2RlIjoiMzMifSx7Im5vbSI6IkjDqXJhdWx0IiwiY29kZSI6IjM0In0seyJub20iOiJJbGxlLWV0LVZpbGFpbmUiLCJjb2RlIjoiMzUifSx7Im5vbSI6IkluZHJlIiwiY29kZSI6IjM2In0seyJub20iOiJJbmRyZS1ldC1Mb2lyZSIsImNvZGUiOiIzNyJ9LHsibm9tIjoiSXPDqHJlIiwiY29kZSI6IjM4In0seyJub20iOiJKdXJhIiwiY29kZSI6IjM5In0seyJub20iOiJMYW5kZXMiLCJjb2RlIjoiNDAifSx7Im5vbSI6IkxvaXItZXQtQ2hlciIsImNvZGUiOiI0MSJ9LHsibm9tIjoiTG9pcmUiLCJjb2RlIjoiNDIifSx7Im5vbSI6IkhhdXRlLUxvaXJlIiwiY29kZSI6IjQzIn0seyJub20iOiJMb2lyZS1BdGxhbnRpcXVlIiwiY29kZSI6IjQ0In0seyJub20iOiJMb2lyZXQiLCJjb2RlIjoiNDUifSx7Im5vbSI6IkxvdCIsImNvZGUiOiI0NiJ9LHsibm9tIjoiTG90LWV0LUdhcm9ubmUiLCJjb2RlIjoiNDcifSx7Im5vbSI6IkxvesOocmUiLCJjb2RlIjoiNDgifSx7Im5vbSI6Ik1haW5lLWV0LUxvaXJlIiwiY29kZSI6IjQ5In0seyJub20iOiJNYW5jaGUiLCJjb2RlIjoiNTAifSx7Im5vbSI6Ik1hcm5lIiwiY29kZSI6IjUxIn0seyJub20iOiJIYXV0ZS1NYXJuZSIsImNvZGUiOiI1MiJ9LHsibm9tIjoiTWF5ZW5uZSIsImNvZGUiOiI1MyJ9LHsibm9tIjoiTWV1cnRoZS1ldC1Nb3NlbGxlIiwiY29kZSI6IjU0In0seyJub20iOiJNZXVzZSIsImNvZGUiOiI1NSJ9LHsibm9tIjoiTW9yYmloYW4iLCJjb2RlIjoiNTYifSx7Im5vbSI6Ik1vc2VsbGUiLCJjb2RlIjoiNTcifSx7Im5vbSI6Ik5pw6h2cmUiLCJjb2RlIjoiNTgifSx7Im5vbSI6Ik5vcmQiLCJjb2RlIjoiNTkifSx7Im5vbSI6Ik9pc2UiLCJjb2RlIjoiNjAifSx7Im5vbSI6Ik9ybmUiLCJjb2RlIjoiNjEifSx7Im5vbSI6IlBhcy1kZS1DYWxhaXMiLCJjb2RlIjoiNjIifSx7Im5vbSI6IlB1eS1kZS1Ew7RtZSIsImNvZGUiOiI2MyJ9LHsibm9tIjoiUHlyw6luw6llcy1BdGxhbnRpcXVlcyIsImNvZGUiOiI2NCJ9LHsibm9tIjoiSGF1dGVzLVB5csOpbsOpZXMiLCJjb2RlIjoiNjUifSx7Im5vbSI6IlB5csOpbsOpZXMtT3JpZW50YWxlcyIsImNvZGUiOiI2NiJ9LHsibm9tIjoiQmFzLVJoaW4iLCJjb2RlIjoiNjcifSx7Im5vbSI6IkhhdXQtUmhpbiIsImNvZGUiOiI2OCJ9LHsibm9tIjoiUmjDtG5lIiwiY29kZSI6IjY5In0seyJub20iOiJIYXV0ZS1TYcO0bmUiLCJjb2RlIjoiNzAifSx7Im5vbSI6IlNhw7RuZS1ldC1Mb2lyZSIsImNvZGUiOiI3MSJ9LHsibm9tIjoiU2FydGhlIiwiY29kZSI6IjcyIn0seyJub20iOiJTYXZvaWUiLCJjb2RlIjoiNzMifSx7Im5vbSI6IkhhdXRlLVNhdm9pZSIsImNvZGUiOiI3NCJ9LHsibm9tIjoiUGFyaXMiLCJjb2RlIjoiNzUifSx7Im5vbSI6IlNlaW5lLU1hcml0aW1lIiwiY29kZSI6Ijc2In0seyJub20iOiJTZWluZS1ldC1NYXJuZSIsImNvZGUiOiI3NyJ9LHsibm9tIjoiWXZlbGluZXMiLCJjb2RlIjoiNzgifSx7Im5vbSI6IkRldXgtU8OodnJlcyIsImNvZGUiOiI3OSJ9LHsibm9tIjoiU29tbWUiLCJjb2RlIjoiODAifSx7Im5vbSI6IlRhcm4iLCJjb2RlIjoiODEifSx7Im5vbSI6IlRhcm4tZXQtR2Fyb25uZSIsImNvZGUiOiI4MiJ9LHsibm9tIjoiVmFyIiwiY29kZSI6IjgzIn0seyJub20iOiJWYXVjbHVzZSIsImNvZGUiOiI4NCJ9LHsibm9tIjoiVmVuZMOpZSIsImNvZGUiOiI4NSJ9LHsibm9tIjoiVmllbm5lIiwiY29kZSI6Ijg2In0seyJub20iOiJIYXV0ZS1WaWVubmUiLCJjb2RlIjoiODcifSx7Im5vbSI6IlZvc2dlcyIsImNvZGUiOiI4OCJ9LHsibm9tIjoiWW9ubmUiLCJjb2RlIjoiODkifSx7Im5vbSI6IlRlcnJpdG9pcmUgZGUgQmVsZm9ydCIsImNvZGUiOiI5MCJ9LHsibm9tIjoiRXNzb25uZSIsImNvZGUiOiI5MSJ9LHsibm9tIjoiSGF1dHMtZGUtU2VpbmUiLCJjb2RlIjoiOTIifSx7Im5vbSI6IlNlaW5lLVNhaW50LURlbmlzIiwiY29kZSI6IjkzIn0seyJub20iOiJWYWwtZGUtTWFybmUiLCJjb2RlIjoiOTQifSx7Im5vbSI6IlZhbC1kJ09pc2UiLCJjb2RlIjoiOTUifSx7Im5vbSI6Ikd1YWRlbG91cGUiLCJjb2RlIjoiOTcxIn0seyJub20iOiJNYXJ0aW5pcXVlIiwiY29kZSI6Ijk3MiJ9LHsibm9tIjoiR3V5YW5lIiwiY29kZSI6Ijk3MyJ9LHsibm9tIjoiTGEgUsOpdW5pb24iLCJjb2RlIjoiOTc0In0seyJub20iOiJNYXlvdHRlIiwiY29kZSI6Ijk3NiJ9XQ==
xZYSjbpF/yfZ5w/0YyVlpDq0sxTmajg8vJzh1z+9Um9773oTVfbe9O51Lt3H
237v75suUpUSsQFjRaGkQXAYBH/IKspl9FHYWkZLo3eyvGeqEdStqIomhfsJ
CccnCRfCqFptA1VMlcmbx/sN10nCsCzL4O80CKvm8YE/Z4zaO4T6b4OQQ/ef
YD8guJN7o8G3T4YX2rpqHSgb3WyaZ7LuE+dUFDuRa8Dpk99UlLUoUAHJTTfC
yLJmgUT2Eo5e2CIN2U03POw+uU21Mc3jb65AcC5cSb/Flc275IPJsQGiVgjF
BRTT5tn5KD+/huMGBN0KHMnzidlqish7aqQNliDkmTa5fuAZDAh5pu0dDmBA
xjPTPG9ZOgm/t4YhQvWhSNbRlVYsmXA/qFJVdfMY5CDeuTDAOqQvD5fPCbRz
fQd2SG5zabCrIWnNlfuRzh4S18fmyQhb1MhLXJdF0W5trQqhgtUJ7rLMubEh
ubWxFzosnwQvqxDNkOw+WSNQHqldCbczbHxEbv44/MKh50fE5iWoaURuB+zH
CrJrY9GkLtzFVT8tE5FhKwPgEdFdaUYIzkV89SfnPiK4K/07JDciuYU/s1fY
j8hwIcqg147J0LUTnvqY8A6AjhVEuBB736m7wxsT30JaU2/a+ha6ks5pEBKg
E/K6j8lvoc2d2gi05jEhniYmvc9uUuxogDHpfXadBBWR2bViQTGJXQfAYgJb
inaYujEgFEwbE9nS7r1mFnaimNyWe9M8lc2Tn7X/vcd8rwzl7p9uRzE5Ium1
UW7SiIIXKybUC7ePmw2fGzGpel8cx8n1eEbGJHsw1UqEYzQh4UPwFVsnhL0S
3lzdbhNSXomdVgwGLbF97JxISHXpXjAgnpDkSvpLdzqHEyI8iLzzwwuWEOSX
nSxcLi5EjjNpf0Wr1sGUkOZKbznQUmK8dSt3eFKy86FXe09KiGuBaZeS4FrY
+yK4synprWWZO/ticfJbO/exZ6TkdrDHiYTU1rp6IJCUzL6EMzQlrFtp3LvU
N+uzXJ5dyOK7NmjOGeG9r6owU3bcGdur3h5zt88s8GDrk5Vr0XU0k+55AF0I
s/CpjoySBUCFk5yHTSkj07kVuSy0/cFiguvi0tfujRJMsSy4M3O7F8FmkmAW
irOb5smWiq/kLAnauNjrmi/YzF+Jb/8A5ygzwMEMAAA=
http_version: http_version:
recorded_at: Fri, 16 Dec 2016 09:25:37 GMT recorded_at: Tue, 23 Oct 2018 13:11:36 GMT
recorded_with: VCR 3.0.3 recorded_with: VCR 4.0.0

View file

@ -7,21 +7,23 @@ http_interactions:
encoding: US-ASCII encoding: US-ASCII
string: '' string: ''
headers: headers:
User-Agent:
- demarches-simplifiees.fr
Accept: Accept:
- "*/*" - application/json
Accept-Encoding: Accept-Encoding:
- gzip, deflate - gzip, deflate
User-Agent: Expect:
- rest-client/2.0.0 (darwin15.6.0 x86_64) ruby/2.3.1p112 - ''
response: response:
status: status:
code: 200 code: 200
message: OK message: OK
headers: headers:
Server: Server:
- nginx - nginx/1.10.3 (Ubuntu)
Date: Date:
- Fri, 16 Dec 2016 09:24:28 GMT - Tue, 23 Oct 2018 13:11:36 GMT
Content-Type: Content-Type:
- application/json; charset=utf-8 - application/json; charset=utf-8
Transfer-Encoding: Transfer-Encoding:
@ -30,13 +32,12 @@ http_interactions:
- keep-alive - keep-alive
Vary: Vary:
- Accept-Encoding - Accept-Encoding
- Accept-Encoding
X-Powered-By: X-Powered-By:
- Express - Express
Access-Control-Allow-Origin: Access-Control-Allow-Origin:
- "*" - "*"
Etag: Etag:
- W/"2dd-2SAFdhiM3SIQ2017gqYxbw" - W/"28d-5OgIzgwL+0K2UaO0foKduqMMBrA"
Strict-Transport-Security: Strict-Transport-Security:
- max-age=15552000 - max-age=15552000
Content-Encoding: Content-Encoding:
@ -44,14 +45,7 @@ http_interactions:
body: body:
encoding: ASCII-8BIT encoding: ASCII-8BIT
string: !binary |- string: !binary |-
H4sIAAAAAAAAA11Ry2rDMBD8FeNLLxE0rybpzTE0F6eYHHopPSyWSASyNllJ W3sibm9tIjoiR3VhZGVsb3VwZSIsImNvZGUiOiIwMSJ9LHsibm9tIjoiTWFydGluaXF1ZSIsImNvZGUiOiIwMiJ9LHsibm9tIjoiR3V5YW5lIiwiY29kZSI6IjAzIn0seyJub20iOiJMYSBSw6l1bmlvbiIsImNvZGUiOiIwNCJ9LHsibm9tIjoiTWF5b3R0ZSIsImNvZGUiOiIwNiJ9LHsibm9tIjoiw45sZS1kZS1GcmFuY2UiLCJjb2RlIjoiMTEifSx7Im5vbSI6IkNlbnRyZS1WYWwgZGUgTG9pcmUiLCJjb2RlIjoiMjQifSx7Im5vbSI6IkJvdXJnb2duZS1GcmFuY2hlLUNvbXTDqSIsImNvZGUiOiIyNyJ9LHsibm9tIjoiTm9ybWFuZGllIiwiY29kZSI6IjI4In0seyJub20iOiJIYXV0cy1kZS1GcmFuY2UiLCJjb2RlIjoiMzIifSx7Im5vbSI6IkdyYW5kIEVzdCIsImNvZGUiOiI0NCJ9LHsibm9tIjoiUGF5cyBkZSBsYSBMb2lyZSIsImNvZGUiOiI1MiJ9LHsibm9tIjoiQnJldGFnbmUiLCJjb2RlIjoiNTMifSx7Im5vbSI6Ik5vdXZlbGxlLUFxdWl0YWluZSIsImNvZGUiOiI3NSJ9LHsibm9tIjoiT2NjaXRhbmllIiwiY29kZSI6Ijc2In0seyJub20iOiJBdXZlcmduZS1SaMO0bmUtQWxwZXMiLCJjb2RlIjoiODQifSx7Im5vbSI6IlByb3ZlbmNlLUFscGVzLUPDtHRlIGQnQXp1ciIsImNvZGUiOiI5MyJ9LHsibm9tIjoiQ29yc2UiLCJjb2RlIjoiOTQifV0=
Abf0F/ofvucP/GO1aIvXPQm0M7MzO68fqcU6fUx3AaQyGM4qnaQVStX/3U/T
z8kfYA/ktdWXwAEzBtiFBiwfztmwgOTQtcFqtEx/MdJv0HvOf2DT7ssoIZV4
IrAVA025xVxZT0q8gEmkSgrUxJAzvmyLgY54tL+CJyVyrH3XDt5mK7b9GakG
KzWXW4/nUpTgosMcDGgnSl0BjRhzfqzMOKh68AnqM0QfGUll+7dAItD8jgtu
vITGxXAG/udbcvktKR9lhzxL3kZ2CdrHLaLQNQanrShRewzREPVXVG5grpaj
Hu0xKImVOPQ8p41BK/ZaalE21LW2a0dUXmEWropi1MOpu8XE5syx61FMwqvq
i/4Biby7eZXIu+w90GBswyPlSI7F3fRqb99L+pyA3QIAAA==
http_version: http_version:
recorded_at: Fri, 16 Dec 2016 09:24:25 GMT recorded_at: Tue, 23 Oct 2018 13:11:36 GMT
recorded_with: VCR 3.0.3 recorded_with: VCR 4.0.0

File diff suppressed because one or more lines are too long

View file

@ -4,18 +4,72 @@ describe ApiGeo::API do
describe '.regions', vcr: { cassette_name: 'api_geo_regions' } do describe '.regions', vcr: { cassette_name: 'api_geo_regions' } do
subject { described_class.regions } subject { described_class.regions }
it { expect(subject.code).to eq 200 } it { expect(subject.size).to eq 18 }
end end
describe '.departements', vcr: { cassette_name: 'api_geo_departements' } do describe '.departements', vcr: { cassette_name: 'api_geo_departements' } do
subject { described_class.departements } subject { described_class.departements }
it { expect(subject.code).to eq 200 } it { expect(subject.size).to eq 101 }
end end
describe '.pays' do describe '.pays' do
subject { described_class.pays } subject { described_class.pays }
let(:pays) {
JSON.parse(File.open('app/lib/api_geo/pays.json').read, symbolize_names: true)
}
it { is_expected.to eq File.open('app/lib/api_geo/pays.json').read } it { is_expected.to eq pays }
end
describe '.search_rpg', vcr: { cassette_name: 'api_geo_search_rpg' } do
let(:coordinates) do
[
[
2.3945903778076176,
46.53312237252731
],
[
2.394933700561524,
46.532590956418076
],
[
2.3948478698730473,
46.53170525134736
],
[
2.393732070922852,
46.530760483351195
],
[
2.3909854888916016,
46.5309376286023
],
[
2.391414642333985,
46.531232869403546
],
[
2.3913288116455083,
46.53253190986272
],
[
2.39278793334961,
46.53329951007484
],
[
2.3945903778076176,
46.53312237252731
]
]
end
let(:geo_json) {
GeojsonService.to_json_polygon_for_rpg(coordinates)
}
subject { described_class.search_rpg(geo_json) }
it { expect(subject[:features].size).to eq 3 }
end end
end end

View file

@ -0,0 +1,61 @@
require 'spec_helper'
describe ApiGeo::RPGAdapter do
subject { described_class.new(coordinates).results }
let(:coordinates) do
[
[
2.3945903778076176,
46.53312237252731
],
[
2.394933700561524,
46.532590956418076
],
[
2.3948478698730473,
46.53170525134736
],
[
2.393732070922852,
46.530760483351195
],
[
2.3909854888916016,
46.5309376286023
],
[
2.391414642333985,
46.531232869403546
],
[
2.3913288116455083,
46.53253190986272
],
[
2.39278793334961,
46.53329951007484
],
[
2.3945903778076176,
46.53312237252731
]
]
end
context 'coordinates are filled', vcr: { cassette_name: 'api_geo_search_rpg' } do
describe 'Attribut filter' do
it { expect(subject.size).to eq(3) }
it do
expect(subject.first.keys).to eq([
:culture,
:code_culture,
:surface,
:bio,
:geometry
])
end
end
end
end

View file

@ -1,17 +1,40 @@
describe AssignTo, type: :model do describe AssignTo, type: :model do
describe '#procedure_presentation_or_default' do describe '#procedure_presentation_or_default_and_errors' do
context "without a procedure_presentation" do let(:procedure) { create(:procedure) }
let!(:assign_to) { AssignTo.create } let(:assign_to) { AssignTo.create(procedure: procedure) }
it { expect(assign_to.procedure_presentation_or_default.persisted?).to be_falsey } let(:procedure_presentation_and_errors) { assign_to.procedure_presentation_or_default_and_errors }
let(:procedure_presentation_or_default) { procedure_presentation_and_errors.first }
let(:errors) { procedure_presentation_and_errors.second }
context "without a procedure_presentation" do
it { expect(procedure_presentation_or_default).not_to be_persisted }
it { expect(procedure_presentation_or_default).to be_valid }
it { expect(errors).to be_nil }
end end
context "with a procedure_presentation" do context "with a procedure_presentation" do
let(:procedure) { create(:procedure) }
let!(:assign_to) { AssignTo.create(procedure: procedure) }
let!(:procedure_presentation) { ProcedurePresentation.create(assign_to: assign_to) } let!(:procedure_presentation) { ProcedurePresentation.create(assign_to: assign_to) }
it { expect(assign_to.procedure_presentation_or_default).to eq(procedure_presentation) } it { expect(procedure_presentation_or_default).to eq(procedure_presentation) }
it { expect(procedure_presentation_or_default).to be_valid }
it { expect(errors).to be_nil }
end
context "with an invalid procedure_presentation" do
let!(:procedure_presentation) do
pp = ProcedurePresentation.new(assign_to: assign_to, displayed_fields: [{ 'table' => 'invalid', 'column' => 'random' }])
pp.save(validate: false)
pp
end
it { expect(procedure_presentation_or_default).not_to be_persisted }
it { expect(procedure_presentation_or_default).to be_valid }
it { expect(errors).to be_present }
it do
procedure_presentation_or_default
expect(assign_to.procedure_presentation).not_to be(procedure_presentation)
end
end end
end end
end end

View file

@ -197,11 +197,36 @@ describe Gestionnaire, type: :model do
end end
end end
describe "procedure_presentation_for_procedure_id" do describe "procedure_presentation_and_errors_for_procedure_id" do
let!(:pp) { ProcedurePresentation.create(assign_to: procedure_assign) } let(:procedure_presentation_and_errors) { gestionnaire.procedure_presentation_and_errors_for_procedure_id(procedure_id) }
let(:procedure_presentation) { procedure_presentation_and_errors.first }
let(:errors) { procedure_presentation_and_errors.second }
it { expect(gestionnaire.procedure_presentation_for_procedure_id(procedure.id)).to eq(pp) } context 'with explicit presentation' do
it { expect(gestionnaire.procedure_presentation_for_procedure_id(procedure_2.id).persisted?).to be_falsey } let(:procedure_id) { procedure.id }
let!(:pp) { ProcedurePresentation.create(assign_to: procedure_assign) }
it { expect(procedure_presentation).to eq(pp) }
it { expect(errors).to be_nil }
end
context 'with invalid presentation' do
let(:procedure_id) { procedure.id }
before do
pp = ProcedurePresentation.create(assign_to: procedure_assign, displayed_fields: [{ 'table' => 'invalid', 'column' => 'random' }])
pp.save(:validate => false)
end
it { expect(procedure_presentation).not_to be_persisted }
it { expect(errors).to be_present }
end
context 'with default presentation' do
let(:procedure_id) { procedure_2.id }
it { expect(procedure_presentation).not_to be_persisted }
it { expect(errors).to be_nil }
end
end end
describe '#notifications_for_dossier' do describe '#notifications_for_dossier' do

View file

@ -6,13 +6,29 @@ describe Champs::CarteChampSerializer do
let(:geo_area) { create(:geo_area) } let(:geo_area) { create(:geo_area) }
let(:champ) { create(:type_de_champ_carte).champ.create(geo_areas: [geo_area]) } let(:champ) { create(:type_de_champ_carte).champ.create(geo_areas: [geo_area]) }
it { context 'and geo_area is cadastre' do
expect(subject[:geo_areas].first).to include( it {
source: GeoArea.sources.fetch(:cadastre), expect(subject[:geo_areas].first).to include(
numero: '42', source: GeoArea.sources.fetch(:cadastre),
feuille: 'A11' numero: '42',
) feuille: 'A11'
} )
expect(subject[:geo_areas].first.key?(:nom)).to be_falsey
}
end
context 'and geo_area is quartier_prioritaire' do
let(:geo_area) { create(:geo_area, :quartier_prioritaire) }
it {
expect(subject[:geo_areas].first).to include(
source: GeoArea.sources.fetch(:quartier_prioritaire),
nom: 'XYZ',
commune: 'Paris'
)
expect(subject[:geo_areas].first.key?(:numero)).to be_falsey
}
end
end end
end end
end end