Merge pull request #5506 from tchak/add-revisions-step-2

Add revisions step 2 (cleanup)
This commit is contained in:
Paul Chavard 2020-09-02 11:40:44 +02:00 committed by GitHub
commit a07f8e2d3d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 490 additions and 626 deletions

View file

@ -66,6 +66,7 @@ module NewAdministrateur
def create def create
@procedure = Procedure.new(procedure_params.merge(administrateurs: [current_administrateur])) @procedure = Procedure.new(procedure_params.merge(administrateurs: [current_administrateur]))
@procedure.draft_revision = @procedure.revisions.build
if !@procedure.save if !@procedure.save
flash.now.alert = @procedure.errors.full_messages flash.now.alert = @procedure.errors.full_messages
@ -73,8 +74,6 @@ module NewAdministrateur
else else
flash.notice = 'Démarche enregistrée.' flash.notice = 'Démarche enregistrée.'
current_administrateur.instructeur.assign_to_procedure(@procedure) current_administrateur.instructeur.assign_to_procedure(@procedure)
# FIXUP: needed during transition to revisions
RevisionsMigration.add_revisions(@procedure)
redirect_to champs_admin_procedure_path(@procedure) redirect_to champs_admin_procedure_path(@procedure)
end end

View file

@ -2,7 +2,6 @@ module NewAdministrateur
class TypesDeChampController < AdministrateurController class TypesDeChampController < AdministrateurController
before_action :retrieve_procedure, only: [:create, :update, :move, :destroy] before_action :retrieve_procedure, only: [:create, :update, :move, :destroy]
before_action :procedure_locked?, only: [:create, :update, :move, :destroy] before_action :procedure_locked?, only: [:create, :update, :move, :destroy]
before_action :revisions_migration
def create def create
type_de_champ = @procedure.draft_revision.add_type_de_champ(type_de_champ_create_params) type_de_champ = @procedure.draft_revision.add_type_de_champ(type_de_champ_create_params)
@ -16,7 +15,7 @@ module NewAdministrateur
end end
def update def update
type_de_champ = @procedure.draft_revision.find_or_clone_type_de_champ(type_de_champ_stable_id) type_de_champ = @procedure.draft_revision.find_or_clone_type_de_champ(TypeDeChamp.to_stable_id(params[:id]))
if type_de_champ.update(type_de_champ_update_params) if type_de_champ.update(type_de_champ_update_params)
reset_procedure reset_procedure
@ -27,13 +26,13 @@ module NewAdministrateur
end end
def move def move
@procedure.draft_revision.move_type_de_champ(type_de_champ_stable_id, (params[:position] || params[:order_place]).to_i) @procedure.draft_revision.move_type_de_champ(TypeDeChamp.to_stable_id(params[:id]), (params[:position] || params[:order_place]).to_i)
head :no_content head :no_content
end end
def destroy def destroy
@procedure.draft_revision.remove_type_de_champ(type_de_champ_stable_id) @procedure.draft_revision.remove_type_de_champ(TypeDeChamp.to_stable_id(params[:id]))
reset_procedure reset_procedure
head :no_content head :no_content
@ -41,19 +40,11 @@ module NewAdministrateur
private private
def type_de_champ_stable_id
TypeDeChamp.find(params[:id]).stable_id
end
def revisions_migration
# FIXUP: needed during transition to revisions
RevisionsMigration.add_revisions(@procedure)
end
def serialize_type_de_champ(type_de_champ) def serialize_type_de_champ(type_de_champ)
{ {
type_de_champ: type_de_champ.as_json( type_de_champ: type_de_champ.as_json(
except: [ except: [
:id,
:created_at, :created_at,
:options, :options,
:order_place, :order_place,
@ -73,7 +64,7 @@ module NewAdministrateur
:piece_justificative_template_url, :piece_justificative_template_url,
:quartiers_prioritaires :quartiers_prioritaires
] ]
) ).merge(id: TypeDeChamp.format_stable_id(type_de_champ.stable_id))
} }
end end
@ -92,7 +83,7 @@ module NewAdministrateur
:type_champ) :type_champ)
if type_de_champ_params[:parent_id].present? if type_de_champ_params[:parent_id].present?
type_de_champ_params[:parent_id] = TypeDeChamp.find(type_de_champ_params[:parent_id]).stable_id type_de_champ_params[:parent_id] = TypeDeChamp.to_stable_id(type_de_champ_params[:parent_id])
end end
type_de_champ_params type_de_champ_params

View file

@ -313,7 +313,8 @@ class StatsController < ApplicationController
procedure_id_type_de_champs_count = TypeDeChamp procedure_id_type_de_champs_count = TypeDeChamp
.where(private: false) .where(private: false)
.group(:procedure_id) .joins(:revision)
.group('procedure_revisions.procedure_id')
.count .count
groupe_instructeur_id_type_de_champs_count = groupe_instructeurs.reduce({}) do |acc, (gi_id, procedure_id)| groupe_instructeur_id_type_de_champs_count = groupe_instructeurs.reduce({}) do |acc, (gi_id, procedure_id)|

View file

