Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
tchak committed Jul 29, 2024
1 parent 2fe4034 commit 826a25e
Show file tree
Hide file tree
Showing 39 changed files with 281 additions and 460 deletions.
2 changes: 1 addition & 1 deletion app/controllers/api/public/v1/dossiers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def create
state: Dossier.states.fetch(:brouillon),
prefilled: true
)
dossier.build_default_individual
dossier.build_default_values
if dossier.save
dossier.prefill!(PrefillChamps.new(dossier, params.to_unsafe_h).to_a, PrefillIdentity.new(dossier, params.to_unsafe_h).to_h)
render json: serialize_dossier(dossier), status: :created
Expand Down
1 change: 1 addition & 0 deletions app/controllers/api/v1/dossiers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def index

def show
dossier = @dossiers.for_api.find(params[:id])
DossierPreloader.load_one(dossier)

render json: { dossier: DossierSerializer.new(dossier).as_json }
rescue ActiveRecord::RecordNotFound
Expand Down
7 changes: 3 additions & 4 deletions app/controllers/champs/repetition_controller.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
class Champs::RepetitionController < Champs::ChampController
def add
row = @champ.add_row(@champ.dossier.revision)
@first_champ_id = row.map(&:focusable_input_id).compact.first
@row_id = row.first&.row_id
@row_id = @champ.add_row(updated_by: current_user.email)
@first_champ_id = @champ.focusable_input_id
@row_number = @row_id.nil? ? 0 : @champ.row_ids.find_index(@row_id) + 1
end

def remove
@champ.remove_row(params[:row_id])
@champ.remove_row(params[:row_id], updated_by: current_user.email)
@to_remove = "safe-row-selector-#{params[:row_id]}"
@to_focus = @champ.focusable_input_id || helpers.dom_id(@champ, :create_repetition)
end
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/users/commencer_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def build_prefilled_dossier
state: Dossier.states.fetch(:brouillon),
prefilled: true
)
@prefilled_dossier.build_default_individual
@prefilled_dossier.build_default_values
if @prefilled_dossier.save
@prefilled_dossier.prefill!(PrefillChamps.new(@prefilled_dossier, params.to_unsafe_h).to_a, PrefillIdentity.new(@prefilled_dossier, params.to_unsafe_h).to_h)
end
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/users/dossiers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ def new
user: current_user,
state: Dossier.states.fetch(:brouillon)
)
dossier.build_default_individual
dossier.build_default_values
dossier.save!
DossierMailer.with(dossier:).notify_new_draft.deliver_later

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def resolve(dossier:, annotation_id:, instructeur:)
return { errors: ["L’annotation \"#{annotation_id}\" n’existe pas"] }
end

annotation.add_row(dossier.revision)
annotation.add_row(updated_by: instructeur.email)

{ annotation:, errors: nil }
end
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/types/dossier_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def champs(id: nil)
.for(object, private: false)
.load(ApplicationRecord.id_from_typed_id(id))
else
object.champs_for_revision(scope: :public, root: true).filter(&:visible?)
object.project_champs_public.filter(&:visible?)
end
end

Expand All @@ -178,7 +178,7 @@ def annotations(id: nil)
.for(object, private: true)
.load(ApplicationRecord.id_from_typed_id(id))
else
object.champs_for_revision(scope: :private, root: true).filter(&:visible?)
object.project_champs_private.filter(&:visible?)
end
end

Expand Down
21 changes: 10 additions & 11 deletions app/lib/data_fixer/dossier_champs_missing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,29 @@ def apply_fix(dossier)
end

def fix_champs_root(dossier)
champs_root, _ = dossier.champs.partition { _1.parent_id.blank? }
expected_tdcs = dossier.revision.revision_types_de_champ.filter { _1.parent.blank? }.map(&:type_de_champ)
champs_root = dossier.champs.filter { !_1.child? }
expected_tdcs = dossier.revision.revision_types_de_champ.filter { !_1.child? }.map(&:type_de_champ)

expected_tdcs.filter { !champs_root.map(&:stable_id).include?(_1.stable_id) }
.map do |missing_tdc|
champ_root_missing = missing_tdc.build_champ

dossier.champs_public << champ_root_missing
champ_root_missing = missing_tdc.build_champ(dossier:)
dossier.champs << champ_root_missing
champ_root_missing
end
end

def fix_champs_in_repetition(dossier)
champs_repetition, _ = dossier.champs.partition(&:repetition?)
champs_repetition = dossier.champs.filter(&:repetition?)

champs_repetition.flat_map do |champ_repetition|
champ_repetition_missing = champ_repetition.rows.flat_map do |row|
expected_tdcs = dossier.revision.children_of(champ_repetition.type_de_champ)
champ_repetition.rows.flat_map do |row|
row_id = row.first.row_id
expected_tdcs = dossier.revision.children_of(champ_repetition.type_de_champ)
row_tdcs = row.map(&:type_de_champ)
row_tdcs = row.filter(&:persisted?).map(&:type_de_champ)

(expected_tdcs - row_tdcs).map do |missing_tdc|
champ_repetition_missing = missing_tdc.build_champ(row_id: row_id)
champ_repetition.champs << champ_repetition_missing
champ_repetition_missing = missing_tdc.build_champ(row_id:, dossier:)
dossier.champs << champ_repetition_missing
champ_repetition_missing
end
end
Expand Down
8 changes: 4 additions & 4 deletions app/models/attestation_template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,13 @@ def attestation_for(dossier)
end

def unspecified_champs_for_dossier(dossier)
champs_by_stable_id = dossier.champs_for_revision(root: true).index_by { "tdc#{_1.stable_id}" }
champs_by_stable_id = dossier.revision.types_de_champ.index_by { "tdc#{_1.stable_id}" }

used_tags.filter_map do |used_tag|
corresponding_champ = champs_by_stable_id[used_tag]
corresponding_type_de_champ = champs_by_stable_id[used_tag]

if corresponding_champ && corresponding_champ.blank?
corresponding_champ
if corresponding_type_de_champ && dossier.project_champ(corresponding_type_de_champ, nil).blank?
corresponding_type_de_champ
end
end
end
Expand Down
20 changes: 6 additions & 14 deletions app/models/champ.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
class Champ < ApplicationRecord
self.ignored_columns += [:parent_id]

include ChampConditionalConcern
include ChampsValidateConcern

self.ignored_columns += [:type_de_champ_id]

belongs_to :dossier, inverse_of: false, touch: true, optional: false
belongs_to :parent, class_name: 'Champ', optional: true
has_many_attached :piece_justificative_file

# We declare champ specific relationships (Champs::CarteChamp, Champs::SiretChamp and Champs::RepetitionChamp)
# here because otherwise we can't easily use includes in our queries.
has_many :geo_areas, -> { order(:created_at) }, dependent: :destroy, inverse_of: :champ
belongs_to :etablissement, optional: true, dependent: :destroy
has_many :champs, foreign_key: :parent_id, inverse_of: :parent

delegate :procedure, to: :dossier

Expand Down Expand Up @@ -81,18 +81,18 @@ def type_de_champ
scope :root, -> { where(parent_id: nil) }
scope :prefilled, -> { where(prefilled: true) }

before_create :set_dossier_id, if: :needs_dossier_id?
before_validation :set_dossier_id, if: :needs_dossier_id?
before_save :cleanup_if_empty
before_save :normalize
after_update_commit :fetch_external_data_later

store_accessor :value_json, :row_deleted_at

def public?
!private?
end

def child?
parent_id.present?
row_id.present? && !repetition?
end

# used for the `required` html attribute
Expand Down Expand Up @@ -229,7 +229,7 @@ def update_with_external_data!(data:)
end

def clone(fork = false)
champ_attributes = [:parent_id, :private, :row_id, :type, :stable_id, :stream]
champ_attributes = [:private, :row_id, :type, :stable_id, :stream]
value_attributes = fork || !private? ? [:value, :value_json, :data, :external_id] : []
relationships = fork || !private? ? [:etablissement, :geo_areas] : []

Expand Down Expand Up @@ -262,14 +262,6 @@ def html_id
"champ-#{public_id}"
end

def needs_dossier_id?
!dossier_id && parent_id
end

def set_dossier_id
self.dossier_id = parent.dossier_id
end

def cleanup_if_empty
if fetch_external_data? && persisted? && external_id_changed?
self.data = nil
Expand Down
29 changes: 8 additions & 21 deletions app/models/champs/repetition_champ.rb
Original file line number Diff line number Diff line change
@@ -1,41 +1,28 @@
class Champs::RepetitionChamp < Champ
accepts_nested_attributes_for :champs
delegate :libelle_for_export, to: :type_de_champ

def rows
dossier
.champs_for_revision(scope: type_de_champ)
.group_by(&:row_id)
.sort
.map(&:second)
dossier.project_rows_for(type_de_champ)
end

def row_ids
rows.map { _1.first.row_id }
dossier.repetition_row_ids(type_de_champ)
end

def add_row(revision)
added_champs = []
transaction do
row_id = ULID.generate
revision.children_of(type_de_champ).each do |type_de_champ|
added_champs << type_de_champ.build_champ(row_id:)
end
self.champs << added_champs
end
added_champs
def add_row(updated_by:)
dossier.repetition_add_row(type_de_champ, updated_by:)
end

def remove_row(row_id)
dossier.champs.where(row_id:).destroy_all
dossier.champs.reload
def remove_row(row_id, updated_by:)
dossier.repetition_remove_row(type_de_champ, row_id, updated_by:)
end

