Merge branch 'dev'

This commit is contained in:
gregoirenovel 2018-11-20 15:01:14 +01:00
commit eeb11ff3b3
54 changed files with 492 additions and 251 deletions

View file

@ -66,7 +66,7 @@ class Admin::ProceduresController < AdminController
@procedure = Procedure.new(procedure_params) @procedure = Procedure.new(procedure_params)
if @procedure.valid? if @procedure.valid?
@procedure.module_api_carto = ModuleAPICarto.new(create_module_api_carto_params) @procedure.module_api_carto = ModuleAPICarto.new
end end
@path = @procedure.path @path = @procedure.path
@ -271,8 +271,4 @@ class Admin::ProceduresController < AdminController
params.require(:procedure).permit(*editable_params, :duree_conservation_dossiers_dans_ds, :duree_conservation_dossiers_hors_ds, :for_individual, :individual_with_siret, :ask_birthday, module_api_carto_attributes: [:id, :use_api_carto, :quartiers_prioritaires, :cadastre]).merge(administrateur_id: current_administrateur.id) params.require(:procedure).permit(*editable_params, :duree_conservation_dossiers_dans_ds, :duree_conservation_dossiers_hors_ds, :for_individual, :individual_with_siret, :ask_birthday, module_api_carto_attributes: [:id, :use_api_carto, :quartiers_prioritaires, :cadastre]).merge(administrateur_id: current_administrateur.id)
end end
end end
def create_module_api_carto_params
params.require(:procedure).require(:module_api_carto_attributes).permit(:id, :use_api_carto, :quartiers_prioritaires, :cadastre)
end
end end

View file

@ -61,7 +61,7 @@ module NewUser
@dossier.update!(autorisation_donnees: true) @dossier.update!(autorisation_donnees: true)
flash.notice = "Identité enregistrée" flash.notice = "Identité enregistrée"
if @dossier.procedure.module_api_carto.use_api_carto if @dossier.use_legacy_carto?
redirect_to users_dossier_carte_path(@dossier.id) redirect_to users_dossier_carte_path(@dossier.id)
else else
redirect_to brouillon_dossier_path(@dossier) redirect_to brouillon_dossier_path(@dossier)

View file