@ -259,8 +259,6 @@ module Users
return redirect_to url_for dossiers_path return redirect_to url_for dossiers_path
end end
# FIXUP: needed during transition to revisions
RevisionsMigration.add_revisions(procedure)
dossier = Dossier.new( dossier = Dossier.new(
revision: procedure.active_revision, revision: procedure.active_revision,
groupe_instructeur: procedure.defaut_groupe_instructeur, groupe_instructeur: procedure.defaut_groupe_instructeur,

View file

@ -8,8 +8,8 @@ class ProcedureDashboard < Administrate::BaseDashboard
# which determines how the attribute is displayed # which determines how the attribute is displayed
# on pages throughout the dashboard. # on pages throughout the dashboard.
ATTRIBUTE_TYPES = { ATTRIBUTE_TYPES = {
types_de_champ: TypesDeChampCollectionField, published_types_de_champ: TypesDeChampCollectionField,
types_de_champ_private: TypesDeChampCollectionField, published_types_de_champ_private: TypesDeChampCollectionField,
path: ProcedureLinkField, path: ProcedureLinkField,
dossiers: Field::HasMany, dossiers: Field::HasMany,
administrateurs: Field::HasMany, administrateurs: Field::HasMany,
@ -70,8 +70,8 @@ class ProcedureDashboard < Administrate::BaseDashboard
:whitelisted_at, :whitelisted_at,
:hidden_at, :hidden_at,
:closed_at, :closed_at,
:types_de_champ, :published_types_de_champ,
:types_de_champ_private, :published_types_de_champ_private,
:for_individual, :for_individual,
:auto_archive_on, :auto_archive_on,
:initiated_mail_template, :initiated_mail_template,

View file

@ -210,7 +210,6 @@ export const FIELDS = [
'drop_down_list_value', 'drop_down_list_value',
'libelle', 'libelle',
'mandatory', 'mandatory',
'order_place',
'parcelles_agricoles', 'parcelles_agricoles',
'parent_id', 'parent_id',
'piece_justificative_template', 'piece_justificative_template',

View file

@ -22,7 +22,7 @@ export function moveTypeDeChampOperation(typeDeChamp, index, queue) {
return queue.enqueue({ return queue.enqueue({
path: `/${typeDeChamp.id}/move`, path: `/${typeDeChamp.id}/move`,
method: 'patch', method: 'patch',
payload: { order_place: index } payload: { position: index }
}); });
} }

View file

@ -37,8 +37,7 @@ export default function typeDeChampsReducer(state, { type, params, done }) {
function addTypeDeChamp(state, typeDeChamps, insertAfter, done) { function addTypeDeChamp(state, typeDeChamps, insertAfter, done) {
const typeDeChamp = { const typeDeChamp = {
...state.defaultTypeDeChampAttributes, ...state.defaultTypeDeChampAttributes
order_place: typeDeChamps.length
}; };
createTypeDeChampOperation(typeDeChamp, state.queue) createTypeDeChampOperation(typeDeChamp, state.queue)

View file

@ -24,7 +24,7 @@ class FindDubiousProceduresJob < CronJob
.where(procedures: { closed_at: nil, whitelisted_at: nil }) .where(procedures: { closed_at: nil, whitelisted_at: nil })
dubious_procedures_and_tdcs = forbidden_tdcs dubious_procedures_and_tdcs = forbidden_tdcs
.group_by(&:procedure_id) .group_by { |type_de_champ| type_de_champ.procedure.id }
.map { |_procedure_id, tdcs| [tdcs[0].procedure, tdcs] } .map { |_procedure_id, tdcs| [tdcs[0].procedure, tdcs] }
AdministrationMailer.dubious_procedures(dubious_procedures_and_tdcs).deliver_later AdministrationMailer.dubious_procedures(dubious_procedures_and_tdcs).deliver_later

View file

@ -1,21 +0,0 @@
class TmpDossiersMigrateRevisionsJob < ApplicationJob
def perform(except)
dossiers = Dossier.with_discarded.where(revision_id: nil)
dossiers.where
.not(id: except)
.includes(procedure: [:draft_revision, :published_revision])
.limit(2000)
.find_each do |dossier|
if dossier.procedure.present?
dossier.update_column(:revision_id, dossier.procedure.active_revision.id)
else
except << dossier.id
end
end
if dossiers.where.not(id: except).exists?
TmpDossiersMigrateRevisionsJob.perform_later(except)
end
end
end

View file

@ -47,6 +47,9 @@ class Champ < ApplicationRecord
scope :public_only, -> { where(private: false) } scope :public_only, -> { where(private: false) }
scope :private_only, -> { where(private: true) } scope :private_only, -> { where(private: true) }
scope :ordered, -> { includes(:type_de_champ).order(:row, 'types_de_champ.order_place') } scope :ordered, -> { includes(:type_de_champ).order(:row, 'types_de_champ.order_place') }
scope :public_ordered, -> { public_only.joins(dossier: { revision: :revision_types_de_champ }).where('procedure_revision_types_de_champ.type_de_champ_id = champs.type_de_champ_id').order(:position) }
scope :private_ordered, -> { private_only.joins(dossier: { revision: :revision_types_de_champ_private }).where('procedure_revision_types_de_champ.type_de_champ_id = champs.type_de_champ_id').order(:position) }
scope :root, -> { where(parent_id: nil) } scope :root, -> { where(parent_id: nil) }
before_validation :set_dossier_id, if: :needs_dossier_id? before_validation :set_dossier_id, if: :needs_dossier_id?

View file

@ -62,8 +62,8 @@ class Dossier < ApplicationRecord
has_one_attached :justificatif_motivation has_one_attached :justificatif_motivation
has_many :champs, -> { root.public_only.ordered }, inverse_of: :dossier, dependent: :destroy has_many :champs, -> { root.public_ordered }, inverse_of: :dossier, dependent: :destroy
has_many :champs_private, -> { root.private_only.ordered }, class_name: 'Champ', inverse_of: :dossier, dependent: :destroy has_many :champs_private, -> { root.private_ordered }, class_name: 'Champ', inverse_of: :dossier, dependent: :destroy
has_many :commentaires, inverse_of: :dossier, dependent: :destroy has_many :commentaires, inverse_of: :dossier, dependent: :destroy
has_many :invites, dependent: :destroy has_many :invites, dependent: :destroy
has_many :follows, -> { active }, inverse_of: :dossier has_many :follows, -> { active }, inverse_of: :dossier
@ -76,10 +76,13 @@ class Dossier < ApplicationRecord
has_many :dossier_operation_logs, -> { order(:created_at) }, dependent: :nullify, inverse_of: :dossier has_many :dossier_operation_logs, -> { order(:created_at) }, dependent: :nullify, inverse_of: :dossier
belongs_to :groupe_instructeur, optional: false belongs_to :groupe_instructeur, optional: false
has_one :procedure, through: :groupe_instructeur belongs_to :revision, class_name: 'ProcedureRevision', optional: false
belongs_to :revision, class_name: 'ProcedureRevision', optional: true
belongs_to :user, optional: false belongs_to :user, optional: false
has_one :procedure, through: :revision
has_many :types_de_champ, through: :revision
has_many :types_de_champ_private, through: :revision
accepts_nested_attributes_for :champs accepts_nested_attributes_for :champs
accepts_nested_attributes_for :champs_private accepts_nested_attributes_for :champs_private
@ -315,7 +318,6 @@ class Dossier < ApplicationRecord
accepts_nested_attributes_for :individual accepts_nested_attributes_for :individual
delegate :siret, :siren, to: :etablissement, allow_nil: true delegate :siret, :siren, to: :etablissement, allow_nil: true
delegate :types_de_champ, to: :procedure
delegate :france_connect_information, to: :user delegate :france_connect_information, to: :user
before_save :build_default_champs, if: Proc.new { groupe_instructeur_id_was.nil? } before_save :build_default_champs, if: Proc.new { groupe_instructeur_id_was.nil? }
@ -326,7 +328,7 @@ class Dossier < ApplicationRecord
after_create :send_draft_notification_email after_create :send_draft_notification_email
validates :user, presence: true validates :user, presence: true
validates :individual, presence: true, if: -> { procedure.for_individual? } validates :individual, presence: true, if: -> { revision.procedure.for_individual? }
validates :groupe_instructeur, presence: true validates :groupe_instructeur, presence: true
def motivation def motivation
@ -351,10 +353,10 @@ class Dossier < ApplicationRecord
end end
def build_default_champs def build_default_champs
procedure.build_champs.each do |champ| revision.build_champs.each do |champ|
champs << champ champs << champ
end end
procedure.build_champs_private.each do |champ| revision.build_champs_private.each do |champ|
champs_private << champ champs_private << champ
end end
end end

View file

@ -56,13 +56,16 @@ class Procedure < ApplicationRecord
MAX_DUREE_CONSERVATION = 36 MAX_DUREE_CONSERVATION = 36
MAX_DUREE_CONSERVATION_EXPORT = 3.hours MAX_DUREE_CONSERVATION_EXPORT = 3.hours
has_many :types_de_champ, -> { root.public_only.ordered }, inverse_of: :procedure, dependent: :destroy
has_many :types_de_champ_private, -> { root.private_only.ordered }, class_name: 'TypeDeChamp', inverse_of: :procedure, dependent: :destroy
has_many :revisions, -> { order(:id) }, class_name: 'ProcedureRevision', inverse_of: :procedure, dependent: :destroy has_many :revisions, -> { order(:id) }, class_name: 'ProcedureRevision', inverse_of: :procedure, dependent: :destroy
belongs_to :draft_revision, class_name: 'ProcedureRevision', optional: true belongs_to :draft_revision, class_name: 'ProcedureRevision', optional: false
belongs_to :published_revision, class_name: 'ProcedureRevision', optional: true belongs_to :published_revision, class_name: 'ProcedureRevision', optional: true
has_many :deleted_dossiers, dependent: :destroy has_many :deleted_dossiers, dependent: :destroy
has_many :published_types_de_champ, through: :published_revision, source: :types_de_champ
has_many :published_types_de_champ_private, through: :published_revision, source: :types_de_champ_private
has_many :draft_types_de_champ, through: :draft_revision, source: :types_de_champ
has_many :draft_types_de_champ_private, through: :draft_revision, source: :types_de_champ_private
has_one :module_api_carto, dependent: :destroy has_one :module_api_carto, dependent: :destroy
has_one :attestation_template, dependent: :destroy has_one :attestation_template, dependent: :destroy
@ -74,6 +77,14 @@ class Procedure < ApplicationRecord
brouillon? ? draft_revision : published_revision brouillon? ? draft_revision : published_revision
end end
def types_de_champ
brouillon? ? draft_types_de_champ : published_types_de_champ
end
def types_de_champ_private
brouillon? ? draft_types_de_champ_private : published_types_de_champ_private
end
has_many :administrateurs_procedures has_many :administrateurs_procedures
has_many :administrateurs, through: :administrateurs_procedures, after_remove: -> (procedure, _admin) { procedure.validate! } has_many :administrateurs, through: :administrateurs_procedures, after_remove: -> (procedure, _admin) { procedure.validate! }
has_many :groupe_instructeurs, dependent: :destroy has_many :groupe_instructeurs, dependent: :destroy
@ -93,9 +104,6 @@ class Procedure < ApplicationRecord
has_one_attached :notice has_one_attached :notice
has_one_attached :deliberation has_one_attached :deliberation
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
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]) }
@ -114,9 +122,15 @@ class Procedure < ApplicationRecord
scope :for_api, -> { scope :for_api, -> {
includes( includes(
:administrateurs, :administrateurs,
:module_api_carto,
published_revision: [
:types_de_champ_private, :types_de_champ_private,
:types_de_champ, :types_de_champ
:module_api_carto ],
draft_revision: [
:types_de_champ_private,
:types_de_champ
]
) )
} }
@ -289,22 +303,13 @@ class Procedure < ApplicationRecord
# to save a dossier created from this method # to save a dossier created from this method
def new_dossier def new_dossier
Dossier.new( Dossier.new(
procedure: self,
revision: active_revision, revision: active_revision,
champs: build_champs, champs: active_revision.build_champs,
champs_private: build_champs_private, champs_private: active_revision.build_champs_private,
groupe_instructeur: defaut_groupe_instructeur groupe_instructeur: defaut_groupe_instructeur
) )
end end
def build_champs
types_de_champ.map(&:build_champ)
end
def build_champs_private
types_de_champ_private.map(&:build_champ)
end
def path_customized? def path_customized?
!path.match?(/[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}/) !path.match?(/[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}/)
end end
@ -318,9 +323,6 @@ class Procedure < ApplicationRecord
end end
def clone(admin, from_library) def clone(admin, from_library)
# FIXUP: needed during transition to revisions
RevisionsMigration.add_revisions(self)
is_different_admin = !admin.owns?(self) is_different_admin = !admin.owns?(self)
populate_champ_stable_ids populate_champ_stable_ids
@ -371,19 +373,11 @@ class Procedure < ApplicationRecord
end end
procedure.save procedure.save
procedure.draft_revision.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_revision.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)
# FIXUP: needed during transition to revisions
procedure.draft_revision.types_de_champ.each do |type_de_champ|
procedure.types_de_champ << type_de_champ
end
procedure.draft_revision.types_de_champ_private.each do |type_de_champ|
procedure.types_de_champ_private << type_de_champ
end
if is_different_admin || from_library if is_different_admin || from_library
procedure.types_de_champ.each { |tdc| tdc.options&.delete(:old_pj) } procedure.draft_types_de_champ.each { |tdc| tdc.options&.delete(:old_pj) }
end end
procedure procedure
@ -608,23 +602,14 @@ class Procedure < ApplicationRecord
end end
def after_publish(canonical_procedure = nil) def after_publish(canonical_procedure = nil)
# FIXUP: needed during transition to revisions
if RevisionsMigration.add_revisions(self)
update!(published_at: Time.zone.now, canonical_procedure: canonical_procedure)
else
update!(published_at: Time.zone.now, canonical_procedure: canonical_procedure, draft_revision: create_new_revision, published_revision: draft_revision) update!(published_at: Time.zone.now, canonical_procedure: canonical_procedure, draft_revision: create_new_revision, published_revision: draft_revision)
end end
end
def after_close def after_close
# FIXUP: needed during transition to revisions
RevisionsMigration.add_revisions(self)
update!(closed_at: Time.zone.now) update!(closed_at: Time.zone.now)
end end
def after_unpublish def after_unpublish
# FIXUP: needed during transition to revisions
RevisionsMigration.add_revisions(self)
update!(unpublished_at: Time.zone.now) update!(unpublished_at: Time.zone.now)
end end

View file

@ -9,15 +9,22 @@
# #
class ProcedureRevision < ApplicationRecord class ProcedureRevision < ApplicationRecord
self.implicit_order_column = :created_at self.implicit_order_column = :created_at
belongs_to :procedure, -> { with_discarded }, inverse_of: :revisions belongs_to :procedure, -> { with_discarded }, inverse_of: :revisions, optional: false
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, -> { 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, -> { 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
def build_champs
types_de_champ.map(&:build_champ)
end
def build_champs_private
types_de_champ_private.map(&:build_champ)
end
def add_type_de_champ(params) def add_type_de_champ(params)
params[:procedure] = procedure
params[:revision] = self params[:revision] = self
if params[:parent_id] if params[:parent_id]
@ -27,15 +34,9 @@ class ProcedureRevision < ApplicationRecord
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)
elsif params[:private] elsif params[:private]
types_de_champ_private.tap do |types_de_champ| types_de_champ_private.create(params)
# FIXUP: needed during transition to revisions
params[:order_place] = types_de_champ.present? ? types_de_champ.last.order_place + 1 : 0
end.create(params)
else else
types_de_champ.tap do |types_de_champ| types_de_champ.create(params)
# FIXUP: needed during transition to revisions
params[:order_place] = types_de_champ.present? ? types_de_champ.last.order_place + 1 : 0
end.create(params)
end end
end end
@ -112,8 +113,6 @@ class ProcedureRevision < ApplicationRecord
if types_de_champ.delete_at(old_index) if types_de_champ.delete_at(old_index)
types_de_champ.insert(new_index, type_de_champ) types_de_champ.insert(new_index, type_de_champ)
.map.with_index do |type_de_champ, index| .map.with_index do |type_de_champ, index|
# FIXUP: needed during transition to revisions
type_de_champ.update!(order_place: index)
[type_de_champ.id, index] [type_de_champ.id, index]
end end
else else

View file

@ -26,15 +26,11 @@ class ProcedureRevisionTypeDeChamp < ApplicationRecord
private private
def set_position def set_position
self.position ||= if private? self.position ||= begin
if revision.types_de_champ_private.present? types_de_champ = (private? ? revision.revision_types_de_champ_private : revision.revision_types_de_champ).filter(&:persisted?)
revision.revision_types_de_champ_private.filter(&:persisted?).last.position + 1
else if types_de_champ.present?
0 types_de_champ.last.position + 1
end
else
if revision.types_de_champ.present?
revision.revision_types_de_champ.filter(&:persisted?).last.position + 1
else else
0 0
end end

View file

@ -18,6 +18,8 @@
# stable_id :bigint # stable_id :bigint
# #
class TypeDeChamp < ApplicationRecord class TypeDeChamp < ApplicationRecord
self.ignored_columns = ['procedure_id']
enum type_champs: { enum type_champs: {
text: 'text', text: 'text',
textarea: 'textarea', textarea: 'textarea',
@ -49,8 +51,8 @@ class TypeDeChamp < ApplicationRecord
repetition: 'repetition' repetition: 'repetition'
} }
belongs_to :procedure, optional: false
belongs_to :revision, class_name: 'ProcedureRevision', optional: true belongs_to :revision, class_name: 'ProcedureRevision', optional: true
has_one :procedure, through: :revision
belongs_to :parent, class_name: 'TypeDeChamp', optional: true belongs_to :parent, class_name: 'TypeDeChamp', optional: true
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
@ -73,7 +75,6 @@ class TypeDeChamp < ApplicationRecord
serialize :options, WithIndifferentAccess serialize :options, WithIndifferentAccess
after_initialize :set_dynamic_type after_initialize :set_dynamic_type
before_validation :setup_procedure
after_create :populate_stable_id after_create :populate_stable_id
attr_reader :dynamic_type attr_reader :dynamic_type
@ -298,9 +299,34 @@ class TypeDeChamp < ApplicationRecord
.merge(include: { types_de_champ: TYPES_DE_CHAMP_BASE }) .merge(include: { types_de_champ: TYPES_DE_CHAMP_BASE })
def self.as_json_for_editor def self.as_json_for_editor
includes(piece_justificative_template_attachment: :blob, includes(piece_justificative_template_attachment: :blob, types_de_champ: [piece_justificative_template_attachment: :blob]).as_json(TYPES_DE_CHAMP)
types_de_champ: [piece_justificative_template_attachment: :blob]) end
.as_json(TYPES_DE_CHAMP)
def read_attribute_for_serialization(name)
if name == 'id'
self.class.format_stable_id(stable_id)
else
super
end
end
# FIXME: We are changing how id is exposed to the editor.
# We used to expose type_de_champ.id as primary key to the editor. With revisions
# we need primary key to be type_de_champ.stable_id because any update can create
# a new version but we do not want editor to know about this.
# This is only needed for a clean migration without downtime. We want to ensure
# that if editor send a simple id because it was loaded before deployment
# we would still do the right thing.
def self.format_stable_id(stable_id)
"stable:#{stable_id}"
end
def self.to_stable_id(id_or_stable_id)
if id_or_stable_id.to_s =~ /^stable:/
id_or_stable_id.to_s.gsub(/^stable:/, '')
else
find(id_or_stable_id).stable_id
end
end end
private private
@ -311,12 +337,6 @@ class TypeDeChamp < ApplicationRecord
result.blank? ? [] : [''] + result result.blank? ? [] : [''] + result
end end
def setup_procedure
types_de_champ.each do |type_de_champ|
type_de_champ.procedure = procedure
end
end
def populate_stable_id def populate_stable_id
if !stable_id if !stable_id
update_column(:stable_id, id) update_column(:stable_id, id)

View file

@ -67,7 +67,7 @@ class DossierSerializer < ActiveModel::Serializer
end end
def types_de_piece_justificative def types_de_piece_justificative
PiecesJustificativesService.serialize_types_de_champ_as_type_pj(object) PiecesJustificativesService.serialize_types_de_champ_as_type_pj(object.revision)
end end
def email def email

View file

@ -48,6 +48,6 @@ class ProcedureSerializer < ActiveModel::Serializer
end end
def types_de_piece_justificative def types_de_piece_justificative
PiecesJustificativesService.serialize_types_de_champ_as_type_pj(object) PiecesJustificativesService.serialize_types_de_champ_as_type_pj(object.active_revision)
end end
end end

View file

@ -12,8 +12,8 @@ class PiecesJustificativesService
.sum(&:byte_size) .sum(&:byte_size)
end end
def self.serialize_types_de_champ_as_type_pj(procedure) def self.serialize_types_de_champ_as_type_pj(revision)
tdcs = procedure.types_de_champ.filter { |type_champ| type_champ.old_pj.present? } tdcs = revision.types_de_champ.filter { |type_champ| type_champ.old_pj.present? }
tdcs.map.with_index do |type_champ, order_place| tdcs.map.with_index do |type_champ, order_place|
description = type_champ.description description = type_champ.description
if /^(?<original_description>.*?)(?:[\r\n]+)Récupérer le formulaire vierge pour mon dossier : (?<lien_demarche>http.*)$/m =~ description if /^(?<original_description>.*?)(?:[\r\n]+)Récupérer le formulaire vierge pour mon dossier : (?<lien_demarche>http.*)$/m =~ description

View file

@ -1,36 +0,0 @@
class RevisionsMigration
def self.add_revisions(procedure)
if procedure.draft_revision.present?
return false
end
procedure.draft_revision = procedure.revisions.create
procedure.save!(validate: false)
add_types_de_champs_to_revision(procedure, :types_de_champ)
add_types_de_champs_to_revision(procedure, :types_de_champ_private)
if !procedure.brouillon?
published_revision = procedure.draft_revision
procedure.draft_revision = procedure.create_new_revision
procedure.published_revision = published_revision
procedure.save!(validate: false)
end
true
end
def self.add_types_de_champs_to_revision(procedure, types_de_champ_scope)
types_de_champ = procedure.send(types_de_champ_scope)
types_de_champ.where(revision_id: nil).update_all(revision_id: procedure.draft_revision.id)
types_de_champ.each.with_index do |type_de_champ, index|
type_de_champ.types_de_champ.where(revision_id: nil).update_all(revision_id: procedure.draft_revision.id)
procedure.draft_revision.send(:"revision_#{types_de_champ_scope}").create!(
type_de_champ: type_de_champ,
position: index
)
end
end
end

View file

@ -40,7 +40,7 @@
- if !@procedure.locked? - if !@procedure.locked?
.card-admin .card-admin
- if @procedure.types_de_champ.count > 0 - if @procedure.draft_types_de_champ.count > 0
%div %div
%span.icon.accept %span.icon.accept
%p.card-admin-status-accept Validé %p.card-admin-status-accept Validé
@ -50,7 +50,7 @@
%p.card-admin-status-todo À faire %p.card-admin-status-todo À faire
%div %div
%p.card-admin-title %p.card-admin-title
%span.badge.baseline= @procedure.types_de_champ.count %span.badge.baseline= @procedure.draft_types_de_champ.count
Champs du formulaire Champs du formulaire
%p.card-admin-subtitle À remplir par les usagers %p.card-admin-subtitle À remplir par les usagers
.card-admin-action .card-admin-action
@ -148,7 +148,7 @@
- if !@procedure.locked? - if !@procedure.locked?
.card-admin .card-admin
- if @procedure.types_de_champ_private.present? - if @procedure.draft_types_de_champ_private.present?
%div %div
%span.icon.accept %span.icon.accept
%p.card-admin-status-accept Validé %p.card-admin-status-accept Validé

View file

@ -255,9 +255,8 @@ describe API::V1::DossiersController do
end end
describe 'repetition' do describe 'repetition' do
let(:procedure) { create(:procedure, administrateur: admin) } let(:procedure) { create(:procedure, :with_repetition, administrateur: admin) }
let(:champ) { build(:champ_repetition) } let(:dossier) { create(:dossier, :en_construction, :with_all_champs, procedure: procedure) }
let(:dossier) { create(:dossier, :en_construction, champs: [champ], procedure: procedure) }
subject { super().first[:rows] } subject { super().first[:rows] }

View file

@ -560,36 +560,34 @@ describe Instructeurs::DossiersController, type: :controller do
end end
describe "#update_annotations" do describe "#update_annotations" do
let(:procedure) do
create(:procedure, :published, types_de_champ_private: [
build(:type_de_champ_multiple_drop_down_list, position: 0),
build(:type_de_champ_linked_drop_down_list, position: 1),
build(:type_de_champ_datetime, position: 2),
build(:type_de_champ_repetition, :with_types_de_champ, position: 3)
], instructeurs: instructeurs)
end
let(:dossier) { create(:dossier, :en_construction, :with_all_annotations, procedure: procedure) }
let(:now) { Time.zone.parse('01/01/2100') }
let(:champ_multiple_drop_down_list) do let(:champ_multiple_drop_down_list) do
tdc = create(:type_de_champ_multiple_drop_down_list, :private, procedure: procedure, libelle: 'libelle') dossier.champs_private.first
create(:champ_multiple_drop_down_list, :private, type_de_champ: tdc, dossier: dossier)
end end
let(:champ_linked_drop_down_list) do let(:champ_linked_drop_down_list) do
tdc = create(:type_de_champ_linked_drop_down_list, :private, procedure: procedure, libelle: 'libelle') dossier.champs_private.second
create(:champ_linked_drop_down_list, :private, type_de_champ: tdc, dossier: dossier)
end end
let(:champ_datetime) do let(:champ_datetime) do
tdc = create(:type_de_champ_datetime, :private, procedure: procedure, libelle: 'libelle') dossier.champs_private.third
create(:champ_datetime, :private, type_de_champ: tdc, dossier: dossier)
end end
let(:champ_repetition) do let(:champ_repetition) do
tdc = create(:type_de_champ_repetition, :private, :with_types_de_champ, procedure: procedure, libelle: 'libelle') dossier.champs_private.fourth
tdc.types_de_champ << create(:type_de_champ_text, procedure: procedure, libelle: 'libelle')
champ = create(:champ_repetition, :private, type_de_champ: tdc, dossier: dossier)
champ.add_row
champ
end end
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
let(:now) { Time.zone.parse('01/01/2100') }
before do before do
dossier.champs_private << [champ_multiple_drop_down_list, champ_linked_drop_down_list, champ_datetime, champ_repetition]
Timecop.freeze(now) Timecop.freeze(now)
patch :update_annotations, params: params patch :update_annotations, params: params
@ -638,13 +636,16 @@ describe Instructeurs::DossiersController, type: :controller do
} }
} }
end end
it { expect(champ_multiple_drop_down_list.value).to eq('["un", "deux"]') }
it { expect(champ_linked_drop_down_list.primary_value).to eq('primary') } it {
it { expect(champ_linked_drop_down_list.secondary_value).to eq('secondary') } expect(champ_multiple_drop_down_list.value).to eq('["un", "deux"]')
it { expect(champ_datetime.value).to eq('21/12/2019 13:17') } expect(champ_linked_drop_down_list.primary_value).to eq('primary')
it { expect(champ_repetition.champs.first.value).to eq('text') } expect(champ_linked_drop_down_list.secondary_value).to eq('secondary')
it { expect(dossier.reload.last_champ_private_updated_at).to eq(now) } expect(champ_datetime.value).to eq('21/12/2019 13:17')
it { expect(response).to redirect_to(annotations_privees_instructeur_dossier_path(dossier.procedure, dossier)) } expect(champ_repetition.champs.first.value).to eq('text')
expect(dossier.reload.last_champ_private_updated_at).to eq(now)
expect(response).to redirect_to(annotations_privees_instructeur_dossier_path(dossier.procedure, dossier))
}
end end
context "without new values for champs_private" do context "without new values for champs_private" do
@ -663,8 +664,11 @@ describe Instructeurs::DossiersController, type: :controller do
} }
} }
end end
it { expect(dossier.reload.last_champ_private_updated_at).to eq(nil) }
it { expect(response).to redirect_to(annotations_privees_instructeur_dossier_path(dossier.procedure, dossier)) } it {
expect(dossier.reload.last_champ_private_updated_at).to eq(nil)
expect(response).to redirect_to(annotations_privees_instructeur_dossier_path(dossier.procedure, dossier))
}
end end
end end

View file

@ -17,7 +17,7 @@ describe Manager::ProceduresController, type: :controller do
describe '#show' do describe '#show' do
render_views render_views
let(:procedure) { create(:procedure, :with_repetition) } let(:procedure) { create(:procedure, :published, :with_repetition) }
before do before do
get :show, params: { id: procedure.id } get :show, params: { id: procedure.id }

View file

@ -2,11 +2,11 @@ describe StatsController, type: :controller do
describe "#last_four_months_hash" do describe "#last_four_months_hash" do
context "while a regular user is logged in" do context "while a regular user is logged in" do
before do before do
FactoryBot.create(:procedure, :created_at => 6.months.ago, :updated_at => 6.months.ago) create(:procedure, created_at: 6.months.ago, updated_at: 6.months.ago)
FactoryBot.create(:procedure, :created_at => 2.months.ago, :updated_at => 62.days.ago) create(:procedure, created_at: 2.months.ago, updated_at: 62.days.ago)
FactoryBot.create(:procedure, :created_at => 2.months.ago, :updated_at => 62.days.ago) create(:procedure, created_at: 2.months.ago, updated_at: 62.days.ago)
FactoryBot.create(:procedure, :created_at => 2.months.ago, :updated_at => 31.days.ago) create(:procedure, created_at: 2.months.ago, updated_at: 31.days.ago)
FactoryBot.create(:procedure, :created_at => 2.months.ago, :updated_at => Time.zone.now) create(:procedure, created_at: 2.months.ago, updated_at: Time.zone.now)
@controller = StatsController.new @controller = StatsController.new
allow(@controller).to receive(:administration_signed_in?).and_return(false) allow(@controller).to receive(:administration_signed_in?).and_return(false)
@ -26,10 +26,10 @@ describe StatsController, type: :controller do
context "while a super admin is logged in" do context "while a super admin is logged in" do
before do before do
FactoryBot.create(:procedure, :updated_at => 6.months.ago) create(:procedure, updated_at: 6.months.ago)
FactoryBot.create(:procedure, :updated_at => 45.days.ago) create(:procedure, updated_at: 45.days.ago)
FactoryBot.create(:procedure, :updated_at => 1.day.ago) create(:procedure, updated_at: 1.day.ago)
FactoryBot.create(:procedure, :updated_at => 1.day.ago) create(:procedure, updated_at: 1.day.ago)
@controller = StatsController.new @controller = StatsController.new
@ -52,11 +52,11 @@ describe StatsController, type: :controller do
describe '#cumulative_hash' do describe '#cumulative_hash' do
before do before do
Timecop.freeze(Time.zone.local(2016, 10, 2)) Timecop.freeze(Time.zone.local(2016, 10, 2))
FactoryBot.create(:procedure, :created_at => 55.days.ago, :updated_at => 43.days.ago) create(:procedure, created_at: 55.days.ago, updated_at: 43.days.ago)
FactoryBot.create(:procedure, :created_at => 45.days.ago, :updated_at => 40.days.ago) create(:procedure, created_at: 45.days.ago, updated_at: 40.days.ago)
FactoryBot.create(:procedure, :created_at => 45.days.ago, :updated_at => 20.days.ago) create(:procedure, created_at: 45.days.ago, updated_at: 20.days.ago)
FactoryBot.create(:procedure, :created_at => 15.days.ago, :updated_at => 20.days.ago) create(:procedure, created_at: 15.days.ago, updated_at: 20.days.ago)
FactoryBot.create(:procedure, :created_at => 15.days.ago, :updated_at => 1.hour.ago) create(:procedure, created_at: 15.days.ago, updated_at: 1.hour.ago)
end end
after { Timecop.return } after { Timecop.return }
@ -104,24 +104,24 @@ describe StatsController, type: :controller do
# dossier_p1_c: 5 days # dossier_p1_c: 5 days
before do before do
procedure_1 = FactoryBot.create(:procedure) procedure_1 = create(:procedure)
procedure_2 = FactoryBot.create(:procedure) procedure_2 = create(:procedure)
dossier_p1_a = FactoryBot.create(:dossier, :accepte, dossier_p1_a = create(:dossier, :accepte,
:procedure => procedure_1, procedure: procedure_1,
:en_construction_at => 2.months.ago.beginning_of_month, en_construction_at: 2.months.ago.beginning_of_month,
:processed_at => 2.months.ago.beginning_of_month + 3.days) processed_at: 2.months.ago.beginning_of_month + 3.days)
dossier_p1_b = FactoryBot.create(:dossier, :accepte, dossier_p1_b = create(:dossier, :accepte,
:procedure => procedure_1, procedure: procedure_1,
:en_construction_at => 2.months.ago.beginning_of_month, en_construction_at: 2.months.ago.beginning_of_month,
:processed_at => 2.months.ago.beginning_of_month + 1.day) processed_at: 2.months.ago.beginning_of_month + 1.day)
dossier_p1_c = FactoryBot.create(:dossier, :accepte, dossier_p1_c = create(:dossier, :accepte,
:procedure => procedure_1, procedure: procedure_1,
:en_construction_at => 1.month.ago.beginning_of_month, en_construction_at: 1.month.ago.beginning_of_month,
:processed_at => 1.month.ago.beginning_of_month + 5.days) processed_at: 1.month.ago.beginning_of_month + 5.days)
dossier_p2_a = FactoryBot.create(:dossier, :accepte, dossier_p2_a = create(:dossier, :accepte,
:procedure => procedure_2, procedure: procedure_2,
:en_construction_at => 2.months.ago.beginning_of_month, en_construction_at: 2.months.ago.beginning_of_month,
:processed_at => 2.months.ago.beginning_of_month + 4.days) processed_at: 2.months.ago.beginning_of_month + 4.days)
@expected_hash = { @expected_hash = {
(2.months.ago.beginning_of_month).to_s => 3.0, (2.months.ago.beginning_of_month).to_s => 3.0,
@ -149,28 +149,28 @@ describe StatsController, type: :controller do
# dossier_p1_c: 50 minutes # dossier_p1_c: 50 minutes
before do before do
procedure_1 = FactoryBot.create(:procedure, :with_type_de_champ, :types_de_champ_count => 24) procedure_1 = create(:procedure, :with_type_de_champ, types_de_champ_count: 24)
procedure_2 = FactoryBot.create(:procedure, :with_type_de_champ, :types_de_champ_count => 48) procedure_2 = create(:procedure, :with_type_de_champ, types_de_champ_count: 48)
dossier_p1_a = FactoryBot.create(:dossier, :accepte, dossier_p1_a = create(:dossier, :accepte,
:procedure => procedure_1, procedure: procedure_1,
:created_at => 2.months.ago.beginning_of_month, created_at: 2.months.ago.beginning_of_month,
:en_construction_at => 2.months.ago.beginning_of_month + 30.minutes, en_construction_at: 2.months.ago.beginning_of_month + 30.minutes,
:processed_at => 2.months.ago.beginning_of_month + 1.day) processed_at: 2.months.ago.beginning_of_month + 1.day)
dossier_p1_b = FactoryBot.create(:dossier, :accepte, dossier_p1_b = create(:dossier, :accepte,
:procedure => procedure_1, procedure: procedure_1,
:created_at => 2.months.ago.beginning_of_month, created_at: 2.months.ago.beginning_of_month,
:en_construction_at => 2.months.ago.beginning_of_month + 10.minutes, en_construction_at: 2.months.ago.beginning_of_month + 10.minutes,
:processed_at => 2.months.ago.beginning_of_month + 1.day) processed_at: 2.months.ago.beginning_of_month + 1.day)
dossier_p1_c = FactoryBot.create(:dossier, :accepte, dossier_p1_c = create(:dossier, :accepte,
:procedure => procedure_1, procedure: procedure_1,
:created_at => 1.month.ago.beginning_of_month, created_at: 1.month.ago.beginning_of_month,
:en_construction_at => 1.month.ago.beginning_of_month + 50.minutes, en_construction_at: 1.month.ago.beginning_of_month + 50.minutes,
:processed_at => 1.month.ago.beginning_of_month + 1.day) processed_at: 1.month.ago.beginning_of_month + 1.day)
dossier_p2_a = FactoryBot.create(:dossier, :accepte, dossier_p2_a = create(:dossier, :accepte,
:procedure => procedure_2, procedure: procedure_2,
:created_at => 2.months.ago.beginning_of_month, created_at: 2.months.ago.beginning_of_month,
:en_construction_at => 2.months.ago.beginning_of_month + 80.minutes, en_construction_at: 2.months.ago.beginning_of_month + 80.minutes,
:processed_at => 2.months.ago.beginning_of_month + 1.day) processed_at: 2.months.ago.beginning_of_month + 1.day)
@expected_hash = { @expected_hash = {
(2.months.ago.beginning_of_month).to_s => 30.0, (2.months.ago.beginning_of_month).to_s => 30.0,

View file

@ -161,23 +161,20 @@ FactoryBot.define do
existing_type_de_champ_text = types_de_champ.find { |tdc| tdc.libelle == 'Nom' } existing_type_de_champ_text = types_de_champ.find { |tdc| tdc.libelle == 'Nom' }
type_de_champ_text = existing_type_de_champ_text || build( type_de_champ_text = existing_type_de_champ_text || build(
:type_de_champ_text, :type_de_champ_text,
order_place: 0, position: 0,
procedure: champ_repetition.dossier.procedure,
parent: champ_repetition.type_de_champ, parent: champ_repetition.type_de_champ,
libelle: 'Nom' libelle: 'Nom'
) )
types_de_champ << type_de_champ_text
existing_type_de_champ_number = types_de_champ.find { |tdc| tdc.libelle == 'Age' } existing_type_de_champ_number = types_de_champ.find { |tdc| tdc.libelle == 'Age' }
type_de_champ_number = existing_type_de_champ_number || build( type_de_champ_number = existing_type_de_champ_number || build(
:type_de_champ_number, :type_de_champ_number,
order_place: 1, position: 1,
procedure: champ_repetition.dossier.procedure,
parent: champ_repetition.type_de_champ, parent: champ_repetition.type_de_champ,
libelle: 'Age' libelle: 'Age'
) )
types_de_champ << type_de_champ_number
champ_repetition.type_de_champ.types_de_champ << [type_de_champ_text, type_de_champ_number]
champ_repetition.champs << [ champ_repetition.champs << [
build(:champ_text, dossier: champ_repetition.dossier, row: 0, type_de_champ: type_de_champ_text, parent: champ_repetition), build(:champ_text, dossier: champ_repetition.dossier, row: 0, type_de_champ: type_de_champ_text, parent: champ_repetition),
build(:champ_number, dossier: champ_repetition.dossier, row: 0, type_de_champ: type_de_champ_number, parent: champ_repetition), build(:champ_number, dossier: champ_repetition.dossier, row: 0, type_de_champ: type_de_champ_number, parent: champ_repetition),
@ -198,13 +195,11 @@ FactoryBot.define do
after(:build) do |champ_repetition, _evaluator| after(:build) do |champ_repetition, _evaluator|
type_de_champ_pj0 = build(:type_de_champ_piece_justificative, type_de_champ_pj0 = build(:type_de_champ_piece_justificative,
procedure: champ_repetition.dossier.procedure, position: 0,
order_place: 0,
parent: champ_repetition.type_de_champ, parent: champ_repetition.type_de_champ,
libelle: 'Justificatif de domicile') libelle: 'Justificatif de domicile')
type_de_champ_pj1 = build(:type_de_champ_piece_justificative, type_de_champ_pj1 = build(:type_de_champ_piece_justificative,
procedure: champ_repetition.dossier.procedure, position: 1,
order_place: 1,
parent: champ_repetition.type_de_champ, parent: champ_repetition.type_de_champ,
libelle: 'Carte d\'identité') libelle: 'Carte d\'identité')

View file

@ -15,6 +15,8 @@ FactoryBot.define do
procedure = create(:procedure, :published, :with_type_de_champ, :with_type_de_champ_private) procedure = create(:procedure, :published, :with_type_de_champ, :with_type_de_champ_private)
end end
dossier.revision = procedure.active_revision
# Assign the procedure to the dossier through the groupe_instructeur # Assign the procedure to the dossier through the groupe_instructeur
if dossier.groupe_instructeur.nil? if dossier.groupe_instructeur.nil?
dossier.groupe_instructeur = procedure.defaut_groupe_instructeur dossier.groupe_instructeur = procedure.defaut_groupe_instructeur
@ -71,7 +73,7 @@ FactoryBot.define do
linked_dossier = create(:dossier, :en_construction) linked_dossier = create(:dossier, :en_construction)
# find first type de champ dossier_link # find first type de champ dossier_link
type_de_champ = dossier.procedure.types_de_champ.find do |t| type_de_champ = dossier.types_de_champ.find do |t|
t.type_champ == TypeDeChamp.type_champs.fetch(:dossier_link) t.type_champ == TypeDeChamp.type_champs.fetch(:dossier_link)
end end
@ -202,7 +204,7 @@ FactoryBot.define do
trait :with_all_champs do trait :with_all_champs do
after(:create) do |dossier, _evaluator| after(:create) do |dossier, _evaluator|
dossier.champs = dossier.procedure.types_de_champ.map do |type_de_champ| dossier.champs = dossier.types_de_champ.map do |type_de_champ|
build(:"champ_#{type_de_champ.type_champ}", dossier: dossier, type_de_champ: type_de_champ) build(:"champ_#{type_de_champ.type_champ}", dossier: dossier, type_de_champ: type_de_champ)
end end
dossier.save! dossier.save!
@ -211,7 +213,7 @@ FactoryBot.define do
trait :with_all_annotations do trait :with_all_annotations do
after(:create) do |dossier, _evaluator| after(:create) do |dossier, _evaluator|
dossier.champs = dossier.procedure.types_de_champ.map do |type_de_champ| dossier.champs = dossier.types_de_champ.map do |type_de_champ|
build(:"champ_#{type_de_champ.type_champ}", dossier: dossier, type_de_champ: type_de_champ) build(:"champ_#{type_de_champ.type_champ}", dossier: dossier, type_de_champ: type_de_champ)
end end
dossier.save! dossier.save!

View file

@ -16,6 +16,9 @@ FactoryBot.define do
transient do transient do
administrateur { } administrateur { }
instructeurs { [] } instructeurs { [] }
types_de_champ { [] }
types_de_champ_private { [] }
updated_at { nil }
end end
after(:build) do |procedure, evaluator| after(:build) do |procedure, evaluator|
@ -24,10 +27,35 @@ FactoryBot.define do
elsif procedure.administrateurs.empty? elsif procedure.administrateurs.empty?
procedure.administrateurs = [create(:administrateur)] procedure.administrateurs = [create(:administrateur)]
end end
procedure.draft_revision = build(:procedure_revision, procedure: procedure)
evaluator.types_de_champ.each do |type_de_champ|
type_de_champ.revision = procedure.draft_revision
type_de_champ.private = false
type_de_champ.revision.revision_types_de_champ << build(:procedure_revision_type_de_champ,
revision: procedure.draft_revision,
position: type_de_champ.order_place,
type_de_champ: type_de_champ)
end
evaluator.types_de_champ_private.each do |type_de_champ|
type_de_champ.revision = procedure.draft_revision
type_de_champ.private = true
type_de_champ.revision.revision_types_de_champ_private << build(:procedure_revision_type_de_champ,
revision: procedure.draft_revision,
position: type_de_champ.order_place,
type_de_champ: type_de_champ)
end
end end
after(:create) do |procedure, evaluator| after(:create) do |procedure, evaluator|
evaluator.instructeurs.each { |i| i.assign_to_procedure(procedure) } evaluator.instructeurs.each { |i| i.assign_to_procedure(procedure) }
if evaluator.updated_at
procedure.update_column(:updated_at, evaluator.updated_at)
end
procedure.reload
end end
factory :procedure_with_dossiers do factory :procedure_with_dossiers do
@ -38,9 +66,7 @@ FactoryBot.define do
after(:create) do |procedure, evaluator| after(:create) do |procedure, evaluator|
user = create(:user) user = create(:user)
evaluator.dossiers_count.times do evaluator.dossiers_count.times do
dossier = procedure.new_dossier create(:dossier, procedure: procedure, user: user)
dossier.user = user
dossier.save!
end end
end end
end end
@ -48,7 +74,7 @@ FactoryBot.define do
factory :simple_procedure do factory :simple_procedure do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
procedure.for_individual = true procedure.for_individual = true
procedure.types_de_champ << build(:type_de_champ, libelle: 'Texte obligatoire', mandatory: true) build(:type_de_champ, libelle: 'Texte obligatoire', mandatory: true, procedure: procedure)
procedure.path = generate(:published_path) procedure.path = generate(:published_path)
procedure.publish! procedure.publish!
end end
@ -96,10 +122,8 @@ FactoryBot.define do
end end
after(:build) do |procedure, evaluator| after(:build) do |procedure, evaluator|
evaluator.types_de_champ_count.times do evaluator.types_de_champ_count.times do |position|
type_de_champ = build(:type_de_champ) build(:type_de_champ, procedure: procedure, position: position)
procedure.types_de_champ << type_de_champ
end end
end end
end end
@ -110,68 +134,51 @@ FactoryBot.define do
end end
after(:build) do |procedure, evaluator| after(:build) do |procedure, evaluator|
evaluator.types_de_champ_private_count.times do evaluator.types_de_champ_private_count.times do |position|
type_de_champ = build(:type_de_champ, :private) build(:type_de_champ, :private, procedure: procedure, position: position)
procedure.types_de_champ_private << type_de_champ
end end
end end
end end
trait :with_type_de_champ_mandatory do trait :with_type_de_champ_mandatory do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
type_de_champ = build(:type_de_champ, mandatory: true) build(:type_de_champ, mandatory: true, procedure: procedure)
procedure.types_de_champ << type_de_champ
end end
end end
trait :with_datetime do trait :with_datetime do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
type_de_champ = build(:type_de_champ_datetime, mandatory: true) build(:type_de_champ_datetime, mandatory: true, procedure: procedure)
procedure.types_de_champ << type_de_champ
end end
end end
trait :with_dossier_link do trait :with_dossier_link do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
type_de_champ = build(:type_de_champ_dossier_link) build(:type_de_champ_dossier_link, procedure: procedure)
procedure.types_de_champ << type_de_champ
end end
end end
trait :with_yes_no do trait :with_yes_no do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
type_de_champ = build(:type_de_champ_yes_no) build(:type_de_champ_yes_no, procedure: procedure)
procedure.types_de_champ << type_de_champ
end end
end end
trait :with_piece_justificative do trait :with_piece_justificative do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
type_de_champ = build(:type_de_champ_piece_justificative) build(:type_de_champ_piece_justificative, procedure: procedure)
procedure.types_de_champ << type_de_champ
end end
end end
trait :with_repetition do trait :with_repetition do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
type_de_champ = build(:type_de_champ_repetition) build(:type_de_champ_repetition, :with_types_de_champ, procedure: procedure)
procedure.types_de_champ << type_de_champ
type_de_champ.types_de_champ << build(:type_de_champ, libelle: 'sub type de champ')
end end
end end
trait :with_number do trait :with_number do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
type_de_champ = build(:type_de_champ_number) build(:type_de_champ_number, procedure: procedure)
procedure.types_de_champ << type_de_champ
end end
end end
@ -228,35 +235,35 @@ FactoryBot.define do
trait :with_all_champs_mandatory do trait :with_all_champs_mandatory do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
procedure.types_de_champ = TypeDeChamp.type_champs.map.with_index do |(libelle, type_champ), index| TypeDeChamp.type_champs.map.with_index do |(libelle, type_champ), index|
if libelle == 'drop_down_list' if libelle == 'drop_down_list'
libelle = 'simple_drop_down_list' libelle = 'simple_drop_down_list'
end end
build(:"type_de_champ_#{type_champ}", procedure: procedure, mandatory: true, libelle: libelle, order_place: index) build(:"type_de_champ_#{type_champ}", procedure: procedure, mandatory: true, libelle: libelle, position: index)
end end
procedure.types_de_champ << build(:type_de_champ_drop_down_list, :long, procedure: procedure, mandatory: true, libelle: 'simple_choice_drop_down_list_long') build(:type_de_champ_drop_down_list, :long, procedure: procedure, mandatory: true, libelle: 'simple_choice_drop_down_list_long', position: TypeDeChamp.type_champs.size)
procedure.types_de_champ << build(:type_de_champ_multiple_drop_down_list, :long, procedure: procedure, mandatory: true, libelle: 'multiple_choice_drop_down_list_long') build(:type_de_champ_multiple_drop_down_list, :long, procedure: procedure, mandatory: true, libelle: 'multiple_choice_drop_down_list_long', position: TypeDeChamp.type_champs.size + 1)
end end
end end
trait :with_all_champs do trait :with_all_champs do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
procedure.types_de_champ = TypeDeChamp.type_champs.map.with_index do |(libelle, type_champ), index| TypeDeChamp.type_champs.map.with_index do |(libelle, type_champ), index|
if libelle == 'drop_down_list' if libelle == 'drop_down_list'
libelle = 'simple_drop_down_list' libelle = 'simple_drop_down_list'
end end
build(:"type_de_champ_#{type_champ}", procedure: procedure, libelle: libelle, order_place: index) build(:"type_de_champ_#{type_champ}", procedure: procedure, libelle: libelle, position: index)
end end
end end
end end
trait :with_all_annotations do trait :with_all_annotations do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
procedure.types_de_champ_private = TypeDeChamp.type_champs.map.with_index do |(libelle, type_champ), index| TypeDeChamp.type_champs.map.with_index do |(libelle, type_champ), index|
if libelle == 'drop_down_list' if libelle == 'drop_down_list'
libelle = 'simple_drop_down_list' libelle = 'simple_drop_down_list'
end end
build(:"type_de_champ_#{type_champ}", procedure: procedure, private: true, libelle: libelle, order_place: index) build(:"type_de_champ_#{type_champ}", procedure: procedure, private: true, libelle: libelle, position: index)
end end
end end
end end

View file

@ -0,0 +1,4 @@
FactoryBot.define do
factory :procedure_revision do
end
end

View file

@ -0,0 +1,4 @@
FactoryBot.define do
factory :procedure_revision_type_de_champ do
end
end

View file

@ -7,7 +7,40 @@ FactoryBot.define do
mandatory { false } mandatory { false }
add_attribute(:private) { false } add_attribute(:private) { false }
association :procedure transient do
procedure { nil }
position { nil }
parent { nil }
end
after(:build) do |type_de_champ, evaluator|
if evaluator.procedure
type_de_champ.revision = evaluator.procedure.active_revision
build(:procedure_revision_type_de_champ,
position: evaluator.position,
revision: evaluator.procedure.active_revision,
type_de_champ: type_de_champ)
if type_de_champ.private?
type_de_champ.revision.types_de_champ_private << type_de_champ
else
type_de_champ.revision.types_de_champ << type_de_champ
end
elsif evaluator.parent
type_de_champ.revision = evaluator.parent.revision
type_de_champ.order_place = evaluator.position || evaluator.parent.types_de_champ.size
evaluator.parent.types_de_champ << type_de_champ
else
type_de_champ.order_place = evaluator.position
end
end
trait :private do
add_attribute(:private) { true }
sequence(:libelle) { |n| "Libelle champ privé #{n}" }
sequence(:description) { |n| "description du champ privé #{n}" }
end
factory :type_de_champ_text do factory :type_de_champ_text do
type_champ { TypeDeChamp.type_champs.fetch(:text) } type_champ { TypeDeChamp.type_champs.fetch(:text) }
@ -96,8 +129,8 @@ FactoryBot.define do
factory :type_de_champ_piece_justificative do factory :type_de_champ_piece_justificative do
type_champ { TypeDeChamp.type_champs.fetch(:piece_justificative) } type_champ { TypeDeChamp.type_champs.fetch(:piece_justificative) }
after(:build) do |tc, _evaluator| after(:build) do |type_de_champ, _evaluator|
tc.piece_justificative_template.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain") type_de_champ.piece_justificative_template.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain")
end end
end end
factory :type_de_champ_siret do factory :type_de_champ_siret do
@ -109,17 +142,23 @@ FactoryBot.define do
factory :type_de_champ_repetition do factory :type_de_champ_repetition do
type_champ { TypeDeChamp.type_champs.fetch(:repetition) } type_champ { TypeDeChamp.type_champs.fetch(:repetition) }
trait :with_types_de_champ do transient do
after(:build) do |type_de_champ, _evaluator| types_de_champ { [] }
type_de_champ.types_de_champ << build(:type_de_champ, procedure: type_de_champ.procedure, libelle: 'sub type de champ')
end end
after(:build) do |type_de_champ_repetition, evaluator|
evaluator.types_de_champ.each do |type_de_champ|
type_de_champ.revision = type_de_champ_repetition.revision
type_de_champ.order_place = type_de_champ_repetition.types_de_champ.size
type_de_champ_repetition.types_de_champ << type_de_champ
end end
end end
trait :private do trait :with_types_de_champ do
add_attribute(:private) { true } after(:build) do |type_de_champ, _evaluator|
sequence(:libelle) { |n| "Libelle champ privé #{n}" } build(:type_de_champ, libelle: 'sub type de champ', parent: type_de_champ)
sequence(:description) { |n| "description du champ privé #{n}" } end
end
end end
end end
end end

View file

@ -6,11 +6,11 @@ feature 'As an administrateur I wanna clone a procedure', js: true do
let(:administrateur) { create(:administrateur) } let(:administrateur) { create(:administrateur) }
before do before do
create :procedure, :with_service, :with_instructeur, create(:procedure, :with_service, :with_instructeur,
aasm_state: :publiee, published_at: Time.zone.now, aasm_state: :publiee,
administrateurs: [administrateur], administrateurs: [administrateur],
libelle: 'libellé de la procédure', libelle: 'libellé de la procédure',
path: 'libelle-de-la-procedure' path: 'libelle-de-la-procedure')
login_as administrateur.user, scope: :user login_as administrateur.user, scope: :user
end end

View file

@ -91,7 +91,7 @@ feature 'Instructing a dossier:' do
end end
scenario 'A instructeur can see the personnes impliquées' do scenario 'A instructeur can see the personnes impliquées' do
instructeur2 = FactoryBot.create(:instructeur, password: password) instructeur2 = create(:instructeur, password: password)
log_in(instructeur.email, password) log_in(instructeur.email, password)
@ -113,8 +113,8 @@ feature 'Instructing a dossier:' do
end end
scenario 'A instructeur can send a dossier to several instructeurs', js: true do scenario 'A instructeur can send a dossier to several instructeurs', js: true do
instructeur_2 = FactoryBot.create(:instructeur) instructeur_2 = create(:instructeur)
instructeur_3 = FactoryBot.create(:instructeur) instructeur_3 = create(:instructeur)
procedure.defaut_groupe_instructeur.instructeurs << [instructeur_2, instructeur_3] procedure.defaut_groupe_instructeur.instructeurs << [instructeur_2, instructeur_3]
send_dossier = double() send_dossier = double()

View file

@ -122,7 +122,7 @@ feature 'As an administrateur I can edit types de champ', js: true do
fill_in 'champ-0-libelle', with: 'Libellé de champ carte', fill_options: { clear: :backspace } fill_in 'champ-0-libelle', with: 'Libellé de champ carte', fill_options: { clear: :backspace }
check 'Cadastres' check 'Cadastres'
wait_until { procedure.types_de_champ.first.cadastres == true } wait_until { procedure.draft_types_de_champ.first.cadastres == true }
expect(page).to have_content('Formulaire enregistré') expect(page).to have_content('Formulaire enregistré')
preview_window = window_opened_by { click_on 'Prévisualiser le formulaire' } preview_window = window_opened_by { click_on 'Prévisualiser le formulaire' }
@ -139,7 +139,7 @@ feature 'As an administrateur I can edit types de champ', js: true do
fill_in 'champ-0-libelle', with: 'Libellé de champ menu déroulant', fill_options: { clear: :backspace } fill_in 'champ-0-libelle', with: 'Libellé de champ menu déroulant', fill_options: { clear: :backspace }
fill_in 'champ-0-drop_down_list_value', with: 'Un menu', fill_options: { clear: :backspace } fill_in 'champ-0-drop_down_list_value', with: 'Un menu', fill_options: { clear: :backspace }
wait_until { procedure.types_de_champ.first.drop_down_list_options == ['', 'Un menu'] } wait_until { procedure.draft_types_de_champ.first.drop_down_list_options == ['', 'Un menu'] }
expect(page).to have_content('Formulaire enregistré') expect(page).to have_content('Formulaire enregistré')
page.refresh page.refresh

View file

@ -97,9 +97,7 @@ feature 'The user' do
end end
let(:procedure_with_repetition) do let(:procedure_with_repetition) do
tdc = create(:type_de_champ_repetition, libelle: 'repetition') create(:procedure, :published, :for_individual, :with_repetition)
tdc.types_de_champ << create(:type_de_champ_text, libelle: 'text')
create(:procedure, :published, :for_individual, types_de_champ: [tdc])
end end
scenario 'fill a dossier with repetition', js: true do scenario 'fill a dossier with repetition', js: true do
@ -107,13 +105,13 @@ feature 'The user' do
fill_individual fill_individual
fill_in('text', with: 'super texte') fill_in('sub type de champ', with: 'super texte')
expect(page).to have_field('text', with: 'super texte') expect(page).to have_field('sub type de champ', with: 'super texte')
click_on 'Ajouter un élément pour' click_on 'Ajouter un élément pour'
within '.row-1' do within '.row-1' do
fill_in('text', with: 'un autre texte') fill_in('sub type de champ', with: 'un autre texte')
end end
expect(page).to have_content('Supprimer', count: 2) expect(page).to have_content('Supprimer', count: 2)
@ -132,7 +130,7 @@ feature 'The user' do
end end
let(:simple_procedure) do let(:simple_procedure) do
tdcs = [create(:type_de_champ, mandatory: true, libelle: 'texte obligatoire')] tdcs = [build(:type_de_champ, mandatory: true, libelle: 'texte obligatoire')]
create(:procedure, :published, :for_individual, types_de_champ: tdcs) create(:procedure, :published, :for_individual, types_de_champ: tdcs)
end end
@ -161,14 +159,14 @@ feature 'The user' do
end end
let(:procedure_with_pj) do let(:procedure_with_pj) do
tdcs = [create(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative')] tdcs = [build(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative')]
create(:procedure, :published, :for_individual, types_de_champ: tdcs) create(:procedure, :published, :for_individual, types_de_champ: tdcs)
end end
let(:procedure_with_pjs) do let(:procedure_with_pjs) do
tdcs = [ tdcs = [
create(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative 1', order_place: 1), build(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative 1', position: 1),
create(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative 2', order_place: 2) build(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative 2', position: 2)
] ]
create(:procedure, :published, :for_individual, types_de_champ: tdcs) create(:procedure, :published, :for_individual, types_de_champ: tdcs)
end end

View file

@ -13,12 +13,10 @@ feature 'linked dropdown lists' do
Secondary 2.3 Secondary 2.3
END_OF_LIST END_OF_LIST
end end
let(:type_de_champ) { create(:type_de_champ_linked_drop_down_list, libelle: 'linked dropdown', drop_down_list_value: list_items) } let(:type_de_champ) { build(:type_de_champ_linked_drop_down_list, libelle: 'linked dropdown', drop_down_list_value: list_items) }
let!(:procedure) do let!(:procedure) do
p = create(:procedure, :published, :for_individual) create(:procedure, :published, :for_individual, types_de_champ: [type_de_champ])
p.types_de_champ << type_de_champ
p
end end
let(:user_dossier) { user.dossiers.first } let(:user_dossier) { user.dossiers.first }

View file

@ -1,23 +1,24 @@
RSpec.describe FindDubiousProceduresJob, type: :job do RSpec.describe FindDubiousProceduresJob, type: :job do
describe 'perform' do describe 'perform' do
let(:mailer_double) { double('mailer', deliver_later: true) } let(:mailer_double) { double('mailer', deliver_later: true) }
let(:procedure) { create(:procedure) } let(:procedure) { create(:procedure, types_de_champ: tdcs) }
let(:allowed_tdc) { create(:type_de_champ, libelle: 'fournir') } let(:allowed_tdc) { build(:type_de_champ, libelle: 'fournir') }
before do before do
procedure
allow(AdministrationMailer).to receive(:dubious_procedures) do |arg| allow(AdministrationMailer).to receive(:dubious_procedures) do |arg|
@dubious_procedures_args = arg @dubious_procedures_args = arg
end.and_return(mailer_double) end.and_return(mailer_double)
procedure.types_de_champ << tdcs
FindDubiousProceduresJob.new.perform FindDubiousProceduresJob.new.perform
end end
context 'with suspicious champs' do context 'with suspicious champs' do
let(:forbidden_tdcs) do let(:forbidden_tdcs) do
[ [
create(:type_de_champ, libelle: 'num de securite sociale, stp'), build(:type_de_champ, libelle: 'num de securite sociale, stp'),
create(:type_de_champ, libelle: "t'aurais une carte bancaire ?") build(:type_de_champ, libelle: "t'aurais une carte bancaire ?")
] ]
end end

View file

@ -1,24 +0,0 @@
RSpec.describe TmpDossiersMigrateRevisionsJob, type: :job do
let(:procedure) { create(:procedure, :published) }
let!(:dossier1) { create(:dossier, procedure: procedure, updated_at: 1.day.ago) }
let!(:dossier2) { create(:dossier, procedure: procedure, updated_at: 2.days.ago) }
context "add revision to dossiers" do
before do
RevisionsMigration.add_revisions(procedure)
end
it {
expect(dossier1.revision).to be_nil
expect(dossier2.revision).to be_nil
TmpDossiersMigrateRevisionsJob.new.perform([])
[dossier1, dossier2].each(&:reload)
expect(dossier1.revision).to eq procedure.active_revision
expect(dossier2.revision).to eq procedure.active_revision
expect(dossier1.updated_at < 1.day.ago).to be_truthy
expect(dossier2.updated_at < 1.day.ago).to be_truthy
}
end
end

View file

@ -427,10 +427,9 @@ describe Champ do
end end
describe 'repetition' do describe 'repetition' do
let(:procedure) { build(:procedure, :published, :with_type_de_champ, :with_type_de_champ_private) } let(:procedure) { create(:procedure, :published, :with_type_de_champ, :with_type_de_champ_private, types_de_champ: [build(:type_de_champ_repetition, types_de_champ: [tdc_text, tdc_integer])]) }
let(:tdc_text) { build(:type_de_champ_text, procedure: procedure) } let(:tdc_text) { build(:type_de_champ_text) }
let(:tdc_integer) { build(:type_de_champ_integer_number, procedure: procedure) } let(:tdc_integer) { build(:type_de_champ_integer_number) }
let(:tdc_repetition) { build(:type_de_champ_repetition, procedure: procedure, types_de_champ: [tdc_text, tdc_integer]) }
let(:dossier) { create(:dossier, procedure: procedure) } let(:dossier) { create(:dossier, procedure: procedure) }
let(:champ) { dossier.champs.find(&:repetition?) } let(:champ) { dossier.champs.find(&:repetition?) }
@ -438,12 +437,6 @@ describe Champ do
let(:champ_integer) { champ.champs.find { |c| c.type_champ == 'integer_number' } } let(:champ_integer) { champ.champs.find { |c| c.type_champ == 'integer_number' } }
let(:champ_text_attrs) { attributes_for(:champ_text, type_de_champ: tdc_text, row: 1) } let(:champ_text_attrs) { attributes_for(:champ_text, type_de_champ: tdc_text, row: 1) }
before do
procedure.types_de_champ << tdc_repetition
procedure.save!
procedure.reload
end
context 'when creating the model directly' do context 'when creating the model directly' do
let(:champ_text_row_1) { create(:champ_text, type_de_champ: tdc_text, row: 2, parent: champ, dossier: nil) } let(:champ_text_row_1) { create(:champ_text, type_de_champ: tdc_text, row: 2, parent: champ, dossier: nil) }

View file

@ -2,11 +2,11 @@ describe Champs::HeaderSectionChamp do
describe '#section_index' do describe '#section_index' do
let(:types_de_champ) do let(:types_de_champ) do
[ [
create(:type_de_champ_header_section, order_place: 1), build(:type_de_champ_header_section, position: 1),
create(:type_de_champ_civilite, order_place: 2), build(:type_de_champ_civilite, position: 2),
create(:type_de_champ_text, order_place: 3), build(:type_de_champ_text, position: 3),
create(:type_de_champ_header_section, order_place: 4), build(:type_de_champ_header_section, position: 4),
create(:type_de_champ_email, order_place: 5) build(:type_de_champ_email, position: 5)
] ]
end end
@ -23,17 +23,12 @@ describe Champs::HeaderSectionChamp do
end end
context 'for repetition champs' do context 'for repetition champs' do
let(:procedure) { create(:procedure, :with_repetition) } let(:procedure) { create(:procedure, types_de_champ: [build(:type_de_champ_repetition, types_de_champ: types_de_champ)]) }
let(:dossier) { create(:dossier, procedure: procedure) } let(:dossier) { create(:dossier, procedure: procedure) }
let(:repetition_tdc) { procedure.types_de_champ.find(&:repetition?) }
let(:first_header) { dossier.champs.first.champs[0] } let(:first_header) { dossier.champs.first.champs[0] }
let(:second_header) { dossier.champs.first.champs[3] } let(:second_header) { dossier.champs.first.champs[3] }
before do
repetition_tdc.types_de_champ = types_de_champ
end
it 'returns the index of the section in the repetition (starting from 1)' do it 'returns the index of the section in the repetition (starting from 1)' do
expect(first_header.section_index).to eq 1 expect(first_header.section_index).to eq 1
expect(second_header.section_index).to eq 2 expect(second_header.section_index).to eq 2

View file

@ -97,8 +97,8 @@ describe TagsSubstitutionConcern, type: :model do
context 'when the procedure has a type de champ named libelleA et libelleB' do context 'when the procedure has a type de champ named libelleA et libelleB' do
let(:types_de_champ) do let(:types_de_champ) do
[ [
create(:type_de_champ, libelle: 'libelleA'), build(:type_de_champ, libelle: 'libelleA'),
create(:type_de_champ, libelle: 'libelleB') build(:type_de_champ, libelle: 'libelleB')
] ]
end end
@ -141,7 +141,7 @@ describe TagsSubstitutionConcern, type: :model do
context 'when the procedure has a type de champ with apostrophes' do context 'when the procedure has a type de champ with apostrophes' do
let(:types_de_champ) do let(:types_de_champ) do
[ [
create(:type_de_champ, libelle: "Intitulé de l'‘«\"évènement\"»’") build(:type_de_champ, libelle: "Intitulé de l'‘«\"évènement\"»’")
] ]
end end
@ -165,9 +165,9 @@ describe TagsSubstitutionConcern, type: :model do
let(:template) { '--Répétition--' } let(:template) { '--Répétition--' }
let(:types_de_champ) do let(:types_de_champ) do
[ [
create(:type_de_champ_repetition, libelle: 'Répétition', types_de_champ: [ build(:type_de_champ_repetition, libelle: 'Répétition', types_de_champ: [
create(:type_de_champ_text, libelle: 'Nom', order_place: 1), build(:type_de_champ_text, libelle: 'Nom', order_place: 1),
create(:type_de_champ_text, libelle: 'Prénom', order_place: 2) build(:type_de_champ_text, libelle: 'Prénom', order_place: 2)
]) ])
] ]
end end
@ -190,7 +190,7 @@ describe TagsSubstitutionConcern, type: :model do
context 'when the procedure has a linked drop down menus type de champ' do context 'when the procedure has a linked drop down menus type de champ' do
let(:type_de_champ) do let(:type_de_champ) do
create(:type_de_champ_linked_drop_down_list, libelle: 'libelle') build(:type_de_champ_linked_drop_down_list, libelle: 'libelle')
end end
let(:types_de_champ) { [type_de_champ] } let(:types_de_champ) { [type_de_champ] }
let(:template) { 'tout : --libelle--, primaire : --libelle/primaire--, secondaire : --libelle/secondaire--' } let(:template) { 'tout : --libelle--, primaire : --libelle/primaire--, secondaire : --libelle/secondaire--' }
@ -219,7 +219,7 @@ describe TagsSubstitutionConcern, type: :model do
let(:types_de_champ) do let(:types_de_champ) do
[ [
type_de_champ, type_de_champ,
create(:type_de_champ_header_section, libelle: 'libelle') build(:type_de_champ_header_section, libelle: 'libelle')
] ]
end end
@ -253,7 +253,7 @@ describe TagsSubstitutionConcern, type: :model do
end end
context 'when the procedure has a type de champ prive named libelleA' do context 'when the procedure has a type de champ prive named libelleA' do
let(:types_de_champ_private) { [create(:type_de_champ, :private, libelle: 'libelleA')] } let(:types_de_champ_private) { [build(:type_de_champ, :private, libelle: 'libelleA')] }
context 'and it is used in the template' do context 'and it is used in the template' do
let(:template) { '--libelleA--' } let(:template) { '--libelleA--' }
@ -274,13 +274,13 @@ describe TagsSubstitutionConcern, type: :model do
# The dossier just transitionned from brouillon to en construction, # The dossier just transitionned from brouillon to en construction,
# so champs private are not valid tags yet # so champs private are not valid tags yet
let(:types_de_champ_private) { [create(:type_de_champ, :private, libelle: 'libelleA')] } let(:types_de_champ_private) { [build(:type_de_champ, :private, libelle: 'libelleA')] }
it { is_expected.to eq('--libelleA--') } it { is_expected.to eq('--libelleA--') }
end end
context 'champs publics are valid tags' do context 'champs publics are valid tags' do
let(:types_de_champ) { [create(:type_de_champ, libelle: 'libelleA')] } let(:types_de_champ) { [build(:type_de_champ, libelle: 'libelleA')] }
before { dossier.champs.first.update(value: 'libelle1') } before { dossier.champs.first.update(value: 'libelle1') }
@ -291,8 +291,8 @@ describe TagsSubstitutionConcern, type: :model do
context 'when the procedure has 2 types de champ date and datetime' do context 'when the procedure has 2 types de champ date and datetime' do
let(:types_de_champ) do let(:types_de_champ) do
[ [
create(:type_de_champ_date, libelle: TypeDeChamp.type_champs.fetch(:date)), build(:type_de_champ_date, libelle: TypeDeChamp.type_champs.fetch(:date)),
create(:type_de_champ_datetime, libelle: TypeDeChamp.type_champs.fetch(:datetime)) build(:type_de_champ_datetime, libelle: TypeDeChamp.type_champs.fetch(:datetime))
] ]
end end
@ -358,13 +358,13 @@ describe TagsSubstitutionConcern, type: :model do
shared_examples "treat all kinds of space as equivalent" do shared_examples "treat all kinds of space as equivalent" do
context 'and the champ has a non breaking space' do context 'and the champ has a non breaking space' do
let(:types_de_champ) { [create(:type_de_champ, libelle: 'mon tag')] } let(:types_de_champ) { [build(:type_de_champ, libelle: 'mon tag')] }
it { is_expected.to eq('valeur') } it { is_expected.to eq('valeur') }
end end
context 'and the champ has an ordinary space' do context 'and the champ has an ordinary space' do
let(:types_de_champ) { [create(:type_de_champ, libelle: 'mon tag')] } let(:types_de_champ) { [build(:type_de_champ, libelle: 'mon tag')] }
it { is_expected.to eq('valeur') } it { is_expected.to eq('valeur') }
end end
@ -401,12 +401,12 @@ describe TagsSubstitutionConcern, type: :model do
let(:types_de_champ) do let(:types_de_champ) do
[ [
create(:type_de_champ, libelle: 'public'), build(:type_de_champ, libelle: 'public'),
create(:type_de_champ_header_section, libelle: 'entête de section'), build(:type_de_champ_header_section, libelle: 'entête de section'),
create(:type_de_champ_explication, libelle: 'explication') build(:type_de_champ_explication, libelle: 'explication')
] ]
end end
let(:types_de_champ_private) { [create(:type_de_champ, :private, libelle: 'privé')] } let(:types_de_champ_private) { [build(:type_de_champ, :private, libelle: 'privé')] }
context 'do not generate tags for champs that cannot have usager content' do context 'do not generate tags for champs that cannot have usager content' do
it { is_expected.not_to include(include({ libelle: 'entête de section' })) } it { is_expected.not_to include(include({ libelle: 'entête de section' })) }

View file

@ -29,14 +29,8 @@ describe Dossier do
end end
describe 'with_champs' do describe 'with_champs' do
let(:procedure) { create(:procedure) } let(:procedure) { create(:procedure, types_de_champ: [build(:type_de_champ, libelle: 'l1', position: 1), build(:type_de_champ, libelle: 'l3', position: 3), build(:type_de_champ, libelle: 'l2', position: 2)]) }
let(:dossier) { Dossier.create(user: create(:user), groupe_instructeur: procedure.defaut_groupe_instructeur) } let(:dossier) { create(:dossier, procedure: procedure) }
before do
create(:type_de_champ, libelle: 'l1', order_place: 1, procedure: procedure)
create(:type_de_champ, libelle: 'l3', order_place: 3, procedure: procedure)
create(:type_de_champ, libelle: 'l2', order_place: 2, procedure: procedure)
end
it do it do
expect(Dossier.with_champs.find(dossier.id).champs.map(&:libelle)).to match(['l1', 'l2', 'l3']) expect(Dossier.with_champs.find(dossier.id).champs.map(&:libelle)).to match(['l1', 'l2', 'l3'])
@ -255,27 +249,15 @@ describe Dossier do
end end
describe '#champs' do describe '#champs' do
let(:procedure) { create(:procedure) } let(:procedure) { create(:procedure, types_de_champ: [build(:type_de_champ, :private, libelle: 'l1', position: 1), build(:type_de_champ, :private, libelle: 'l3', position: 3), build(:type_de_champ, :private, libelle: 'l2', position: 2)]) }
let(:dossier) { Dossier.create(user: create(:user), groupe_instructeur: procedure.defaut_groupe_instructeur) } let(:dossier) { create(:dossier, procedure: procedure) }
before do
create(:type_de_champ, libelle: 'l1', order_place: 1, procedure: procedure)
create(:type_de_champ, libelle: 'l3', order_place: 3, procedure: procedure)
create(:type_de_champ, libelle: 'l2', order_place: 2, procedure: procedure)
end
it { expect(dossier.champs.pluck(:libelle)).to match(['l1', 'l2', 'l3']) } it { expect(dossier.champs.pluck(:libelle)).to match(['l1', 'l2', 'l3']) }
end end
describe '#champs_private' do describe '#champs_private' do
let(:procedure) { create :procedure } let(:procedure) { create(:procedure, types_de_champ_private: [build(:type_de_champ, :private, libelle: 'l1', position: 1), build(:type_de_champ, :private, libelle: 'l3', position: 3), build(:type_de_champ, :private, libelle: 'l2', position: 2)]) }
let(:dossier) { Dossier.create(user: create(:user), groupe_instructeur: procedure.defaut_groupe_instructeur) } let(:dossier) { create(:dossier, procedure: procedure) }
before do
create :type_de_champ, :private, libelle: 'l1', order_place: 1, procedure: procedure
create :type_de_champ, :private, libelle: 'l3', order_place: 3, procedure: procedure
create :type_de_champ, :private, libelle: 'l2', order_place: 2, procedure: procedure
end
it { expect(dossier.champs_private.pluck(:libelle)).to match(['l1', 'l2', 'l3']) } it { expect(dossier.champs_private.pluck(:libelle)).to match(['l1', 'l2', 'l3']) }
end end
@ -525,7 +507,7 @@ describe Dossier do
dossier = nil dossier = nil
expect do expect do
perform_enqueued_jobs do perform_enqueued_jobs do
dossier = Dossier.create(groupe_instructeur: procedure.defaut_groupe_instructeur, state: Dossier.states.fetch(:brouillon), user: user) dossier = create(:dossier, procedure: procedure, state: Dossier.states.fetch(:brouillon), user: user)
end end
end.to change(ActionMailer::Base.deliveries, :size).from(0).to(1) end.to change(ActionMailer::Base.deliveries, :size).from(0).to(1)
@ -535,17 +517,19 @@ describe Dossier do
end end
it "does not send an email when the dossier is created with a non brouillon state" do it "does not send an email when the dossier is created with a non brouillon state" do
expect { Dossier.create(groupe_instructeur: procedure.defaut_groupe_instructeur, state: Dossier.states.fetch(:en_construction), user: user) }.not_to change(ActionMailer::Base.deliveries, :size) expect { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_construction), user: user) }.not_to change(ActionMailer::Base.deliveries, :size)
expect { Dossier.create(groupe_instructeur: procedure.defaut_groupe_instructeur, state: Dossier.states.fetch(:en_instruction), user: user) }.not_to change(ActionMailer::Base.deliveries, :size) expect { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction), user: user) }.not_to change(ActionMailer::Base.deliveries, :size)
expect { Dossier.create(groupe_instructeur: procedure.defaut_groupe_instructeur, state: Dossier.states.fetch(:accepte), user: user) }.not_to change(ActionMailer::Base.deliveries, :size) expect { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:accepte), user: user) }.not_to change(ActionMailer::Base.deliveries, :size)
expect { Dossier.create(groupe_instructeur: procedure.defaut_groupe_instructeur, state: Dossier.states.fetch(:refuse), user: user) }.not_to change(ActionMailer::Base.deliveries, :size) expect { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:refuse), user: user) }.not_to change(ActionMailer::Base.deliveries, :size)
expect { Dossier.create(groupe_instructeur: procedure.defaut_groupe_instructeur, state: Dossier.states.fetch(:sans_suite), user: user) }.not_to change(ActionMailer::Base.deliveries, :size) expect { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:sans_suite), user: user) }.not_to change(ActionMailer::Base.deliveries, :size)
end end
end end
describe "#unspecified_attestation_champs" do describe "#unspecified_attestation_champs" do
let(:procedure) { create(:procedure, attestation_template: attestation_template) } let(:procedure) { create(:procedure, attestation_template: attestation_template, types_de_champ: types_de_champ, types_de_champ_private: types_de_champ_private) }
let(:dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction)) } let(:dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction)) }
let(:types_de_champ) { [] }
let(:types_de_champ_private) { [] }
subject { dossier.unspecified_attestation_champs.map(&:libelle) } subject { dossier.unspecified_attestation_champs.map(&:libelle) }
@ -574,14 +558,17 @@ describe Dossier do
context "wich is enabled" do context "wich is enabled" do
let(:activated) { true } let(:activated) { true }
let!(:tdc_1) { create(:type_de_champ, libelle: "specified champ-in-title", procedure: procedure) } let(:types_de_champ) { [tdc_1, tdc_2, tdc_3, tdc_4] }
let!(:tdc_2) { create(:type_de_champ, libelle: "unspecified champ-in-title", procedure: procedure) } let(:types_de_champ_private) { [tdc_5, tdc_6, tdc_7, tdc_8] }
let!(:tdc_3) { create(:type_de_champ, libelle: "specified champ-in-body", procedure: procedure) }
let!(:tdc_4) { create(:type_de_champ, libelle: "unspecified champ-in-body", procedure: procedure) } let(:tdc_1) { build(:type_de_champ, libelle: "specified champ-in-title") }
let!(:tdc_5) { create(:type_de_champ, private: true, libelle: "specified annotation privée-in-title", procedure: procedure) } let(:tdc_2) { build(:type_de_champ, libelle: "unspecified champ-in-title") }
let!(:tdc_6) { create(:type_de_champ, private: true, libelle: "unspecified annotation privée-in-title", procedure: procedure) } let(:tdc_3) { build(:type_de_champ, libelle: "specified champ-in-body") }
let!(:tdc_7) { create(:type_de_champ, private: true, libelle: "specified annotation privée-in-body", procedure: procedure) } let(:tdc_4) { build(:type_de_champ, libelle: "unspecified champ-in-body") }
let!(:tdc_8) { create(:type_de_champ, private: true, libelle: "unspecified annotation privée-in-body", procedure: procedure) } let(:tdc_5) { build(:type_de_champ, private: true, libelle: "specified annotation privée-in-title") }
let(:tdc_6) { build(:type_de_champ, private: true, libelle: "unspecified annotation privée-in-title") }
let(:tdc_7) { build(:type_de_champ, private: true, libelle: "specified annotation privée-in-body") }
let(:tdc_8) { build(:type_de_champ, private: true, libelle: "unspecified annotation privée-in-body") }
before do before do
(dossier.champs + dossier.champs_private) (dossier.champs + dossier.champs_private)
@ -1014,7 +1001,7 @@ describe Dossier do
end end
context "with mandatory SIRET champ" do context "with mandatory SIRET champ" do
let(:type_de_champ) { create(:type_de_champ_siret, mandatory: true) } let(:type_de_champ) { create(:type_de_champ_siret, mandatory: true, procedure: procedure) }
let(:champ_siret) { create(:champ_siret, type_de_champ: type_de_champ) } let(:champ_siret) { create(:champ_siret, type_de_champ: type_de_champ) }
before do before do
@ -1041,12 +1028,11 @@ describe Dossier do
end end
context "with champ repetition" do context "with champ repetition" do
let(:procedure) { create(:procedure) } let(:procedure) { create(:procedure, types_de_champ: [type_de_champ_repetition]) }
let(:type_de_champ_repetition) { create(:type_de_champ_repetition, mandatory: true) } let(:type_de_champ_repetition) { build(:type_de_champ_repetition, mandatory: true) }
before do before do
procedure.types_de_champ << type_de_champ_repetition create(:type_de_champ_text, mandatory: true, parent: type_de_champ_repetition)
type_de_champ_repetition.types_de_champ << create(:type_de_champ_text, mandatory: true)
end end
context "when no champs" do context "when no champs" do
@ -1261,9 +1247,14 @@ describe Dossier do
end end
describe "to_feature_collection" do describe "to_feature_collection" do
let(:dossier) { create(:dossier) }
let(:type_de_champ_carte) { create(:type_de_champ_carte, procedure: dossier.procedure) }
let(:geo_area) { create(:geo_area, :selection_utilisateur, :polygon) } let(:geo_area) { create(:geo_area, :selection_utilisateur, :polygon) }
let(:champ) { create(:champ_carte, geo_areas: [geo_area]) } let(:champ_carte) { create(:champ_carte, type_de_champ: type_de_champ_carte, geo_areas: [geo_area]) }
let(:dossier) { create(:dossier, champs: [champ]) }
before do
dossier.champs << champ_carte
end
it 'should have all champs carto' do it 'should have all champs carto' do
expect(dossier.to_feature_collection).to eq({ expect(dossier.to_feature_collection).to eq({
@ -1279,7 +1270,7 @@ describe Dossier do
}, },
properties: { properties: {
area: 219.0, area: 219.0,
champ_id: champ.stable_id, champ_id: champ_carte.stable_id,
dossier_id: dossier.id, dossier_id: dossier.id,
id: geo_area.id, id: geo_area.id,
source: 'selection_utilisateur' source: 'selection_utilisateur'

View file

@ -50,7 +50,7 @@ describe ProcedurePresentation do
describe "#fields" do describe "#fields" do
context 'when the procedure can have a SIRET number' do context 'when the procedure can have a SIRET number' do
let(:procedure) { create(:procedure, :with_type_de_champ, :with_type_de_champ_private, :types_de_champ_count => 4, :types_de_champ_private_count => 4) } let(:procedure) { create(:procedure, :with_type_de_champ, :with_type_de_champ_private, types_de_champ_count: 4, types_de_champ_private_count: 4) }
let(:tdc_1) { procedure.types_de_champ[0] } let(:tdc_1) { procedure.types_de_champ[0] }
let(:tdc_2) { procedure.types_de_champ[1] } let(:tdc_2) { procedure.types_de_champ[1] }
let(:tdc_private_1) { procedure.types_de_champ_private[0] } let(:tdc_private_1) { procedure.types_de_champ_private[0] }

View file

@ -9,10 +9,6 @@ describe ProcedureRevision do
type_de_champ type_de_champ
end end
before do
RevisionsMigration.add_revisions(procedure)
end
describe '#add_type_de_champ' do describe '#add_type_de_champ' do
it 'type_de_champ' do it 'type_de_champ' do
expect(revision.types_de_champ.size).to eq(2) expect(revision.types_de_champ.size).to eq(2)
@ -20,11 +16,8 @@ describe ProcedureRevision do
type_champ: TypeDeChamp.type_champs.fetch(:text), type_champ: TypeDeChamp.type_champs.fetch(:text),
libelle: "Un champ text" libelle: "Un champ text"
}) })
procedure.reload revision.reload
expect(revision.types_de_champ.size).to eq(3) expect(revision.types_de_champ.size).to eq(3)
expect(procedure.types_de_champ.size).to eq(3)
expect(procedure.types_de_champ.last).to eq(new_type_de_champ)
expect(revision.types_de_champ.last).to eq(new_type_de_champ) expect(revision.types_de_champ.last).to eq(new_type_de_champ)
expect(revision.revision_types_de_champ.last.position).to eq(2) expect(revision.revision_types_de_champ.last.position).to eq(2)
expect(revision.revision_types_de_champ.last.type_de_champ).to eq(new_type_de_champ) expect(revision.revision_types_de_champ.last.type_de_champ).to eq(new_type_de_champ)
@ -37,9 +30,8 @@ describe ProcedureRevision do
libelle: "Un champ text", libelle: "Un champ text",
private: true private: true
}) })
procedure.reload revision.reload
expect(revision.types_de_champ_private.size).to eq(2) expect(revision.types_de_champ_private.size).to eq(2)
expect(procedure.types_de_champ_private.size).to eq(2)
end end
it 'type_de_champ_repetition' do it 'type_de_champ_repetition' do
@ -49,7 +41,6 @@ describe ProcedureRevision do
libelle: "Un champ text", libelle: "Un champ text",
parent_id: type_de_champ_repetition.stable_id parent_id: type_de_champ_repetition.stable_id
}) })
type_de_champ_repetition.reload
expect(type_de_champ_repetition.types_de_champ.size).to eq(2) expect(type_de_champ_repetition.types_de_champ.size).to eq(2)
end end
end end
@ -113,26 +104,21 @@ describe ProcedureRevision do
revision.remove_type_de_champ(type_de_champ.stable_id) revision.remove_type_de_champ(type_de_champ.stable_id)
procedure.reload procedure.reload
expect(revision.types_de_champ.size).to eq(1) expect(revision.types_de_champ.size).to eq(1)
expect(procedure.types_de_champ.size).to eq(1)
end end
it 'type_de_champ_private' do it 'type_de_champ_private' do
expect(revision.types_de_champ_private.size).to eq(1) expect(revision.types_de_champ_private.size).to eq(1)
revision.remove_type_de_champ(type_de_champ_private.stable_id) revision.remove_type_de_champ(type_de_champ_private.stable_id)
procedure.reload
expect(revision.types_de_champ_private.size).to eq(0) expect(revision.types_de_champ_private.size).to eq(0)
expect(procedure.types_de_champ_private.size).to eq(0)
end end
it 'type_de_champ_repetition' do it 'type_de_champ_repetition' do
expect(type_de_champ_repetition.types_de_champ.size).to eq(1) expect(type_de_champ_repetition.types_de_champ.size).to eq(1)
expect(revision.types_de_champ.size).to eq(2) expect(revision.types_de_champ.size).to eq(2)
revision.remove_type_de_champ(type_de_champ_repetition.types_de_champ.first.stable_id) revision.remove_type_de_champ(type_de_champ_repetition.types_de_champ.first.stable_id)
procedure.reload
type_de_champ_repetition.reload type_de_champ_repetition.reload
expect(type_de_champ_repetition.types_de_champ.size).to eq(0) expect(type_de_champ_repetition.types_de_champ.size).to eq(0)
expect(revision.types_de_champ.size).to eq(2) expect(revision.types_de_champ.size).to eq(2)
expect(procedure.types_de_champ.size).to eq(2)
end end
end end

View file

@ -279,15 +279,6 @@ describe Procedure do
end end
end end
describe '#types_de_champ (ordered)' do
let(:procedure) { create(:procedure) }
let!(:type_de_champ_0) { create(:type_de_champ, procedure: procedure, order_place: 1) }
let!(:type_de_champ_1) { create(:type_de_champ, procedure: procedure, order_place: 0) }
subject { procedure.types_de_champ }
it { expect(subject.first).to eq(type_de_champ_1) }
it { expect(subject.last).to eq(type_de_champ_0) }
end
describe 'active' do describe 'active' do
let(:procedure) { create(:procedure) } let(:procedure) { create(:procedure) }
subject { Procedure.active(procedure.id) } subject { Procedure.active(procedure.id) }
@ -333,22 +324,22 @@ describe Procedure do
end end
describe 'clone' do describe 'clone' do
let!(:service) { create(:service) } let(:service) { create(:service) }
let(:procedure) { create(:procedure, received_mail: received_mail, service: service) } let(:procedure) { create(:procedure, received_mail: received_mail, service: service, types_de_champ: [type_de_champ_0, type_de_champ_1, type_de_champ_2, type_de_champ_pj], types_de_champ_private: [type_de_champ_private_0, type_de_champ_private_1, type_de_champ_private_2]) }
let!(:type_de_champ_0) { create(:type_de_champ, procedure: procedure, order_place: 0) } let(:type_de_champ_0) { build(:type_de_champ, position: 0) }
let!(:type_de_champ_1) { create(:type_de_champ, procedure: procedure, order_place: 1) } let(:type_de_champ_1) { build(:type_de_champ, position: 1) }
let!(:type_de_champ_2) { create(:type_de_champ_drop_down_list, procedure: procedure, order_place: 2) } let(:type_de_champ_2) { build(:type_de_champ_drop_down_list, position: 2) }
let!(:type_de_champ_pj) { create(:type_de_champ_piece_justificative, procedure: procedure, order_place: 3, old_pj: { stable_id: 2713 }) } let(:type_de_champ_pj) { build(:type_de_champ_piece_justificative, position: 3, old_pj: { stable_id: 2713 }) }
let!(:type_de_champ_private_0) { create(:type_de_champ, :private, procedure: procedure, order_place: 0) } let(:type_de_champ_private_0) { build(:type_de_champ, :private, position: 0) }
let!(:type_de_champ_private_1) { create(:type_de_champ, :private, procedure: procedure, order_place: 1) } let(:type_de_champ_private_1) { build(:type_de_champ, :private, position: 1) }
let!(:type_de_champ_private_2) { create(:type_de_champ_drop_down_list, :private, procedure: procedure, order_place: 2) } let(:type_de_champ_private_2) { build(:type_de_champ_drop_down_list, :private, position: 2) }
let(:received_mail) { build(:received_mail) } let(:received_mail) { build(:received_mail) }
let(:from_library) { false } let(:from_library) { false }
let(:administrateur) { procedure.administrateurs.first } let(:administrateur) { procedure.administrateurs.first }
let!(:groupe_instructeur_1) { create(:groupe_instructeur, procedure: procedure, label: "groupe_1") } let(:groupe_instructeur_1) { create(:groupe_instructeur, procedure: procedure, label: "groupe_1") }
let!(:instructeur_1) { create(:instructeur) } let(:instructeur_1) { create(:instructeur) }
let!(:instructeur_2) { create(:instructeur) } let(:instructeur_2) { create(:instructeur) }
let!(:assign_to_1) { create(:assign_to, procedure: procedure, groupe_instructeur: groupe_instructeur_1, instructeur: instructeur_1) } let!(:assign_to_1) { create(:assign_to, procedure: procedure, groupe_instructeur: groupe_instructeur_1, instructeur: instructeur_1) }
let!(:assign_to_2) { create(:assign_to, procedure: procedure, groupe_instructeur: groupe_instructeur_1, instructeur: instructeur_2) } let!(:assign_to_2) { create(:assign_to, procedure: procedure, groupe_instructeur: groupe_instructeur_1, instructeur: instructeur_2) }
@ -379,28 +370,18 @@ describe Procedure do
it 'should duplicate specific objects with different id' do it 'should duplicate specific objects with different id' do
expect(subject.id).not_to eq(procedure.id) expect(subject.id).not_to eq(procedure.id)
expect(subject.types_de_champ.size).to eq(procedure.types_de_champ.size) expect(subject.draft_types_de_champ.size).to eq(procedure.draft_types_de_champ.size)
expect(subject.types_de_champ_private.size).to eq procedure.types_de_champ_private.size expect(subject.draft_types_de_champ_private.size).to eq(procedure.draft_types_de_champ_private.size)
expect(subject.types_de_champ.map(&:drop_down_options).compact.size).to eq procedure.types_de_champ.map(&:drop_down_options).compact.size
expect(subject.types_de_champ_private.map(&:drop_down_options).compact.size).to eq procedure.types_de_champ_private.map(&:drop_down_options).compact.size
expect(subject.draft_revision.types_de_champ.size).to eq(procedure.draft_revision.types_de_champ.size)
expect(subject.draft_revision.types_de_champ_private.size).to eq(procedure.draft_revision.types_de_champ_private.size)
procedure.types_de_champ.zip(subject.types_de_champ).each do |ptc, stc| procedure.draft_types_de_champ.zip(subject.draft_types_de_champ).each do |ptc, stc|
expect(stc).to have_same_attributes_as(ptc, except: ["revision_id"]) expect(stc).to have_same_attributes_as(ptc, except: ["revision_id"])
expect(stc.revision).to eq(subject.draft_revision) expect(stc.revision).to eq(subject.draft_revision)
end end
procedure.types_de_champ.zip(procedure.draft_revision.types_de_champ).each do |ptc, rtc|
expect(ptc).to eq(rtc)
end
subject.types_de_champ_private.zip(procedure.types_de_champ_private).each do |stc, ptc| procedure.draft_types_de_champ_private.zip(subject.draft_types_de_champ_private).each do |ptc, stc|
expect(stc).to have_same_attributes_as(ptc, except: ["revision_id"]) expect(stc).to have_same_attributes_as(ptc, except: ["revision_id"])
expect(stc.revision).to eq(subject.draft_revision) expect(stc.revision).to eq(subject.draft_revision)
end end
procedure.types_de_champ_private.zip(procedure.draft_revision.types_de_champ_private).each do |ptc, rtc|
expect(ptc).to eq(rtc)
end
expect(subject.attestation_template.title).to eq(procedure.attestation_template.title) expect(subject.attestation_template.title).to eq(procedure.attestation_template.title)
@ -423,7 +404,7 @@ describe Procedure do
end end
it 'should discard old pj information' do it 'should discard old pj information' do
subject.types_de_champ.each do |stc| subject.draft_types_de_champ.each do |stc|
expect(stc.old_pj).to be_nil expect(stc.old_pj).to be_nil
end end
end end
@ -459,7 +440,7 @@ describe Procedure do
end end
it 'should discard old pj information' do it 'should discard old pj information' do
subject.types_de_champ.each do |stc| subject.draft_types_de_champ.each do |stc|
expect(stc.old_pj).to be_nil expect(stc.old_pj).to be_nil
end end
end end
@ -519,12 +500,12 @@ describe Procedure do
end end
it 'should keep types_de_champ ids stable' do it 'should keep types_de_champ ids stable' do
expect(subject.types_de_champ.first.id).not_to eq(procedure.types_de_champ.first.id) expect(subject.draft_types_de_champ.first.id).not_to eq(procedure.draft_types_de_champ.first.id)
expect(subject.types_de_champ.first.stable_id).to eq(procedure.types_de_champ.first.id) expect(subject.draft_types_de_champ.first.stable_id).to eq(procedure.draft_types_de_champ.first.id)
end end
it 'should duplicate piece_justificative_template on a type_de_champ' do it 'should duplicate piece_justificative_template on a type_de_champ' do
expect(subject.types_de_champ.where(type_champ: "piece_justificative").first.piece_justificative_template.attached?).to be true expect(subject.draft_types_de_champ.where(type_champ: "piece_justificative").first.piece_justificative_template.attached?).to be true
end end
context 'with a notice attached' do context 'with a notice attached' do
@ -805,7 +786,7 @@ describe Procedure do
end end
describe 'suggested_path' do describe 'suggested_path' do
let(:procedure) { create :procedure, aasm_state: :publiee, libelle: 'Inscription au Collège' } let(:procedure) { create(:procedure, aasm_state: :publiee, libelle: 'Inscription au Collège') }
subject { procedure.suggested_path(procedure.administrateurs.first) } subject { procedure.suggested_path(procedure.administrateurs.first) }
@ -821,7 +802,7 @@ describe Procedure do
context 'when the suggestion conflicts with one procedure' do context 'when the suggestion conflicts with one procedure' do
before do before do
create :procedure, aasm_state: :publiee, path: 'inscription-au-college' create(:procedure, aasm_state: :publiee, path: 'inscription-au-college')
end end
it { is_expected.to eq 'inscription-au-college-2' } it { is_expected.to eq 'inscription-au-college-2' }
@ -829,8 +810,8 @@ describe Procedure do
context 'when the suggestion conflicts with several procedures' do context 'when the suggestion conflicts with several procedures' do
before do before do
create :procedure, aasm_state: :publiee, path: 'inscription-au-college' create(:procedure, aasm_state: :publiee, path: 'inscription-au-college')
create :procedure, aasm_state: :publiee, path: 'inscription-au-college-2' create(:procedure, aasm_state: :publiee, path: 'inscription-au-college-2')
end end
it { is_expected.to eq 'inscription-au-college-3' } it { is_expected.to eq 'inscription-au-college-3' }
@ -838,7 +819,7 @@ describe Procedure do
context 'when the suggestion conflicts with another procedure of the same admin' do context 'when the suggestion conflicts with another procedure of the same admin' do
before do before do
create :procedure, aasm_state: :publiee, path: 'inscription-au-college', administrateurs: procedure.administrateurs create(:procedure, aasm_state: :publiee, path: 'inscription-au-college', administrateurs: procedure.administrateurs)
end end
it { is_expected.to eq 'inscription-au-college' } it { is_expected.to eq 'inscription-au-college' }
@ -903,13 +884,14 @@ describe Procedure do
describe '#new_dossier' do describe '#new_dossier' do
let(:procedure) do let(:procedure) do
procedure = create(:procedure) create(:procedure,
types_de_champ: [
create(:type_de_champ_text, procedure: procedure, order_place: 1) build(:type_de_champ_text, position: 0),
create(:type_de_champ_number, procedure: procedure, order_place: 2) build(:type_de_champ_number, position: 1)
create(:type_de_champ_textarea, :private, procedure: procedure) ],
types_de_champ_private: [
procedure build(:type_de_champ_textarea, :private)
])
end end
let(:dossier) { procedure.new_dossier } let(:dossier) { procedure.new_dossier }

View file

@ -153,44 +153,6 @@ shared_examples 'type_de_champ_spec' do
end end
end end
describe "repetition" do
let(:procedure) { create(:procedure) }
let(:type_de_champ) { create(:type_de_champ_repetition, procedure: procedure) }
let(:type_de_champ_text) { create(:type_de_champ_text, procedure: procedure) }
let(:type_de_champ_integer_number_attrs) { attributes_for(:type_de_champ_integer_number) }
it "associates nested types_de_champ to the parent procedure" do
expect(type_de_champ.types_de_champ.size).to eq(0)
expect(procedure.types_de_champ.size).to eq(1)
procedure.update!(types_de_champ_attributes: [
{
id: type_de_champ.id,
libelle: type_de_champ.libelle,
types_de_champ_attributes: [type_de_champ_integer_number_attrs]
}
])
procedure.reload
type_de_champ.reload
expect(procedure.types_de_champ.size).to eq(1)
expect(type_de_champ.types_de_champ.size).to eq(1)
expect(type_de_champ.types_de_champ.first.parent).to eq(type_de_champ)
expect(type_de_champ.types_de_champ.first.procedure).to eq(procedure)
expect(type_de_champ.types_de_champ.first.private?).to eq(false)
type_de_champ.types_de_champ << type_de_champ_text
expect(type_de_champ.types_de_champ.size).to eq(2)
expect(type_de_champ_text.parent).to eq(type_de_champ)
admin = create(:administrateur)
cloned_procedure = procedure.clone(admin, false)
expect(cloned_procedure.types_de_champ.first.types_de_champ).not_to be_empty
end
end
describe "linked_drop_down_list" do describe "linked_drop_down_list" do
let(:type_de_champ) { create(:type_de_champ_linked_drop_down_list) } let(:type_de_champ) { create(:type_de_champ_linked_drop_down_list) }

View file

@ -49,12 +49,11 @@ describe DossierSerializer do
context 'when a type de champ PJ was cloned from a legacy PJ' do context 'when a type de champ PJ was cloned from a legacy PJ' do
let(:original_pj_id) { 3 } let(:original_pj_id) { 3 }
let(:cloned_type_de_champ) do let(:cloned_type_de_champ) do
tdc = create(:type_de_champ_piece_justificative, build(:type_de_champ_piece_justificative,
libelle: "Vidéo de votre demande de subvention", libelle: "Vidéo de votre demande de subvention",
description: "Pour optimiser vos chances, soignez la chorégraphie et privilégiez le chant polyphonique.\r\nRécupérer le formulaire vierge pour mon dossier : https://www.dance-academy.gouv.fr", description: "Pour optimiser vos chances, soignez la chorégraphie et privilégiez le chant polyphonique.\r\nRécupérer le formulaire vierge pour mon dossier : https://www.dance-academy.gouv.fr",
order_place: 0) old_pj: { stable_id: original_pj_id },
tdc.old_pj = { stable_id: original_pj_id } position: 0)
tdc
end end
let(:procedure) { create(:procedure, :published, types_de_champ: [cloned_type_de_champ]) } let(:procedure) { create(:procedure, :published, types_de_champ: [cloned_type_de_champ]) }
let(:dossier) { create(:dossier, procedure: procedure) } let(:dossier) { create(:dossier, procedure: procedure) }