def focusable_input_id
rows.last&.first&.focusable_input_id
end

def blank?
champs.empty?
row_ids.empty?
end

def search_terms
Expand Down
8 changes: 6 additions & 2 deletions app/models/concerns/champs_validate_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ def valid_champ_value?
def validate_champ_value?
case validation_context
when :champs_public_value
public? && visible?
public? && in_dossier_revision? && visible?
when :champs_private_value
private? && visible?
private? && in_dossier_revision? && visible?
else
false
end
Expand All @@ -25,5 +25,9 @@ def validate_champ_value?
def validate_champ_value_or_prefill?
validate_champ_value? || validation_context == :prefill
end

def in_dossier_revision?
dossier.revision.types_de_champ.map(&:stable_id).include?(stable_id)
end
end
end
76 changes: 56 additions & 20 deletions app/models/concerns/dossier_champs_concern.rb
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
module DossierChampsConcern
extend ActiveSupport::Concern

def champs_for_revision(scope: nil, root: false)
def champs_for_revision(scope: nil)
champs_index = champs.group_by(&:stable_id)
# Due to some bad data we can have multiple copies of the same champ. Ignore extra copy.
.transform_values { _1.sort_by(&:id).uniq(&:row_id) }
.transform_values { |champs| champs.sort_by { _1.id || 0 }.uniq(&:row_id) }

if scope.is_a?(TypeDeChamp)
revision
.children_of(scope)
.flat_map { champs_index[_1.stable_id] || [] }
.filter(&:child?) # TODO: remove once bad data (child champ without a row id) is cleaned
else
revision
.types_de_champ_for(scope:, root:)
.flat_map { champs_index[_1.stable_id] || [] }
end
revision.types_de_champ_for(scope:)
.flat_map { champs_index[_1.stable_id] || [] }
end

# Get all the champs values for the types de champ in the final list.
Expand All @@ -33,7 +25,7 @@ def champs_for_export(types_de_champ, row_id = nil)
def project_champ(type_de_champ, row_id)
champ = champs_by_public_id[type_de_champ.public_id(row_id)]
if champ.nil?
type_de_champ.build_champ(dossier: self, row_id:)
type_de_champ.champ.build(dossier: self, row_id:)
else
champ
end
Expand Down Expand Up @@ -72,6 +64,54 @@ def update_champs_attributes(attributes, scope, updated_by:)
assign_attributes(champs_attributes:)
end

def project_champs_public
revision.types_de_champ_public.map { project_champ(_1, nil) }
end

def project_champs_private
revision.types_de_champ_private.map { project_champ(_1, nil) }
end

def repetition_row_ids(type_de_champ)
stable_ids = [type_de_champ.stable_id] + revision.children_of(type_de_champ).map(&:stable_id)
champs.filter { _1.stable_id.in?(stable_ids) && _1.row_id.present? && _1.row_deleted_at.blank? }
.map(&:row_id)
.uniq
.sort
end

def repetition_add_row(type_de_champ, updated_by:)
row_id = ULID.generate
champ_for_update(type_de_champ, row_id, updated_by:).save!
@champs_by_public_id = nil
row_id
end

def repetition_remove_row(type_de_champ, row_id, updated_by:)
row_champ = champ_for_update(type_de_champ, row_id, updated_by:)
row_champ.row_deleted_at = Time.zone.now

transaction do
champs.where(row_id:).where.not(stable_id: type_de_champ.stable_id).destroy_all
row_champ.save!
end
champs.reload
@champs_by_public_id = nil
end

def project_rows_for(type_de_champ)
types_de_champ = revision.children_of(type_de_champ)
repetition_row_ids(type_de_champ).map do |row_id|
types_de_champ.map { project_champ(_1, row_id) }
end
end

def reload
super.tap do
@champs_by_public_id = nil
end
end

private

def champs_by_public_id
Expand All @@ -94,6 +134,9 @@ def champ_attributes_by_public_id(public_id, attributes, scope, updated_by:)
end

def champ_with_attributes_for_update(type_de_champ, row_id, updated_by:)
if type_de_champ.repetition? && row_id.nil?
raise ArgumentError, "row_id is required for repetition champ"
end
attributes = type_de_champ.params_for_champ
# TODO: Once we have the right index in place, we should change this to use `create_or_find_by` instead of `find_or_create_by`
champ = champs
Expand All @@ -111,13 +154,6 @@ def champ_with_attributes_for_update(type_de_champ, row_id, updated_by:)
attributes[:data] = nil
end

parent = revision.parent_of(type_de_champ)
if parent.present?
attributes[:parent] = champs.find { _1.stable_id == parent.stable_id }
else
attributes[:parent] = nil
end

@champs_by_public_id = nil

[champ, attributes]
Expand Down
Loading

0 comments on commit 826a25e

Please sign in to comment.