Add compatibility cadsatre layer with old API GEO
This commit is contained in:
parent
e74dcb0056
commit
3b85ade440
11 changed files with 206 additions and 155 deletions
|
@ -4,29 +4,26 @@ class Champs::CarteController < ApplicationController
|
|||
def index
|
||||
@selector = ".carte-#{params[:champ_id]}"
|
||||
@champ = policy_scope(Champ).find(params[:champ_id])
|
||||
@update_cadastres = params[:cadastres]
|
||||
|
||||
if @champ.cadastres? && @update_cadastres
|
||||
@champ.geo_areas.cadastres.destroy_all
|
||||
@champ.geo_areas += GeoArea.from_feature_collection(cadastres_features_collection(@champ.to_feature_collection))
|
||||
@champ.save!
|
||||
end
|
||||
rescue APICarto::API::ResourceNotFound
|
||||
flash.alert = 'Les données cartographiques sont temporairement indisponibles. Réessayez dans un instant.'
|
||||
response.status = 503
|
||||
@focus = params[:focus].present?
|
||||
end
|
||||
|
||||
def create
|
||||
champ = policy_scope(Champ).find(params[:champ_id])
|
||||
geo_area = champ.geo_areas.selections_utilisateur.new
|
||||
geo_area = if params_source == GeoArea.sources.fetch(:cadastre)
|
||||
champ.geo_areas.find_by("properties->>'id' = :id", id: params_feature[:properties][:id])
|
||||
end
|
||||
|
||||
if geo_area.nil?
|
||||
geo_area = champ.geo_areas.build(source: params_source, properties: {})
|
||||
save_feature!(geo_area, params_feature)
|
||||
end
|
||||
|
||||
render json: { feature: geo_area.to_feature }, status: :created
|
||||
end
|
||||
|
||||
def update
|
||||
champ = policy_scope(Champ).find(params[:champ_id])
|
||||
geo_area = champ.geo_areas.selections_utilisateur.find(params[:id])
|
||||
geo_area = champ.geo_areas.find(params[:id])
|
||||
save_feature!(geo_area, params_feature)
|
||||
|
||||
head :no_content
|
||||
|
@ -34,66 +31,42 @@ class Champs::CarteController < ApplicationController
|
|||
|
||||
def destroy
|
||||
champ = policy_scope(Champ).find(params[:champ_id])
|
||||
champ.geo_areas.selections_utilisateur.find(params[:id]).destroy!
|
||||
champ.geo_areas.find(params[:id]).destroy!
|
||||
|
||||
head :no_content
|
||||
end
|
||||
|
||||
def import
|
||||
champ = policy_scope(Champ).find(params[:champ_id])
|
||||
params_features.each do |feature|
|
||||
geo_area = champ.geo_areas.selections_utilisateur.new
|
||||
save_feature!(geo_area, feature)
|
||||
end
|
||||
|
||||
render json: champ.to_feature_collection, status: :created
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def params_feature
|
||||
params[:feature]
|
||||
def params_source
|
||||
params[:source]
|
||||
end
|
||||
|
||||
def params_features
|
||||
params[:features]
|
||||
def params_feature
|
||||
params.require(:feature).permit(properties: [
|
||||
:filename,
|
||||
:description,
|
||||
:arpente,
|
||||
:commune,
|
||||
:contenance,
|
||||
:created,
|
||||
:id,
|
||||
:numero,
|
||||
:prefixe,
|
||||
:section,
|
||||
:updated
|
||||
]).tap do |feature|
|
||||
feature[:geometry] = params[:feature][:geometry]
|
||||
end
|
||||
end
|
||||
|
||||
def save_feature!(geo_area, feature)
|
||||
if feature[:geometry]
|
||||
geo_area.geometry = feature[:geometry]
|
||||
end
|
||||
if feature[:properties] && feature[:properties][:description]
|
||||
geo_area.description = feature[:properties][:description]
|
||||
if feature[:properties]
|
||||
geo_area.properties.merge!(feature[:properties])
|
||||
end
|
||||
geo_area.save!
|
||||
end
|
||||
|
||||
def cadastres_features_collection(feature_collection)
|
||||
coordinates = feature_collection[:features].filter do |feature|
|
||||
feature[:properties][:source] == GeoArea.sources.fetch(:selection_utilisateur) && feature[:geometry] && feature[:geometry]['type'] == 'Polygon'
|
||||
end.map do |feature|
|
||||
feature[:geometry]['coordinates'][0].map { |(lng, lat)| { 'lng' => lng, 'lat' => lat } }
|
||||
end
|
||||
|
||||
if coordinates.present?
|
||||
cadastres = APICartoService.generate_cadastre(coordinates)
|
||||
|
||||
{
|
||||
type: 'FeatureCollection',
|
||||
features: cadastres.map do |cadastre|
|
||||
{
|
||||
type: 'Feature',
|
||||
geometry: cadastre.delete(:geometry),
|
||||
properties: cadastre.merge(source: GeoArea.sources.fetch(:cadastre))
|
||||
}
|
||||
end
|
||||
}
|
||||
else
|
||||
{
|
||||
type: 'FeatureCollection',
|
||||
features: []
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1467,18 +1467,21 @@ type PageInfo {
|
|||
}
|
||||
|
||||
type ParcelleCadastrale implements GeoArea {
|
||||
codeArr: String!
|
||||
codeCom: String!
|
||||
codeDep: String!
|
||||
feuille: Int!
|
||||
codeArr: String! @deprecated(reason: "Utilisez le champ `prefixe` à la place.")
|
||||
codeCom: String! @deprecated(reason: "Utilisez le champ `commune` à la place.")
|
||||
codeDep: String! @deprecated(reason: "Utilisez le champ `commune` à la place.")
|
||||
commune: String!
|
||||
feuille: Int! @deprecated(reason: "L‘information n‘est plus disponible.")
|
||||
geometry: GeoJSON!
|
||||
id: ID!
|
||||
nomCom: String!
|
||||
nomCom: String! @deprecated(reason: "Utilisez le champ `commune` à la place.")
|
||||
numero: String!
|
||||
prefixe: String!
|
||||
section: String!
|
||||
source: GeoAreaSource!
|
||||
surfaceIntersection: Float!
|
||||
surfaceParcelle: Float!
|
||||
surface: String!
|
||||
surfaceIntersection: Float! @deprecated(reason: "L‘information n‘est plus disponible.")
|
||||
surfaceParcelle: Float! @deprecated(reason: "Utilisez le champ `surface` à la place.")
|
||||
}
|
||||
|
||||
type PersonneMorale implements Demandeur {
|
||||
|
@ -1587,6 +1590,7 @@ type Revision {
|
|||
}
|
||||
|
||||
type SelectionUtilisateur implements GeoArea {
|
||||
description: String!
|
||||
geometry: GeoJSON!
|
||||
id: ID!
|
||||
source: GeoAreaSource!
|
||||
|
|
|
@ -2,14 +2,18 @@ module Types::GeoAreas
|
|||
class ParcelleCadastraleType < Types::BaseObject
|
||||
implements Types::GeoAreaType
|
||||
|
||||
field :surface_intersection, Float, null: false
|
||||
field :surface_parcelle, Float, null: false
|
||||
field :numero, String, null: false
|
||||
field :feuille, Int, null: false
|
||||
field :section, String, null: false
|
||||
field :code_dep, String, null: false
|
||||
field :nom_com, String, null: false
|
||||
field :code_com, String, null: false
|
||||
field :code_arr, String, null: false
|
||||
field :surface, String, null: false
|
||||
field :prefixe, String, null: false
|
||||
field :commune, String, null: false
|
||||
|
||||
field :code_dep, String, null: false, deprecation_reason: 'Utilisez le champ `commune` à la place.'
|
||||
field :nom_com, String, null: false, deprecation_reason: 'Utilisez le champ `commune` à la place.'
|
||||
field :code_com, String, null: false, deprecation_reason: 'Utilisez le champ `commune` à la place.'
|
||||
field :code_arr, String, null: false, deprecation_reason: 'Utilisez le champ `prefixe` à la place.'
|
||||
field :feuille, Int, null: false, deprecation_reason: 'L‘information n‘est plus disponible.'
|
||||
field :surface_intersection, Float, null: false, deprecation_reason: 'L‘information n‘est plus disponible.'
|
||||
field :surface_parcelle, Float, null: false, deprecation_reason: 'Utilisez le champ `surface` à la place.'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
module Types::GeoAreas
|
||||
class SelectionUtilisateurType < Types::BaseObject
|
||||
implements Types::GeoAreaType
|
||||
|
||||
field :description, String, null: false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -36,7 +36,7 @@ module ChampHelper
|
|||
case geo_area.source
|
||||
when GeoArea.sources.fetch(:cadastre)
|
||||
capture do
|
||||
concat "Parcelle n° #{geo_area.numero} - Feuille #{geo_area.code_arr} #{geo_area.section} #{geo_area.feuille} - #{geo_area.surface_parcelle.round} m"
|
||||
concat "Parcelle n° #{geo_area.numero} - Feuille #{geo_area.prefixe} #{geo_area.section} - #{geo_area.surface.round} m"
|
||||
concat tag.sup("2")
|
||||
end
|
||||
when GeoArea.sources.fetch(:selection_utilisateur)
|
||||
|
|
|
@ -14,25 +14,33 @@
|
|||
class GeoArea < ApplicationRecord
|
||||
belongs_to :champ, optional: false
|
||||
|
||||
store :properties, accessors: [
|
||||
:description,
|
||||
:surface_intersection,
|
||||
:surface_parcelle,
|
||||
:numero,
|
||||
:feuille,
|
||||
:section,
|
||||
:code_dep,
|
||||
:nom_com,
|
||||
:code_com,
|
||||
:code_arr,
|
||||
:code,
|
||||
:nom,
|
||||
:commune,
|
||||
:culture,
|
||||
:code_culture,
|
||||
:surface,
|
||||
:bio
|
||||
]
|
||||
# FIXME: once geo_areas are migrated to not use YAML serialization we can enable store_accessor
|
||||
# store_accessor :properties, :description, :numero, :section
|
||||
|
||||
def properties
|
||||
value = read_attribute(:properties)
|
||||
if value.is_a? String
|
||||
ActiveRecord::Coders::YAMLColumn.new(:properties).load(value)
|
||||
else
|
||||
value
|
||||
end
|
||||
end
|
||||
|
||||
def description
|
||||
properties['description']
|
||||
end
|
||||
|
||||
def numero
|
||||
properties['numero']
|
||||
end
|
||||
|
||||
def section
|
||||
properties['section']
|
||||
end
|
||||
|
||||
def filename
|
||||
properties['filename']
|
||||
end
|
||||
|
||||
enum source: {
|
||||
cadastre: 'cadastre',
|
||||
|
@ -48,10 +56,12 @@ class GeoArea < ApplicationRecord
|
|||
{
|
||||
type: 'Feature',
|
||||
geometry: safe_geometry,
|
||||
properties: properties.symbolize_keys.merge(
|
||||
properties: cadastre_properties.merge(
|
||||
source: source,
|
||||
area: area,
|
||||
length: length,
|
||||
description: description,
|
||||
filename: filename,
|
||||
id: id,
|
||||
champ_id: champ.stable_id,
|
||||
dossier_id: champ.dossier_id
|
||||
|
@ -69,16 +79,6 @@ class GeoArea < ApplicationRecord
|
|||
nil
|
||||
end
|
||||
|
||||
def self.from_feature_collection(feature_collection)
|
||||
feature_collection[:features].map do |feature|
|
||||
GeoArea.new(
|
||||
source: feature[:properties].delete(:source),
|
||||
properties: feature[:properties],
|
||||
geometry: feature[:geometry]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def area
|
||||
if polygon?
|
||||
GeojsonService.area(geometry.deep_symbolize_keys).round(1)
|
||||
|
@ -108,4 +108,107 @@ class GeoArea < ApplicationRecord
|
|||
def point?
|
||||
geometry['type'] == 'Point'
|
||||
end
|
||||
|
||||
def legacy_cadastre?
|
||||
cadastre? && properties['surface_intersection'].present?
|
||||
end
|
||||
|
||||
def cadastre?
|
||||
source == GeoArea.sources.fetch(:cadastre)
|
||||
end
|
||||
|
||||
def cadastre_properties
|
||||
if cadastre?
|
||||
{
|
||||
cid: cid,
|
||||
numero: numero,
|
||||
section: section,
|
||||
prefixe: prefixe,
|
||||
commune: commune,
|
||||
surface: surface
|
||||
}
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
def code_dep
|
||||
if legacy_cadastre?
|
||||
properties['code_dep']
|
||||
else
|
||||
properties['commune'][0..1]
|
||||
end
|
||||
end
|
||||
|
||||
def code_com
|
||||
if legacy_cadastre?
|
||||
properties['code_com']
|
||||
else
|
||||
properties['commune'][2...commune.size]
|
||||
end
|
||||
end
|
||||
|
||||
def nom_com
|
||||
if legacy_cadastre?
|
||||
properties['nom_com']
|
||||
else
|
||||
''
|
||||
end
|
||||
end
|
||||
|
||||
def surface_intersection
|
||||
if legacy_cadastre?
|
||||
properties['surface_intersection']
|
||||
else
|
||||
''
|
||||
end
|
||||
end
|
||||
|
||||
def feuille
|
||||
if legacy_cadastre?
|
||||
properties['feuille']
|
||||
else
|
||||
1
|
||||
end
|
||||
end
|
||||
|
||||
def code_arr
|
||||
prefixe
|
||||
end
|
||||
|
||||
def surface_parcelle
|
||||
surface
|
||||
end
|
||||
|
||||
def surface
|
||||
if legacy_cadastre?
|
||||
properties['surface_parcelle']
|
||||
else
|
||||
properties['contenance']
|
||||
end
|
||||
end
|
||||
|
||||
def prefixe
|
||||
if legacy_cadastre?
|
||||
properties['code_arr']
|
||||
else
|
||||
properties['prefixe']
|
||||
end
|
||||
end
|
||||
|
||||
def commune
|
||||
if legacy_cadastre?
|
||||
"#{properties['code_dep']}#{properties['code_com']}"
|
||||
else
|
||||
properties['commune']
|
||||
end
|
||||
end
|
||||
|
||||
def cid
|
||||
if legacy_cadastre?
|
||||
"#{code_dep}#{code_com}#{code_arr}#{section}#{numero}"
|
||||
else
|
||||
properties['id']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
partial: 'shared/champs/carte/geo_areas',
|
||||
locals: { champ: @champ, editing: true }) %>
|
||||
|
||||
<% if @update_cadastres %>
|
||||
<%= fire_event('cadastres:update', { featureCollection: @champ.to_feature_collection }.to_json) %>
|
||||
<% if @focus %>
|
||||
<%= fire_event('map:feature:focus', { bbox: @champ.bounding_box }.to_json) %>
|
||||
<% end %>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
- if editing
|
||||
= link_to '#', data: { geo_area: geo_area.id } do
|
||||
= geo_area_label(geo_area)
|
||||
= text_field_tag :description, geo_area.description, data: { geo_area: geo_area.id }, placeholder: 'Description de la sélection'
|
||||
= text_field_tag :description, geo_area.description, data: { geo_area: geo_area.id }, placeholder: 'Description de la sélection', class: 'no-margin'
|
||||
- else
|
||||
= link_to '#', data: { geo_area: geo_area.id } do
|
||||
= geo_area_label(geo_area)
|
||||
|
|
|
@ -25,7 +25,8 @@ describe Champs::CarteController, type: :controller do
|
|||
let(:params) do
|
||||
{
|
||||
champ_id: champ.id,
|
||||
feature: feature
|
||||
feature: feature,
|
||||
source: GeoArea.sources.fetch(:selection_utilisateur)
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -98,67 +99,37 @@ describe Champs::CarteController, type: :controller do
|
|||
it { expect(response.status).to eq 204 }
|
||||
end
|
||||
|
||||
describe 'POST #import' do
|
||||
describe 'GET #index' do
|
||||
render_views
|
||||
|
||||
let(:params) do
|
||||
{
|
||||
champ_id: champ.id,
|
||||
features: [feature]
|
||||
|
||||
}
|
||||
{ champ_id: champ.id }
|
||||
end
|
||||
|
||||
before do
|
||||
post :import, params: params
|
||||
end
|
||||
|
||||
it {
|
||||
expect(response.status).to eq 201
|
||||
expect(response.body).to include("bbox")
|
||||
}
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
render_views
|
||||
|
||||
before do
|
||||
request.accept = "application/javascript"
|
||||
request.content_type = "application/javascript"
|
||||
get :index, params: params
|
||||
end
|
||||
|
||||
context 'with cadastres update' do
|
||||
context "update list" do
|
||||
it {
|
||||
expect(response.body).not_to include("DS.fire('map:feature:focus'")
|
||||
expect(response.status).to eq 200
|
||||
}
|
||||
end
|
||||
|
||||
context "update list and focus" do
|
||||
let(:params) do
|
||||
{
|
||||
champ_id: champ.id,
|
||||
cadastres: 'update'
|
||||
focus: true
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
get :index, params: params
|
||||
end
|
||||
|
||||
it {
|
||||
expect(response.body).to include("DS.fire('map:feature:focus'")
|
||||
expect(response.status).to eq 200
|
||||
expect(response.body).to include("DS.fire('cadastres:update'")
|
||||
}
|
||||
end
|
||||
|
||||
context 'without cadastres update' do
|
||||
let(:params) do
|
||||
{
|
||||
champ_id: champ.id
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
get :index, params: params
|
||||
end
|
||||
|
||||
it {
|
||||
expect(response.status).to eq 200
|
||||
expect(response.body).not_to include("DS.fire('cadastres:update'")
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
FactoryBot.define do
|
||||
factory :geo_area do
|
||||
association :champ
|
||||
properties { {} }
|
||||
|
||||
trait :cadastre do
|
||||
source { GeoArea.sources.fetch(:cadastre) }
|
||||
numero { '42' }
|
||||
feuille { 'A11' }
|
||||
end
|
||||
|
||||
trait :quartier_prioritaire do
|
||||
source { GeoArea.sources.fetch(:quartier_prioritaire) }
|
||||
nom { 'XYZ' }
|
||||
commune { 'Paris' }
|
||||
properties { { numero: '42', section: 'A11', commune: '75127' } }
|
||||
end
|
||||
|
||||
trait :selection_utilisateur do
|
||||
|
|
|
@ -85,7 +85,7 @@ describe ChampSerializer do
|
|||
source: GeoArea.sources.fetch(:cadastre),
|
||||
geometry: geo_json,
|
||||
numero: '42',
|
||||
feuille: 'A11'
|
||||
section: 'A11'
|
||||
)
|
||||
expect(subject[:geo_areas].first.key?(:nom)).to be_falsey
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue