From c18796d02aa43d91bb83ae70a8de6f03f057e9f3 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 29 Nov 2018 08:43:51 +0100 Subject: [PATCH 1/8] Fix geojson exposed on legacy carto API --- app/models/champs/carte_champ.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/champs/carte_champ.rb b/app/models/champs/carte_champ.rb index db922d24e..17e1f91ab 100644 --- a/app/models/champs/carte_champ.rb +++ b/app/models/champs/carte_champ.rb @@ -52,7 +52,7 @@ class Champs::CarteChamp < Champ type: 'Polygon', coordinates: [ geo_json[0].map do |polygon| - [polygon['lat'], polygon['lng']] + [polygon['lng'], polygon['lat']] end ] } From dd07a8ca1f5d468df515bd664fb235683e8c8991 Mon Sep 17 00:00:00 2001 From: Frederic Merizen Date: Tue, 27 Nov 2018 21:48:10 +0100 Subject: [PATCH 2/8] [#2180] Use different container for activestorage and for carrierwave --- config/storage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/storage.yml b/config/storage.yml index f3370122c..2d3348eab 100644 --- a/config/storage.yml +++ b/config/storage.yml @@ -11,7 +11,7 @@ clever_cloud: bucket: <%= ENV['CLEVER_CLOUD_BUCKET'] %> openstack: service: OpenStack - container: "<%= ENV['FOG_DIRECTORY'] %>" + container: "<%= ENV['FOG_ACTIVESTORAGE_DIRECTORY'] %>" credentials: openstack_tenant: "<%= ENV['FOG_OPENSTACK_TENANT'] %>" openstack_api_key: "<%= ENV['FOG_OPENSTACK_API_KEY'] %>" From fb57a0792705109887cdc520f0e5f83603e2b439 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 23 Nov 2018 19:22:33 +0100 Subject: [PATCH 3/8] Add stable_id to types_de_champ --- .../20181123181020_add_stable_id_to_types_de_champ.rb | 6 ++++++ db/schema.rb | 2 ++ 2 files changed, 8 insertions(+) create mode 100644 db/migrate/20181123181020_add_stable_id_to_types_de_champ.rb diff --git a/db/migrate/20181123181020_add_stable_id_to_types_de_champ.rb b/db/migrate/20181123181020_add_stable_id_to_types_de_champ.rb new file mode 100644 index 000000000..958eb90a2 --- /dev/null +++ b/db/migrate/20181123181020_add_stable_id_to_types_de_champ.rb @@ -0,0 +1,6 @@ +class AddStableIdToTypesDeChamp < ActiveRecord::Migration[5.2] + def change + add_column :types_de_champ, :stable_id, :bigint + add_index :types_de_champ, :stable_id + end +end diff --git a/db/schema.rb b/db/schema.rb index b8b98f83e..1d8759dfa 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -556,7 +556,9 @@ ActiveRecord::Schema.define(version: 2018_11_23_195208) do t.datetime "created_at" t.datetime "updated_at" t.jsonb "options" + t.bigint "stable_id" t.index ["private"], name: "index_types_de_champ_on_private" + t.index ["stable_id"], name: "index_types_de_champ_on_stable_id" end create_table "types_de_piece_justificative", id: :serial, force: :cascade do |t| From 1883c57c8744f841784a3386bf44d50197549b4e Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 27 Nov 2018 14:52:20 +0100 Subject: [PATCH 4/8] Add stable ids to types_de_champ after every update --- app/models/procedure.rb | 7 +++++++ app/models/type_de_champ.rb | 7 +++++++ spec/models/procedure_spec.rb | 5 +++++ spec/models/type_de_champ_shared_example.rb | 9 +++++++++ 4 files changed, 28 insertions(+) diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 2498604cf..718342060 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -199,6 +199,7 @@ class Procedure < ApplicationRecord end def clone(admin, from_library) + populate_champ_stable_ids procedure = self.deep_clone(include: { types_de_piece_justificative: nil, @@ -358,6 +359,12 @@ class Procedure < ApplicationRecord gestionnaire || gestionnaires.first end + def populate_champ_stable_ids + TypeDeChamp.where(procedure: self, stable_id: nil).find_each do |type_de_champ| + type_de_champ.update_column(:stable_id, type_de_champ.id) + end + end + private def claim_path_ownership!(path) diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index c2d9a9ae6..61bf18695 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -36,6 +36,7 @@ class TypeDeChamp < ApplicationRecord store :options, accessors: [:cadastres, :quartiers_prioritaires, :parcelles_agricoles] after_initialize :set_dynamic_type + after_create :populate_stable_id attr_reader :dynamic_type @@ -117,6 +118,12 @@ class TypeDeChamp < ApplicationRecord private + def populate_stable_id + if !stable_id + update_column(:stable_id, id) + end + end + def remove_piece_justificative_template if type_champ != TypeDeChamp.type_champs.fetch(:piece_justificative) && piece_justificative_template.attached? piece_justificative_template.purge_later diff --git a/spec/models/procedure_spec.rb b/spec/models/procedure_spec.rb index aa9934e67..cb9f92ad8 100644 --- a/spec/models/procedure_spec.rb +++ b/spec/models/procedure_spec.rb @@ -424,6 +424,11 @@ describe Procedure do expect(subject.path).to be_nil end end + + it 'should keep types_de_champ ids stable' do + expect(subject.types_de_champ_ordered.first.id).not_to eq(procedure.types_de_champ_ordered.first.id) + expect(subject.types_de_champ_ordered.first.stable_id).to eq(procedure.types_de_champ_ordered.first.id) + end end describe '#publish!' do diff --git a/spec/models/type_de_champ_shared_example.rb b/spec/models/type_de_champ_shared_example.rb index 092527bbc..5fbceb3bd 100644 --- a/spec/models/type_de_champ_shared_example.rb +++ b/spec/models/type_de_champ_shared_example.rb @@ -39,6 +39,15 @@ shared_examples 'type_de_champ_spec' do it { is_expected.to allow_value('blabla').for(:description) } end + context 'stable_id' do + it { + type_de_champ = create(:type_de_champ_text) + expect(type_de_champ.id).to eq(type_de_champ.stable_id) + cloned_type_de_champ = type_de_champ.clone + expect(cloned_type_de_champ.stable_id).to eq(type_de_champ.stable_id) + } + end + context 'remove piece_justificative_template' do context 'when the tdc is piece_justificative' do let(:template_double) { double('template', attached?: attached, purge_later: true) } From 8d222757424d1cc68973c7552b62ae3f59dcd9ad Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 27 Nov 2018 14:52:53 +0100 Subject: [PATCH 5/8] Make type_de_champ API ids stable --- app/serializers/type_de_champ_serializer.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/serializers/type_de_champ_serializer.rb b/app/serializers/type_de_champ_serializer.rb index 152e908e1..b8ef6ecb7 100644 --- a/app/serializers/type_de_champ_serializer.rb +++ b/app/serializers/type_de_champ_serializer.rb @@ -4,4 +4,8 @@ class TypeDeChampSerializer < ActiveModel::Serializer :type_champ, :order_place, :description + + def id + object.stable_id || object.id + end end From c1a2506b018288dc4c7028f809c407ea7239e14f Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 27 Nov 2018 14:53:09 +0100 Subject: [PATCH 6/8] Add stable ids to all types de champ --- ...123181252_add_stable_id_to_types_de_champ.rake | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 lib/tasks/deployment/20181123181252_add_stable_id_to_types_de_champ.rake diff --git a/lib/tasks/deployment/20181123181252_add_stable_id_to_types_de_champ.rake b/lib/tasks/deployment/20181123181252_add_stable_id_to_types_de_champ.rake new file mode 100644 index 000000000..dbb3283dd --- /dev/null +++ b/lib/tasks/deployment/20181123181252_add_stable_id_to_types_de_champ.rake @@ -0,0 +1,15 @@ +namespace :after_party do + desc 'Deployment task: add_stable_id_to_types_de_champ' + task add_stable_id_to_types_de_champ: :environment do + types_de_champ = TypeDeChamp.where(stable_id: nil) + bar = RakeProgressbar.new(types_de_champ.count) + + types_de_champ.find_each do |type_de_champ| + type_de_champ.update_column(:stable_id, type_de_champ.id) + bar.inc + end + bar.finished + + AfterParty::TaskRecord.create version: '20181123181252' + end +end From ca147969ab42b3739365b8d3847b711cc796b723 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 29 Nov 2018 14:35:42 +0100 Subject: [PATCH 7/8] Fix number champs validation --- app/models/champs/decimal_number_champ.rb | 2 +- app/models/champs/integer_number_champ.rb | 2 +- spec/models/champs/decimal_number_champ_spec.rb | 12 ++++++++++++ spec/models/champs/integer_number_champ_spec.rb | 12 ++++++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/app/models/champs/decimal_number_champ.rb b/app/models/champs/decimal_number_champ.rb index dcfcea707..b22fb2379 100644 --- a/app/models/champs/decimal_number_champ.rb +++ b/app/models/champs/decimal_number_champ.rb @@ -1,5 +1,5 @@ class Champs::DecimalNumberChamp < Champ - validates :value, numericality: { allow_nil: true } + validates :value, numericality: { allow_nil: true, allow_blank: true } def value_for_export value.to_f diff --git a/app/models/champs/integer_number_champ.rb b/app/models/champs/integer_number_champ.rb index d1e82ec4a..d7ca399a7 100644 --- a/app/models/champs/integer_number_champ.rb +++ b/app/models/champs/integer_number_champ.rb @@ -1,5 +1,5 @@ class Champs::IntegerNumberChamp < Champ - validates :value, numericality: { only_integer: true, allow_nil: true } + validates :value, numericality: { only_integer: true, allow_nil: true, allow_blank: true } def value_for_export value.to_i diff --git a/spec/models/champs/decimal_number_champ_spec.rb b/spec/models/champs/decimal_number_champ_spec.rb index 3e3bb9c26..8ec0ebdaf 100644 --- a/spec/models/champs/decimal_number_champ_spec.rb +++ b/spec/models/champs/decimal_number_champ_spec.rb @@ -21,5 +21,17 @@ describe Champs::DecimalNumberChamp do it { is_expected.to_not be_valid } end + + context 'when the value is blank' do + let(:value) { '' } + + it { is_expected.to be_valid } + end + + context 'when the value is nil' do + let(:value) { nil } + + it { is_expected.to be_valid } + end end end diff --git a/spec/models/champs/integer_number_champ_spec.rb b/spec/models/champs/integer_number_champ_spec.rb index 957d5e5c6..6a7152759 100644 --- a/spec/models/champs/integer_number_champ_spec.rb +++ b/spec/models/champs/integer_number_champ_spec.rb @@ -21,5 +21,17 @@ describe Champs::IntegerNumberChamp do it { is_expected.to_not be_valid } end + + context 'when the value is blank' do + let(:value) { '' } + + it { is_expected.to be_valid } + end + + context 'when the value is nil' do + let(:value) { nil } + + it { is_expected.to be_valid } + end end end From 35d2bc36fc15233e26448a671558b09e31e58ec2 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 29 Nov 2018 11:40:07 +0100 Subject: [PATCH 8/8] cleanup selection_utilisateur geo_json --- app/controllers/champs/carte_controller.rb | 18 +++++++++--------- app/models/champs/carte_champ.rb | 18 +++++++++--------- app/services/geojson_service.rb | 17 +++++++++++++++++ spec/serializers/champ_serializer_spec.rb | 22 +++++++++++++++++++++- 4 files changed, 56 insertions(+), 19 deletions(-) diff --git a/app/controllers/champs/carte_controller.rb b/app/controllers/champs/carte_controller.rb index 3609272fd..9b96f24bb 100644 --- a/app/controllers/champs/carte_controller.rb +++ b/app/controllers/champs/carte_controller.rb @@ -8,9 +8,9 @@ class Champs::CarteController < ApplicationController @selector = ".carte-#{params[:position]}" if params[:dossier].key?(:champs_attributes) - geo_json = params[:dossier][:champs_attributes][params[:position]][:value] + coordinates = params[:dossier][:champs_attributes][params[:position]][:value] else - geo_json = params[:dossier][:champs_private_attributes][params[:position]][:value] + coordinates = params[:dossier][:champs_private_attributes][params[:position]][:value] end if params[:champ_id].present? @@ -30,18 +30,18 @@ class Champs::CarteController < ApplicationController geo_areas = [] - if geo_json == EMPTY_GEO_JSON + if coordinates == EMPTY_GEO_JSON @champ.value = nil @champ.geo_areas = [] - elsif geo_json == ERROR_GEO_JSON + elsif coordinates == ERROR_GEO_JSON @error = true @champ.value = nil @champ.geo_areas = [] else - geo_json = JSON.parse(geo_json) + coordinates = JSON.parse(coordinates) if @champ.cadastres? - cadastres = ModuleApiCartoService.generate_cadastre(geo_json) + cadastres = ModuleApiCartoService.generate_cadastre(coordinates) geo_areas += cadastres.map do |cadastre| cadastre[:source] = GeoArea.sources.fetch(:cadastre) cadastre @@ -49,7 +49,7 @@ class Champs::CarteController < ApplicationController end if @champ.quartiers_prioritaires? - quartiers_prioritaires = ModuleApiCartoService.generate_qp(geo_json) + quartiers_prioritaires = ModuleApiCartoService.generate_qp(coordinates) geo_areas += quartiers_prioritaires.map do |qp| qp[:source] = GeoArea.sources.fetch(:quartier_prioritaire) qp @@ -57,7 +57,7 @@ class Champs::CarteController < ApplicationController end if @champ.parcelles_agricoles? - parcelles_agricoles = ModuleApiCartoService.generate_rpg(geo_json) + parcelles_agricoles = ModuleApiCartoService.generate_rpg(coordinates) geo_areas += parcelles_agricoles.map do |parcelle_agricole| parcelle_agricole[:source] = GeoArea.sources.fetch(:parcelle_agricole) parcelle_agricole @@ -68,7 +68,7 @@ class Champs::CarteController < ApplicationController GeoArea.new(geo_area) end - @champ.value = geo_json.to_json + @champ.value = GeojsonService.to_json_polygon_for_selection_utilisateur(coordinates) end if @champ.persisted? diff --git a/app/models/champs/carte_champ.rb b/app/models/champs/carte_champ.rb index 17e1f91ab..7eff98481 100644 --- a/app/models/champs/carte_champ.rb +++ b/app/models/champs/carte_champ.rb @@ -44,18 +44,18 @@ class Champs::CarteChamp < Champ end def geo_json - @geo_json ||= value.blank? ? [] : JSON.parse(value) + @geo_json ||= value.blank? ? nil : JSON.parse(value) end def user_geometry - { - type: 'Polygon', - coordinates: [ - geo_json[0].map do |polygon| - [polygon['lng'], polygon['lat']] - end - ] - } + # We used to store in the value column a json array with coordinates. + if geo_json.is_a?(Array) + # If it is a coordinates array, format it as a GEO-JSON + GeojsonService.to_json_polygon_for_selection_utilisateur(geo_json) + else + # It is already a GEO-JSON + geo_json + end end def user_geo_area diff --git a/app/services/geojson_service.rb b/app/services/geojson_service.rb index d7d3a3519..bfa717982 100644 --- a/app/services/geojson_service.rb +++ b/app/services/geojson_service.rb @@ -36,4 +36,21 @@ class GeojsonService polygon.to_json end + + def self.to_json_polygon_for_selection_utilisateur(coordinates) + coordinates = coordinates.map do |lat_longs| + outbounds = lat_longs.map do |lat_long| + [lat_long['lng'], lat_long['lat']] + end + + [outbounds] + end + + polygon = { + type: 'MultiPolygon', + coordinates: coordinates + } + + polygon.to_json + end end diff --git a/spec/serializers/champ_serializer_spec.rb b/spec/serializers/champ_serializer_spec.rb index 840f79516..1c82e296a 100644 --- a/spec/serializers/champ_serializer_spec.rb +++ b/spec/serializers/champ_serializer_spec.rb @@ -21,7 +21,27 @@ describe ChampSerializer do context 'when type champ is carte' do let(:geo_area) { create(:geo_area) } - let(:champ) { create(:type_de_champ_carte).champ.create(geo_areas: [geo_area]) } + let(:coordinates) { [[{ "lat": 48.87442541960633, "lng": 2.3859214782714844 }, { "lat": 48.87273183590832, "lng": 2.3850631713867183 }, { "lat": 48.87081237174292, "lng": 2.3809432983398438 }, { "lat": 48.8712640169951, "lng": 2.377510070800781 }, { "lat": 48.87510283703279, "lng": 2.3778533935546875 }, { "lat": 48.87544154230615, "lng": 2.382831573486328 }, { "lat": 48.87442541960633, "lng": 2.3859214782714844 }]] } + + let(:champ_carte) { create(:champ_carte, value: coordinates.to_json, geo_areas: [geo_area]) } + let(:champ) { champ_carte } + + context 'legacy champ user_geometry' do + let(:champ) { champ_carte.user_geo_area } + + it { + expect(subject).to include( + type_de_champ: { + descripton: "", + id: -1, + libelle: "user geometry", + order_place: -1, + type_champ: "user_geometry" + }, + value: champ_carte.user_geometry + ) + } + end context 'and geo_area is cadastre' do it {