Skip to content

Commit

Permalink
Merge branch 'feature/import-2023-07-19'
Browse files Browse the repository at this point in the history
  • Loading branch information
maatinito committed Dec 4, 2023
2 parents 672e89d + afd90e9 commit 9e8418c
Show file tree
Hide file tree
Showing 45 changed files with 403 additions and 58 deletions.
1 change: 1 addition & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,7 @@ Rails/CreateTableWithTimestamps:
- db/migrate/2017*.rb
- db/migrate/2018*.rb
- db/migrate/20200630140356_create_traitements.rb
- db/migrate/20230630091637_create_dossier_assignments.rb

Rails/Date:
Enabled: false
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ gem 'rack-attack'
gem 'rails-i18n' # Locales par défaut
gem 'rake-progressbar', require: false
gem 'redcarpet'
gem 'redis'
gem 'rexml' # add missing gem due to ruby3 (https://github.com/Shopify/bootsnap/issues/325)
gem 'rqrcode'
gem 'saml_idp'
Expand Down
6 changes: 6 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ GEM
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
concurrent-ruby (1.2.2)
connection_pool (2.4.1)
content_disposition (1.0.0)
crack (0.4.5)
rexml
Expand Down Expand Up @@ -587,6 +588,10 @@ GEM
rb-inotify (0.10.1)
ffi (~> 1.0)
redcarpet (3.6.0)
redis (5.0.6)
redis-client (>= 0.9.0)
redis-client (0.14.1)
connection_pool
regexp_parser (2.8.1)
request_store (1.5.0)
rack (>= 1.4)
Expand Down Expand Up @@ -922,6 +927,7 @@ DEPENDENCIES
rails-i18n
rake-progressbar
redcarpet
redis
rexml
rqrcode
rspec-rails
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def reaffecter
target_group = procedure.groupe_instructeurs.find(params[:target_group])
reaffecter_bulk_messages(target_group)
groupe_instructeur.dossiers.find_each do |dossier|
dossier.assign_to_groupe_instructeur(target_group, current_administrateur)
dossier.assign_to_groupe_instructeur(target_group, DossierAssignment.modes.fetch(:manual), current_administrateur)
end

flash[:notice] = "Les dossiers du groupe « #{groupe_instructeur.label} » ont été réaffectés au groupe « #{target_group.label} »."
Expand All @@ -210,7 +210,7 @@ def reaffecter
def reaffecter_all_dossiers_to_defaut_groupe
procedure.groupe_instructeurs_but_defaut.each do |gi|
gi.dossiers.find_each do |dossier|
dossier.assign_to_groupe_instructeur(procedure.defaut_groupe_instructeur, current_administrateur)
dossier.assign_to_groupe_instructeur(procedure.defaut_groupe_instructeur, DossierAssignment.modes.fetch(:manual), current_administrateur)
end
end
end
Expand Down
2 changes: 0 additions & 2 deletions app/controllers/administrateurs/procedures_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,6 @@ def show
.find(params[:id])

@procedure.validate(:publication)

@current_administrateur = current_administrateur
end

def edit
Expand Down
5 changes: 2 additions & 3 deletions app/controllers/instructeurs/dossiers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def personnes_impliquees
@avis_emails = dossier.experts.map(&:email)
@invites_emails = dossier.invites.map(&:email)
@potential_recipients = dossier.groupe_instructeur.instructeurs.reject { |g| g == current_instructeur }
@manual_assignments = dossier.dossier_assignments.manual.includes(:groupe_instructeur, :previous_groupe_instructeur)
end

def send_to_instructeurs
Expand Down Expand Up @@ -365,9 +366,7 @@ def reaffecter
.procedure
.groupe_instructeurs.find(params[:groupe_instructeur_id])

dossier.assign_to_groupe_instructeur(new_group)

dossier.update!(forced_groupe_instructeur: true)
dossier.assign_to_groupe_instructeur(new_group, DossierAssignment.modes.fetch(:manual), current_instructeur)

flash.notice = t('instructeurs.dossiers.reaffectation', dossier_id: dossier.id, label: new_group.label)
redirect_to instructeur_procedure_path(procedure)
Expand Down
2 changes: 0 additions & 2 deletions app/controllers/users/dossiers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -561,8 +561,6 @@ def submit_dossier_and_compute_errors
errors += format_errors(errors: @dossier.errors)
errors += format_errors(errors: @dossier.check_mandatory_and_visible_champs)

