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 db922d24e..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['lat'], polygon['lng']] - 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/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/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/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 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/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'] %>" 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| 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 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 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) } 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 {