Merge pull request #6722 from betagouv/main

2021-12-07-01
This commit is contained in:
Paul Chavard 2021-12-07 10:55:15 +01:00 committed by GitHub
commit 685601be87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
49 changed files with 288 additions and 103 deletions

View file

@ -50,7 +50,9 @@
color: $black; color: $black;
} }
.text-sm {
font-size: 14px;
}
.mt-1 { .mt-1 {
margin-top: $default-spacer; margin-top: $default-spacer;

View file

@ -57,8 +57,8 @@ class StatsController < ApplicationController
"procedures.libelle", "procedures.libelle",
"users.id", "users.id",
"dossiers.state", "dossiers.state",
"dossiers.en_construction_at - dossiers.created_at", "dossiers.depose_at - dossiers.created_at",
"dossiers.en_instruction_at - dossiers.en_construction_at", "dossiers.en_instruction_at - dossiers.depose_at",
"dossiers.processed_at - dossiers.en_instruction_at" "dossiers.processed_at - dossiers.en_instruction_at"
) )
end end
@ -121,7 +121,7 @@ class StatsController < ApplicationController
end_date = monthly_report[:end_date].to_time.localtime end_date = monthly_report[:end_date].to_time.localtime
replies_count = monthly_report[:replies_sent] replies_count = monthly_report[:replies_sent]
dossiers_count = Dossier.where(en_construction_at: start_date..end_date).count dossiers_count = Dossier.where(depose_at: start_date..end_date).count
monthly_contact_percentage = replies_count.fdiv(dossiers_count || 1) * 100 monthly_contact_percentage = replies_count.fdiv(dossiers_count || 1) * 100
[I18n.l(start_date, format: '%b %y'), monthly_contact_percentage.round(1)] [I18n.l(start_date, format: '%b %y'), monthly_contact_percentage.round(1)]

View file

@ -43,6 +43,7 @@ class API::V2::Schema < GraphQL::Schema
Types::Champs::CarteChampType, Types::Champs::CarteChampType,
Types::Champs::CheckboxChampType, Types::Champs::CheckboxChampType,
Types::Champs::CiviliteChampType, Types::Champs::CiviliteChampType,
Types::Champs::CommuneChampType,
Types::Champs::DateChampType, Types::Champs::DateChampType,
Types::Champs::DatetimeChampType, Types::Champs::DatetimeChampType,
Types::Champs::DecimalNumberChampType, Types::Champs::DecimalNumberChampType,

View file