View file

@ -12,12 +12,11 @@ describe ProcedureSerializer do
context 'when a type PJ was cloned to a type champ PJ' do context 'when a type PJ was cloned to a type champ PJ' do
let(:original_pj_id) { 3 } let(:original_pj_id) { 3 }
let(:cloned_type_de_champ) do let(:cloned_type_de_champ) do
tdc = create(:type_de_champ_piece_justificative, build(:type_de_champ_piece_justificative,
libelle: "Vidéo de votre demande de subvention", libelle: "Vidéo de votre demande de subvention",
description: "Pour optimiser vos chances, soignez la chorégraphie et privilégiez le chant polyphonique.\r\nRécupérer le formulaire vierge pour mon dossier : https://www.dance-academy.gouv.fr", description: "Pour optimiser vos chances, soignez la chorégraphie et privilégiez le chant polyphonique.\r\nRécupérer le formulaire vierge pour mon dossier : https://www.dance-academy.gouv.fr",
order_place: 0) old_pj: { stable_id: original_pj_id },
tdc.old_pj = { stable_id: original_pj_id } position: 0)
tdc
end end
let(:procedure) { create(:procedure, :published, types_de_champ: [cloned_type_de_champ]) } let(:procedure) { create(:procedure, :published, types_de_champ: [cloned_type_de_champ]) }