RoutingEngine.compute(@dossier)

errors
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class DossierChangerGroupeInstructeur < Mutations::BaseMutation
field :errors, [Types::ValidationErrorType], null: true

def resolve(dossier:, groupe_instructeur:)
dossier.assign_to_groupe_instructeur(groupe_instructeur)
dossier.assign_to_groupe_instructeur(groupe_instructeur, DossierAssignment.modes.fetch(:manual), current_administrateur)

{ dossier: }
end
Expand Down
6 changes: 5 additions & 1 deletion app/lib/api_entreprise/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ def current_status

private

def recipient
@procedure&.service && @procedure.service.siret.presence || ENV.fetch('API_ENTREPRISE_DEFAULT_SIRET')
end

def call_with_siret(resource_name, siret_or_siren, user_id: nil)
url = make_url(resource_name, siret_or_siren)

Expand Down Expand Up @@ -157,7 +161,7 @@ def build_params(user_id)
def base_params
{
context: APPLICATION_NAME,
recipient: ENV.fetch('API_ENTREPRISE_DEFAULT_SIRET'),
recipient: recipient,
non_diffusables: true
}
end
Expand Down
4 changes: 4 additions & 0 deletions app/models/administrateur.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ def merge(old_admin)
i.administrateurs << self
i.administrateurs.delete(old_admin)
end

old_admin.api_tokens.where('version >= ?', 3).find_each do |token|
self.api_tokens << token
end
end

def zones
Expand Down
1 change: 0 additions & 1 deletion app/models/concerns/dossier_clone_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ def merge_fork(editing_fork)
diff = make_diff(editing_fork)
apply_diff(diff)
touch(:last_champ_updated_at)
assign_to_groupe_instructeur(editing_fork.groupe_instructeur)
end
reload
update_search_terms_later
Expand Down
21 changes: 12 additions & 9 deletions app/models/concerns/tags_substitution_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -354,15 +354,18 @@ def parse_tags(text)
end

