Merge pull request #4788 from betagouv/dev

2020-02-17-01
This commit is contained in:
Kara Diaby 2020-02-17 15:08:05 +01:00 committed by GitHub
commit 1a6c2364be
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
106 changed files with 246 additions and 1975 deletions

View file

@ -1,17 +0,0 @@
---
name: Amélioration
about: Suggérer une amélioration ou une nouvelle fonctionnalité
title: ''
labels: idea
assignees: ''
---
**Votre amélioration est liée à un problème spécifique ?**
Si oui, décrivez brièvement quel est le problème que vous rencontrez. Par exemple : Sur demarches-simplifiees.fr, je suis agacé quand je dois […]
**Décrivez la solution proposée**
Une description rapide de la manière dont vous voudriez résoudre le problème.
**Plus de contexte**
Ajoutez éventuellement des éléments de contexte concernant votre proposition d'amélioration, ou des captures d'écran.

15
.github/ISSUE_TEMPLATE/amelioration.md vendored Normal file
View file

@ -0,0 +1,15 @@
---
name: Amélioration
about: Suggérer une amélioration ou une nouvelle fonctionnalité
title: ''
labels: idea
assignees: ''
---
Vous avez une amélioration à suggérer ?
**Explorez dabord notre [tableau de bord des suggestions](https://demarches-simplifiees.featureupvote.com/).**
- Votez pour les améliorations existantes ;
- Si nécessaire, [proposez facilement](https://demarches-simplifiees.featureupvote.com/) votre suggestion damélioration.

View file

@ -23,6 +23,7 @@ gem 'delayed_job_active_record'
gem 'delayed_job_web' gem 'delayed_job_web'
gem 'devise' # Gestion des comptes utilisateurs gem 'devise' # Gestion des comptes utilisateurs
gem 'devise-async' gem 'devise-async'
gem 'discard'
gem 'dotenv-rails', require: 'dotenv/rails-now' # dotenv should always be loaded before rails gem 'dotenv-rails', require: 'dotenv/rails-now' # dotenv should always be loaded before rails
gem 'flipper' gem 'flipper'
gem 'flipper-active_record' gem 'flipper-active_record'

View file

@ -187,6 +187,8 @@ GEM
activejob (>= 5.0) activejob (>= 5.0)
devise (>= 4.0) devise (>= 4.0)
diff-lcs (1.3) diff-lcs (1.3)
discard (1.1.0)
activerecord (>= 4.2, < 7)
domain_name (0.5.20180417) domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
dotenv (2.5.0) dotenv (2.5.0)
@ -737,6 +739,7 @@ DEPENDENCIES
delayed_job_web delayed_job_web
devise devise
devise-async devise-async
discard
dotenv-rails dotenv-rails
factory_bot factory_bot
flipper flipper

View file

@ -11,3 +11,8 @@
.mb-4 { .mb-4 {
margin-bottom: 4 * $default-spacer; margin-bottom: 4 * $default-spacer;
} }
.numbers-delimiter {
display: inline-block;
width: 5px;
}

View file

@ -231,8 +231,7 @@ module Instructeurs
end end
def update_email_notifications def update_email_notifications
assign_to.update!(email_notifications_enabled: params[:assign_to][:email_notifications_enabled]) assign_to.update!(assign_to_params)
flash.notice = 'Vos notifications sont enregistrées.' flash.notice = 'Vos notifications sont enregistrées.'
redirect_to instructeur_procedure_path(procedure) redirect_to instructeur_procedure_path(procedure)
end end
@ -246,6 +245,10 @@ module Instructeurs
private private
def assign_to_params
params.require(:assign_to).permit(:email_notifications_enabled, :weekly_email_notifications_enabled)
end
def assign_exports def assign_exports
groupe_instructeurs_for_procedure = current_instructeur.groupe_instructeurs.where(procedure: procedure) groupe_instructeurs_for_procedure = current_instructeur.groupe_instructeurs.where(procedure: procedure)
@xlsx_export = Export.find_for_format_and_groupe_instructeurs(:xlsx, groupe_instructeurs_for_procedure) @xlsx_export = Export.find_for_format_and_groupe_instructeurs(:xlsx, groupe_instructeurs_for_procedure)

View file

@ -9,10 +9,10 @@ module Manager
def scoped_resource def scoped_resource
if unfiltered_list? if unfiltered_list?
# Don't display deleted dossiers in the unfiltered list… # Don't display deleted dossiers in the unfiltered list…
Procedure Procedure.kept
else else
# … but allow them to be searched and displayed. # … but allow them to be searched and displayed.
Procedure.with_hidden Procedure.with_discarded
end end
end end

View file

@ -25,7 +25,7 @@ class Users::RegistrationsController < Devise::RegistrationsController
existing_user = User.find_by(email: params[:user][:email]) existing_user = User.find_by(email: params[:user][:email])
if existing_user.present? if existing_user.present?
if existing_user.confirmed? if existing_user.confirmed?
UserMailer.new_account_warning(existing_user).deliver_later UserMailer.new_account_warning(existing_user, @procedure).deliver_later
else else
existing_user.resend_confirmation_instructions existing_user.resend_confirmation_instructions
end end

View file

@ -0,0 +1,6 @@
module NumberHelper
def number_with_html_delimiter(num)
# we are using the span delimiter that doesn't insert spaces when copying and pasting the number
number_with_delimiter(num, delimiter: tag.span(class: 'numbers-delimiter'))
end
end

View file

@ -1,12 +1,15 @@
# Preview all emails at http://localhost:3000/rails/mailers/user_mailer # Preview all emails at http://localhost:3000/rails/mailers/user_mailer
class UserMailer < ApplicationMailer class UserMailer < ApplicationMailer
helper MailerHelper
layout 'mailers/layout' layout 'mailers/layout'
def new_account_warning(user) def new_account_warning(user, procedure = nil)
@user = user @user = user
@subject = "Demande de création de compte" @subject = "Demande de création de compte"
@procedure = procedure
mail(to: user.email, subject: @subject) mail(to: user.email, subject: @subject, procedure: @procedure)
end end
def account_already_taken(user, requested_email) def account_already_taken(user, requested_email)

View file

@ -25,6 +25,14 @@ class Champ < ApplicationRecord
!private? !private?
end end
def siblings
if public?
dossier&.champs
else
dossier&.champs_private
end
end
def mandatory_and_blank? def mandatory_and_blank?
mandatory? && blank? mandatory? && blank?
end end

View file

@ -2,4 +2,10 @@ class Champs::HeaderSectionChamp < Champ
def search_terms def search_terms
# The user cannot enter any information here so it doesnt make much sense to search # The user cannot enter any information here so it doesnt make much sense to search
end end
def section_index
siblings
.filter { |c| c.type_champ == TypeDeChamp.type_champs.fetch(:header_section) }
.index(self) + 1
end
end end

View file

@ -2,6 +2,10 @@ class Dossier < ApplicationRecord
self.ignored_columns = ['json_latlngs'] self.ignored_columns = ['json_latlngs']
include DossierFilteringConcern include DossierFilteringConcern
include Discard::Model
self.discard_column = :hidden_at
default_scope -> { kept }
enum state: { enum state: {
brouillon: 'brouillon', brouillon: 'brouillon',
en_construction: 'en_construction', en_construction: 'en_construction',
@ -94,9 +98,6 @@ class Dossier < ApplicationRecord
end end
end end
default_scope { where(hidden_at: nil) }
scope :hidden, -> { unscope(where: :hidden_at).where.not(hidden_at: nil) }
scope :with_hidden, -> { unscope(where: :hidden_at) }
scope :state_brouillon, -> { where(state: states.fetch(:brouillon)) } scope :state_brouillon, -> { where(state: states.fetch(:brouillon)) }
scope :state_not_brouillon, -> { where.not(state: states.fetch(:brouillon)) } scope :state_not_brouillon, -> { where.not(state: states.fetch(:brouillon)) }
scope :state_en_construction, -> { where(state: states.fetch(:en_construction)) } scope :state_en_construction, -> { where(state: states.fetch(:en_construction)) }
@ -378,7 +379,7 @@ class Dossier < ApplicationRecord
def delete_and_keep_track(author) def delete_and_keep_track(author)
deleted_dossier = DeletedDossier.create_from_dossier(self) deleted_dossier = DeletedDossier.create_from_dossier(self)
update(hidden_at: deleted_dossier.deleted_at) discard!
if en_construction? if en_construction?
administration_emails = followers_instructeurs.present? ? followers_instructeurs.map(&:email) : procedure.administrateurs.map(&:email) administration_emails = followers_instructeurs.present? ? followers_instructeurs.map(&:email) : procedure.administrateurs.map(&:email)

View file

@ -75,11 +75,12 @@ class Instructeur < ApplicationRecord
start_date = Time.zone.now.beginning_of_week start_date = Time.zone.now.beginning_of_week
active_procedure_overviews = procedures active_procedure_overviews = procedures
.where(assign_tos: { weekly_email_notifications_enabled: true })
.publiees .publiees
.map { |procedure| procedure.procedure_overview(start_date, groupe_instructeurs) } .map { |procedure| procedure.procedure_overview(start_date, groupe_instructeurs) }
.filter(&:had_some_activities?) .filter(&:had_some_activities?)
if active_procedure_overviews.count == 0 if active_procedure_overviews.empty?
nil nil
else else
{ {

View file

@ -16,5 +16,7 @@ class Invite < ApplicationRecord
# and Dossier from their respective `default_scope`s. # and Dossier from their respective `default_scope`s.
# Therefore, we also remove `Invite`s for such effectively deleted `Dossier`s # Therefore, we also remove `Invite`s for such effectively deleted `Dossier`s
# from their default scope. # from their default scope.
default_scope { joins(:dossier).where(dossiers: { hidden_at: nil }) } scope :kept, -> { joins(:dossier).merge(Dossier.kept) }
default_scope { kept }
end end

View file

@ -5,6 +5,10 @@ class Procedure < ApplicationRecord
include ProcedureStatsConcern include ProcedureStatsConcern
include Discard::Model
self.discard_column = :hidden_at
default_scope -> { kept }
MAX_DUREE_CONSERVATION = 36 MAX_DUREE_CONSERVATION = 36
MAX_DUREE_CONSERVATION_EXPORT = 3.hours MAX_DUREE_CONSERVATION_EXPORT = 3.hours
@ -44,9 +48,6 @@ class Procedure < ApplicationRecord
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_champ_private, reject_if: proc { |attributes| attributes['libelle'].blank? }, allow_destroy: true accepts_nested_attributes_for :types_de_champ_private, reject_if: proc { |attributes| attributes['libelle'].blank? }, allow_destroy: true
default_scope { where(hidden_at: nil) }
scope :hidden, -> { unscope(where: :hidden_at).where.not(hidden_at: nil) }
scope :with_hidden, -> { unscope(where: :hidden_at) }
scope :brouillons, -> { where(aasm_state: :brouillon) } scope :brouillons, -> { where(aasm_state: :brouillon) }
scope :publiees, -> { where(aasm_state: :publiee) } scope :publiees, -> { where(aasm_state: :publiee) }
scope :closes, -> { where(aasm_state: [:close, :depubliee]) } scope :closes, -> { where(aasm_state: [:close, :depubliee]) }
@ -99,7 +100,6 @@ class Procedure < ApplicationRecord
state :brouillon, initial: true state :brouillon, initial: true
state :publiee state :publiee
state :close state :close
state :hidden
state :depubliee state :depubliee
event :publish, before: :before_publish, after: :after_publish do event :publish, before: :before_publish, after: :after_publish do
@ -112,12 +112,6 @@ class Procedure < ApplicationRecord
transitions from: :publiee, to: :close transitions from: :publiee, to: :close
end end
event :hide, after: :after_hide do
transitions from: :brouillon, to: :hidden
transitions from: :publiee, to: :hidden
transitions from: :close, to: :hidden
end
event :unpublish, after: :after_unpublish do event :unpublish, after: :after_unpublish do
transitions from: :publiee, to: :depubliee transitions from: :publiee, to: :depubliee
end end
@ -597,6 +591,12 @@ class Procedure < ApplicationRecord
groupe_instructeurs.count > 1 groupe_instructeurs.count > 1
end end
def hide!
discard!
dossiers.discard_all
purge_export_files
end
private private
def move_type_de_champ_attributes(types_de_champ, type_de_champ, new_index) def move_type_de_champ_attributes(types_de_champ, type_de_champ, new_index)
@ -629,13 +629,6 @@ class Procedure < ApplicationRecord
purge_export_files purge_export_files
end end
def after_hide
now = Time.zone.now
update!(hidden_at: now)
dossiers.update_all(hidden_at: now)
purge_export_files
end
def after_unpublish def after_unpublish
update!(unpublished_at: Time.zone.now) update!(unpublished_at: Time.zone.now)
end end

View file

@ -108,7 +108,7 @@ class User < ApplicationRecord
dossiers.each do |dossier| dossiers.each do |dossier|
dossier.delete_and_keep_track(administration) dossier.delete_and_keep_track(administration)
end end
dossiers.with_hidden.destroy_all dossiers.with_discarded.destroy_all
destroy! destroy!
end end

View file

@ -27,18 +27,18 @@
= form.radio_button :email_notifications_enabled, false = form.radio_button :email_notifications_enabled, false
Non Non
= form.label nil, "Recevoir un récapitulatif hebdomadaire" = form.label :email_notification, "Recevoir un récapitulatif hebdomadaire"
%p.notice %p.notice
Cet email récapitule lactivité de la semaine sur lensemble de vos démarches. Cet email récapitule lactivité de la semaine sur lensemble de vos démarches.
%p.notice %p.notice
Il est envoyé chaque semaine le lundi matin, et nest pas désactivable. Il est envoyé chaque semaine le lundi matin.
.radios .radios
%label %label
= radio_button_tag "not_implemented", "Oui", true, disabled: true = form.radio_button :weekly_email_notifications_enabled, true
Oui Oui
%label %label
= radio_button_tag "not_implemented", "Non", false, disabled: true = form.radio_button :weekly_email_notifications_enabled, false
Non Non
.send-wrapper .send-wrapper

View file

@ -39,7 +39,7 @@ as well as a link to its edit page.
<%= link_to 'whitelister', whitelist_manager_procedure_path(procedure), method: :post, class: 'button' %> <%= link_to 'whitelister', whitelist_manager_procedure_path(procedure), method: :post, class: 'button' %>
<% end %> <% end %>
<% if !procedure.hidden? %> <% if !procedure.discarded? %>
<%= link_to 'supprimer la démarche', hide_manager_procedure_path(procedure), method: :post, class: 'button', data: { confirm: "Confirmez-vous la suppression de la démarche ?" } %> <%= link_to 'supprimer la démarche', hide_manager_procedure_path(procedure), method: :post, class: 'button', data: { confirm: "Confirmez-vous la suppression de la démarche ?" } %>
<% end %> <% end %>
<div> <div>

View file

@ -35,7 +35,7 @@
- when TypeDeChamp.type_champs.fetch(:datetime) - when TypeDeChamp.type_champs.fetch(:datetime)
= c.to_s = c.to_s
- when TypeDeChamp.type_champs.fetch(:number) - when TypeDeChamp.type_champs.fetch(:number)
= number_with_delimiter(c.to_s) = number_with_html_delimiter(c.to_s)
- else - else
= format_text_value(c.to_s) = format_text_value(c.to_s)

View file

@ -1,2 +1,5 @@
%h2.header-section %h2.header-section
- libelle_starts_with_number = (champ.libelle =~ /^\d/)
- if !libelle_starts_with_number
= "#{champ.section_index}."
= champ.libelle = champ.libelle

View file

@ -7,9 +7,25 @@
Une demande de création de compte a été réalisée sur le site demarches-simplifiees.fr pour l'email #{@user.email}. Une demande de création de compte a été réalisée sur le site demarches-simplifiees.fr pour l'email #{@user.email}.
%p %p
Votre compte existe déjà. Si vous souhaitez changer votre mot de passe, veuillez suivre les instructions à l'adresse suivante %strong Votre compte existe déjà.
#{link_to(new_password_url(@user), new_password_url(@user))}.
- if @procedure
%p
Si vous souhaitez remplir la démarche
= surround '« ', ' »,' do
%i= @procedure.libelle
cliquez sur le bouton ci-dessous.
= round_button("Commencer la démarche « #{@procedure.libelle.truncate(60)} »", commencer_sign_in_url(path: @procedure.path), :primary)
= vertical_margin(16)
= round_button('Jai oublié mon mot de passe', new_password_url(@user), :secondary)
- else
%p
Vous n'avez rien à faire. Si vous avez oublié votre mot de passe, cliquez sur le bouton ci-dessous.
= round_button('Jai oublié mon mot de passe', new_password_url(@user), :secondary)
= vertical_margin(6)
%p %p
Si vous n'êtes pas à l'origine de cette demande, vous pouvez ignorer ce mail. Si vous n'êtes pas à l'origine de cette demande, vous pouvez ignorer ce mail.

View file

@ -0,0 +1,5 @@
class AddWeeklyEmailNotificationsToAssignTos < ActiveRecord::Migration[5.2]
def change
add_column :assign_tos, :weekly_email_notifications_enabled, :boolean, default: true, null: false
end
end

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_01_30_165328) do ActiveRecord::Schema.define(version: 2020_02_10_100938) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -104,6 +104,7 @@ ActiveRecord::Schema.define(version: 2020_01_30_165328) do
t.datetime "updated_at" t.datetime "updated_at"
t.boolean "email_notifications_enabled", default: false, null: false t.boolean "email_notifications_enabled", default: false, null: false
t.bigint "groupe_instructeur_id" t.bigint "groupe_instructeur_id"
t.boolean "weekly_email_notifications_enabled", default: true, null: false
t.index ["groupe_instructeur_id", "instructeur_id"], name: "unique_couple_groupe_instructeur_instructeur", unique: true t.index ["groupe_instructeur_id", "instructeur_id"], name: "unique_couple_groupe_instructeur_instructeur", unique: true
t.index ["groupe_instructeur_id"], name: "index_assign_tos_on_groupe_instructeur_id" t.index ["groupe_instructeur_id"], name: "index_assign_tos_on_groupe_instructeur_id"
t.index ["instructeur_id", "procedure_id"], name: "index_assign_tos_on_instructeur_id_and_procedure_id", unique: true t.index ["instructeur_id", "procedure_id"], name: "index_assign_tos_on_instructeur_id_and_procedure_id", unique: true

View file

@ -1,15 +0,0 @@
namespace :'2017_07_18_clean_followed_dossiers' do
task clean: :environment do
Follow.where(gestionnaire_id: nil).destroy_all
Follow.where(dossier_id: nil).destroy_all
duplicate_follows = Follow.group('gestionnaire_id', 'dossier_id').count.filter { |_gestionnaire_id_dossier_id, count| count > 1 }.keys
duplicate_ids = duplicate_follows.map { |gestionnaire_id, dossier_id| Follow.where(gestionnaire_id: gestionnaire_id, dossier_id: dossier_id).pluck(:id) }
duplicate_ids.each do |ids|
ids.pop
Follow.where(id: ids).destroy_all
end
end
end

View file

@ -1,29 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2017_07_26_clean_birthdate_on_individual' do
task clean: :environment do
# remove duplicates
duplicate_individuals = Individual.group("dossier_id").count.filter { |_dossier_id, count| count > 1 }.keys
duplicate_individuals.each { |dossier_id| Individual.where(dossier_id: dossier_id, nom: nil).delete_all }
# Match "" => nil
Individual.where(birthdate: "").update_all(birthdate: nil)
individuals_with_date = Individual.where.not(birthdate: nil)
# Match 31/12/2017 => 2017-12-31
individuals_with_date.filter { |i| /^\d{2}\/\d{2}\/\d{4}$/.match(i.birthdate) }.each do |i|
rake_puts "cleaning #{i.birthdate}"
i.update(birthdate: Date.parse(i.birthdate).iso8601) rescue nil
end
# Match 31/12/17 => 2017-12-31
individuals_with_date.filter { |i| /^\d{2}\/\d{2}\/\d{2}$/.match(i.birthdate) }.each do |i|
rake_puts "cleaning #{i.birthdate}"
new_date = Date.strptime(i.birthdate, "%d/%m/%y")
if new_date.year > 2017
new_date = new_date - 100.years
end
i.update(birthdate: new_date.iso8601)
end
end
end

View file

@ -1,12 +0,0 @@
namespace :'2017_08_01_clean_assign_to' do
task clean: :environment do
duplicates = AssignTo.group(:gestionnaire_id, :procedure_id).count.filter { |_gestionnaire_id_procedure_id, count| count > 1 }.keys
duplicate_ids = duplicates.map { |gestionnaire_id, procedure_id| AssignTo.where(gestionnaire_id: gestionnaire_id, procedure_id: procedure_id).pluck(:id) }
duplicate_ids.each do |ids|
ids.pop
AssignTo.where(id: ids).destroy_all
end
end
end

View file

@ -1,5 +0,0 @@
namespace :'2017_09_19_set_confidentialite_to_old_avis' do
task set: :environment do
Avis.unscope(:joins).update_all(confidentiel: true)
end
end

View file

@ -1,5 +0,0 @@
namespace :'2017_09_22_set_dossier_updated_replied_to_initiated' do
task set: :environment do
Dossier.with_hidden.where(state: [:updated, :replied]).update_all(state: :initiated)
end
end

View file

@ -1,50 +0,0 @@
namespace :'2017_10_06_set_follow_date' do
task set: :environment do
set_default_date_to_champs_and_pieces_justificatives
set_all_dossiers_as_read
apply_legacy_notification_to_new_system
end
def set_default_date_to_champs_and_pieces_justificatives
ActiveRecord::Base.connection
.execute('UPDATE champs SET created_at = dossiers.created_at, updated_at = dossiers.updated_at FROM dossiers where champs.dossier_id = dossiers.id')
PieceJustificative.includes(:dossier).where(created_at: nil).each do |piece_justificative|
piece_justificative.update_attribute('created_at', piece_justificative.dossier.created_at)
end
ActiveRecord::Base.connection
.execute('UPDATE pieces_justificatives SET updated_at = created_at')
end
def set_all_dossiers_as_read
Gestionnaire.includes(:follows).all.each do |gestionnaire|
gestionnaire.follows.update_all(
demande_seen_at: gestionnaire.current_sign_in_at,
annotations_privees_seen_at: gestionnaire.current_sign_in_at,
avis_seen_at: gestionnaire.current_sign_in_at,
messagerie_seen_at: gestionnaire.current_sign_in_at
)
end
end
def apply_legacy_notification_to_new_system
Notification.joins(dossier: :follows).unread.each do |notification|
if notification.demande?
notification.dossier.follows.update_all(demande_seen_at: notification.created_at)
end
if notification.annotations_privees?
notification.dossier.follows.update_all(annotations_privees_seen_at: notification.created_at)
end
if notification.avis?
notification.dossier.follows.update_all(avis_seen_at: notification.created_at)
end
if notification.messagerie?
notification.dossier.follows.update_all(messagerie_seen_at: notification.created_at)
end
end
end
end

View file

@ -1,31 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2017_10_18_regenerate_attestation' do
task set: :environment do
include ActiveSupport::Testing::TimeHelpers
if ENV['ATTESTATION_ID'].present?
regenerate_attestations(Attestation.find(ENV['ATTESTATION_ID']))
else
Attestation.all.each { |attestation| regenerate_attestations(attestation) }
end
end
def regenerate_attestations(attestation)
Procedure.with_hidden do
Dossier.with_hidden do
dossier = attestation.dossier
procedure = dossier.procedure
rake_puts "processing dossier #{dossier.id}"
travel_to(dossier.processed_at) do
new_attestation = procedure.attestation_template.attestation_for(dossier)
attestation.delete
dossier.attestation = new_attestation
dossier.save
end
end
end
end
end

View file

@ -1,37 +0,0 @@
namespace :'2017_12_04_translate_dossier_state_to_french' do
task brouillon: :environment do
Dossier.with_hidden.where(state: 'draft').update_all(state: 'brouillon')
end
task en_construction: :environment do
Dossier.with_hidden.where(state: 'initiated').update_all(state: 'en_construction')
end
task en_instruction: :environment do
Dossier.with_hidden.where(state: 'received').update_all(state: 'en_instruction')
end
task accepte: :environment do
Dossier.with_hidden.where(state: 'closed').update_all(state: 'accepte')
end
task refuse: :environment do
Dossier.with_hidden.where(state: 'refused').update_all(state: 'refuse')
end
task sans_suite: :environment do
Dossier.with_hidden.where(state: 'without_continuation').update_all(state: 'sans_suite')
end
task all: [:brouillon, :en_construction, :en_instruction, :accepte, :refuse, :sans_suite] do
end
task revert: :environment do
Dossier.with_hidden.where(state: 'brouillon').update_all(state: 'draft')
Dossier.with_hidden.where(state: 'en_construction').update_all(state: 'initiated')
Dossier.with_hidden.where(state: 'en_instruction').update_all(state: 'received')
Dossier.with_hidden.where(state: 'accepte').update_all(state: 'closed')
Dossier.with_hidden.where(state: 'refuse').update_all(state: 'refused')
Dossier.with_hidden.where(state: 'sans_suite').update_all(state: 'without_continuation')
end
end

View file

@ -1,21 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2017_12_05_initialize_timestamps_for_entreprises' do
task set: :environment do
entreprises = Entreprise.where(created_at: nil).includes(:dossier)
rake_puts "#{entreprises.count} to initialize..."
entreprises.each { |e| initialize_entreprise(e) }
end
def initialize_entreprise(entreprise)
rake_puts "initializing entreprise #{entreprise.id}"
if entreprise.dossier.present?
entreprise.update_columns(created_at: entreprise.dossier.created_at, updated_at: entreprise.dossier.created_at)
else
rake_puts "dossier #{entreprise.dossier_id} is missing for entreprise #{entreprise.id}"
entreprise.update_columns(created_at: Time.zone.now, updated_at: Time.zone.now)
end
end
end

View file

@ -1,10 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2017_12_20_delete_old_administration' do
task set: :environment do
Administration.all.each do |a|
rake_puts "Deleting #{a.email}"
a.destroy
end
end
end

View file

@ -1,22 +0,0 @@
namespace :'2017_12_21_replace_deprecated_mail_template_tags' do
task set: :environment do
replace_tag('numero_dossier', 'numéro du dossier')
replace_tag('date_de_decision', 'date de décision')
replace_tag('libelle_procedure', 'libellé démarche')
replace_tag('lien_dossier', 'lien dossier')
end
def replace_tag(old_tag, new_tag)
mails = [Mails::ClosedMail, Mails::InitiatedMail, Mails::ReceivedMail, Mails::RefusedMail, Mails::WithoutContinuationMail]
mails.each do |mail|
replace_tag_in(mail, 'object', old_tag, new_tag)
replace_tag_in(mail, 'body', old_tag, new_tag)
end
end
def replace_tag_in(mail, field, old_tag, new_tag)
mail
.where("#{field} LIKE ?", "%#{old_tag}%")
.update_all("#{field} = REPLACE(#{field}, '#{old_tag}', '#{new_tag}')")
end
end

View file

@ -1,7 +0,0 @@
namespace :'2018_01_11_add_active_state_to_administrators' do
task set: :environment do
Administrateur.find_each do |administrateur|
administrateur.update_column(:active, true)
end
end
end

View file

@ -1,32 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2018_01_18_clean_datetime_in_champs' do
task clean: :environment do
datetime_champs = TypeDeChamp.where(type_champ: "datetime").flat_map(&:champ)
# Match " HH:MM" => nil a datetime is not valid if not composed by date AND time
datetime_champs.filter { |c| /^\s\d{2}:\d{2}$/.match(c.value) }.each do |c|
rake_puts "cleaning #{c.value} => nil"
c.update_columns(value: nil)
end
# Match "dd/mm/YYYY HH:MM" => "YYYY-mm-dd HH:MM"
datetime_champs.filter { |c| /^\d{2}\/\d{2}\/\d{4}\s\d{2}:\d{2}$/ =~ c.value }.each do |c|
formated_date = Time.zone.strptime(c.value, "%d/%m/%Y %H:%M").strftime("%Y-%m-%d %H:%M")
rake_puts "cleaning #{c.value} => #{formated_date}"
c.update_columns(value: formated_date)
end
# Match "ddmmYYYY HH:MM" => "YYYY-mm-dd HH:MM"
datetime_champs.filter { |c| /^\d{8}\s\d{2}:\d{2}$/ =~ c.value }.each do |c|
day = c.value[0, 2]
month = c.value[2, 2]
year = c.value[4, 4]
hours = c.value[9, 2]
minutes = c.value[12, 2]
formated_date = "#{year}-#{month}-#{day} #{hours}:#{minutes}"
rake_puts "cleaning #{c.value} => #{formated_date}"
c.update_columns(value: formated_date)
end
end
end

View file

@ -1,16 +0,0 @@
namespace :'2018_02_13_fill_champ_private_and_type' do
task set: :environment do
Champ.includes(:type_de_champ).find_each do |champ|
if champ.type_de_champ.present?
champ.update_columns(champ.type_de_champ.params_for_champ)
end
end
TypeDeChamp.find_each do |type_de_champ|
type_de_champ.update_columns(
private: type_de_champ.private?,
type: TypeDeChamp.type_champ_to_class_name(type_de_champ.type_champ)
)
end
end
end

View file

@ -1,14 +0,0 @@
namespace :'2018_02_14_clean_double_champ_private' do
task clean: :environment do
Champ.where(private: true).group_by(&:dossier_id).each_value do |champs|
seen = []
champs.each do |champ|
if champ.type_de_champ_id.in?(seen)
champ.destroy
else
seen << champ.type_de_champ_id
end
end
end
end
end

View file

@ -1,17 +0,0 @@
namespace :'2018_02_20_remove_duplicated_assign_tos' do
task remove: :environment do
duplicates = AssignTo.group(:gestionnaire_id, :procedure_id)
.having("COUNT(*) > 1")
.size
.to_a
duplicates.each do |duplicate|
keys = duplicate.first
gestionnaire_id = keys.first
procedure_id = keys.last
assign_tos = AssignTo.where(gestionnaire_id: gestionnaire_id, procedure_id: procedure_id).to_a
assign_tos.shift
assign_tos.each(&:destroy)
end
end
end

View file

@ -1,7 +0,0 @@
namespace :'2018_02_20_set_processed_at' do
task set: :environment do
Dossier.where(state: :accepte, processed_at: nil).find_each do |dossier|
dossier.update_column(:processed_at, dossier.en_instruction_at)
end
end
end

View file

@ -1,11 +0,0 @@
namespace :'2018_02_28_clean_invalid_emails_accounts' do
task clean: :environment do
Gestionnaire.pluck(:email, :id).filter { |e, _id| e.include?(" ") }.each do |_email, id|
Gestionnaire.find_by(id: id, current_sign_in_at: nil)&.destroy # ensure account was never used
end
User.pluck(:email, :id).filter { |e, _id| e.include?(" ") }.each do |_email, id|
User.find_by(id: id, current_sign_in_at: nil)&.destroy # ensure account was never used
end
end
end

View file

@ -1,24 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
require Rails.root.join("app", "helpers", "html_to_string_helper")
namespace :'2018_03_06_clean_html_textareas' do
task clean: :environment do
include ActionView::Helpers::TextHelper
include HtmlToStringHelper
rake_puts "PUTS Will migrate champs"
champs = Champ.joins(:type_de_champ)
.where(types_de_champ: { type_champ: "textarea" })
.where("value LIKE '%<%'")
total = champs.count
champs.find_each(batch_size: 100).with_index do |c, i|
if (i % 100) == 0
rake_puts "Champ #{i}/#{total}\n"
end
c.update_column(:value, html_to_string(c.value))
end
end
end

View file

@ -1,28 +0,0 @@
namespace :'2018_03_08_send_missing_accuse_reception' do
task send: :environment do
# Send accusés de réception that were missed because of #1510
#
# The bug was introduced in production with the 2018-03-01-01 release
# and fixed with the 2018-03-05-03 release.
#
# `bug_date` and `fix_date` were determined empirically by looking at the release times,
# and checking for dossiers with a missing accusé de réception.
bug_date = Time.zone.local(2018, 3, 1, 9, 50)
fix_date = Time.zone.local(2018, 3, 5, 18, 40)
# Only send the accusé for dossiers that are still en construction.
# For dossiers that have moved on, other mails have been sent since, and a late
# accusé de réception would add more confusion than its worth
problem_dossiers = Dossier.where(en_construction_at: bug_date..fix_date)
total = problem_dossiers.count
problem_dossiers.find_each(batch_size: 100).with_index do |dossier, i|
print "Dossier #{i}/#{total}\n"
template = dossier.procedure.initiated_mail_template
date_depot = dossier.en_construction_at.in_time_zone("Paris").strftime('%d/%m/%Y à %H:%M')
body_prefix = "<p>Suite à une difficulté technique, veuillez recevoir par la présente laccusé de réception pour votre dossier déposé le #{date_depot}.<br>Léquipe demarches-simplifiees.fr vous présente ses excuses pour la gène occasionnée.</p><hr>\n"
template.body = body_prefix + template.body
NotificationMailer.send_notification(dossier, template).deliver_now!
end
end
end

View file

@ -1,53 +0,0 @@
namespace :'2018_03_29_inline_entreprise_association' do
task fix_date_fin_exercice: :environment do
Exercice.where(date_fin_exercice: nil).find_each do |exercice|
exercice.update_column(:date_fin_exercice, exercice.dateFinExercice)
end
end
task fix_missing_entreprise: :environment do
Etablissement.includes(:entreprise).where(entreprise_siren: nil).find_each do |etablissement|
dossier_id = etablissement.dossier_id
if !etablissement.entreprise
etablissement.entreprise = Dossier.find_by(id: dossier_id)&.entreprise
end
etablissement.save
end
end
task inline_entreprise_association: :environment do
Etablissement.includes(entreprise: :rna_information, exercices: []).where(entreprise_siren: nil).find_each do |etablissement|
entreprise = etablissement.entreprise
if entreprise
etablissement.entreprise_siren = entreprise.siren
etablissement.entreprise_capital_social = entreprise.capital_social
etablissement.entreprise_numero_tva_intracommunautaire = entreprise.numero_tva_intracommunautaire
etablissement.entreprise_forme_juridique = entreprise.forme_juridique
etablissement.entreprise_forme_juridique_code = entreprise.forme_juridique_code
etablissement.entreprise_nom_commercial = entreprise.nom_commercial
etablissement.entreprise_raison_sociale = entreprise.raison_sociale
etablissement.entreprise_siret_siege_social = entreprise.siret_siege_social
etablissement.entreprise_code_effectif_entreprise = entreprise.code_effectif_entreprise
etablissement.entreprise_date_creation = entreprise.date_creation
etablissement.entreprise_nom = entreprise.nom
etablissement.entreprise_prenom = entreprise.prenom
association = entreprise.rna_information
if association && association.association_id
etablissement.association_rna = association.association_id
etablissement.association_titre = association.titre
etablissement.association_objet = association.objet
etablissement.association_date_creation = association.date_creation
etablissement.association_date_declaration = association.date_declaration
etablissement.association_date_publication = association.date_publication
end
etablissement.save
end
end
end
end

View file

@ -1,17 +0,0 @@
require Rails.root.join("app", "helpers", "html_to_string_helper")
namespace :'2018_03_29_procedure_description_markup' do
task strip: :environment do
include ActionView::Helpers::TextHelper
include HtmlToStringHelper
total = Procedure.count
Procedure.find_each(batch_size: 100).with_index do |p, i|
if (i % 100) == 0
print "Procedure #{i}/#{total}\n"
end
p.update_column(:description, html_to_string(p.description))
end
end
end

View file

@ -1,20 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2018_03_29_remove_code_tags_from_mail_templates' do
task clean: :environment do
remove_code_tag_from_body(Mails::ClosedMail)
remove_code_tag_from_body(Mails::InitiatedMail)
remove_code_tag_from_body(Mails::ReceivedMail)
remove_code_tag_from_body(Mails::RefusedMail)
remove_code_tag_from_body(Mails::WithoutContinuationMail)
end
def remove_code_tag_from_body(model_class)
mails = model_class.where("body LIKE ?", "%<code>%")
rake_puts "#{mails.count} #{model_class.name} to clean"
mails.each do |m|
rake_puts "cleaning #{model_class.name} ##{m.id}"
m.update(body: m.body.gsub("<code>", "").gsub("</code>", ""))
end
end
end

View file

@ -1,12 +0,0 @@
namespace :'2018_04_03_attestation_closed_mail_discrepancy' do
task mail_adminstrators: :environment do
Administrateur.includes(:procedures).find_each(batch_size: 10) do |admin|
procedures = admin.procedures.where(archived_at: nil).filter { |p| p.closed_mail_template_attestation_inconsistency_state == :missing_tag }
if procedures.any?
# Use `deliver_now` because the delayed job cannot find the `Mailers::AttestationClosedMailDiscrepancyMaile` class in production
Mailers::AttestationClosedMailDiscrepancyMailer.missing_attestation_tag_email(admin, procedures).deliver_now!
print "#{admin.email}\n"
end
end
end
end

View file

@ -1,14 +0,0 @@
namespace :'2018_04_03_type_individual_date' do
task set: :environment do
Individual.all.each { |individual| save_birthdate_in_datetime_format(individual) }
end
def save_birthdate_in_datetime_format(individual)
if individual.birthdate.present?
begin
individual.update_column(:second_birthdate, Date.parse(individual.birthdate))
rescue
end
end
end
end

View file

@ -1,19 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2018_04_04_fetch_etablissement_with_no_entreprise' do
task fetch: :environment do
dossiers = Entreprise.joins('LEFT JOIN etablissements et ON entreprises.id = et.entreprise_id')
.where('et.id IS NULL')
.map(&:dossier_id).map { |id| Dossier.with_hidden.find_by(id: id) }.compact
dossiers.each do |dossier|
siret = dossier.entreprise.siret_siege_social
rake_puts "Fetch siret: #{siret} for dossier: #{dossier.id}"
if siret
EtablissementUpdateJob.perform_later(dossier, siret)
end
end
end
end

View file

@ -1,31 +0,0 @@
namespace :'2018_04_11_admin_or_gestionnaire_users' do
task create_missing: :environment do
create_missing_users(Administrateur)
create_missing_users(Gestionnaire)
end
def create_missing_users(klass)
klasses = klass.name.downcase.pluralize
accounts = klass.joins("LEFT JOIN users on users.email = #{klasses}.email").where('users.id is null')
processed_count = 0
accounts.find_each(batch_size: 100) do |account|
# To pass validation, we need to set dummy password even though
# we override encrypted_password afterwards
user = User.create({
email: account.email,
password: SecureRandom.hex(5),
encrypted_password: account.encrypted_password
})
if user.persisted?
processed_count += 1
else
print "Failed to create user for #{account.email}\n"
end
end
print "Created users for #{processed_count} #{klasses}\n"
end
end

View file

@ -1,8 +0,0 @@
namespace :'2018_05_09_add_test_started_at_to_procedure' do
task set: :environment do
Procedure.publiees_ou_archivees.where(test_started_at: nil).find_each do |procedure|
procedure.test_started_at = procedure.published_at
procedure.save
end
end
end

View file

@ -1,8 +0,0 @@
namespace :'2018_05_15_add_aasm_state_to_procedure' do
task set: :environment do
Procedure.archivees.update_all(aasm_state: :archivee)
Procedure.publiees.update_all(aasm_state: :publiee)
Procedure.brouillons.update_all(aasm_state: :brouillon)
Procedure.hidden.update_all(aasm_state: :hidden)
end
end

View file

@ -1,25 +0,0 @@
namespace :'2018_05_21_cerfa_to_pj' do
task set: :environment do
dossiers = Cerfa.includes(dossier: [:procedure]).all.reject(&:empty?).map(&:dossier).compact.uniq
dossiers.group_by(&:procedure).each do |procedure, dossiers|
if !procedure.types_de_champ.find_by(libelle: 'CERFA')
type_de_champ = procedure.types_de_champ.create(
type_champ: 'piece_justificative',
libelle: 'CERFA'
)
dossiers.each do |dossier|
cerfa = dossier.cerfa.last
champ = type_de_champ.champ.create(dossier: dossier)
response = Typhoeus.get(cerfa.content_url, timeout: 5)
if response.success?
champ.piece_justificative_file.attach(
io: StringIO.new(response.body),
filename: cerfa.content.filename
)
end
end
end
end
end
end

View file

@ -1,5 +0,0 @@
namespace :'2018_05_24_optional_durees_conservation_for_legacy_procedures' do
task set: :environment do
Procedure.all.update_all(durees_conservation_required: false)
end
end

View file

@ -1,29 +0,0 @@
namespace :'2018_05_30_missed_ar_messages' do
task restore: :environment do
create_commentaires(:en_construction_at, :initiated_mail_template)
create_commentaires(:processed_at, :closed_mail_template, Dossier.where(state: 'accepte'))
create_commentaires(:processed_at, :refused_mail_template, Dossier.where(state: 'refuse'))
create_commentaires(:processed_at, :without_continuation_mail_template, Dossier.where(state: 'sans_suite'))
end
def create_commentaires(date_name, template_name, dossiers = Dossier)
error_range = Time.zone.local(2018, 05, 28, 13, 33)..Time.zone.local(2018, 05, 30, 15, 39)
dossiers.includes(:procedure).where(date_name => error_range).find_each(batch_size: 100) do |dossier|
print "#{dossier.id}\n"
create_commentaire(dossier, dossier.procedure.send(template_name), dossier.send(date_name))
end
end
def create_commentaire(dossier, template, date)
subject = template.subject_for_dossier(dossier)
body = template.body_for_dossier(dossier)
Commentaire.create(
dossier: dossier,
email: CONTACT_EMAIL,
body: "[#{subject}]<br><br>#{body}",
created_at: date
)
end
end

View file

@ -1,5 +0,0 @@
namespace :'2018_06_01_optional_juridique_for_legacy_procedures' do
task set: :environment do
Procedure.all.update_all(juridique_required: false)
end
end

View file

@ -1,5 +0,0 @@
namespace :'2018_06_04_scan_pjs' do
task scan_all: :environment do
Champs::PieceJustificativeChamp.all.each(&:create_virus_scan)
end
end

View file

@ -1,20 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2018_06_05_resend_attestations' do
task set: :environment do
procedure = Procedure.find(4247)
dossiers = procedure.dossiers.includes(:attestation).where(state: 'accepte').filter do |d|
d.processed_at < procedure.attestation_template.updated_at
end
dossiers.each do |dossier|
attestation = dossier.attestation
attestation.destroy
dossier.attestation = dossier.build_attestation
ResendAttestationMailer.resend_attestation(dossier).deliver_later
rake_puts "Email envoyé à #{dossier.user.email} pour le dossier #{dossier.id}"
end
end
end

View file

@ -1,52 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2018_06_05_send_new_attestation' do
task set: :environment do
ids = [
20982,
21262,
54914,
59769,
63747,
59520,
21496,
13386,
13371,
14585,
15307,
17212,
16037,
60403,
60400,
20534,
60123,
16361,
16359,
57147,
51979,
49632,
48628,
48624,
22077,
41103
]
dossiers = ids.map { |id| Dossier.find_by(id: id) }.compact
dossiers.each do |dossier|
attestation = dossier.attestation
if attestation
id = attestation.id
attestation.destroy
rake_puts "Attestation #{id} détruite"
end
dossier.attestation = dossier.build_attestation
NewAttestationMailer.new_attestation(dossier).deliver_later
rake_puts "Email envoyé à #{dossier.user.email} pour le dossier #{dossier.id}"
rake_puts
end
end
end

View file

@ -1,31 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2018_06_06_users_for_admins_and_gestionnaires' do
task preactivate: :environment do
preactivate_users(Gestionnaire, 'accompagnateur') { |g| g.reset_password_token.nil? }
preactivate_users(Administrateur, &:active?)
end
def preactivate_users(model, role_name = nil, &block)
table_name = model.table_name
role_name ||= table_name.singularize
already_activated = model
.joins("INNER JOIN users ON #{table_name}.email = users.email")
.where(users: { confirmed_at: nil })
.to_a
.filter(&block)
rake_puts "Sending emails to #{already_activated.count} #{table_name} that were already confirmed"
already_activated.each { |m| PreactivateUsersMailer.reinvite(m, role_name).deliver_later }
count =
User
.joins("INNER JOIN #{table_name} ON #{table_name}.email = users.email")
.where(confirmed_at: nil)
.update_all(confirmed_at: Time.zone.now)
rake_puts "Fixed #{count} #{table_name} with unconfirmed user"
end
end

View file

@ -1,11 +0,0 @@
namespace :'2018_06_13_unhide_dossiers' do
task run: :environment do
Dossier.hidden.state_instruction_commencee.each do |d|
if !d.procedure.nil? # ensure the procedure was not deleted by administrateur for testing
d.update(hidden_at: nil)
DeletedDossier.find_by(dossier_id: d.id)&.destroy
DossierMailer.notify_unhide_to_user(d).deliver_later
end
end
end
end

View file

@ -1,16 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2018_06_26_purge_preview_dossiers' do
task run: :environment do
# We use delete_all and manually destroy associations because its so much faster that Champ.where(dossier_id: 0).destroy_all
c_count = Commentaire.joins(:champ).where(champs: { dossier_id: 0 }).delete_all
rake_puts("Deleted #{c_count} commentaires\n")
a_count = ActiveStorage::Attachment.joins('join champs ON active_storage_attachments.record_id = champs.id').where(champs: { dossier_id: 0 }).delete_all
rake_puts("Deleted #{a_count} attachments\n")
v_count = VirusScan.joins(:champ).where(champs: { dossier_id: 0 }).delete_all
rake_puts("Deleted #{v_count} virus scans\n")
ch_count = Champ.where(dossier_id: 0).delete_all
rake_puts("Deleted #{ch_count} champs\n")
end
end

View file

@ -1,17 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2018_07_24_refresh_search_terms' do
task run: :environment do
# For dossiers belonging to an archived procedure, the check for the `build_default_individual` `after_save` callback fails.
# So, we filter those out by joining with `procedure`, whose default scope excludes archived procedures.
ds = Dossier.joins(:procedure)
total_count = ds.count
one_percent = total_count / 100
Dossier.joins(:procedure).find_each(batch_size: 100).with_index do |d, i|
if i % one_percent == 0
rake_puts("#{i}/#{total_count} (#{i / one_percent}%)")
end
d.save(touch: false)
end
end
end

View file

@ -1,10 +0,0 @@
namespace :'2018_08_24_encrypt_tokens' do
task run: :environment do
Administrateur
.where
.not(api_token: nil)
.each do |admin|
admin.update(encrypted_token: BCrypt::Password.create(admin.api_token))
end
end
end

View file

@ -1,19 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2018_08_27_migrate_feedbacks' do
task run: :environment do
MAPPING = {
0 => Feedback.ratings.fetch(:unhappy),
1 => Feedback.ratings.fetch(:neutral),
2 => Feedback.ratings.fetch(:happy)
}
MAPPING.keys.each do |mark|
rating = MAPPING[mark]
Feedback
.where(mark: mark)
.update_all(rating: rating)
end
end
end

View file

@ -1,7 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2018_08_31_monthly_dossier_expiration_summary' do
task enable: :environment do
WarnExpiringDossiersJob.set(cron: "0 0 1 * *").perform_later
end
end

View file

@ -1,79 +0,0 @@
namespace :'2018_09_12_fix_templates' do
task run: :environment do
dossiers_with_invalid_attestations = find_dossiers_with_sent_and_invalid_attestations
fix_templates
delete_then_regenerate_attestations(dossiers_with_invalid_attestations)
send_regenerated_attestations(dossiers_with_invalid_attestations)
end
# 16:15 in Paris -> 14:15 UTC
# rubocop:disable Rails/TimeZone
# because we are in a ruby context so Time.zone = nil
DEPLOY_DATETIME = Time.local(2018, 9, 5, 14, 15, 0)
# rubocop:enable Rails/TimeZone
def find_dossiers_with_sent_and_invalid_attestations
invalid_procedures_ids = AttestationTemplate
.where("body LIKE '%--libellé procédure--%'")
.pluck(:procedure_id)
dossiers_with_invalid_template_ids = Dossier
.where(procedure_id: invalid_procedures_ids)
.where(processed_at: DEPLOY_DATETIME..Time.zone.now)
.pluck(:id)
Attestation
.includes(:dossier)
.where(created_at: DEPLOY_DATETIME..Time.zone.now)
.where(dossier_id: dossiers_with_invalid_template_ids)
.map(&:dossier)
end
def fix_templates
klasses = [
Mails::ClosedMail,
Mails::InitiatedMail,
Mails::ReceivedMail,
Mails::RefusedMail,
Mails::WithoutContinuationMail,
AttestationTemplate
]
klasses.each do |klass|
klass
.where("body LIKE '%--libellé procédure--%'")
.each do |instance|
instance.update(body: instance.body.gsub("--libellé procédure--", "--libellé démarche--"))
rake_puts "Body mis-à-jour pour #{klass}##{instance.id}"
end
end
end
def delete_then_regenerate_attestations(dossiers_with_invalid_attestations)
dossiers_with_invalid_attestations.each do |dossier|
begin
dossier.attestation.destroy
dossier.attestation = dossier.build_attestation
dossier.save
rake_puts "Attestation regénérée pour le dossier #{dossier.id}"
rescue
rake_puts "Erreur lors de la régénération de l'attestation pour le dossier #{dossier.id}"
end
end
end
def send_regenerated_attestations(dossiers_with_invalid_attestations)
dossiers_with_invalid_attestations.each do |dossier|
begin
ResendAttestationMailer.resend_attestation(dossier).deliver_later
rake_puts "Email envoyé à #{dossier.user.email} pour le dossier #{dossier.id}"
rescue
rake_puts "Erreur lors de l'envoi de l'email à #{dossier.user.email} pour le dossier #{dossier.id}"
end
end
end
end

View file

@ -1,89 +0,0 @@
namespace :'2018_09_12_ftap' do
task run: :environment do
procedure = Procedure.find(5812)
dossiers = procedure.dossiers.all
labels_for_text_tdc = [
'Bref descriptif du projet',
'Montant et nature des économies générées',
'Contacts en cours avec les porteurs de projets'
]
labels_for_text_tdc.each_with_index { |l, i| add_first_text(procedure, dossiers, l, i) }
ditp_private_tdc_order_place = procedure.types_de_champ_private.find_by(libelle: 'Avis DITP').order_place
labels_for_mark_before_DITP = [
'Ambition usagers/agents',
'Caractère stratégique et novateur',
'Gouvernance'
]
labels_for_mark_before_DITP.each_with_index { |l, i| add_mark(procedure, dossiers, l, ditp_private_tdc_order_place + i) }
change_to_select_with_number(procedure, 'Avis DINSIC')
change_to_select_with_number(procedure, 'Avis DB')
change_option_for_avis_tdc(procedure)
end
def change_option_for_avis_tdc(procedure)
drop_down_list = procedure.types_de_champ_private.find_by(libelle: 'Avis', type_champ: 'drop_down_list').drop_down_list
drop_down_list.update(value: "Favorable\r\nDéfavorable\r\nFavorable avec réserves\r\nFavorable avec réserves - stratégique")
end
def add_first_text(procedure, dossiers, libelle, order_place)
if procedure.types_de_champ_private.find_by(libelle: libelle).nil?
move_down_tdc_below(procedure, order_place)
tdc = TypesDeChamp::TextareaTypeDeChamp.create!(
libelle: libelle,
type_champ: 'textarea',
procedure: procedure,
order_place: order_place,
private: true
)
procedure.types_de_champ_private << tdc
dossiers.each do |dossier|
dossier.champs << Champs::TextareaChamp.create!(type_de_champ: tdc, private: true)
end
end
end
def add_mark(procedure, dossiers, libelle, order_place)
if procedure.types_de_champ_private.find_by(libelle: libelle).nil?
move_down_tdc_below(procedure, order_place)
tdc = TypesDeChamp::DropDownListTypeDeChamp.create!(
libelle: libelle,
type_champ: 'drop_down_list',
procedure: procedure,
order_place: order_place,
private: true
)
DropDownList.create!(value: "0\r\n1\r\n2\r\n3\r\n4", type_de_champ: tdc)
procedure.types_de_champ_private << tdc
dossiers.each do |dossier|
dossier.champs << Champs::DropDownListChamp.create!(type_de_champ: tdc, private: true)
end
end
end
def move_down_tdc_below(procedure, order_place)
tdcs_to_move_down = procedure.types_de_champ_private.where('order_place >= ?', order_place)
tdcs_to_move_down.each do |tdc|
tdc.update(order_place: (tdc.order_place + 1))
end
end
def change_to_select_with_number(procedure, libelle)
drop_down_list = procedure.types_de_champ_private.find_by(libelle: libelle, type_champ: 'drop_down_list').drop_down_list
drop_down_list.update(value: "0\r\n1\r\n2\r\n3\r\n4")
end
end

View file

@ -1,51 +0,0 @@
namespace :'2018_09_20_procedure_presentation_entreprise' do
task run: :environment do
Class.new do
def run
fix_displayed_fields
fix_sort
fix_filters
end
def fix_displayed_fields
ProcedurePresentation.where(%q`displayed_fields @> '[{"table": "entreprise"}]'`).each do |procedure_presentation|
procedure_presentation.displayed_fields.each { |field| entreprise_to_etablissement(field) }
procedure_presentation.save
end
end
def fix_sort
ProcedurePresentation.where(%q`sort @> '{"table": "entreprise"}'`).each do |procedure_presentation|
entreprise_to_etablissement(procedure_presentation['sort'])
procedure_presentation.save
end
end
def fix_filters
ProcedurePresentation.find_by_sql(
<<~SQL
SELECT procedure_presentations.*, array_agg(key) as keys
FROM procedure_presentations, LATERAL jsonb_each(filters)
WHERE value @> '[{"table": "entreprise"}]'
GROUP BY id;
SQL
).each do |procedure_presentation|
procedure_presentation.keys.each do |key|
procedure_presentation.filters[key].each { |filter| entreprise_to_etablissement(filter) }
end
procedure_presentation.save
end
end
def entreprise_to_etablissement(field)
if field['table'] == 'entreprise'
field['table'] = 'etablissement'
field['column'] = "entreprise_#{field['column']}"
end
end
end.new.run
end
end

View file

@ -1,11 +0,0 @@
namespace :'2018_09_20_procedure_presentation_jsonb' do
task run: :environment do
ProcedurePresentation.update_all(
<<~SQL
displayed_fields = ('[' || ARRAY_TO_STRING(old_displayed_fields, ',') || ']')::JSONB,
sort = (sort #>> '{}')::jsonb,
filters = (filters #>> '{}')::jsonb
SQL
)
end
end

View file

@ -1,9 +0,0 @@
namespace :'2018_09_27_fill_missing_en_instruction_at' do
task run: :environment do
dossiers_with_missing_instruction_at = Dossier
.where.not(processed_at: nil)
.where(en_instruction_at: nil)
dossiers_with_missing_instruction_at.each { |d| d.update(en_instruction_at: d.processed_at) }
end
end

View file

@ -1,52 +0,0 @@
namespace :'2018_10_03_remove_fc_from_procedure_presentation' do
task run: :environment do
Class.new do
def run
fix_displayed_fields
fix_sort
fix_filters
end
def fix_displayed_fields
ProcedurePresentation.where(%q`displayed_fields @> '[{"table": "france_connect_information"}]'`).each do |procedure_presentation|
procedure_presentation.displayed_fields = procedure_presentation.displayed_fields.reject do |df|
df['table'] == 'france_connect_information'
end
procedure_presentation.save(validate: false)
end
end
def fix_sort
ProcedurePresentation.where(%q`sort @> '{"table": "france_connect_information"}'`).each do |procedure_presentation|
procedure_presentation.sort = {
"order" => "desc",
"table" => "notifications",
"column" => "notifications"
}
procedure_presentation.save(validate: false)
end
end
def fix_filters
ProcedurePresentation.find_by_sql(
<<~SQL
SELECT procedure_presentations.*
FROM procedure_presentations, LATERAL jsonb_each(filters)
WHERE value @> '[{"table": "france_connect_information"}]'
GROUP BY id;
SQL
).each do |procedure_presentation|
procedure_presentation.filters.keys.each do |key|
procedure_presentation.filters[key] = procedure_presentation.filters[key].reject do |filter|
filter['table'] == 'france_connect_information'
end
end
procedure_presentation.save
end
end
end.new.run
end
end

View file

@ -1,94 +0,0 @@
namespace :'2018_10_03_fix_mailjet_mistakes' do
task activation_emails: :environment do
activation_file_path = ENV['ACTIVATION']
if File.file?(activation_file_path)
rake_puts "loading #{activation_file_path} file for account activation"
else
rake_puts "no file #{activation_file_path} found"
end
emails = File.new(activation_file_path).readlines.map(&:strip)
emails.each do |email|
user = User.find_by(email: email)
if user.present?
rake_puts "sending activation mail for #{email}"
if user.confirmed?
UserMailer.new_account_warning(user).deliver_later
else
user.resend_confirmation_instructions
end
else
rake_puts "user #{email} does not exist"
end
end
end
task password_emails: :environment do
password_file_path = ENV['PASSWORD']
if File.file?(password_file_path)
rake_puts "loading #{password_file_path} file for changing password"
else
rake_puts "no file #{password_file_path} found"
end
emails = File.new(password_file_path).readlines.map(&:strip)
emails.each do |email|
user = User.find_by(email: email)
if user.present?
rake_puts "sending changing password mail for #{email}"
user.send_reset_password_instructions
else
rake_puts "user #{email} does not exist"
end
end
end
task notification_emails: :environment do
notification_file_path = ENV['NOTIFICATION']
if File.file?(notification_file_path)
rake_puts "loading #{notification_file_path} file for notification"
else
rake_puts "no file #{notification_file_path} found"
end
lines = File.new(notification_file_path).readlines.map(&:strip)
lines.each do |line|
email, *subject = line.split(',')
subject = *subject.join
user = User.find_by(email: email)
body = <<-EOS
Bonjour,
Suite à un incident technique concernant les envois d'emails sur le site demarches-simplifiees.fr, nous n'avons pas pu vous remettre l'email intitulé #{subject}.
Vous pouvez néanmoins le consulter directement dans la messagerie de votre dossier en vous connectant sur https://www.demarches-simplifiees.fr/users/sign_in .
Veuillez nous excuser pour la gêne occasionnée.
Cordialement,
L'équipe de demarches-simplifiees.fr
EOS
if user.present?
rake_puts "sending notification for #{email}"
ActionMailer::Base.mail(
from: "contact@demarches-simplifiees.fr",
to: email,
subject: subject,
body: body
).deliver_later
else
rake_puts "user #{email} does not exist"
end
end
end
end

View file

@ -1,15 +0,0 @@
namespace :'2018_10_30_admin_has_gestionnaire' do
task run: :environment do
admin_without_gestionnaire_ids = Administrateur
.find_by_sql('SELECT administrateurs.id FROM administrateurs LEFT OUTER JOIN gestionnaires ON gestionnaires.email = administrateurs.email WHERE gestionnaires.email IS NULL')
.pluck(:id)
admin_without_gestionnaire_ids.each do |admin_id|
admin = Administrateur.find(admin_id)
g = Gestionnaire.new
g.email = admin.email
g.encrypted_password = admin.encrypted_password
g.save(validate: false)
end
end
end

View file

@ -1,185 +0,0 @@
namespace :'2018_12_03_finish_piece_jointe_transfer' do
task run: :environment do
Class.new do
def run
notify_dry_run
refresh_outdated_files
remove_unused_openstack_objects
fix_openstack_mime_types
notify_dry_run
end
def notify_dry_run
if !force?
rake_puts "Dry run, run with FORCE=1 to actually perform changes"
end
end
def force?
if !defined? @force
@force = (ENV['FORCE'].presence || '0').to_i != 0
end
@force
end
def verbose?
if !defined? @verbose
@verbose = (ENV['VERBOSE'].presence || '0').to_i != 0
end
@verbose
end
def old_pj_adapter
raise NotImplementedError, "No connection adapter for old PJ storage"
end
def new_pjs
if !defined? @new_pjs
fog_credentials = {
provider: 'OpenStack',
openstack_tenant: Rails.application.secrets.fog[:openstack_tenant],
openstack_api_key: Rails.application.secrets.fog[:openstack_api_key],
openstack_username: Rails.application.secrets.fog[:openstack_username],
openstack_auth_url: Rails.application.secrets.fog[:openstack_auth_url],
openstack_region: Rails.application.secrets.fog[:openstack_region],
openstack_identity_api_version: Rails.application.secrets.fog[:openstack_identity_api_version]
}
new_pj_storage = Fog::Storage.new(fog_credentials)
@new_pjs = new_pj_storage.directories.get(ENV['FOG_ACTIVESTORAGE_DIRECTORY'])
end
@new_pjs
end
# After the initial bulk transfer, but before ActiveStorage is switched to the new storage,
# there is a window where new attachments can be added to the old storage.
#
# This task ports them to the new storage after the switch, while being careful not to
# overwrite attachments that may have changed in the new storage after the switch.
def refresh_outdated_files
refreshed_keys = []
old_pj_adapter.session do |old_pjs|
rake_puts "List old PJs"
old_pj_listing = old_pjs.list_prefixed('')
rake_puts "List new PJs"
new_pj_listing = {}
progress = ProgressReport.new(new_pjs.count.to_i)
new_pjs.files.each do |f|
new_pj_listing[f.key] = f.last_modified.in_time_zone
progress.inc
end
progress.finish
rake_puts "Refresh outdated attachments"
progress = ProgressReport.new(old_pj_listing.count)
old_pj_listing.each do |key, old_pj_last_modified|
new_pj_last_modified = new_pj_listing[key]
if new_pj_last_modified.nil? || new_pj_last_modified < old_pj_last_modified
# Looks like we need to refresh this PJ.
# Fetch fresh metadata to avoid overwriting a last-minute change
new_pj_metadata = new_pjs.files.head(key)
refresh_needed = new_pj_metadata.nil?
if !refresh_needed
new_pj_last_modified = new_pj_metadata.last_modified.in_time_zone
refresh_needed = new_pj_last_modified < old_pj_last_modified
end
end
if refresh_needed
refreshed_keys.push(key)
if force?
file = Tempfile.new(key)
file.binmode
old_pjs.download(key) do |chunk|
file.write(chunk)
end
file.rewind
new_pjs.files.create(
:key => key,
:body => file,
:public => false
)
file.close
file.unlink
end
end
progress.inc
end
progress.finish
end
if verbose?
rake_puts "Refreshed #{refreshed_keys.count} attachments\n#{refreshed_keys.join(', ')}"
end
end
# For OpenStack, the content type cannot be forced dynamically from a direct download URL.
#
# The ActiveStorage-OpenStack adapter works around this by monkey patching ActiveStorage
# to statically set the correct MIME type on each OpenStack object.
#
# However, for objects that have been migrated from another storage, the content-type might
# be wrong, so we manually fix it.
def fix_openstack_mime_types
if !ActiveStorage::Blob.service.respond_to?(:change_content_type)
rake_puts "Not running on openstack, not fixing MIME types"
return
end
rake_puts "Fix MIME types"
progress = ProgressReport.new(new_pjs.count.to_i)
failed_keys = []
updated_keys = []
new_pjs.files.each do |file|
blob = ActiveStorage::Blob.find_by(key: file.key)
if blob.nil?
failed_keys.push(file.key)
elsif blob.identified? && blob.content_type.present?
updated_keys.push(file.key)
if force?
if !blob.service.change_content_type(file.key, blob.content_type)
failed_keys.push(file.key)
end
end
end
progress.inc
end
progress.finish
if verbose?
rake_puts "Updated MIME Type for #{updated_keys.count} keys\n#{updated_keys.join(', ')}"
end
if failed_keys.present?
rake_puts "failed to update #{failed_keys.count} keys\n#{failed_keys.join(', ')}"
end
end
# Garbage collect objects that might have been removed in the meantime
def remove_unused_openstack_objects
rake_puts "Remove unused files"
progress = ProgressReport.new(new_pjs.count.to_i)
removed_keys = []
new_pjs.files.each do |file|
if !ActiveStorage::Blob.exists?(key: file.key)
removed_keys.push(file.key)
if force?
file.destroy
end
end
progress.inc
end
progress.finish
if verbose?
rake_puts "Removed #{removed_keys.count} unused objects\n#{removed_keys.join(', ')}"
end
end
end.new.run
end
end

View file

@ -4,7 +4,7 @@ namespace :fix_timestamps_of_migrated_dossiers do
desc 'Fix the timestamps of dossiers affected by the faulty PJ migration' desc 'Fix the timestamps of dossiers affected by the faulty PJ migration'
task run: :environment do task run: :environment do
affected_time_range = Time.utc(2019, 6, 4, 8, 0)..Time.utc(2019, 6, 4, 18, 0) affected_time_range = Time.utc(2019, 6, 4, 8, 0)..Time.utc(2019, 6, 4, 18, 0)
dossiers = Dossier.with_hidden.includes(:groupe_instructeur).where(groupe_instructeurs: { procedure_id: 0..1000 }).where(updated_at: affected_time_range) dossiers = Dossier.with_discarded.includes(:groupe_instructeur).where(groupe_instructeurs: { procedure_id: 0..1000 }).where(updated_at: affected_time_range)
progress = ProgressReport.new(dossiers.count) progress = ProgressReport.new(dossiers.count)

View file

@ -1,8 +0,0 @@
namespace :after_party do
desc 'Deployment task: remove_path_from_archived_procedures'
task remove_path_from_archived_procedures: :environment do
Procedure.archivees.where.not(path: nil).update_all(path: nil)
AfterParty::TaskRecord.create version: '20181031104615'
end
end

View file

@ -1,128 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :after_party do
desc 'Deployment task: approve / reject dossiers for procedure 8670'
task mass_process_procedure_8670_dossiers: :environment do
class MassProcessProcedure8670
DOSSIER_IDS_TO_ACCEPT = [
194722, 172178, 170186, 177122, 171783, 173930, 176042, 183202, 192081, 170387,
171136, 171765, 173743, 173784, 173802, 173904, 173915, 171744, 173945, 170839,
173954, 173967, 173990, 174003, 172217, 170449, 176603, 175921, 172634, 179048,
180970, 181508, 182035, 181526, 178543, 170822, 170782, 186579, 187928, 188183,
188399, 176860, 170614, 194011, 194100, 196307, 200282, 171544, 201953, 176316,
205882, 205907, 205962, 178940, 181650, 202114, 180333, 174687, 192439, 169826,
170121, 169894, 170635, 170626, 171896, 171993, 171935, 172028, 172087, 172094,
172138, 172206, 172456, 172468, 172533, 172627, 172758, 172834, 172845, 172879,
172884, 173411, 173662, 172256, 173909, 191259, 197681, 200041, 177306, 202624,
203230, 204556, 205785, 198252, 170227, 173513, 172296, 174292, 174483, 174492,
175076, 176540, 177177, 177322, 183210, 183498, 184353, 195189, 195967, 186147,
170799, 178152, 177440, 184132, 169967, 175335, 177364, 179365, 197527, 172820,
187060, 200326, 169921, 183622, 174745, 175484, 174512, 180860, 189163, 170054,
170106, 206667, 170263, 173759, 169879, 170632, 190310, 170325, 170336, 170650,
171520, 171050, 170414, 173804, 173911, 173947, 178986, 172030, 177428, 182875,
198458, 199080, 172489, 200406, 204297, 171184, 171265, 171338, 171347, 172620,
173162, 171939, 171597, 173878, 173758, 175861, 175923, 176851, 176957, 172479,
183279, 177429, 185382, 185586, 188898, 172840, 180340, 195351, 171135, 170583,
171680, 174150, 175066, 177164, 172951, 170623, 172863, 178732, 178268, 179848,
179896, 179923, 179283, 180083, 185764, 192455, 190329, 197121, 169897, 170005,
170023, 170127, 170399, 170371, 170351, 170519, 170654, 170680, 170774, 170781,
171892, 169828, 171989, 172070, 171952, 171923, 172184, 174859, 175560, 175865,
172922, 171889, 173550, 181501, 179897, 185241, 190364, 193743, 178551, 199361,
173739, 169885, 169893, 171777, 179338, 179818, 170339, 178090, 187012, 191063,
179911, 195101, 177916, 170242, 173537, 173895, 173700, 174642, 174749, 174880,
174818, 175011, 174863, 175422, 175644, 177797, 177829, 174276, 200208, 204312,
204356, 179106, 177928, 180376, 181086, 180048, 192202, 194193, 204479, 204979,
183388, 185549
]
DOSSIER_IDS_TO_REJECT = [
172516, 177423, 177002, 179031, 176856, 179193, 179237, 179333, 179912, 179949,
181001, 185704, 185710, 177001, 186898, 175420, 175412, 195668, 174463, 175347,
174606, 176668, 176749, 177007, 177037, 174306, 177373, 174496, 174583, 205297,
191646, 178553, 184288, 174296, 199563, 202567, 180596, 194441, 196523, 183504,
190011, 184563, 175047, 177243, 174108, 174423, 170552, 171931, 170955, 170415,
170652, 170145, 170044, 169841, 171280, 177569, 174711, 180357, 180554, 175594,
181370, 180370, 180279, 182877, 188432, 183516, 191845, 184965, 198962, 199250,
202324, 205887, 172006, 196073, 197861, 198389, 188855, 198639, 203881, 205520,
205626, 206468, 196904, 206619, 206730, 175088, 191405, 173038, 195082, 185849,
188454, 188501, 188713, 171057, 177541, 177882, 178185, 178951, 178962, 178997,
179090, 179234, 173959, 177621, 174022, 181414, 181895, 183081, 175935, 175951,
176156, 176200, 176506, 176567, 173898, 173906, 173905, 173932, 173810, 173949,
173961, 174033, 172939, 174227, 172362, 173008, 174979, 173396, 173196, 172143,
173790, 173745, 173779, 172151, 170332, 171424, 171434, 170459, 171635, 171689,
170409, 171429, 171940, 170266, 172632, 172742, 170689, 206612, 169877, 170402,
170563, 170605, 170658, 170653, 170699, 170511, 170835, 183559, 187911, 188163,
188685, 188702, 170678, 183994, 173899, 194530, 194873, 194433, 173971, 174004,
174239, 174430, 175849, 175850, 176265, 176630, 176789, 175946, 172407, 177398,
170027, 170002, 170404, 173678, 170655, 170328, 170405, 170686, 171106, 171763,
172317, 172763, 172880, 173250, 174938, 170714, 175798, 175899, 176015, 176041,
176258, 176341, 176909, 176944, 174031, 180109, 170316, 174100, 174540, 175910,
177872, 178117, 179092, 183923, 175005, 185795, 186580, 181383, 189186, 194998,
177475, 174446, 180508, 181216, 181290, 181905, 191344, 187745, 192016, 193188,
170201, 170288, 170568
]
def run
rake_puts "Running deploy task 'mass_process_procedure_8670_dossiers'\n"
reject_dossiers
accept_dossiers
AfterParty::TaskRecord.create version: '20181106170434'
end
def reject_dossiers
rake_puts "Rejecting dossiers\n"
dossiers_for_traitement.where(id: DOSSIER_IDS_TO_REJECT).find_each do |dossier|
if skip_dossier?(dossier)
next
end
dossier.update(
state: Dossier.states.fetch(:refuse),
motivation: "Malheureusement, votre dossier n'a pas été tiré au sort",
processed_at: Time.zone.now
)
NotificationMailer.send_refused_notification(dossier).deliver_later
end
end
def accept_dossiers
rake_puts "Accepting dossiers\n"
dossiers_for_traitement.where(id: DOSSIER_IDS_TO_ACCEPT).find_each do |dossier|
if skip_dossier?(dossier)
next
end
dossier.update(
state: Dossier.states.fetch(:accepte),
processed_at: Time.zone.now
)
dossier.attestation = dossier.build_attestation
dossier.save
NotificationMailer.send_closed_notification(dossier).deliver_later
end
end
def dossiers_for_traitement
Dossier.includes(:procedure, :user, :etablissement, :champs, :champs_private)
end
def skip_dossier?(dossier)
if dossier.procedure_id != 8670
rake_puts "Skipping dossier #{dossier.id} (wrong procedure)\n"
return true
end
if !dossier.en_instruction?
rake_puts "Skipping dossier #{dossier.id} (not en instruction)\n"
return true
end
return false
end
end
MassProcessProcedure8670.new.run
end
end

View file

@ -1,54 +0,0 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :after_party do
# Matches "ne pas répondre", plus some content before and after:
# - try to remove dashes before the footer
# - try to remove line-breaks and empty HTML tags before the footer text
# - matches "Veuillez ne pas répondre" or "Merci de ne pas répondre"
# - once the footer text is found, extend the match to the end of the body
FOOTER_REGEXP = /(—|---|-)?( |\r|\n|<br>|<p>|<\/p>|<small>|<\/small>|<b>|<\/b>|&nbsp;)*(Veuillez)?(Merci)?( |\r|\n)*(de)? ne pas répondre(.*)$/m
# When the footer contains any of these words, it is kept untouched.
FOOTER_EXCEPTIONS = [
'PDF',
'@',
'Hadrien',
'Esther',
'Sicoval',
'a323',
'SNC',
'Polynésie',
'drac',
'theplatform'
]
desc 'Deployment task: remove_footer_from_email_templates'
task remove_footer_from_email_templates: :environment do
rake_puts "Running deploy task 'remove_footer_from_email_templates'"
models = [
Mails::ClosedMail,
Mails::InitiatedMail,
Mails::ReceivedMail,
Mails::RefusedMail,
Mails::WithoutContinuationMail
]
models.each do |model_class|
model_class.all.find_each do |template|
remove_footer(template)
end
end
# Update task as completed. If you remove the line below, the task will
# run with every deploy (or every time you call after_party:run).
AfterParty::TaskRecord.create version: '20181120133842'
end # task :remove_footer_from_email_templates
def remove_footer(template)
matches = template.body.match(FOOTER_REGEXP)
if matches && FOOTER_EXCEPTIONS.none? { |exception| matches[0].include?(exception) }
rake_puts "#{template.model_name} \##{template.id}: removing footer"
template.update(body: matches.pre_match)
end
end
end # namespace :after_party

View file

@ -1,28 +0,0 @@
require 'rake-progressbar'
namespace :after_party do
desc 'Deployment task: fix_notifications_after_carto_migration'
task fix_notifications_after_carto_migration: :environment do
def fix_notifications(dossier)
updated_at = dossier.champs[1..-1].map(&:updated_at).max
champ_carte = dossier.champs.first
if updated_at && (!champ_carte.updated_at || champ_carte.updated_at > updated_at)
champ_carte.update_columns(updated_at: updated_at, created_at: updated_at)
end
end
dossiers = Dossier.includes(:champs)
.joins(procedure: :module_api_carto)
.where(procedure: { module_api_cartos: { migrated: true } })
bar = RakeProgressbar.new(dossiers.count)
dossiers.find_each do |dossier|
fix_notifications(dossier)
bar.inc
end
bar.finished
AfterParty::TaskRecord.create version: '20181121153709'
end
end

View file

@ -1,15 +0,0 @@
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

View file

@ -1,17 +0,0 @@
namespace :after_party do
desc 'Deployment task: destroy_orphaned_dossier_operation_logs'
task destroy_orphaned_dossier_operation_logs: :environment do
bar = RakeProgressbar.new(DossierOperationLog.count)
DossierOperationLog.find_each do |log|
if log.dossier.blank?
log.destroy
end
bar.inc
end
bar.finished
AfterParty::TaskRecord.create version: '20181128155650'
end
end

View file

@ -1,20 +0,0 @@
namespace :after_party do
desc 'Deployment task: remove_champ_pj_feature'
task remove_champ_pj_feature: :environment do
rake_puts "Running deploy task 'remove_champ_pj_feature'"
Administrateur.find_by_sql(
<<~SQL
SELECT administrateurs.*
FROM administrateurs, lateral jsonb_each(features)
WHERE key = 'champ_pj'
GROUP BY id
SQL
).each do |admin|
admin.features.delete('champ_pj')
admin.save
end
AfterParty::TaskRecord.create version: '20181210185634'
end
end

View file

@ -1,28 +0,0 @@
namespace :after_party do
desc 'Deployment task: fix_email_templates_subjects'
task fix_email_templates_subjects: :environment do
rake_puts "Running deploy task 'fix_email_templates_subjects'"
klasses = [
Mails::ClosedMail,
Mails::InitiatedMail,
Mails::ReceivedMail,
Mails::RefusedMail,
Mails::WithoutContinuationMail
]
klasses.each do |klass|
klass
.where("subject LIKE '%--libellé procédure--%'")
.each do |instance|
instance.update(subject: instance.subject.gsub("--libellé procédure--", "--libellé démarche--"))
rake_puts "Subject mis-à-jour pour #{klass}##{instance.id}"
end
end
# Update task as completed. If you remove the line below, the task will
# run with every deploy (or every time you call after_party:run).
AfterParty::TaskRecord.create version: '20181219122438'
end # task :fix_email_templates_subjects
end # namespace :after_party

View file

@ -1,17 +0,0 @@
namespace :after_party do
desc 'Deployment task: migrate_types_de_champ_options_to_json'
task migrate_types_de_champ_options_to_json: :environment do
rake_puts "Running deploy task 'migrate_types_de_champ_options_to_json'"
dirty_tdcs = TypeDeChamp.where.not(options: nil)
progress = ProgressReport.new(dirty_tdcs.count)
dirty_tdcs.find_each do |tdc|
tdc.options_will_change!
tdc.save
progress.inc
end
progress.finish
AfterParty::TaskRecord.create version: '20181219175043'
end
end

View file

@ -3,7 +3,7 @@ namespace :after_party do
task create_dummy_paths_for_archived_and_hidden_procedures: :environment do task create_dummy_paths_for_archived_and_hidden_procedures: :environment do
rake_puts "Running deploy task 'create_dummy_paths_for_archived_procedures'" rake_puts "Running deploy task 'create_dummy_paths_for_archived_procedures'"
Procedure.with_hidden.archivees.where(path: nil).each do |p| Procedure.with_discarded.archivees.where(path: nil).each do |p|
p.update_column(:path, SecureRandom.uuid) p.update_column(:path, SecureRandom.uuid)
end end

View file

@ -2,7 +2,7 @@ namespace :after_party do
desc 'Deployment task: create_default_groupe_instructeur' desc 'Deployment task: create_default_groupe_instructeur'
task create_default_groupe_instructeur: :environment do task create_default_groupe_instructeur: :environment do
Procedure Procedure
.with_hidden .with_discarded
.left_outer_joins(:groupe_instructeurs) .left_outer_joins(:groupe_instructeurs)
.where('groupe_instructeurs.id is null') .where('groupe_instructeurs.id is null')
.find_each do |procedure| .find_each do |procedure|

View file

@ -61,7 +61,7 @@ FactoryBot.define do
archived { false } archived { false }
end end
trait :hidden do trait :discarded do
hidden_at { Time.zone.now } hidden_at { Time.zone.now }
end end

View file

@ -185,7 +185,7 @@ FactoryBot.define do
end end
end end
trait :hidden do trait :discarded do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
procedure.path = generate(:published_path) procedure.path = generate(:published_path)
procedure.publish! procedure.publish!

View file

@ -91,27 +91,52 @@ feature 'Signing up:' do
end end
end end
context 'when a user is not confirmed yet' do context 'when the user is not confirmed yet' do
before do before do
create(:user, :unconfirmed, email: user_email, password: user_password)
end
scenario 'the email confirmation page is displayed' do
visit commencer_path(path: procedure.path) visit commencer_path(path: procedure.path)
click_on 'Créer un compte demarches-simplifiees.fr' click_on 'Créer un compte'
sign_up_with user_email, user_password sign_up_with user_email, user_password
# The same page than for initial sign-ups is displayed, to avoid leaking informations
# about the accound existence.
expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
# The confirmation email is sent again
confirmation_email = open_email(user_email)
expect(confirmation_email.body).to have_text('Pour activer votre compte')
end
end end
# Ideally, when signing-in with an unconfirmed account, context 'when the user already has a confirmed account' do
# the user would be redirected to the "resend email confirmation" page. before do
# create(:user, email: user_email, password: user_password)
# However the check for unconfirmed accounts is made by Warden every time a page is loaded  end
# and much earlier than SessionsController#create.
#
# For now only test the default behavior (an error message is displayed).
scenario 'they get an error message' do
visit root_path
click_on 'Connexion'
sign_in_with user_email, user_password scenario 'they get a warning email, containing a link to the procedure' do
expect(page).to have_content 'Vous devez confirmer votre adresse email pour continuer' visit commencer_path(path: procedure.path)
click_on 'Créer un compte'
sign_up_with user_email, user_password
# The same page than for initial sign-ups is displayed, to avoid leaking informations
# about the accound existence.
expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
# A warning email is sent
warning_email = open_email(user_email)
expect(warning_email.body).to have_text('Votre compte existe déjà')
# When clicking the main button, the user has a link to directly sign-in
# for the procedure they were initially starting
click_procedure_sign_in_link_for user_email
expect(page).to have_current_path new_user_session_path
expect(page).to have_procedure_description(procedure)
end end
end end
end end

View file

@ -46,8 +46,8 @@ RSpec.describe FindDubiousProceduresJob, type: :job do
it { expect(AdministrationMailer).to have_received(:dubious_procedures).with([]) } it { expect(AdministrationMailer).to have_received(:dubious_procedures).with([]) }
end end
context 'and a hidden procedure' do context 'and a discarded procedure' do
let(:procedure) { create(:procedure, :hidden) } let(:procedure) { create(:procedure, :discarded) }
it { expect(AdministrationMailer).to have_received(:dubious_procedures).with([]) } it { expect(AdministrationMailer).to have_received(:dubious_procedures).with([]) }
end end

View file

@ -1,26 +0,0 @@
require 'spec_helper'
describe '2018_03_06_clean_html_textareas#clean' do
let(:procedure) { create(:procedure) }
let(:type_champ) { create(:type_de_champ_textarea, procedure: procedure) }
let(:champ) { type_champ.champ.create(value: "<p>Gnahar<br>greu bouahaha</p>") }
let(:champ_date) { Time.zone.local(1995) }
let(:rake_date) { Time.zone.local(2018) }
let(:rake_task) { Rake::Task['2018_03_06_clean_html_textareas:clean'] }
before do
Timecop.freeze(champ_date) { champ }
Timecop.freeze(rake_date) { rake_task.invoke }
champ.reload
end
after { rake_task.reenable }
it 'cleans up html tags' do
expect(champ.value).to eq("Gnahar\ngreu bouahaha\n")
end
it 'does not change the models dates' do
expect(champ.updated_at).to eq(champ_date)
end
end

View file

@ -1,30 +0,0 @@
require 'spec_helper'
describe '2018_03_29_remove_code_tags_from_mail_templates#clean' do
let(:rake_task) { Rake::Task['2018_03_29_remove_code_tags_from_mail_templates:clean'] }
let!(:dirty_closed_mail) { create(:closed_mail, body: "<h1>Salut</h1><br>Voici ton email avec une balise <code>--balise--</code>") }
let!(:dirty_initiated_mail) { create(:initiated_mail, body: "<h1>Salut</h1><br>Voici ton email avec une balise <code>--balise--</code>") }
let!(:dirty_received_mail) { create(:received_mail, body: "<h1>Salut</h1><br>Voici ton email avec une balise <code>--balise--</code>") }
let!(:dirty_refused_mail) { create(:refused_mail, body: "<h1>Salut</h1><br>Voici ton email avec une balise <code>--balise--</code>") }
let!(:dirty_without_continuation_mail) { create(:without_continuation_mail, body: "<h1>Salut</h1><br>Voici ton email avec une balise <code>--balise--</code>") }
before do
rake_task.invoke
dirty_closed_mail.reload
dirty_initiated_mail.reload
dirty_received_mail.reload
dirty_refused_mail.reload
dirty_without_continuation_mail.reload
end
after { rake_task.reenable }
it 'cleans up code tags' do
expect(dirty_closed_mail.body).to eq("<h1>Salut</h1><br>Voici ton email avec une balise --balise--")
expect(dirty_initiated_mail.body).to eq("<h1>Salut</h1><br>Voici ton email avec une balise --balise--")
expect(dirty_received_mail.body).to eq("<h1>Salut</h1><br>Voici ton email avec une balise --balise--")
expect(dirty_refused_mail.body).to eq("<h1>Salut</h1><br>Voici ton email avec une balise --balise--")
expect(dirty_without_continuation_mail.body).to eq("<h1>Salut</h1><br>Voici ton email avec une balise --balise--")
end
end

View file

@ -1,72 +0,0 @@
describe '20181120133842_remove_footer_from_email_templates.rake' do
let(:rake_task) { Rake::Task['after_party:remove_footer_from_email_templates'] }
let(:templates) do
bodies.map { |body| create(:received_mail, body: body) }
end
before do
templates
end
subject! do
rake_task.invoke
end
after do
rake_task.reenable
end
context 'when emails have "do not reply" footers' do
let(:bodies) do
[
"<p>Some content</p>--- <br>\r\n<br>\r\nMerci de ne pas répondre à cet email. Postez directement vos questions dans\r\nvotre dossier sur la plateforme.</p>",
"<p>Some content</p>-<br>\r\n<br>\r\nMerci de ne pas répondre à cet email. Postez directement vos questions dans\r\nvotre dossier sur la plateforme.</p>",
"<p>Some content</p>— <br>\r\n<br>\r\nMerci de ne pas répondre à cet email. Postez directement vos questions dans\r\nvotre dossier sur la plateforme.</p>",
"<p>Some content</p>--- <br>\r\n<br>\r\nMerci de ne pas répondre à cet email. Postez directement vos questions dans\r\nvotre dossier sur demarches-simplifiees.fr.</p>",
"<p>Some content</p>— <br><br><small></small><b></b>Merci de ne pas répondre à cet email. Postez directement vos questions dans\r\nvotre dossier sur la plateforme.</p>",
"<p>Some content</p>--- <br>\r\n<br>\r\nMerci de ne pas répondre à cet email. Postez directement vos questions dans\r\nvotre dossier --libelle-dossier--.</p>",
"<p>Some content</p>--- <br>\r\n<br>\r\nMerci de ne pas répondre à cet email. Postez directement vos questions dans\r\nvotre dossier sur la plateforme, mais ne répondez pas à ce message.</p><p>\r\n\r\n</p><p>&nbsp;</p><p>\r\n<br></p><br>",
"<p>Some content</p>--- <br>\r\n<br>\r\Veuillez ne pas répondre à cet email. Postez directement vos questions dans\r\nvotre dossier sur la plateforme.</p>",
"<p>Some content</p>--- <br>\r\n<br>\r\nMerci\r\nde ne pas répondre à cet email. Postez directement vos questions dans\r\nvotre dossier sur la plateforme, mais ne répondez pas à ce message.</p><p>\r\n\r\n</p><p>&nbsp;</p><p>\r\n<br></p><br>",
"<p>Some content</p>--- <br>\r\n<br>\r\Veuillez ne pas répondre à ce mail. Postez directement vos questions dans\r\nvotre dossier sur la plateforme.</p>"
]
end
it 'removes footer from mail template body' do
templates.each do |template|
expect(template.reload.body).to eq '<p>Some content</p>'
end
end
end
context 'when emails dont have the standard boilerplate in the footer' do
let(:bodies) do
[
"<p>Some content.</p><p>Merci, l'équipe demarches-simplifiees.fr.\r\n</p>",
"<p>Some content.</p><p>Merci, l'équipe TPS.\r\n</p><small></small>"
]
end
it 'keeps the footer' do
templates.each do |template|
expect(bodies).to include(template.reload.body)
end
end
end
context 'when the footer contains some excluded strings' do
let(:bodies) do
[
"<p>Some content</p>--- <br>\r\n<br>\r\nMerci de ne pas répondre à cet email. Le texte du présent e-mail n'a aucune valeur d'autorisation provisoire. Seule l'attestation d'autorisation provisoire de travail au format PDF, si délivrée, fera foi.",
"<p>Some content</p>--- <br>\r\n<br>\r\nMerci de ne pas répondre à cet email. En cas de question, utilisez la messagerie ou écrivez à instructeur@exemple.gouv.fr.",
"<p>Some content</p>--- <br>\r\n<br>Merci de ne pas répondre à cet email. Postez directement vos questions dans votre dossier sur la plateforme, ou trouvez le contact de votre conseiller cinéma sur <a target=\"_blank\" rel=\"nofollow\" href=\"http://www.cnc.fr/web/fr/conseillers-drac\">http://www.cnc.fr/web/fr/conseillers-drac</a><br>"
]
end
it 'keeps the footer' do
templates.each do |template|
expect(bodies).to include(template.reload.body)
end
end
end
end

View file

@ -18,17 +18,17 @@ describe '20190819142551_create_default_groupe_instructeur.rake' do
end end
end end
context 'with a procedure hidden without gi' do context 'with a procedure discarded without gi' do
let!(:procedure_hidden_without_gi) { create(:procedure, :hidden) } let!(:procedure_discarded_without_gi) { create(:procedure, :discarded) }
before do before do
procedure_hidden_without_gi.groupe_instructeurs.destroy_all procedure_discarded_without_gi.groupe_instructeurs.destroy_all
end end
it do it do
expect(procedure_hidden_without_gi.groupe_instructeurs).to be_empty expect(procedure_discarded_without_gi.groupe_instructeurs).to be_empty
subject subject
expect(procedure_hidden_without_gi.reload.groupe_instructeurs.pluck(:label)).to eq(['défaut']) expect(procedure_discarded_without_gi.reload.groupe_instructeurs.pluck(:label)).to eq(['défaut'])
end end
end end

View file

@ -3,6 +3,11 @@ class UserMailerPreview < ActionMailer::Preview
UserMailer.new_account_warning(user) UserMailer.new_account_warning(user)
end end
def new_account_warning___with_procedure
procedure = Procedure.new(libelle: 'Dotation dÉquipement des Territoires Ruraux - Exercice 2019', path: 'dotation-etr')
UserMailer.new_account_warning(user, procedure)
end
def account_already_taken def account_already_taken
UserMailer.account_already_taken(user, 'dircab@territoires.gouv.fr') UserMailer.account_already_taken(user, 'dircab@territoires.gouv.fr')
end end

View file

@ -8,6 +8,15 @@ RSpec.describe UserMailer, type: :mailer do
it { expect(subject.to).to eq([user.email]) } it { expect(subject.to).to eq([user.email]) }
it { expect(subject.body).to include(user.email) } it { expect(subject.body).to include(user.email) }
it { expect(subject.body).to have_link('Jai oublié mon mot de passe') }
context 'when a procedure is provided' do
let(:procedure) { build(:procedure) }
subject { described_class.new_account_warning(user, procedure) }
it { expect(subject.body).to have_link("Commencer la démarche « #{procedure.libelle} »", href: commencer_sign_in_url(path: procedure.path)) }
end
end end
describe '.account_already_taken' do describe '.account_already_taken' do

View file

@ -22,6 +22,20 @@ describe Champ do
end end
end end
describe '#siblings' do
let(:procedure) { create(:procedure, :with_type_de_champ, :with_type_de_champ_private, types_de_champ_count: 1, types_de_champ_private_count: 1) }
let(:dossier) { create(:dossier, procedure: procedure) }
let(:public_champ) { dossier.champs.first }
let(:private_champ) { dossier.champs_private.first }
let(:standalone_champ) { create(:champ, dossier: nil) }
it 'returns the sibling champs of a champ' do
expect(public_champ.siblings).to eq(dossier.champs)
expect(private_champ.siblings).to eq(dossier.champs_private)
expect(standalone_champ.siblings).to be_nil
end
end
describe '#format_datetime' do describe '#format_datetime' do
let(:type_de_champ) { build(:type_de_champ_datetime) } let(:type_de_champ) { build(:type_de_champ_datetime) }
let(:champ) { type_de_champ.champ.build(value: value) } let(:champ) { type_de_champ.champ.build(value: value) }

View file

@ -0,0 +1,24 @@
require 'spec_helper'
describe Champs::HeaderSectionChamp do
describe '#section_index' do
let(:types_de_champ) do
[
create(:type_de_champ_header_section, order_place: 1),
create(:type_de_champ_civilite, order_place: 2),
create(:type_de_champ_text, order_place: 3),
create(:type_de_champ_header_section, order_place: 4),
create(:type_de_champ_email, order_place: 5)
]
end
let(:procedure) { create(:procedure, types_de_champ: types_de_champ) }
let(:dossier) { create(:dossier, procedure: procedure) }
let(:first_header) { dossier.champs[0] }
let(:second_header) { dossier.champs[3] }
it 'returns the index of the section (starting from 1)' do
expect(first_header.section_index).to eq 1
expect(second_header.section_index).to eq 2
end
end
end

Some files were not shown because too many files have changed in this diff Show more