View file

@ -61,7 +61,7 @@ describe AdministrateurUsageStatisticsService do
end end
context 'with a freshly active procedure' do context 'with a freshly active procedure' do
let(:procedure) { create(:procedure, aasm_state: 'publiee') } let(:procedure) { create(:procedure, :published) }
it do it do
is_expected.to include( is_expected.to include(
@ -82,7 +82,7 @@ describe AdministrateurUsageStatisticsService do
end end
context 'with a procedure close' do context 'with a procedure close' do
let(:procedure) { create(:procedure, aasm_state: 'close') } let(:procedure) { create(:procedure, :closed) }
let!(:dossiers) do let!(:dossiers) do
(1..7).flat_map do (1..7).flat_map do
[ [
@ -163,7 +163,7 @@ describe AdministrateurUsageStatisticsService do
end end
context 'with a procedure en prod' do context 'with a procedure en prod' do
let(:procedure) { create(:procedure, aasm_state: 'publiee') } let(:procedure) { create(:procedure, :published) }
let!(:dossiers) do let!(:dossiers) do
[ [
create(:dossier, :en_construction, procedure: procedure), create(:dossier, :en_construction, procedure: procedure),
@ -191,7 +191,7 @@ describe AdministrateurUsageStatisticsService do
end end
context 'with a procedure en prod and more than 20 dossiers' do context 'with a procedure en prod and more than 20 dossiers' do
let(:procedure) { create(:procedure, aasm_state: 'publiee') } let(:procedure) { create(:procedure, :published) }
let!(:dossiers) do let!(:dossiers) do
(1..7).flat_map do (1..7).flat_map do
[ [

View file

@ -18,10 +18,10 @@ describe ProcedureExportService do
before do before do
# change one tdc place to check if the header is ordered # change one tdc place to check if the header is ordered
tdc_first = procedure.types_de_champ.first tdc_first = procedure.active_revision.revision_types_de_champ.first
tdc_last = procedure.types_de_champ.last tdc_last = procedure.active_revision.revision_types_de_champ.last
tdc_first.update(order_place: tdc_last.order_place + 1) tdc_first.update(position: tdc_last.position + 1)
procedure.reload procedure.reload
end end

View file

@ -12,11 +12,6 @@ module FeatureHelpers
login_as instructeur, scope: :instructeur login_as instructeur, scope: :instructeur
end end
def create_dossier
dossier = FactoryBot.create(:dossier)
dossier
end
def sign_in_with(email, password, sign_in_by_link = false) def sign_in_with(email, password, sign_in_by_link = false)
fill_in :user_email, with: email fill_in :user_email, with: email
fill_in :user_password, with: password fill_in :user_password, with: password