def used_tags_and_libelle_for(text)
parse_tags(text).filter_map do |token|
case token
in { tag: tag, id: id }
[id, tag]
in { tag: tag }
[tag]
else
nil
end
# MD5 should be enough and it avoids long key
Rails.cache.fetch(["parse_tags", Digest::MD5.hexdigest(text)], expires_in: 1.day) do
parse_tags(text).filter_map do |token|
case token
in { tag: tag, id: id }
[id, tag]
in { tag: tag }
[tag]
else
nil
end
end
end
end
end
23 changes: 21 additions & 2 deletions app/models/dossier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ def classer_sans_suite(motivation: nil, instructeur: nil, processed_at: Time.zon
has_one :traitement, -> { order(processed_at: :desc) }, inverse_of: false

has_many :dossier_operation_logs, -> { order(:created_at) }, inverse_of: :dossier
has_many :dossier_assignments, -> { order(:assigned_at) }, inverse_of: :dossier, dependent: :destroy
has_one :dossier_assignment, -> { order(assigned_at: :desc) }, inverse_of: false

belongs_to :groupe_instructeur, optional: true
belongs_to :revision, class_name: 'ProcedureRevision', optional: false
Expand Down Expand Up @@ -474,7 +476,6 @@ def classer_sans_suite(motivation: nil, instructeur: nil, processed_at: Time.zon

validates :user, presence: true, if: -> { deleted_user_email_never_send.nil? }, unless: -> { prefilled }
validates :individual, presence: true, if: -> { revision.procedure.for_individual? }
validates :groupe_instructeur, presence: true, if: -> { !brouillon? }

validates_associated :prefilled_champs_public, on: :prefilling

Expand Down Expand Up @@ -686,13 +687,17 @@ def show_procedure_state_warning?
procedure.discarded? || (brouillon? && !procedure.dossier_can_transition_to_en_construction?)
end

def assign_to_groupe_instructeur(groupe_instructeur, author = nil)
def assign_to_groupe_instructeur(groupe_instructeur, mode, author = nil)
return if groupe_instructeur.present? && groupe_instructeur.procedure != procedure
return if self.groupe_instructeur == groupe_instructeur

previous_groupe_instructeur = self.groupe_instructeur

update!(groupe_instructeur:, groupe_instructeur_updated_at: Time.zone.now)
update!(forced_groupe_instructeur: true) if mode == DossierAssignment.modes.fetch(:manual)

if !brouillon?
create_assignment(mode, previous_groupe_instructeur, groupe_instructeur, author&.email)
unfollow_stale_instructeurs
if author.present?
log_dossier_operation(author, :changer_groupe_instructeur, self)
Expand Down Expand Up @@ -908,6 +913,7 @@ def after_passer_en_construction
MailTemplatePresenterService.create_commentaire_for_state(self)
NotificationMailer.send_en_construction_notification(self).deliver_later
procedure.compute_dossiers_count
RoutingEngine.compute(self)
end

def after_passer_en_instruction(h)
Expand Down Expand Up @@ -1319,6 +1325,19 @@ def sva_svr_decision_in_days
(sva_svr_decision_on - Date.current).to_i
end

def create_assignment(mode, previous_groupe_instructeur, groupe_instructeur, instructeur_email = nil)
DossierAssignment.create!(
dossier_id: self.id,
mode: mode,
previous_groupe_instructeur_id: previous_groupe_instructeur&.id,
groupe_instructeur_id: groupe_instructeur.id,
previous_groupe_instructeur_label: previous_groupe_instructeur&.label,
groupe_instructeur_label: groupe_instructeur.label,
assigned_at: Time.zone.now,
assigned_by: instructeur_email
)
end

private

def create_missing_traitemets
Expand Down
34 changes: 34 additions & 0 deletions app/models/dossier_assignment.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# == Schema Information
#
# Table name: dossier_assignments
#
# id :bigint not null, primary key
# assigned_at :datetime not null
# assigned_by :string
# groupe_instructeur_label :string
# mode :string not null
# previous_groupe_instructeur_label :string
# dossier_id :bigint not null
# groupe_instructeur_id :bigint
# previous_groupe_instructeur_id :bigint
#
class DossierAssignment < ApplicationRecord
belongs_to :dossier

belongs_to :groupe_instructeur, optional: true, inverse_of: :assignments
belongs_to :previous_groupe_instructeur, class_name: 'GroupeInstructeur', optional: true, inverse_of: :previous_assignments

enum mode: {
auto: 'auto',
manual: 'manual'
}
scope :manual, -> { where(mode: :manual) }

def groupe_instructeur_label
@groupe_instructeur_label ||= groupe_instructeur&.label.presence || read_attribute(:groupe_instructeur_label)
end

def previous_groupe_instructeur_label
@previous_groupe_instructeur_label ||= previous_groupe_instructeur&.label.presence || read_attribute(:previous_groupe_instructeur_label)
end
end
10 changes: 10 additions & 0 deletions app/models/etablissement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ class Etablissement < ApplicationRecord
fermé: "fermé"
}, _prefix: true

def entreprise_raison_sociale
read_attribute(:entreprise_raison_sociale).presence || raison_sociale_for_ei
end

def raison_sociale_for_ei
if entreprise_nom || entreprise_prenom
[entreprise_nom, entreprise_prenom].join(' ')
end
end

def search_terms
[
entreprise_siren,
Expand Down
2 changes: 2 additions & 0 deletions app/models/groupe_instructeur.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class GroupeInstructeur < ApplicationRecord
has_many :dossiers
has_many :deleted_dossiers
has_many :batch_operations, through: :dossiers, source: :batch_operations
has_many :assignments, class_name: 'DossierAssignment', dependent: :nullify, inverse_of: :groupe_instructeur
has_many :previous_assignments, class_name: 'DossierAssignment', dependent: :nullify, inverse_of: :previous_groupe_instructeur
has_and_belongs_to_many :exports, dependent: :destroy
has_and_belongs_to_many :bulk_messages, dependent: :destroy

Expand Down
3 changes: 1 addition & 2 deletions app/models/procedure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,7 @@ def revisions_with_pending_dossiers

validates :lien_site_web, presence: true, if: :publiee?
validates :lien_notice, url: { no_local: true, allow_blank: true }
validates :lien_dpo, format: { with: Devise.email_regexp, message: "n'est pas valide" }, if: :lien_dpo_email?
validates :lien_dpo, url: { no_local: true, allow_blank: true }, unless: :lien_dpo_email?
validates :lien_dpo, url: { no_local: true, allow_blank: true, accept_email: true }

validates :draft_types_de_champ_public,
'types_de_champ/no_empty_block': true,
Expand Down
4 changes: 3 additions & 1 deletion app/models/routing_engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ def self.compute(dossier)
matching_groupe = dossier.procedure.groupe_instructeurs.active.reject(&:invalid_rule?).find do |gi|
gi.routing_rule&.compute(dossier.champs)
end

matching_groupe ||= dossier.procedure.defaut_groupe_instructeur
dossier.assign_to_groupe_instructeur(matching_groupe)

dossier.assign_to_groupe_instructeur(matching_groupe, DossierAssignment.modes.fetch(:auto))
end
end
5 changes: 4 additions & 1 deletion app/services/archive_uploader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,13 @@ def retryable_syscall_to_custom_uploader(blob)
limit_to_retry = 1
begin
syscall_to_custom_uploader(blob)
rescue
rescue => e
if limit_to_retry > 0
limit_to_retry = limit_to_retry - 1
retry
else
Sentry.set_tags(procedure:)
Sentry.capture_exception(e, extra: { filename: })
end
end
end
Expand Down
8 changes: 7 additions & 1 deletion app/services/geojson_service.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
class GeojsonService
def self.valid?(json)
schemer = JSONSchemer.schema(Rails.root.join('app/schemas/geojson.json'))
schemer.valid?(json)
if schemer.valid?(json)
if ActiveRecord::Base.connection.execute("SELECT 1 as one FROM pg_extension WHERE extname = 'postgis';").count.zero?
true
else
ActiveRecord::Base.connection.exec_query('select ST_IsValid(ST_GeomFromGeoJSON($1)) as valid;', 'ValidateGeoJSON', [json.to_json]).first['valid']
end
end
end

def self.to_json_polygon_for_cadastre(coordinates)
Expand Down
18 changes: 11 additions & 7 deletions app/validators/url_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def initialize(options)
options.reverse_merge!(no_local: false)
options.reverse_merge!(public_suffix: false)
options.reverse_merge!(accept_array: false)
options.reverse_merge!(accept_email: false)

super(options)
end
Expand Down Expand Up @@ -53,15 +54,18 @@ def filtered_options(value)

def validate_url(record, attribute, value, message, schemes)
uri = Addressable::URI.parse(value)
host = uri && uri.host
scheme = uri && uri.scheme

valid_scheme = host && scheme && schemes.include?(scheme)
valid_no_local = !options.fetch(:no_local) || (host && host.include?('.'))
valid_suffix = !options.fetch(:public_suffix) || (host && PublicSuffix.valid?(host, default_rule: nil))
unless options.fetch(:accept_email) && uri.path.match?(/^(.+)@(.+)$/)
host = uri && uri.host
scheme = uri && uri.scheme

unless valid_scheme && valid_no_local && valid_suffix
record.errors.add(attribute, message, **filtered_options(value))
valid_scheme = host && scheme && schemes.include?(scheme)
valid_no_local = !options.fetch(:no_local) || (host && host.include?('.'))
valid_suffix = !options.fetch(:public_suffix) || (host && PublicSuffix.valid?(host, default_rule: nil))

unless valid_scheme && valid_no_local && valid_suffix
record.errors.add(attribute, message, **filtered_options(value))
end
end
rescue Addressable::URI::InvalidURIError
record.errors.add(attribute, message, **filtered_options(value))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
%th{ colspan: 2 }= t(".existing_groupe", count: @groupes_instructeurs.total_count)
%tbody
- @groupes_instructeurs.each do |group|
%tr
%td= group.label
%td.actions= button_to 'Réaffecter les dossiers à ce groupe',
.flex.justify-between.align-center.fr-mb-2w
%p.fr-mb-0= group.label
= button_to 'Réaffecter les dossiers à ce groupe',
reaffecter_admin_procedure_groupe_instructeur_path(:target_group => group),
{ class: 'button',
{ class: 'fr-btn fr-btn--secondary fr-btn--sm',
data: { confirm: "Êtes-vous sûr de vouloir réaffecter les dossiers du groupe « #{@groupe_instructeur.label} » vers le groupe  « #{group.label} » ?" } }

= paginate @groupes_instructeurs, views_prefix: 'shared'
Loading

0 comments on commit 9e8418c

Please sign in to comment.