@ -233,6 +233,30 @@ type CiviliteChamp implements Champ {
value: Civilite value: Civilite
} }
type Commune {
"""
Le code INSEE
"""
code: String!
name: String!
}
type CommuneChamp implements Champ {
commune: Commune
departement: Departement
id: ID!
"""
Libellé du champ.
"""
label: String!
"""
La valeur du champ sous forme texte.
"""
stringValue: String
}
""" """
GeoJSON coordinates GeoJSON coordinates
""" """
@ -649,6 +673,11 @@ enum DemarcheState {
publiee publiee
} }
type Departement {
code: String!
name: String!
}
""" """
Represents direct upload credentials Represents direct upload credentials
""" """
@ -688,23 +717,28 @@ type Dossier {
avis(id: ID): [Avis!]! avis(id: ID): [Avis!]!
champs(id: ID): [Champ!]! champs(id: ID): [Champ!]!
"""
Date de dépôt.
"""
dateDepot: ISO8601DateTime!
""" """
Date de la dernière modification. Date de la dernière modification.
""" """
dateDerniereModification: ISO8601DateTime! dateDerniereModification: ISO8601DateTime!
""" """
Date de dépôt. Date du dernier passage en construction.
""" """
datePassageEnConstruction: ISO8601DateTime! datePassageEnConstruction: ISO8601DateTime!
""" """
Date de passage en instruction. Date du dernier passage en instruction.
""" """
datePassageEnInstruction: ISO8601DateTime datePassageEnInstruction: ISO8601DateTime
""" """
Date de traitement. Date du dernier traitement.
""" """
dateTraitement: ISO8601DateTime dateTraitement: ISO8601DateTime
demandeur: Demandeur! demandeur: Demandeur!

View file

@ -25,6 +25,12 @@ module Types
else else
Types::Champs::DateChampType Types::Champs::DateChampType
end end
when ::Champs::CommuneChamp
if context.has_fragment?(:CommuneChamp)
Types::Champs::CommuneChampType
else
Types::Champs::TextChampType
end
when ::Champs::DossierLinkChamp when ::Champs::DossierLinkChamp
Types::Champs::DossierLinkChampType Types::Champs::DossierLinkChampType
when ::Champs::PieceJustificativeChamp when ::Champs::PieceJustificativeChamp

View file

@ -0,0 +1,36 @@
module Types::Champs
class CommuneChampType < Types::BaseObject
implements Types::ChampType
class CommuneType < Types::BaseObject
field :name, String, null: false
field :code, String, "Le code INSEE", null: false
end
class DepartementType < Types::BaseObject
field :name, String, null: false
field :code, String, null: false
end
field :commune, CommuneType, null: true
field :departement, DepartementType, null: true
def commune
if object.code?
{
name: object.to_s,
code: object.code
}
end
end
def departement
if object.departement?
{
name: object.name_departement,
code: object.code_departement
}
end
end
end
end

View file

@ -14,9 +14,10 @@ module Types
field :demarche, Types::DemarcheDescriptorType, null: false, method: :procedure field :demarche, Types::DemarcheDescriptorType, null: false, method: :procedure
field :date_passage_en_construction, GraphQL::Types::ISO8601DateTime, "Date de dépôt.", null: false, method: :en_construction_at field :date_depot, GraphQL::Types::ISO8601DateTime, "Date de dépôt.", null: false, method: :depose_at
field :date_passage_en_instruction, GraphQL::Types::ISO8601DateTime, "Date de passage en instruction.", null: true, method: :en_instruction_at field :date_passage_en_construction, GraphQL::Types::ISO8601DateTime, "Date du dernier passage en construction.", null: false, method: :en_construction_at
field :date_traitement, GraphQL::Types::ISO8601DateTime, "Date de traitement.", null: true, method: :processed_at field :date_passage_en_instruction, GraphQL::Types::ISO8601DateTime, "Date du dernier passage en instruction.", null: true, method: :en_instruction_at
field :date_traitement, GraphQL::Types::ISO8601DateTime, "Date du dernier traitement.", null: true, method: :processed_at
field :date_derniere_modification, GraphQL::Types::ISO8601DateTime, "Date de la dernière modification.", null: false, method: :updated_at field :date_derniere_modification, GraphQL::Types::ISO8601DateTime, "Date de la dernière modification.", null: false, method: :updated_at
field :archived, Boolean, null: false field :archived, Boolean, null: false

View file

@ -93,10 +93,10 @@ function ComboCommunesSearch(params) {
placeholder={placeholderDepartement} placeholder={placeholderDepartement}
addForeignDepartement={false} addForeignDepartement={false}
required={params.mandatory} required={params.mandatory}
onChange={(value, result) => { onChange={(_, result) => {
setDepartementCode(result?.code); setDepartementCode(result?.code);
if (hiddenDepartementField && hiddenCodeDepartementField) { if (hiddenDepartementField && hiddenCodeDepartementField) {
hiddenDepartementField.setAttribute('value', value); hiddenDepartementField.setAttribute('value', result?.nom);
hiddenCodeDepartementField.setAttribute('value', result?.code); hiddenCodeDepartementField.setAttribute('value', result?.code);
} }
}} }}

View file

@ -25,4 +25,25 @@ class Champs::CommuneChamp < Champs::TextChamp
def for_export def for_export
[value, external_id] [value, external_id]
end end
def name_departement
# FIXME we originaly saved already formatted departement with the code in the name
departement&.gsub(/^(.[0-9])\s-\s/, '')
end
def departement_code_and_name
"#{code_departement} - #{name_departement}"
end
def departement?
departement.present?
end
def code?
code.present?
end
def code
external_id
end
end end

View file

@ -67,14 +67,14 @@ module ProcedureStatsConcern
def traitement_times(date_range) def traitement_times(date_range)
Traitement.for_traitement_time_stats(self) Traitement.for_traitement_time_stats(self)
.where(processed_at: date_range) .where(processed_at: date_range)
.pluck('dossiers.en_construction_at', :processed_at) .pluck('dossiers.depose_at', :processed_at)
.map { |en_construction_at, processed_at| { en_construction_at: en_construction_at, processed_at: processed_at } } .map { |depose_at, processed_at| { depose_at: depose_at, processed_at: processed_at } }
end end
def usual_traitement_time_by_month_in_days def usual_traitement_time_by_month_in_days
traitement_times(first_processed_at..last_considered_processed_at) traitement_times(first_processed_at..last_considered_processed_at)
.group_by { |t| t[:processed_at].beginning_of_month } .group_by { |t| t[:processed_at].beginning_of_month }
.transform_values { |month| month.map { |h| h[:processed_at] - h[:en_construction_at] } } .transform_values { |month| month.map { |h| h[:processed_at] - h[:depose_at] } }
.transform_values { |traitement_times_for_month| traitement_times_for_month.percentile(USUAL_TRAITEMENT_TIME_PERCENTILE).ceil } .transform_values { |traitement_times_for_month| traitement_times_for_month.percentile(USUAL_TRAITEMENT_TIME_PERCENTILE).ceil }
.transform_values { |seconds| seconds == 0 ? nil : seconds } .transform_values { |seconds| seconds == 0 ? nil : seconds }
.transform_values { |seconds| convert_seconds_in_days(seconds) } .transform_values { |seconds| convert_seconds_in_days(seconds) }
@ -85,7 +85,7 @@ module ProcedureStatsConcern
now = Time.zone.now now = Time.zone.now
traitement_time = traitement_time =
traitement_times((now - nb_days.days)..now) traitement_times((now - nb_days.days)..now)
.map { |times| times[:processed_at] - times[:en_construction_at] } .map { |times| times[:processed_at] - times[:depose_at] }
.percentile(USUAL_TRAITEMENT_TIME_PERCENTILE) .percentile(USUAL_TRAITEMENT_TIME_PERCENTILE)
.ceil .ceil

View file

@ -13,8 +13,8 @@ module TagsSubstitutionConcern
}, },
{ {
libelle: 'date de dépôt', libelle: 'date de dépôt',
description: 'Date du passage en construction du dossier par lusager', description: 'Date de dépôt du dossier par lusager',
lambda: -> (d) { format_date(d.en_construction_at) }, lambda: -> (d) { format_date(d.depose_at) },
available_for_states: Dossier::SOUMIS available_for_states: Dossier::SOUMIS
}, },
{ {

View file

@ -208,9 +208,9 @@ class Dossier < ApplicationRecord
scope :not_hidden_by_user, -> { where(hidden_by_user_at: nil) } scope :not_hidden_by_user, -> { where(hidden_by_user_at: nil) }
scope :order_by_updated_at, -> (order = :desc) { order(updated_at: order) } scope :order_by_updated_at, -> (order = :desc) { order(updated_at: order) }
scope :order_by_created_at, -> (order = :asc) { order(en_construction_at: order, created_at: order, id: order) } scope :order_by_created_at, -> (order = :asc) { order(depose_at: order, created_at: order, id: order) }
scope :updated_since, -> (since) { where('dossiers.updated_at >= ?', since) } scope :updated_since, -> (since) { where('dossiers.updated_at >= ?', since) }
scope :created_since, -> (since) { where('dossiers.en_construction_at >= ?', since) } scope :created_since, -> (since) { where('dossiers.depose_at >= ?', since) }
scope :with_type_de_champ, -> (stable_id) { scope :with_type_de_champ, -> (stable_id) {
joins('INNER JOIN champs ON champs.dossier_id = dossiers.id INNER JOIN types_de_champ ON types_de_champ.id = champs.type_de_champ_id') joins('INNER JOIN champs ON champs.dossier_id = dossiers.id INNER JOIN types_de_champ ON types_de_champ.id = champs.type_de_champ_id')
@ -249,7 +249,7 @@ class Dossier < ApplicationRecord
], ],
avis: [:claimant, :expert], avis: [:claimant, :expert],
etablissement: :champ etablissement: :champ
).order(en_construction_at: 'asc') ).order(depose_at: 'asc')
} }
scope :en_cours, -> { not_archived.state_en_construction_ou_instruction } scope :en_cours, -> { not_archived.state_en_construction_ou_instruction }
scope :without_followers, -> { left_outer_joins(:follows).where(follows: { id: nil }) } scope :without_followers, -> { left_outer_joins(:follows).where(follows: { id: nil }) }
@ -459,11 +459,6 @@ class Dossier < ApplicationRecord
traitement&.motivation || read_attribute(:motivation) traitement&.motivation || read_attribute(:motivation)
end end
def processed_at
return nil if !termine?
traitement&.processed_at || read_attribute(:processed_at)
end
def update_search_terms def update_search_terms
self.search_terms = [ self.search_terms = [
user&.email, user&.email,
@ -636,7 +631,7 @@ class Dossier < ApplicationRecord
else else
parts = [ parts = [
"Dossier déposé le ", "Dossier déposé le ",
en_construction_at.strftime("%d/%m/%Y"), depose_at.strftime("%d/%m/%Y"),
" sur la démarche ", " sur la démarche ",
procedure.libelle, procedure.libelle,
" gérée par l'organisme ", " gérée par l'organisme ",
@ -1040,7 +1035,7 @@ class Dossier < ApplicationRecord
['Archivé', :archived], ['Archivé', :archived],
['État du dossier', Dossier.human_attribute_name("state.#{state}")], ['État du dossier', Dossier.human_attribute_name("state.#{state}")],
['Dernière mise à jour le', :updated_at], ['Dernière mise à jour le', :updated_at],
['Déposé le', :en_construction_at], ['Déposé le', :depose_at],
['Passé en instruction le', :en_instruction_at], ['Passé en instruction le', :en_instruction_at],
['Traité le', :processed_at], ['Traité le', :processed_at],
['Motivation de la décision', :motivation], ['Motivation de la décision', :motivation],

View file

@ -111,9 +111,9 @@ class DossierOperationLog < ApplicationRecord
nil nil
elsif operation == operations.fetch(:supprimer) elsif operation == operations.fetch(:supprimer)
{ {
date_de_depot: subject.en_construction_at, date_de_depot: subject.depose_at,
date_de_mise_en_instruction: subject.en_instruction_at, date_de_mise_en_instruction: subject.en_instruction_at,
date_de_decision: subject.termine? ? subject.traitements.last.processed_at : nil date_de_decision: subject.processed_at
}.as_json }.as_json
else else
case subject case subject

View file

@ -99,7 +99,7 @@ class Export < ApplicationRecord
def io(since: nil) def io(since: nil)
dossiers = Dossier.where(groupe_instructeur: groupe_instructeurs) dossiers = Dossier.where(groupe_instructeur: groupe_instructeurs)
if since.present? if since.present?
dossiers = dossiers.where('dossiers.en_construction_at > ?', since) dossiers = dossiers.where('dossiers.depose_at > ?', since)
end end
service = ProcedureExportService.new(procedure, dossiers) service = ProcedureExportService.new(procedure, dossiers)

View file

@ -105,7 +105,7 @@ class Procedure < ApplicationRecord
if brouillon? if brouillon?
TypeDeChamp.fillable TypeDeChamp.fillable
.joins(:revision_types_de_champ) .joins(:revision_types_de_champ)
.where(revision_types_de_champ: { revision: draft_revision }) .where(revision_types_de_champ: { revision: draft_revision, parent_id: nil })
.order(:private, :position) .order(:private, :position)
else else
# fetch all type_de_champ.stable_id for all the revisions expect draft # fetch all type_de_champ.stable_id for all the revisions expect draft
@ -114,12 +114,14 @@ class Procedure < ApplicationRecord
.joins(:revisions) .joins(:revisions)
.where(procedure_revisions: { procedure_id: id }) .where(procedure_revisions: { procedure_id: id })
.where.not(procedure_revisions: { id: draft_revision_id }) .where.not(procedure_revisions: { id: draft_revision_id })
.where(revision_types_de_champ: { parent_id: nil })
.group(:stable_id) .group(:stable_id)
.select('MAX(types_de_champ.id)') .select('MAX(types_de_champ.id)')
# fetch the more recent procedure_revision_types_de_champ # fetch the more recent procedure_revision_types_de_champ
# which includes recents_ids # which includes recents_ids
recents_prtdc = ProcedureRevisionTypeDeChamp recents_prtdc = ProcedureRevisionTypeDeChamp
.root
.where(type_de_champ_id: recent_ids) .where(type_de_champ_id: recent_ids)
.where.not(revision_id: draft_revision_id) .where.not(revision_id: draft_revision_id)
.group(:type_de_champ_id) .group(:type_de_champ_id)
@ -139,7 +141,10 @@ class Procedure < ApplicationRecord
TypeDeChamp.root TypeDeChamp.root
.public_only .public_only
.fillable .fillable
.where(revision: revisions - [draft_revision]) .joins(:revisions)
.where(procedure_revisions: { procedure_id: id })
.where.not(procedure_revisions: { id: draft_revision_id })
.where(revision_types_de_champ: { parent_id: nil })
.order(:created_at) .order(:created_at)
.uniq .uniq
end end
@ -152,7 +157,10 @@ class Procedure < ApplicationRecord
TypeDeChamp.root TypeDeChamp.root
.private_only .private_only
.fillable .fillable
.where(revision: revisions - [draft_revision]) .joins(:revisions)
.where(procedure_revisions: { procedure_id: id })
.where.not(procedure_revisions: { id: draft_revision_id })
.where(revision_types_de_champ: { parent_id: nil })
.order(:created_at) .order(:created_at)
.uniq .uniq
end end
@ -471,7 +479,9 @@ class Procedure < ApplicationRecord
procedure.save procedure.save
procedure.draft_types_de_champ.update_all(revision_id: procedure.draft_revision.id) procedure.draft_types_de_champ.update_all(revision_id: procedure.draft_revision.id)
procedure.draft_types_de_champ_private.update_all(revision_id: procedure.draft_revision.id) procedure.draft_types_de_champ_private.update_all(revision_id: procedure.draft_revision.id)
TypeDeChamp.where(parent: procedure.draft_types_de_champ.repetition + procedure.draft_types_de_champ_private.repetition).update_all(revision_id: procedure.draft_revision.id) types_de_champ_in_repetition = TypeDeChamp.where(parent: procedure.draft_types_de_champ.repetition + procedure.draft_types_de_champ_private.repetition)
types_de_champ_in_repetition.update_all(revision_id: procedure.draft_revision.id)
types_de_champ_in_repetition.each(&:migrate_parent!)
if is_different_admin || from_library if is_different_admin || from_library
procedure.draft_types_de_champ.each { |tdc| tdc.options&.delete(:old_pj) } procedure.draft_types_de_champ.each { |tdc| tdc.options&.delete(:old_pj) }

View file

@ -20,7 +20,7 @@ class ProcedureOverview
@dossiers_en_construction_count = dossiers.state_en_construction.count @dossiers_en_construction_count = dossiers.state_en_construction.count
@old_dossiers_en_construction = dossiers @old_dossiers_en_construction = dossiers
.state_en_construction .state_en_construction
.where('en_construction_at < ?', 1.week.ago) .where('depose_at < ?', 1.week.ago)
@created_dossiers_count = dossiers @created_dossiers_count = dossiers
.where(created_at: start_date..Time.zone.now) .where(created_at: start_date..Time.zone.now)

View file

@ -38,6 +38,7 @@ class ProcedurePresentation < ApplicationRecord
fields = [ fields = [
field_hash('Créé le', 'self', 'created_at'), field_hash('Créé le', 'self', 'created_at'),
field_hash('En construction le', 'self', 'en_construction_at'), field_hash('En construction le', 'self', 'en_construction_at'),
field_hash('Déposé le', 'self', 'depose_at'),
field_hash('Mis à jour le', 'self', 'updated_at'), field_hash('Mis à jour le', 'self', 'updated_at'),
field_hash('Demandeur', 'user', 'email'), field_hash('Demandeur', 'user', 'email'),
field_hash('Email instructeur', 'followers_instructeurs', 'email'), field_hash('Email instructeur', 'followers_instructeurs', 'email'),

View file

@ -14,8 +14,8 @@ class ProcedureRevision < ApplicationRecord
has_many :dossiers, inverse_of: :revision, foreign_key: :revision_id has_many :dossiers, inverse_of: :revision, foreign_key: :revision_id
has_many :revision_types_de_champ, -> { public_only.ordered }, class_name: 'ProcedureRevisionTypeDeChamp', foreign_key: :revision_id, dependent: :destroy, inverse_of: :revision has_many :revision_types_de_champ, -> { root.public_only.ordered }, class_name: 'ProcedureRevisionTypeDeChamp', foreign_key: :revision_id, dependent: :destroy, inverse_of: :revision
has_many :revision_types_de_champ_private, -> { private_only.ordered }, class_name: 'ProcedureRevisionTypeDeChamp', foreign_key: :revision_id, dependent: :destroy, inverse_of: :revision has_many :revision_types_de_champ_private, -> { root.private_only.ordered }, class_name: 'ProcedureRevisionTypeDeChamp', foreign_key: :revision_id, dependent: :destroy, inverse_of: :revision
has_many :types_de_champ, through: :revision_types_de_champ, source: :type_de_champ has_many :types_de_champ, through: :revision_types_de_champ, source: :type_de_champ
has_many :types_de_champ_private, through: :revision_types_de_champ_private, source: :type_de_champ has_many :types_de_champ_private, through: :revision_types_de_champ_private, source: :type_de_champ
@ -23,6 +23,8 @@ class ProcedureRevision < ApplicationRecord
has_one :draft_procedure, -> { with_discarded }, class_name: 'Procedure', foreign_key: :draft_revision_id, dependent: :nullify, inverse_of: :draft_revision has_one :draft_procedure, -> { with_discarded }, class_name: 'Procedure', foreign_key: :draft_revision_id, dependent: :nullify, inverse_of: :draft_revision
has_one :published_procedure, -> { with_discarded }, class_name: 'Procedure', foreign_key: :published_revision_id, dependent: :nullify, inverse_of: :published_revision has_one :published_procedure, -> { with_discarded }, class_name: 'Procedure', foreign_key: :published_revision_id, dependent: :nullify, inverse_of: :published_revision
scope :ordered, -> { order(:created_at) }
def build_champs def build_champs
types_de_champ.map(&:build_champ) types_de_champ.map(&:build_champ)
end end
@ -39,7 +41,7 @@ class ProcedureRevision < ApplicationRecord
.types_de_champ .types_de_champ
.tap do |types_de_champ| .tap do |types_de_champ|
params[:order_place] = types_de_champ.present? ? types_de_champ.last.order_place + 1 : 0 params[:order_place] = types_de_champ.present? ? types_de_champ.last.order_place + 1 : 0
end.create(params) end.create(params).migrate_parent!
elsif params[:private] elsif params[:private]
types_de_champ_private.create(params) types_de_champ_private.create(params)
else else
@ -66,7 +68,9 @@ class ProcedureRevision < ApplicationRecord
repetition_type_de_champ = find_or_clone_type_de_champ(id).parent repetition_type_de_champ = find_or_clone_type_de_champ(id).parent
move_type_de_champ_hash(repetition_type_de_champ.types_de_champ.to_a, type_de_champ, position).each do |(id, position)| move_type_de_champ_hash(repetition_type_de_champ.types_de_champ.to_a, type_de_champ, position).each do |(id, position)|
repetition_type_de_champ.types_de_champ.find(id).update!(order_place: position) type_de_champ = repetition_type_de_champ.types_de_champ.find(id)
type_de_champ.update!(order_place: position)
type_de_champ.revision_type_de_champ&.update!(position: position)
end end
elsif type_de_champ.private? elsif type_de_champ.private?
move_type_de_champ_hash(types_de_champ_private.to_a, type_de_champ, position).each do |(id, position)| move_type_de_champ_hash(types_de_champ_private.to_a, type_de_champ, position).each do |(id, position)|
@ -294,6 +298,7 @@ class ProcedureRevision < ApplicationRecord
end end
cloned_type_de_champ.revision = self cloned_type_de_champ.revision = self
association.update!(type_de_champ: cloned_type_de_champ) association.update!(type_de_champ: cloned_type_de_champ)
cloned_type_de_champ.types_de_champ.each(&:migrate_parent!)
cloned_type_de_champ cloned_type_de_champ
end end

View file

@ -6,6 +6,7 @@
# position :integer not null # position :integer not null
# created_at :datetime not null # created_at :datetime not null
# updated_at :datetime not null # updated_at :datetime not null
# parent_id :bigint
# revision_id :bigint not null # revision_id :bigint not null
# type_de_champ_id :bigint not null # type_de_champ_id :bigint not null
# #
@ -13,7 +14,11 @@ class ProcedureRevisionTypeDeChamp < ApplicationRecord
belongs_to :revision, class_name: 'ProcedureRevision' belongs_to :revision, class_name: 'ProcedureRevision'
belongs_to :type_de_champ belongs_to :type_de_champ
belongs_to :parent, class_name: 'ProcedureRevisionTypeDeChamp', optional: true
has_many :revision_types_de_champ, -> { ordered }, foreign_key: :parent_id, class_name: 'ProcedureRevisionTypeDeChamp', inverse_of: :parent, dependent: :destroy
scope :root, -> { where(parent: nil) }
scope :ordered, -> { order(:position) } scope :ordered, -> { order(:position) }
scope :revision_ordered, -> { order(:revision_id) }
scope :public_only, -> { joins(:type_de_champ).where(types_de_champ: { private: false }) } scope :public_only, -> { joins(:type_de_champ).where(types_de_champ: { private: false }) }
scope :private_only, -> { joins(:type_de_champ).where(types_de_champ: { private: true }) } scope :private_only, -> { joins(:type_de_champ).where(types_de_champ: { private: true }) }

View file

@ -31,11 +31,11 @@ class Stat < ApplicationRecord
dossiers_not_brouillon: states['not_brouillon'], dossiers_not_brouillon: states['not_brouillon'],
dossiers_termines: states['termines'], dossiers_termines: states['termines'],
dossiers_cumulative: cumulative_hash([ dossiers_cumulative: cumulative_hash([
[Dossier.state_not_brouillon, :en_construction_at], [Dossier.state_not_brouillon, :depose_at],
[DeletedDossier.where.not(state: :brouillon), :deleted_at] [DeletedDossier.where.not(state: :brouillon), :deleted_at]
]), ]),
dossiers_in_the_last_4_months: last_four_months_hash([ dossiers_in_the_last_4_months: last_four_months_hash([
[Dossier.state_not_brouillon, :en_construction_at], [Dossier.state_not_brouillon, :depose_at],
[DeletedDossier.where.not(state: :brouillon), :deleted_at] [DeletedDossier.where.not(state: :brouillon), :deleted_at]
]), ]),
administrations_partenaires: AdministrateursProcedure.joins(:procedure).merge(Procedure.publiees_ou_closes).select('distinct administrateur_id').count administrations_partenaires: AdministrateursProcedure.joins(:procedure).merge(Procedure.publiees_ou_closes).select('distinct administrateur_id').count
@ -48,8 +48,8 @@ class Stat < ApplicationRecord
sanitize_and_exec(Dossier, <<-EOF sanitize_and_exec(Dossier, <<-EOF
SELECT SELECT
COUNT(*) FILTER ( WHERE state != 'brouillon' ) AS "not_brouillon", COUNT(*) FILTER ( WHERE state != 'brouillon' ) AS "not_brouillon",
COUNT(*) FILTER ( WHERE state != 'brouillon' and en_construction_at BETWEEN :one_month_ago AND :now ) AS "dossiers_depose_avant_30_jours", COUNT(*) FILTER ( WHERE state != 'brouillon' and depose_at BETWEEN :one_month_ago AND :now ) AS "dossiers_depose_avant_30_jours",
COUNT(*) FILTER ( WHERE state != 'brouillon' and en_construction_at BETWEEN :two_months_ago AND :one_month_ago ) AS "dossiers_deposes_entre_60_et_30_jours", COUNT(*) FILTER ( WHERE state != 'brouillon' and depose_at BETWEEN :two_months_ago AND :one_month_ago ) AS "dossiers_deposes_entre_60_et_30_jours",
COUNT(*) FILTER ( WHERE state = 'brouillon' ) AS "brouillon", COUNT(*) FILTER ( WHERE state = 'brouillon' ) AS "brouillon",
COUNT(*) FILTER ( WHERE state = 'en_construction' ) AS "en_construction", COUNT(*) FILTER ( WHERE state = 'en_construction' ) AS "en_construction",
COUNT(*) FILTER ( WHERE state = 'en_instruction' ) AS "en_instruction", COUNT(*) FILTER ( WHERE state = 'en_instruction' ) AS "en_instruction",

View file

@ -22,7 +22,7 @@ class Traitement < ApplicationRecord
includes(:dossier) includes(:dossier)
.termine .termine
.where(dossier: procedure.dossiers) .where(dossier: procedure.dossiers)
.where.not('dossiers.en_construction_at' => nil, :processed_at => nil) .where.not('dossiers.depose_at' => nil, processed_at: nil)
.order(:processed_at) .order(:processed_at)
end end

View file

@ -6,6 +6,7 @@
# description :text # description :text
# libelle :string # libelle :string
# mandatory :boolean default(FALSE) # mandatory :boolean default(FALSE)
# migrated_parent :boolean
# options :jsonb # options :jsonb
# order_place :integer # order_place :integer
# private :boolean default(FALSE), not null # private :boolean default(FALSE), not null
@ -59,8 +60,9 @@ class TypeDeChamp < ApplicationRecord
has_many :types_de_champ, -> { ordered }, foreign_key: :parent_id, class_name: 'TypeDeChamp', inverse_of: :parent, dependent: :destroy has_many :types_de_champ, -> { ordered }, foreign_key: :parent_id, class_name: 'TypeDeChamp', inverse_of: :parent, dependent: :destroy
store_accessor :options, :cadastres, :old_pj, :drop_down_options, :skip_pj_validation, :skip_content_type_pj_validation, :drop_down_secondary_libelle, :drop_down_secondary_description, :drop_down_other store_accessor :options, :cadastres, :old_pj, :drop_down_options, :skip_pj_validation, :skip_content_type_pj_validation, :drop_down_secondary_libelle, :drop_down_secondary_description, :drop_down_other
has_many :revision_types_de_champ, class_name: 'ProcedureRevisionTypeDeChamp', dependent: :destroy, inverse_of: :type_de_champ has_many :revision_types_de_champ, -> { revision_ordered }, class_name: 'ProcedureRevisionTypeDeChamp', dependent: :destroy, inverse_of: :type_de_champ
has_many :revisions, through: :revision_types_de_champ has_one :revision_type_de_champ, -> { revision_ordered }, class_name: 'ProcedureRevisionTypeDeChamp', inverse_of: false
has_many :revisions, -> { ordered }, through: :revision_types_de_champ
delegate :tags_for_template, :libelle_for_export, to: :dynamic_type delegate :tags_for_template, :libelle_for_export, to: :dynamic_type
@ -373,6 +375,17 @@ class TypeDeChamp < ApplicationRecord
end end
end end
def migrate_parent!
if parent_id.present? && migrated_parent.nil?
ProcedureRevisionTypeDeChamp.create(parent: parent.revision_type_de_champ,
type_de_champ: self,
revision_id: parent.revision_type_de_champ.revision_id,
position: order_place)
update_column(:migrated_parent, true)
end
self
end
private private
def parse_drop_down_list_value(value) def parse_drop_down_list_value(value)

View file

@ -87,7 +87,7 @@ class DossierSerializer < ActiveModel::Serializer
end end
def initiated_at def initiated_at
object.en_construction_at&.in_time_zone('UTC') object.depose_at&.in_time_zone('UTC')
end end
def received_at def received_at

View file

@ -11,7 +11,7 @@ class DossiersSerializer < ActiveModel::Serializer
end end
def initiated_at def initiated_at
object.en_construction_at&.in_time_zone('UTC') object.depose_at&.in_time_zone('UTC')
end end
def state def state

View file

@ -30,7 +30,7 @@
- dossier = not_drafts.first - dossier = not_drafts.first
%h2.huge-title= t('views.commencer.show.already_not_draft') %h2.huge-title= t('views.commencer.show.already_not_draft')
%p %p
= t('views.commencer.show.already_not_draft_detail_html', time_ago: time_ago_in_words(dossier.en_construction_at), procedure: dossier.procedure.libelle) = t('views.commencer.show.already_not_draft_detail_html', time_ago: time_ago_in_words(dossier.depose_at), procedure: dossier.procedure.libelle)
= link_to t('views.commencer.show.show_my_submitted_file'), dossier_path(dossier), class: ['button large expand primary'] = link_to t('views.commencer.show.show_my_submitted_file'), dossier_path(dossier), class: ['button large expand primary']
= link_to t('views.commencer.show.start_new_file'), url_for_new_dossier(@revision), class: ['button large expand'] = link_to t('views.commencer.show.start_new_file'), url_for_new_dossier(@revision), class: ['button large expand']

View file

@ -193,8 +193,8 @@ def add_etat_dossier(pdf, dossier)
end end
def add_etats_dossier(pdf, dossier) def add_etats_dossier(pdf, dossier)
if dossier.en_construction_at.present? if dossier.depose_at.present?
format_in_2_columns(pdf, "Déposé le", try_format_date(dossier.en_construction_at)) format_in_2_columns(pdf, "Déposé le", try_format_date(dossier.depose_at))
end end
if dossier.en_instruction_at.present? if dossier.en_instruction_at.present?
format_in_2_columns(pdf, "En instruction le", try_format_date(dossier.en_instruction_at)) format_in_2_columns(pdf, "En instruction le", try_format_date(dossier.en_instruction_at))

View file

@ -1,4 +1,9 @@
= format_text_value(champ.to_s) = format_text_value(champ.to_s)
- if champ.external_id.present? - if champ.code?
%p.text-sm
Code INSEE : Code INSEE :
= champ.external_id = champ.code
- if champ.departement?
%br
Departement :
= champ.departement_code_and_name

View file

@ -1,5 +1,5 @@
.container .container
- if dossier.en_construction_at.present? - if dossier.depose_at.present?
.card .card
= render partial: "shared/dossiers/infos_generales", locals: { dossier: dossier } = render partial: "shared/dossiers/infos_generales", locals: { dossier: dossier }

View file

@ -2,7 +2,7 @@
%tbody %tbody
%tr %tr
%th.libelle Déposé le : %th.libelle Déposé le :
%td= l(dossier.en_construction_at, format: '%d %B %Y') %td= l(dossier.depose_at, format: '%d %B %Y')
- if dossier.justificatif_motivation.attached? - if dossier.justificatif_motivation.attached?
%tr %tr
%th.libelle Justificatif : %th.libelle Justificatif :

View file

@ -19,7 +19,7 @@
= dossier.id = dossier.id
%td= dossier.procedure.libelle %td= dossier.procedure.libelle
%td= status_badge(dossier.state) %td= status_badge(dossier.state)
%td{ style: 'padding: 18px;' }= (dossier.en_construction_at || dossier.created_at).strftime('%d/%m/%Y') %td{ style: 'padding: 18px;' }= (dossier.depose_at || dossier.created_at).strftime('%d/%m/%Y')
.transfer-actions.mt-4 .transfer-actions.mt-4
= link_to "Accepter", transfer_path(transfer), class: "button primary", method: :put = link_to "Accepter", transfer_path(transfer), class: "button primary", method: :put

View file

@ -7,8 +7,8 @@
%h1= dossier.procedure.libelle %h1= dossier.procedure.libelle
%h2 %h2
= t('views.users.dossiers.show.header.dossier_number', dossier_id: dossier.id) = t('views.users.dossiers.show.header.dossier_number', dossier_id: dossier.id)
- if dossier.en_construction_at.present? - if dossier.depose_at.present?
= t('views.users.dossiers.show.header.submit_date', date_du_dossier: I18n.l(dossier.en_construction_at)) = t('views.users.dossiers.show.header.submit_date', date_du_dossier: I18n.l(dossier.depose_at))
= render(partial: 'users/dossiers/expiration_banner', locals: {dossier: dossier}) = render(partial: 'users/dossiers/expiration_banner', locals: {dossier: dossier})

View file

@ -0,0 +1,5 @@
class AddParentIdToProcedureRevisionTypeDeChamp < ActiveRecord::Migration[6.1]
def change
add_belongs_to :procedure_revision_types_de_champ, :parent, index: true, foreign_key: { to_table: :procedure_revision_types_de_champ }
end
end

View file

@ -0,0 +1,5 @@
class AddMigratedParentToTypesDeChamp < ActiveRecord::Migration[6.1]
def change
add_column :types_de_champ, :migrated_parent, :boolean
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: 2021_12_01_135804) do ActiveRecord::Schema.define(version: 2021_12_02_135804) 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"
@ -581,6 +581,8 @@ ActiveRecord::Schema.define(version: 2021_12_01_135804) do
t.integer "position", null: false t.integer "position", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.bigint "parent_id"
t.index ["parent_id"], name: "index_procedure_revision_types_de_champ_on_parent_id"
t.index ["revision_id"], name: "index_procedure_revision_types_de_champ_on_revision_id" t.index ["revision_id"], name: "index_procedure_revision_types_de_champ_on_revision_id"
t.index ["type_de_champ_id"], name: "index_procedure_revision_types_de_champ_on_type_de_champ_id" t.index ["type_de_champ_id"], name: "index_procedure_revision_types_de_champ_on_type_de_champ_id"
end end
@ -766,6 +768,7 @@ ActiveRecord::Schema.define(version: 2021_12_01_135804) do
t.bigint "stable_id" t.bigint "stable_id"
t.bigint "parent_id" t.bigint "parent_id"
t.bigint "revision_id" t.bigint "revision_id"
t.boolean "migrated_parent"
t.index ["parent_id"], name: "index_types_de_champ_on_parent_id" t.index ["parent_id"], name: "index_types_de_champ_on_parent_id"
t.index ["private"], name: "index_types_de_champ_on_private" t.index ["private"], name: "index_types_de_champ_on_private"
t.index ["revision_id"], name: "index_types_de_champ_on_revision_id" t.index ["revision_id"], name: "index_types_de_champ_on_revision_id"
@ -865,6 +868,7 @@ ActiveRecord::Schema.define(version: 2021_12_01_135804) do
add_foreign_key "initiated_mails", "procedures" add_foreign_key "initiated_mails", "procedures"
add_foreign_key "merge_logs", "users" add_foreign_key "merge_logs", "users"
add_foreign_key "procedure_presentations", "assign_tos" add_foreign_key "procedure_presentations", "assign_tos"
add_foreign_key "procedure_revision_types_de_champ", "procedure_revision_types_de_champ", column: "parent_id"
add_foreign_key "procedure_revision_types_de_champ", "procedure_revisions", column: "revision_id" add_foreign_key "procedure_revision_types_de_champ", "procedure_revisions", column: "revision_id"
add_foreign_key "procedure_revision_types_de_champ", "types_de_champ" add_foreign_key "procedure_revision_types_de_champ", "types_de_champ"
add_foreign_key "procedure_revisions", "procedures" add_foreign_key "procedure_revisions", "procedures"

View file

@ -0,0 +1,23 @@
namespace :after_party do
desc 'Deployment task: migrate_type_de_champ_parent'
task migrate_type_de_champ_parent: :environment do
puts "Running deploy task 'migrate_type_de_champ_parent'"
types_de_champ = TypeDeChamp
.where.not(parent_id: nil)
.where(migrated_parent: nil)
.includes(:revisions, parent: :revision_type_de_champ)
progress = ProgressReport.new(types_de_champ.count)
types_de_champ.find_each do |type_de_champ|
type_de_champ.migrate_parent!
progress.inc
end
progress.finish
# 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: AfterParty::TaskRecorder.new(__FILE__).timestamp
end
end

View file

@ -319,6 +319,7 @@ describe API::V2::GraphqlController do
datePassageEnConstruction datePassageEnConstruction
datePassageEnInstruction datePassageEnInstruction
dateTraitement dateTraitement
dateDepot
motivation motivation
motivationAttachment { motivationAttachment {
url url
@ -396,6 +397,7 @@ describe API::V2::GraphqlController do
state: 'en_construction', state: 'en_construction',
dateDerniereModification: dossier.updated_at.iso8601, dateDerniereModification: dossier.updated_at.iso8601,
datePassageEnConstruction: dossier.en_construction_at.iso8601, datePassageEnConstruction: dossier.en_construction_at.iso8601,
dateDepot: dossier.depose_at.iso8601,
datePassageEnInstruction: nil, datePassageEnInstruction: nil,
dateTraitement: nil, dateTraitement: nil,
motivation: nil, motivation: nil,

View file

@ -108,6 +108,7 @@ FactoryBot.define do
dossier.state = Dossier.states.fetch(:en_construction) dossier.state = Dossier.states.fetch(:en_construction)
dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur
dossier.en_construction_at ||= dossier.created_at + 1.minute dossier.en_construction_at ||= dossier.created_at + 1.minute
dossier.depose_at ||= dossier.en_construction_at
dossier.save! dossier.save!
end end
end end
@ -117,6 +118,7 @@ FactoryBot.define do
dossier.state = Dossier.states.fetch(:en_instruction) dossier.state = Dossier.states.fetch(:en_instruction)
dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur
dossier.en_construction_at ||= dossier.created_at + 1.minute dossier.en_construction_at ||= dossier.created_at + 1.minute
dossier.depose_at ||= dossier.en_construction_at
dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute
dossier.save! dossier.save!
end end
@ -125,23 +127,22 @@ FactoryBot.define do
trait :accepte do trait :accepte do
transient do transient do
motivation { nil } motivation { nil }
processed_at { nil }
end end
after(:create) do |dossier, evaluator| after(:create) do |dossier, evaluator|
dossier.state = Dossier.states.fetch(:accepte) dossier.state = Dossier.states.fetch(:accepte)
dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur
processed_at = evaluator.processed_at if dossier.processed_at.present?
if processed_at.present? dossier.en_construction_at ||= dossier.processed_at - 2.minutes
dossier.en_construction_at ||= processed_at - 2.minutes dossier.depose_at ||= dossier.en_construction_at
dossier.en_instruction_at ||= processed_at - 1.minute dossier.en_instruction_at ||= dossier.processed_at - 1.minute
dossier.processed_at = processed_at dossier.traitements.accepter(motivation: evaluator.motivation, processed_at: dossier.processed_at)
dossier.traitements.accepter(motivation: evaluator.motivation, processed_at: processed_at)
else else
dossier.en_construction_at ||= dossier.created_at + 1.minute dossier.en_construction_at ||= dossier.created_at + 1.minute
dossier.depose_at ||= dossier.en_construction_at
dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute
dossier.processed_at = dossier.en_instruction_at + 1.minute dossier.processed_at = dossier.en_instruction_at + 1.minute
dossier.traitements.accepter(motivation: evaluator.motivation, processed_at: dossier.en_instruction_at + 1.minute) dossier.traitements.accepter(motivation: evaluator.motivation, processed_at: dossier.processed_at)
end end
dossier.save! dossier.save!
end end
@ -152,6 +153,7 @@ FactoryBot.define do
dossier.state = Dossier.states.fetch(:refuse) dossier.state = Dossier.states.fetch(:refuse)
dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur
dossier.en_construction_at ||= dossier.created_at + 1.minute dossier.en_construction_at ||= dossier.created_at + 1.minute
dossier.depose_at ||= dossier.en_construction_at
dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute
dossier.traitements.refuser(processed_at: dossier.en_instruction_at + 1.minute) dossier.traitements.refuser(processed_at: dossier.en_instruction_at + 1.minute)
dossier.save! dossier.save!
@ -163,6 +165,7 @@ FactoryBot.define do
dossier.state = Dossier.states.fetch(:sans_suite) dossier.state = Dossier.states.fetch(:sans_suite)
dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur dossier.groupe_instructeur ||= dossier.procedure&.defaut_groupe_instructeur
dossier.en_construction_at ||= dossier.created_at + 1.minute dossier.en_construction_at ||= dossier.created_at + 1.minute
dossier.depose_at ||= dossier.en_construction_at
dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute dossier.en_instruction_at ||= dossier.en_construction_at + 1.minute
dossier.traitements.classer_sans_suite(processed_at: dossier.en_instruction_at + 1.minute) dossier.traitements.classer_sans_suite(processed_at: dossier.en_instruction_at + 1.minute)
dossier.save! dossier.save!

View file

@ -89,6 +89,6 @@ describe ProcedureStatsConcern do
private private
def create_dossier(construction_date:, instruction_date:, processed_date:) def create_dossier(construction_date:, instruction_date:, processed_date:)
dossier = create(:dossier, :accepte, procedure: procedure, en_construction_at: construction_date, en_instruction_at: instruction_date, processed_at: processed_date) dossier = create(:dossier, :accepte, procedure: procedure, depose_at: construction_date, en_instruction_at: instruction_date, processed_at: processed_date)
end end
end end

View file

@ -356,15 +356,15 @@ describe Dossier do
let(:service) { create(:service, nom: 'nom du service') } let(:service) { create(:service, nom: 'nom du service') }
let(:procedure) { create(:procedure, libelle: "Démarche", organisation: "Organisme", service: service) } let(:procedure) { create(:procedure, libelle: "Démarche", organisation: "Organisme", service: service) }
context 'when the dossier has been en_construction' do context 'when the dossier has been submitted' do
let(:dossier) { create :dossier, procedure: procedure, state: Dossier.states.fetch(:en_construction), en_construction_at: "31/12/2010".to_date } let(:dossier) { create :dossier, procedure: procedure, state: Dossier.states.fetch(:en_construction), depose_at: "31/12/2010".to_date }
subject { dossier.text_summary } subject { dossier.text_summary }
it { is_expected.to eq("Dossier déposé le 31/12/2010 sur la démarche Démarche gérée par l'organisme nom du service") } it { is_expected.to eq("Dossier déposé le 31/12/2010 sur la démarche Démarche gérée par l'organisme nom du service") }
end end
context 'when the dossier has not been en_construction' do context 'when the dossier has not been submitted' do
let(:dossier) { create :dossier, procedure: procedure, state: Dossier.states.fetch(:brouillon) } let(:dossier) { create :dossier, procedure: procedure, state: Dossier.states.fetch(:brouillon) }
subject { dossier.text_summary } subject { dossier.text_summary }
@ -538,9 +538,9 @@ describe Dossier do
describe '.downloadable_sorted' do describe '.downloadable_sorted' do
let(:procedure) { create(:procedure) } let(:procedure) { create(:procedure) }
let!(:dossier) { create(:dossier, :with_entreprise, procedure: procedure, state: Dossier.states.fetch(:brouillon)) } let!(:dossier) { create(:dossier, :with_entreprise, procedure: procedure, state: Dossier.states.fetch(:brouillon)) }
let!(:dossier2) { create(:dossier, :with_entreprise, procedure: procedure, state: Dossier.states.fetch(:en_construction), en_construction_at: Time.zone.parse('03/01/2010')) } let!(:dossier2) { create(:dossier, :with_entreprise, procedure: procedure, state: Dossier.states.fetch(:en_construction), depose_at: Time.zone.parse('03/01/2010')) }
let!(:dossier3) { create(:dossier, :with_entreprise, procedure: procedure, state: Dossier.states.fetch(:en_instruction), en_construction_at: Time.zone.parse('01/01/2010')) } let!(:dossier3) { create(:dossier, :with_entreprise, procedure: procedure, state: Dossier.states.fetch(:en_instruction), depose_at: Time.zone.parse('01/01/2010')) }
let!(:dossier4) { create(:dossier, :with_entreprise, procedure: procedure, state: Dossier.states.fetch(:en_instruction), archived: true, en_construction_at: Time.zone.parse('02/01/2010')) } let!(:dossier4) { create(:dossier, :with_entreprise, procedure: procedure, state: Dossier.states.fetch(:en_instruction), archived: true, depose_at: Time.zone.parse('02/01/2010')) }
subject { procedure.dossiers.downloadable_sorted } subject { procedure.dossiers.downloadable_sorted }

View file

@ -60,6 +60,7 @@ describe ProcedurePresentation do
[ [
{ "label" => 'Créé le', "table" => 'self', "column" => 'created_at' }, { "label" => 'Créé le', "table" => 'self', "column" => 'created_at' },
{ "label" => 'En construction le', "table" => 'self', "column" => 'en_construction_at' }, { "label" => 'En construction le', "table" => 'self', "column" => 'en_construction_at' },
{ "label" => 'Déposé le', "table" => 'self', "column" => 'depose_at' },
{ "label" => 'Mis à jour le', "table" => 'self', "column" => 'updated_at' }, { "label" => 'Mis à jour le', "table" => 'self', "column" => 'updated_at' },
{ "label" => 'Demandeur', "table" => 'user', "column" => 'email' }, { "label" => 'Demandeur', "table" => 'user', "column" => 'email' },
{ "label" => 'Email instructeur', "table" => 'followers_instructeurs', "column" => 'email' }, { "label" => 'Email instructeur', "table" => 'followers_instructeurs', "column" => 'email' },

View file

@ -437,7 +437,7 @@ describe Procedure do
end end
TypeDeChamp.where(parent: procedure.draft_types_de_champ.repetition).zip(TypeDeChamp.where(parent: subject.draft_types_de_champ.repetition)).each do |ptc, stc| TypeDeChamp.where(parent: procedure.draft_types_de_champ.repetition).zip(TypeDeChamp.where(parent: subject.draft_types_de_champ.repetition)).each do |ptc, stc|
expect(stc).to have_same_attributes_as(ptc, except: ["revision_id", "parent_id"]) expect(stc).to have_same_attributes_as(ptc, except: ["revision_id", "parent_id", "migrated_parent"])
expect(stc.revision).to eq(subject.draft_revision) expect(stc.revision).to eq(subject.draft_revision)
end end
@ -447,7 +447,7 @@ describe Procedure do
end end
TypeDeChamp.where(parent: procedure.draft_types_de_champ_private.repetition).zip(TypeDeChamp.where(parent: subject.draft_types_de_champ_private.repetition)).each do |ptc, stc| TypeDeChamp.where(parent: procedure.draft_types_de_champ_private.repetition).zip(TypeDeChamp.where(parent: subject.draft_types_de_champ_private.repetition)).each do |ptc, stc|
expect(stc).to have_same_attributes_as(ptc, except: ["revision_id", "parent_id"]) expect(stc).to have_same_attributes_as(ptc, except: ["revision_id", "parent_id", "migrated_parent"])
expect(stc.revision).to eq(subject.draft_revision) expect(stc.revision).to eq(subject.draft_revision)
end end

View file

@ -54,11 +54,11 @@ describe Stat do
describe '.cumulative_hash' do describe '.cumulative_hash' do
it 'works count and cumulate counters by month for both dossier and deleted dossiers' do it 'works count and cumulate counters by month for both dossier and deleted dossiers' do
12.downto(1).map do |i| 12.downto(1).map do |i|
create(:dossier, state: :en_construction, en_construction_at: i.months.ago) create(:dossier, state: :en_construction, depose_at: i.months.ago)
create(:deleted_dossier, dossier_id: i + 100, state: :en_construction, deleted_at: i.month.ago) create(:deleted_dossier, dossier_id: i + 100, state: :en_construction, deleted_at: i.month.ago)
end end
rs = Stat.send(:cumulative_hash, [ rs = Stat.send(:cumulative_hash, [
[Dossier.state_not_brouillon, :en_construction_at], [Dossier.state_not_brouillon, :depose_at],
[DeletedDossier.where.not(state: :brouillon), :deleted_at] [DeletedDossier.where.not(state: :brouillon), :deleted_at]
]) ])
expect(rs).to eq({ expect(rs).to eq({
@ -82,11 +82,11 @@ describe Stat do
it 'works count and cumulate counters by month for both dossier and deleted dossiers' do it 'works count and cumulate counters by month for both dossier and deleted dossiers' do
travel_to Time.zone.local(2021, 11, 25) do travel_to Time.zone.local(2021, 11, 25) do
4.downto(1).map do |i| 4.downto(1).map do |i|
create(:dossier, state: :en_construction, en_construction_at: i.months.ago) create(:dossier, state: :en_construction, depose_at: i.months.ago)
create(:deleted_dossier, dossier_id: i + 100, state: :en_construction, deleted_at: i.month.ago) create(:deleted_dossier, dossier_id: i + 100, state: :en_construction, deleted_at: i.month.ago)
end end
rs = Stat.send(:last_four_months_hash, [ rs = Stat.send(:last_four_months_hash, [
[Dossier.state_not_brouillon, :en_construction_at], [Dossier.state_not_brouillon, :depose_at],
[DeletedDossier.where.not(state: :brouillon), :deleted_at] [DeletedDossier.where.not(state: :brouillon), :deleted_at]
]) ])
expect(rs).to eq([ expect(rs).to eq([

View file

@ -5,7 +5,7 @@ describe DossierSerializer do
context 'when the dossier is en_construction' do context 'when the dossier is en_construction' do
let(:dossier) { create(:dossier, :en_construction) } let(:dossier) { create(:dossier, :en_construction) }
it { is_expected.to include(initiated_at: dossier.en_construction_at) } it { is_expected.to include(initiated_at: dossier.depose_at) }
it { is_expected.to include(state: 'initiated') } it { is_expected.to include(state: 'initiated') }
end end

View file

@ -5,7 +5,7 @@ describe DossiersSerializer do
context 'when the dossier is en_construction' do context 'when the dossier is en_construction' do
let(:dossier) { create(:dossier, :en_construction) } let(:dossier) { create(:dossier, :en_construction) }
it { is_expected.to include(initiated_at: dossier.en_construction_at) } it { is_expected.to include(initiated_at: dossier.depose_at) }
it { is_expected.to include(state: 'initiated') } it { is_expected.to include(state: 'initiated') }
end end
end end

View file

@ -70,6 +70,13 @@ describe DossierProjectionService do
it { is_expected.to eq('17/10/2018') } it { is_expected.to eq('17/10/2018') }
end end
context 'for depose_at column' do
let(:column) { 'depose_at' }
let(:dossier) { create(:dossier, :en_construction, depose_at: Time.zone.local(2018, 10, 17)) }
it { is_expected.to eq('17/10/2018') }
end
context 'for updated_at column' do context 'for updated_at column' do
let(:column) { 'updated_at' } let(:column) { 'updated_at' }
let(:dossier) { create(:dossier) } let(:dossier) { create(:dossier) }

View file

@ -91,10 +91,10 @@ describe ProcedureExportService do
expect(etablissements_sheet.data.size).to eq(1) expect(etablissements_sheet.data.size).to eq(1)
# SimpleXlsxReader is transforming datetimes in utc... It is only used in test so we just hack around. # SimpleXlsxReader is transforming datetimes in utc... It is only used in test so we just hack around.
offset = dossier.en_construction_at.utc_offset offset = dossier.depose_at.utc_offset
en_construction_at = Time.zone.at(dossiers_sheet.data[0][8] - offset.seconds) depose_at = Time.zone.at(dossiers_sheet.data[0][8] - offset.seconds)
en_instruction_at = Time.zone.at(dossiers_sheet.data[0][9] - offset.seconds) en_instruction_at = Time.zone.at(dossiers_sheet.data[0][9] - offset.seconds)
expect(en_construction_at).to eq(dossier.en_construction_at.round) expect(depose_at).to eq(dossier.depose_at.round)
expect(en_instruction_at).to eq(dossier.en_instruction_at.round) expect(en_instruction_at).to eq(dossier.en_instruction_at.round)
end end

View file

@ -17,7 +17,7 @@ describe 'Dossier details:' do
end end
describe "the user can see the mean time they are expected to wait" do describe "the user can see the mean time they are expected to wait" do
let(:other_dossier) { create(:dossier, :accepte, :with_individual, procedure: procedure, en_construction_at: 10.days.ago, en_instruction_at: 9.days.ago, processed_at: Time.zone.now) } let(:other_dossier) { create(:dossier, :accepte, :with_individual, procedure: procedure, depose_at: 10.days.ago, en_instruction_at: 9.days.ago, processed_at: Time.zone.now) }
context "when the dossier is in construction" do context "when the dossier is in construction" do
it "displays the estimated wait duration" do it "displays the estimated wait duration" do

View file

@ -58,7 +58,7 @@ RSpec.describe 'commencer/show.html.haml', type: :view do
it 'renders a link to the submitted dossier' do it 'renders a link to the submitted dossier' do
subject subject
expect(rendered).to have_text(time_ago_in_words(dossier.en_construction_at)) expect(rendered).to have_text(time_ago_in_words(dossier.depose_at))
expect(rendered).to have_link('Voir mon dossier', href: dossier_path(dossier)) expect(rendered).to have_link('Voir mon dossier', href: dossier_path(dossier))
end end
end end

View file

@ -28,7 +28,7 @@ describe 'users/dossiers/demande.html.haml', type: :view do
it { is_expected.not_to have_link('Modifier le dossier') } it { is_expected.not_to have_link('Modifier le dossier') }
end end
context 'when the dossier has no en_construction_at date' do context 'when the dossier has no depose_at date' do
let(:dossier) { create(:dossier, :with_entreprise, procedure: procedure) } let(:dossier) { create(:dossier, :with_entreprise, procedure: procedure) }
it { expect(rendered).not_to have_text('Déposé le') } it { expect(rendered).not_to have_text('Déposé le') }