@ -20,10 +20,20 @@ delegate('ajax:send', '[data-remote]', ({ target }) => {
// jQuery-less version of rails-ujs it breaks. // jQuery-less version of rails-ujs it breaks.
// https://github.com/Sology/smart_listing/blob/master/app/assets/javascripts/smart_listing.coffee.erb#L9 // https://github.com/Sology/smart_listing/blob/master/app/assets/javascripts/smart_listing.coffee.erb#L9
addEventListener('load', () => { addEventListener('load', () => {
const { href } = Rails; const { href, handleRemote } = Rails;
Rails.href = function(element) { Rails.href = function(element) {
return element.href || href(element); return element.href || href(element);
}; };
Rails.handleRemote = function(e) {
if (this instanceof HTMLElement) {
handleRemote.call(this, e);
} else {
let element = e.find('[data-remote]')[0];
let event = new CustomEvent('click');
Object.defineProperty(event, 'target', { value: element });
return handleRemote.call(element, event);
}
};
}); });
// rails-ujs installs CSRFProtection for its own ajax implementation. We might need // rails-ujs installs CSRFProtection for its own ajax implementation. We might need

View file

@ -1,3 +1,4 @@
# Preview all emails at http://localhost:3000/rails/mailers/administrateur_mailer
class AdministrateurMailer < ApplicationMailer class AdministrateurMailer < ApplicationMailer
layout 'mailers/layout' layout 'mailers/layout'

View file

@ -1,3 +1,4 @@
# Preview all emails at http://localhost:3000/rails/mailers/administration_mailer
class AdministrationMailer < ApplicationMailer class AdministrationMailer < ApplicationMailer
layout 'mailers/layout' layout 'mailers/layout'

View file

@ -1,3 +1,4 @@
# Preview all emails at http://localhost:3000/rails/mailers/avis_mailer
class AvisMailer < ApplicationMailer class AvisMailer < ApplicationMailer
def avis_invitation(avis) def avis_invitation(avis)
@avis = avis @avis = avis

View file

@ -1,3 +1,4 @@
# Preview all emails at http://localhost:3000/rails/mailers/devise_user_mailer
class DeviseUserMailer < Devise::Mailer class DeviseUserMailer < Devise::Mailer
helper :application # gives access to all helpers defined within `application_helper`. helper :application # gives access to all helpers defined within `application_helper`.
include Devise::Controllers::UrlHelpers # Optional. eg. `confirmation_url` include Devise::Controllers::UrlHelpers # Optional. eg. `confirmation_url`

View file

@ -1,6 +1,23 @@
# Preview all emails at http://localhost:3000/rails/mailers/dossier_mailer
class DossierMailer < ApplicationMailer class DossierMailer < ApplicationMailer
layout 'mailers/layout' layout 'mailers/layout'
def notify_new_draft(dossier)
@dossier = dossier
subject = "Retrouvez votre brouillon pour la démarche \"#{dossier.procedure.libelle}\""
mail(to: dossier.user.email, subject: subject)
end
def notify_new_answer(dossier)
@dossier = dossier
subject = "Nouveau message pour votre dossier nº #{dossier.id}"
mail(to: dossier.user.email, subject: subject) do |format|
format.html { render layout: 'mailers/notification' }
end
end
def notify_deletion_to_user(deleted_dossier, to_email) def notify_deletion_to_user(deleted_dossier, to_email)
@deleted_dossier = deleted_dossier @deleted_dossier = deleted_dossier
subject = "Votre dossier n° #{@deleted_dossier.dossier_id} a bien été supprimé" subject = "Votre dossier n° #{@deleted_dossier.dossier_id} a bien été supprimé"

View file

@ -1,3 +1,4 @@
# Preview all emails at http://localhost:3000/rails/mailers/gestionnaire_mailer
class GestionnaireMailer < ApplicationMailer class GestionnaireMailer < ApplicationMailer
layout 'mailers/layout' layout 'mailers/layout'

View file

@ -1,3 +1,4 @@
# Preview all emails at http://localhost:3000/rails/mailers/invite_mailer
class InviteMailer < ApplicationMailer class InviteMailer < ApplicationMailer
def invite_user(invite) def invite_user(invite)
subject = "Participez à l'élaboration d'un dossier" subject = "Participez à l'élaboration d'un dossier"

View file

@ -1,3 +1,4 @@
# Preview all emails at http://localhost:3000/rails/mailers/new_attestation_mailer
class NewAttestationMailer < ApplicationMailer class NewAttestationMailer < ApplicationMailer
include Rails.application.routes.url_helpers include Rails.application.routes.url_helpers

View file

@ -1,16 +1,11 @@
# Preview all emails at http://localhost:3000/rails/mailers/notification_mailer
# A Notification is attached as a Comment to the relevant discussion,
# then sent by email to the user.
#
# The subject and body of a Notification can be customized by each demarche.
#
class NotificationMailer < ApplicationMailer class NotificationMailer < ApplicationMailer
def new_answer(dossier)
subject = "Nouveau message pour votre dossier nº #{dossier.id}"
send_mail(dossier, subject)
end
def send_draft_notification(dossier)
subject = "Retrouvez votre brouillon pour la démarche \"#{dossier.procedure.libelle}\""
send_mail(dossier, subject)
end
def send_dossier_received(dossier) def send_dossier_received(dossier)
send_notification(dossier, dossier.procedure.received_mail_template) send_notification(dossier, dossier.procedure.received_mail_template)
end end
@ -33,13 +28,6 @@ class NotificationMailer < ApplicationMailer
private private
def send_mail(dossier, subject)
@dossier = dossier
email = dossier.user.email
mail(subject: subject, to: email)
end
def send_notification(dossier, mail_template) def send_notification(dossier, mail_template)
email = dossier.user.email email = dossier.user.email

View file

@ -1,3 +1,4 @@
# Preview all emails at http://localhost:3000/rails/mailers/user_mailer
class UserMailer < ApplicationMailer class UserMailer < ApplicationMailer
layout 'mailers/layout' layout 'mailers/layout'

View file

@ -43,7 +43,27 @@ class Champs::CarteChamp < Champ
end end
end end
def zones def geo_json
value.blank? ? [] : JSON.parse(value) @geo_json ||= value.blank? ? [] : JSON.parse(value)
end
def user_geometry
{
type: 'Polygon',
coordinates: [
geo_json[0].map do |polygon|
[polygon['lat'], polygon['lng']]
end
]
}
end
def user_geo_area
if geo_json.present?
GeoArea.new(
geometry: user_geometry,
source: GeoArea.sources.fetch(:selection_utilisateur)
)
end
end end
end end

View file

@ -48,7 +48,7 @@ class Commentaire < ApplicationRecord
end end
def notify_user def notify_user
NotificationMailer.new_answer(dossier).deliver_later DossierMailer.notify_new_answer(dossier).deliver_later
end end
def is_virus_free? def is_virus_free?

View file

@ -245,6 +245,14 @@ class Dossier < ApplicationRecord
end end
end end
def use_legacy_carto?
procedure.use_legacy_carto?
end
def expose_legacy_carto_api?
procedure.expose_legacy_carto_api?
end
def user_geometry def user_geometry
if json_latlngs.present? if json_latlngs.present?
UserGeometry.new(json_latlngs) UserGeometry.new(json_latlngs)
@ -348,7 +356,7 @@ class Dossier < ApplicationRecord
def send_draft_notification_email def send_draft_notification_email
if brouillon? if brouillon?
NotificationMailer.send_draft_notification(self).deliver_later DossierMailer.notify_new_draft(self).deliver_later
end end
end end

View file

@ -23,7 +23,8 @@ class GeoArea < ApplicationRecord
enum source: { enum source: {
quartier_prioritaire: 'quartier_prioritaire', quartier_prioritaire: 'quartier_prioritaire',
cadastre: 'cadastre', cadastre: 'cadastre',
parcelle_agricole: 'parcelle_agricole' parcelle_agricole: 'parcelle_agricole',
selection_utilisateur: 'selection_utilisateur'
} }
scope :quartiers_prioritaires, -> { where(source: sources.fetch(:quartier_prioritaire)) } scope :quartiers_prioritaires, -> { where(source: sources.fetch(:quartier_prioritaire)) }

View file

@ -30,8 +30,6 @@ class Procedure < ApplicationRecord
has_one_attached :notice has_one_attached :notice
has_one_attached :deliberation has_one_attached :deliberation
delegate :use_api_carto, to: :module_api_carto
accepts_nested_attributes_for :types_de_champ, :reject_if => proc { |attributes| attributes['libelle'].blank? }, :allow_destroy => true accepts_nested_attributes_for :types_de_champ, :reject_if => proc { |attributes| attributes['libelle'].blank? }, :allow_destroy => true
accepts_nested_attributes_for :types_de_piece_justificative, :reject_if => proc { |attributes| attributes['libelle'].blank? }, :allow_destroy => true accepts_nested_attributes_for :types_de_piece_justificative, :reject_if => proc { |attributes| attributes['libelle'].blank? }, :allow_destroy => true
accepts_nested_attributes_for :module_api_carto accepts_nested_attributes_for :module_api_carto
@ -133,6 +131,14 @@ class Procedure < ApplicationRecord
publiee? || archivee? publiee? || archivee?
end end
def use_legacy_carto?
module_api_carto.use_api_carto? && !module_api_carto.migrated?
end
def expose_legacy_carto_api?
module_api_carto.use_api_carto? && module_api_carto.migrated?
end
# Warning: dossier after_save build_default_champs must be removed # Warning: dossier after_save build_default_champs must be removed
# to save a dossier created from this method # to save a dossier created from this method
def new_dossier def new_dossier

View file

@ -5,7 +5,7 @@ class UserGeometry
@json_latlngs = json_latlngs @json_latlngs = json_latlngs
end end
def value def geometry
to_geo_json(@json_latlngs) to_geo_json(@json_latlngs)
end end

View file

@ -1,17 +0,0 @@
class CadastreSerializer < ActiveModel::Serializer
attributes :value, :type_de_champ
def value
object.geometry
end
def type_de_champ
{
id: -1,
libelle: 'cadastre',
type_champ: 'cadastre',
order_place: -1,
descripton: ''
}
end
end

View file

@ -5,11 +5,99 @@ class ChampSerializer < ActiveModel::Serializer
has_one :type_de_champ has_one :type_de_champ
has_many :geo_areas, if: :include_geo_areas?
has_one :etablissement, if: :include_etablissement?
has_one :entreprise, if: :include_etablissement?
def value def value
if object.piece_justificative_file.attached? case object
url_for(object.piece_justificative_file) when GeoArea, UserGeometry, Cadastre, QuartierPrioritaire
object.geometry
when Champs::CarteChamp
if object.value.present?
JSON.parse(object.value)
end
when Champs::DecimalNumberChamp
if object.value.present?
object.value.to_f
end
when Champs::IntegerNumberChamp
if object.value.present?
object.value.to_i
end
when Champs::LinkedDropDownListChamp
if object.value.present?
{ primary: object.primary_value, secondary: object.secondary_value }
end
when Champs::PieceJustificativeChamp
if object.piece_justificative_file.attached?
url_for(object.piece_justificative_file)
end
else else
object.value object.value
end end
end end
def type_de_champ
case object
when GeoArea, UserGeometry, Cadastre, QuartierPrioritaire
legacy_type_de_champ
else
object.type_de_champ
end
end
def etablissement
object.etablissement
end
def entreprise
object.etablissement&.entreprise
end
def include_etablissement?
object.is_a?(Champs::SiretChamp)
end
def include_geo_areas?
object.is_a?(Champs::CarteChamp)
end
private
def legacy_type_de_champ
{
id: -1,
libelle: legacy_carto_libelle,
type_champ: legacy_carto_type_champ,
order_place: -1,
descripton: ''
}
end
def legacy_carto_libelle
case object
when UserGeometry, Cadastre, QuartierPrioritaire
object.class.name.underscore.tr('_', ' ')
else
if object.source == GeoArea.sources.fetch(:selection_utilisateur)
'user geometry'
else
object.source.to_s.tr('_', ' ')
end
end
end
def legacy_carto_type_champ
case object
when UserGeometry, Cadastre, QuartierPrioritaire
object.class.name.underscore
else
if object.source == GeoArea.sources.fetch(:selection_utilisateur)
'user_geometry'
else
object.source.to_s
end
end
end
end end

View file

@ -1,11 +0,0 @@
class Champs::CarteChampSerializer < ChampSerializer
has_many :geo_areas
def value
if object.value.present?
JSON.parse(object.value)
else
nil
end
end
end

View file

@ -1,7 +0,0 @@
class Champs::DecimalNumberChampSerializer < ChampSerializer
def value
if object.value.present?
object.value.to_f
end
end
end

View file

@ -1,7 +0,0 @@
class Champs::IntegerNumberChampSerializer < ChampSerializer
def value
if object.value.present?
object.value.to_i
end
end
end

View file

@ -1,5 +0,0 @@
class Champs::LinkedDropDownListChampSerializer < ChampSerializer
def value
{ primary: object.primary_value, secondary: object.secondary_value }
end
end

View file

@ -1,12 +0,0 @@
class Champs::SiretChampSerializer < ChampSerializer
has_one :etablissement
has_one :entreprise
def etablissement
object.etablissement
end
def entreprise
object.etablissement&.entreprise
end
end

View file

@ -23,11 +23,30 @@ class DossierSerializer < ActiveModel::Serializer
has_many :pieces_justificatives has_many :pieces_justificatives
has_many :types_de_piece_justificative has_many :types_de_piece_justificative
has_many :champs do has_many :champs, serializer: ChampSerializer
champs = object.champs + object.quartier_prioritaires + object.cadastres
if object.user_geometry.present? def champs
champs << object.user_geometry champs = object.champs.to_a
if object.use_legacy_carto?
champs += object.quartier_prioritaires
champs += object.cadastres
if object.user_geometry.present?
champs << object.user_geometry
end
elsif object.expose_legacy_carto_api?
champ_carte = champs.find do |champ|
champ.type_de_champ.type_champ == TypeDeChamp.type_champs.fetch(:carte)
end
if champ_carte.present?
carto_champs = champ_carte.geo_areas.to_a
carto_champs << champ_carte.user_geo_area
champs += carto_champs.compact
end
end end
champs champs
end end
@ -74,19 +93,4 @@ class DossierSerializer < ActiveModel::Serializer
def processed_at def processed_at
object.processed_at&.in_time_zone('UTC') object.processed_at&.in_time_zone('UTC')
end end
private
def user_geometry(dossier)
{
value: dossier.geometry,
type_de_champ: {
id: -1,
libelle: 'user_geometry',
type_champ: 'user_geometry',
order_place: -1,
descripton: ''
}
}
end
end end

View file

@ -1,17 +0,0 @@
class QuartierPrioritaireSerializer < ActiveModel::Serializer
attributes :value, :type_de_champ
def value
object.geometry
end
def type_de_champ
{
id: -1,
libelle: 'quartier prioritaire',
type_champ: 'quartier_prioritaire',
order_place: -1,
descripton: ''
}
end
end

View file

@ -1,3 +0,0 @@
class UserGeometrySerializer < ActiveModel::Serializer
attributes :value, :type_de_champ
end

View file

@ -3,6 +3,6 @@ class UserRoutesAuthorizationService
auth = controller.route_authorization auth = controller.route_authorization
auth[:states].include?(dossier.state) && auth[:states].include?(dossier.state) &&
(auth[:api_carto].nil? ? true : auth[:api_carto] == dossier.procedure.use_api_carto) (auth[:api_carto].nil? ? true : auth[:api_carto] == dossier.use_legacy_carto?)
end end
end end

View file

@ -119,30 +119,6 @@
Afficher le drapeau européen Afficher le drapeau européen
- if !@procedure.locked? - if !@procedure.locked?
.row
.col-md-6
%h4 Cartographie
= f.fields_for :module_api_carto, @procedure.module_api_carto do |ff|
.checkbox
%label
= ff.check_box :use_api_carto, id: "procedure-module-api-carto-use-api-carto"
Utilisation de la cartographie
%ul#modules-api-carto
%li
.checkbox
%label
= ff.check_box :quartiers_prioritaires
Quartiers prioritaires
%li
.checkbox
%label
= ff.check_box :cadastre
Cadastre
.col-md-6
.row .row
.col-md-6 .col-md-6
%h4 Particuliers %h4 Particuliers

View file

@ -13,9 +13,3 @@
%p %p
L'équipe demarches-simplifiees.fr L'équipe demarches-simplifiees.fr
%p
%p
Merci de ne pas répondre à cet email. Postez directement vos questions dans votre dossier sur la plateforme.

View file

@ -17,7 +17,7 @@
- if champs.any? - if champs.any?
= render partial: "shared/dossiers/champs", locals: { champs: champs, dossier: @dossier, demande_seen_at: nil, profile: 'instructeur' } = render partial: "shared/dossiers/champs", locals: { champs: champs, dossier: @dossier, demande_seen_at: nil, profile: 'instructeur' }
- if @dossier.procedure.use_api_carto - if @dossier.use_legacy_carto?
%h3 Cartographie %h3 Cartographie
- if @dossier.quartier_prioritaires.any? - if @dossier.quartier_prioritaires.any?
%h4 Quartiers prioritaires %h4 Quartiers prioritaires

View file

@ -25,7 +25,7 @@
.actions .actions
= link_to 'Utiliser un autre numéro SIRET', siret_dossier_path(@dossier), class: 'button' = link_to 'Utiliser un autre numéro SIRET', siret_dossier_path(@dossier), class: 'button'
- if @dossier.procedure.use_api_carto - if @dossier.use_legacy_carto?
/ Until the old layout is gone, we need to disable turbolinks / Until the old layout is gone, we need to disable turbolinks
/ to avoid the map loading twice (once for the turbolinks preview, / to avoid the map loading twice (once for the turbolinks preview,
/ once when turbolinks notices the layout are differents and reloads / once when turbolinks notices the layout are differents and reloads

View file

@ -6,7 +6,7 @@
- elsif champ.value.blank? - elsif champ.value.blank?
Aucune zone tracée Aucune zone tracée
- elsif champ.quartiers_prioritaires.blank? - elsif champ.quartiers_prioritaires.blank?
= t('errors.messages.quartiers_prioritaires_empty', count: champ.zones.size) = t('errors.messages.quartiers_prioritaires_empty', count: champ.geo_json.size)
- else - else
%ul %ul
- champ.quartiers_prioritaires.each do |qp| - champ.quartiers_prioritaires.each do |qp|
@ -20,7 +20,7 @@
- elsif champ.value.blank? - elsif champ.value.blank?
Aucune zone tracée Aucune zone tracée
- elsif champ.cadastres.blank? - elsif champ.cadastres.blank?
= t('errors.messages.cadastres_empty', count: champ.zones.size) = t('errors.messages.cadastres_empty', count: champ.geo_json.size)
- else - else
%ul %ul
- champ.cadastres.each do |pc| - champ.cadastres.each do |pc|
@ -34,7 +34,7 @@
- elsif champ.value.blank? - elsif champ.value.blank?
Aucune zone tracée Aucune zone tracée
- elsif champ.parcelles_agricoles.blank? - elsif champ.parcelles_agricoles.blank?
= t('errors.messages.parcelles_agricoles_empty', count: champ.zones.size) = t('errors.messages.parcelles_agricoles_empty', count: champ.geo_json.size)
- else - else
%ul %ul
- champ.parcelles_agricoles.each do |pa| - champ.parcelles_agricoles.each do |pa|

View file

@ -15,7 +15,7 @@
.card .card
= render partial: "shared/dossiers/champs", locals: { champs: champs, demande_seen_at: demande_seen_at, profile: profile } = render partial: "shared/dossiers/champs", locals: { champs: champs, demande_seen_at: demande_seen_at, profile: profile }
- if dossier.procedure.use_api_carto - if dossier.use_legacy_carto?
.tab-title Cartographie .tab-title Cartographie
.card .card
= render partial: "shared/dossiers/map", locals: { dossier: dossier } = render partial: "shared/dossiers/map", locals: { dossier: dossier }

View file

@ -0,0 +1,5 @@
class AddMigratedToModuleAPICartos < ActiveRecord::Migration[5.2]
def change
add_column :module_api_cartos, :migrated, :boolean
end
end

View file

@ -408,6 +408,7 @@ ActiveRecord::Schema.define(version: 2018_11_08_151929) do
t.boolean "cadastre", default: false t.boolean "cadastre", default: false
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.boolean "migrated"
t.index ["procedure_id"], name: "index_module_api_cartos_on_procedure_id", unique: true t.index ["procedure_id"], name: "index_module_api_cartos_on_procedure_id", unique: true
end end

View file

@ -0,0 +1,80 @@
namespace :after_party do
desc 'Deployment task: migrate_carto_to_carte'
task migrate_carto_to_carte: :environment do
def add_champ_carte_if_needed(procedure)
champ_carte = procedure.types_de_champ_ordered.to_a.find do |type_de_champ|
type_de_champ.type_champ == TypeDeChamp.type_champs.fetch(:carte)
end
if champ_carte
puts "Procedure##{procedure.id} already migrated to use champ carte"
else
add_champ_carte(procedure)
end
end
def add_champ_carte(procedure)
qp = !!procedure.module_api_carto.quartiers_prioritaires
ca = !!procedure.module_api_carto.cadastre
puts "Creating champ carte on Procedure##{procedure.id} with qp:#{qp} and ca:#{ca}..."
procedure.types_de_champ.update_all('order_place = order_place + 1')
type_de_champ = procedure.types_de_champ.create(
order_place: 0,
libelle: 'Cartographie',
type_champ: TypeDeChamp.type_champs.fetch(:carte),
quartiers_prioritaires: qp,
cadastres: ca,
mandatory: true
)
procedure.dossiers.each do |dossier|
champ = type_de_champ.champ.create(dossier: dossier, value: dossier.json_latlngs)
if ca && !dossier.cadastres.empty?
puts "Creating Cadastres on Dossier##{dossier.id}..."
dossier.cadastres.each do |cadastre|
champ.geo_areas.create(
source: GeoArea.sources.fetch(:cadastre),
geometry: cadastre.geometry,
surface_intersection: cadastre.surface_intersection,
surface_parcelle: cadastre.surface_parcelle,
numero: cadastre.numero,
feuille: cadastre.feuille,
section: cadastre.section,
code_dep: cadastre.code_dep,
nom_com: cadastre.nom_com,
code_com: cadastre.code_com,
code_arr: cadastre.code_arr
)
end
end
if qp && !dossier.quartier_prioritaires.empty?
puts "Creating Quartiers Prioritaires on Dossier##{dossier.id}..."
dossier.quartier_prioritaires.each do |qp|
champ.geo_areas.create(
source: GeoArea.sources.fetch(:quartier_prioritaire),
geometry: qp.geometry,
code: qp.code,
nom: qp.nom,
commune: qp.commune
)
end
end
end
procedure.module_api_carto.update(migrated: true)
end
Procedure.includes(:types_de_champ, dossiers: [:cadastres, :quartier_prioritaires])
.joins(:module_api_carto)
.where(module_api_cartos: { use_api_carto: true, migrated: nil })
.find_each do |procedure|
add_champ_carte_if_needed(procedure)
end
AfterParty::TaskRecord.create version: '20181030155307'
end
end

View file

@ -201,18 +201,6 @@ describe Admin::ProceduresController, type: :controller do
it { expect(subject.duree_conservation_dossiers_hors_ds).to eq(duree_conservation_dossiers_hors_ds) } it { expect(subject.duree_conservation_dossiers_hors_ds).to eq(duree_conservation_dossiers_hors_ds) }
end end
describe 'procedure module api carto attributs in database' do
let(:procedure) { Procedure.last }
let(:use_api_carto) { '1' }
let(:quartiers_prioritaires) { '1' }
subject { ModuleAPICarto.last }
it { expect(subject.procedure).to eq(procedure) }
it { expect(subject.use_api_carto).to be_truthy }
it { expect(subject.quartiers_prioritaires).to be_truthy }
end
it { is_expected.to redirect_to(admin_procedure_types_de_champ_path(procedure_id: Procedure.last.id)) } it { is_expected.to redirect_to(admin_procedure_types_de_champ_path(procedure_id: Procedure.last.id)) }
it { expect(flash[:notice]).to be_present } it { expect(flash[:notice]).to be_present }
@ -346,7 +334,7 @@ describe Admin::ProceduresController, type: :controller do
it { expect(subject.for_individual).not_to eq procedure_params[:for_individual] } it { expect(subject.for_individual).not_to eq procedure_params[:for_individual] }
it { expect(subject.individual_with_siret).not_to eq procedure_params[:individual_with_siret] } it { expect(subject.individual_with_siret).not_to eq procedure_params[:individual_with_siret] }
it { expect(subject.use_api_carto).not_to eq procedure_params[:module_api_carto_attributes][:use_api_carto] } it { expect(subject.use_legacy_carto?).not_to eq procedure_params[:module_api_carto_attributes][:use_api_carto] }
end end
end end
end end

View file

@ -3,7 +3,7 @@ require 'spec_helper'
describe API::V1::DossiersController do describe API::V1::DossiersController do
let(:admin) { create(:administrateur) } let(:admin) { create(:administrateur) }
let(:token) { admin.renew_api_token } let(:token) { admin.renew_api_token }
let(:procedure) { create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ, :with_type_de_champ_private, administrateur: admin) } let(:procedure) { create(:procedure, :with_api_carto, :with_two_type_de_piece_justificative, :with_type_de_champ, :with_type_de_champ_private, administrateur: admin) }
let(:wrong_procedure) { create(:procedure) } let(:wrong_procedure) { create(:procedure) }
it { expect(described_class).to be < APIController } it { expect(described_class).to be < APIController }
@ -290,8 +290,8 @@ describe API::V1::DossiersController do
super().find { |champ| champ[:type_de_champ][:type_champ] == 'user_geometry' } super().find { |champ| champ[:type_de_champ][:type_champ] == 'user_geometry' }
end end
it { expect(subject[:type_de_champ]).to match({ id: -1, libelle: 'user_geometry', type_champ: 'user_geometry', order_place: -1, descripton: '' }) } it { expect(subject[:type_de_champ]).to match({ id: -1, libelle: 'user geometry', type_champ: 'user_geometry', order_place: -1, descripton: '' }) }
it { expect(subject[:value]).to match(UserGeometry.new(dossier.json_latlngs).value) } it { expect(subject[:value]).to match(UserGeometry.new(dossier.json_latlngs).geometry) }
end end
end end

View file

@ -28,4 +28,41 @@ FactoryBot.define do
end end
end end
end end
factory :champ_integer_number, class: 'Champs::IntegerNumberChamp' do
type_de_champ { create(:type_de_champ_integer_number) }
value { '42' }
end
factory :champ_decimal_number, class: 'Champs::DecimalNumberChamp' do
type_de_champ { create(:type_de_champ_decimal_number) }
value { '42.1' }
end
factory :champ_linked_drop_down_list, class: 'Champs::LinkedDropDownListChamp' do
type_de_champ { create(:type_de_champ_linked_drop_down_list) }
value { '{}' }
end
factory :champ_carte, class: 'Champs::CarteChamp' do
type_de_champ { create(:type_de_champ_carte) }
end
factory :champ_siret, class: 'Champs::SiretChamp' do
type_de_champ { create(:type_de_champ_siret) }
value { '44011762001530' }
etablissement { create(:etablissement) }
before(:create) do |champ, evaluator|
champ.etablissement.signature = champ.etablissement.sign
end
end
factory :champ_piece_justificative, class: 'Champs::PieceJustificativeChamp' do
type_de_champ { create(:type_de_champ_piece_justificative) }
after(:create) do |champ, evaluator|
champ.piece_justificative_file.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain")
end
end
end end

View file

@ -0,0 +1,39 @@
require 'spec_helper'
describe '2018_10_30_migrate_carto_to_carte' do
let(:rake_task) { Rake::Task['after_party:migrate_carto_to_carte'] }
let(:procedure) { create(:procedure, :published, :with_api_carto) }
let(:dossier) { create(:dossier, :with_two_quartier_prioritaires, :with_two_cadastres) }
def run_task
procedure.module_api_carto.quartiers_prioritaires = true
procedure.module_api_carto.cadastre = true
procedure.module_api_carto.save
procedure.dossiers << dossier
rake_task.invoke
procedure.reload
dossier.reload
end
after { rake_task.reenable }
context 'on happy path' do
before do
run_task
end
it {
expect(procedure.module_api_carto.migrated?).to be_truthy
expect(dossier.cadastres.count).to eq(2)
expect(dossier.quartier_prioritaires.count).to eq(2)
expect(dossier.champs.first.type_champ).to eq('carte')
expect(dossier.champs.first.order_place).to eq(0)
expect(dossier.champs.first.libelle).to eq('Cartographie')
expect(dossier.champs.first.geo_areas.count).to eq(4)
expect(dossier.champs.first.mandatory?).to be_truthy
expect(dossier.champs.first.cadastres?).to be_truthy
expect(dossier.champs.first.quartiers_prioritaires?).to be_truthy
}
end
end

View file

@ -3,6 +3,27 @@ require "rails_helper"
RSpec.describe DossierMailer, type: :mailer do RSpec.describe DossierMailer, type: :mailer do
let(:to_email) { 'gestionnaire@exemple.gouv.fr' } let(:to_email) { 'gestionnaire@exemple.gouv.fr' }
describe '.notify_new_draft' do
let(:dossier) { create(:dossier, procedure: build(:simple_procedure)) }
subject { described_class.notify_new_draft(dossier) }
it { expect(subject.subject).to include("brouillon") }
it { expect(subject.subject).to include(dossier.id.to_s) }
it { expect(subject.body).to include(dossier.procedure.libelle) }
it { expect(subject.body).to include(dossier_url(dossier)) }
end
describe '.notify_new_answer' do
let(:dossier) { create(:dossier, procedure: build(:simple_procedure)) }
subject { described_class.notify_new_answer(dossier) }
it { expect(subject.subject).to include("Nouveau message") }
it { expect(subject.subject).to include(dossier.id.to_s) }
it { expect(subject.body).to include(messagerie_dossier_url(dossier)) }
end
describe '.notify_deletion_to_user' do describe '.notify_deletion_to_user' do
let(:deleted_dossier) { build(:deleted_dossier) } let(:deleted_dossier) { build(:deleted_dossier) }

View file

@ -55,12 +55,4 @@ RSpec.describe NotificationMailer, type: :mailer do
it_behaves_like "create a commentaire not notified" it_behaves_like "create a commentaire not notified"
end end
describe ".new_answer" do
subject(:subject) { described_class.new_answer(dossier) }
it { expect(subject.body).to match('Un nouveau message est disponible dans votre espace demarches-simplifiees.fr.') }
it { expect(subject.body).to include(messagerie_dossier_url(dossier)) }
it { expect(subject.subject).to eq("Nouveau message pour votre dossier nº #{dossier.id}") }
end
end end

View file

@ -1,5 +1,13 @@
# Preview all emails at http://localhost:3000/rails/mailers/dossier_mailer # Preview all emails at http://localhost:3000/rails/mailers/dossier_mailer
class DossierMailerPreview < ActionMailer::Preview class DossierMailerPreview < ActionMailer::Preview
def notify_new_draft
DossierMailer.notify_new_draft(Dossier.last)
end
def notify_new_answer
DossierMailer.notify_new_answer(Dossier.last)
end
def notify_deletion_to_user def notify_deletion_to_user
DossierMailer.notify_deletion_to_user(DeletedDossier.last, "user@ds.fr") DossierMailer.notify_deletion_to_user(DeletedDossier.last, "user@ds.fr")
end end

View file

@ -1,9 +1,21 @@
class NotificationMailerPreview < ActionMailer::Preview class NotificationMailerPreview < ActionMailer::Preview
def send_notification def send_dossier_received
NotificationMailer.send_dossier_received(Dossier.last)
end
def send_initiated_notification
NotificationMailer.send_initiated_notification(Dossier.last) NotificationMailer.send_initiated_notification(Dossier.last)
end end
def send_draft_notification def send_closed_notification
NotificationMailer.send_draft_notification(Dossier.last) NotificationMailer.send_closed_notification(Dossier.last)
end
def send_refused_notification
NotificationMailer.send_refused_notification(Dossier.last)
end
def send_without_continuation_notification
NotificationMailer.send_without_continuation_notification(Dossier.last)
end end
end end

View file

@ -1,4 +1,4 @@
class UserPreview < ActionMailer::Preview class UserMailerPreview < ActionMailer::Preview
def new_account_warning def new_account_warning
UserMailer.new_account_warning(User.first) UserMailer.new_account_warning(User.first)
end end

View file

@ -841,7 +841,7 @@ describe Dossier do
} }
end end
subject{ dossier.user_geometry.value } subject{ dossier.user_geometry.geometry }
it { is_expected.to eq(expected) } it { is_expected.to eq(expected) }
end end

View file

@ -5,7 +5,7 @@ describe ChampSerializer do
context 'when type champ is piece justificative' do context 'when type champ is piece justificative' do
include Rails.application.routes.url_helpers include Rails.application.routes.url_helpers
let(:champ) { create(:champ, type_de_champ: create(:type_de_champ_piece_justificative)) } let(:champ) { create(:champ_piece_justificative) }
before { champ.piece_justificative_file.attach({ filename: __FILE__, io: File.open(__FILE__) }) } before { champ.piece_justificative_file.attach({ filename: __FILE__, io: File.open(__FILE__) }) }
after { champ.piece_justificative_file.purge } after { champ.piece_justificative_file.purge }
@ -18,5 +18,45 @@ describe ChampSerializer do
it { is_expected.to include(value: "blah") } it { is_expected.to include(value: "blah") }
end end
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]) }
context 'and geo_area is cadastre' do
it {
expect(subject[:geo_areas].first).to include(
source: GeoArea.sources.fetch(:cadastre),
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
context 'when type champ is siret' do
let(:etablissement) { create(:etablissement) }
let(:champ) { create(:type_de_champ_siret).champ.create(etablissement: etablissement, value: etablissement.siret) }
it {
is_expected.to include(value: etablissement.siret)
expect(subject[:etablissement]).to include(siret: etablissement.siret)
expect(subject[:entreprise]).to include(capital_social: etablissement.entreprise_capital_social)
}
end
end end
end end

View file

@ -1,34 +0,0 @@
describe Champs::CarteChampSerializer do
describe '#attributes' do
subject { Champs::CarteChampSerializer.new(champ).serializable_hash }
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]) }
context 'and geo_area is cadastre' do
it {
expect(subject[:geo_areas].first).to include(
source: GeoArea.sources.fetch(:cadastre),
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

View file

@ -1,16 +0,0 @@
describe Champs::SiretChampSerializer do
describe '#attributes' do
subject { Champs::SiretChampSerializer.new(champ).serializable_hash }
context 'when type champ is siret' do
let(:etablissement) { create(:etablissement) }
let(:champ) { create(:type_de_champ_siret).champ.create(etablissement: etablissement, value: etablissement.siret) }
it {
is_expected.to include(value: etablissement.siret)
expect(subject[:etablissement]).to include(siret: etablissement.siret)
expect(subject[:entreprise]).to include(capital_social: etablissement.entreprise_capital_social)
}
end
end
end

View file

@ -14,5 +14,36 @@ describe DossierSerializer do
it { is_expected.to include(received_at: dossier.en_instruction_at) } it { is_expected.to include(received_at: dossier.en_instruction_at) }
end end
context 'champs' do
subject { super()[:champs] }
let(:dossier) { create(:dossier, :en_construction, :with_two_quartier_prioritaires, procedure: create(:procedure, :published, :with_api_carto, :with_type_de_champ)) }
before do
dossier.champs << create(:champ_carte)
dossier.champs << create(:champ_siret)
dossier.champs << create(:champ_integer_number)
dossier.champs << create(:champ_decimal_number)
dossier.champs << create(:champ_linked_drop_down_list)
end
it {
expect(subject.size).to eq(8)
expect(subject[0][:type_de_champ][:type_champ]).to eq(TypeDeChamp.type_champs.fetch(:text))
expect(subject[1][:type_de_champ][:type_champ]).to eq(TypeDeChamp.type_champs.fetch(:carte))
expect(subject[2][:type_de_champ][:type_champ]).to eq(TypeDeChamp.type_champs.fetch(:siret))
expect(subject[7][:type_de_champ][:type_champ]).to eq('quartier_prioritaire')
expect(subject[1][:geo_areas].size).to eq(0)
expect(subject[2][:etablissement]).to be_present
expect(subject[2][:entreprise]).to be_present
expect(subject[3][:value]).to eq(42)
expect(subject[4][:value]).to eq(42.1)
expect(subject[5][:value]).to eq({ primary: nil, secondary: nil })
}
end
end end
end end