Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: condition sur les colonnes #11129

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions app/components/conditions/conditions_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,15 @@ def empty_target_for_select
end

def available_targets_for_select
@source_tdcs
original = @source_tdcs
.filter(&:conditionable?)
.map { |tdc| [tdc.libelle, champ_value(tdc.stable_id).to_json] }
#
# TO REMOVE
procedure = Procedure.find(@procedure_id)
columns = @source_tdcs.flat_map { |tdc| tdc.columns(procedure:) }.filter { _1.type != :text }

original + columns.map { |column| [column.label + " (col)", column_value(column).to_json] }
end

def operator_tag(operator_name, targeted_champ, row_index)
Expand Down Expand Up @@ -118,7 +124,7 @@ def compatibles_operators_for_select(left)
[t(IncludeOperator.name, scope: 'logic.operators'), IncludeOperator.name],
[t(ExcludeOperator.name, scope: 'logic.operators'), ExcludeOperator.name]
]
when ChampValue::CHAMP_VALUE_TYPE.fetch(:number)
when ChampValue::CHAMP_VALUE_TYPE.fetch(:number), :integer, :decimal
[Eq, LessThan, GreaterThan, LessThanEq, GreaterThanEq]
.map(&:name)
.map { |name| [t(name, scope: 'logic.operators'), name] }
Expand Down Expand Up @@ -164,7 +170,7 @@ def right_operand_tag(left, right, row_index, operator_name)
id: input_id_for('value', row_index),
class: { 'fr-select': true, alert: right_invalid }
)
when :number
when :number, :integer, :decimal
text_field_tag(
input_name_for('value'),
right.value,
Expand Down
1 change: 1 addition & 0 deletions app/models/columns/linked_drop_down_column.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def typed_value(champ)
end

def unpack_values(value)
return [] if value.blank?
JSON.parse(value)
rescue JSON::ParserError
[]
Expand Down
2 changes: 1 addition & 1 deletion app/models/condition_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def row_to_condition(row)
def parse_value(left_type, value)
return empty if value.blank?

if left_type == :number
if left_type == :number || left_type == :integer || left_type == :decimal
# in this special case, we try to cast as Float, then Integer
# but it can still be a previous string value or a mistap
number = parse_to_number(value)
Expand Down
11 changes: 7 additions & 4 deletions app/models/logic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def self.from_json(s)
def self.class_from_name(name)
[
ChampValue,
ColumnValue,
Constant,
Empty,
LessThan,
Expand Down Expand Up @@ -50,9 +51,9 @@ def self.ensure_compatibility_from_left(condition, type_de_champs)
operator_class = Eq
in [:enums, _]
operator_class = IncludeOperator
in [:number, EmptyOperator]
in [:number, EmptyOperator] | [:integer, EmptyOperator] | [:decimal, EmptyOperator]
operator_class = Eq
in [:number, _]
in [:number, _] | [:integer, _] | [:decimal, _]
end

if !compatible_type?(left, right, type_de_champs)
Expand All @@ -63,7 +64,7 @@ def self.ensure_compatibility_from_left(condition, type_de_champs)
Empty.new
when :enum, :enums, :commune_enum, :epci_enum, :departement_enum, :address
Constant.new(left.options(type_de_champs).first.second)
when :number
when :number, :integer, :decimal
Constant.new(0)
end
end
Expand All @@ -75,7 +76,7 @@ def self.compatible_type?(left, right, type_de_champs)
case [left.type(type_de_champs), right.type(type_de_champs)]
in [a, ^a] # syntax for same type
true
in [:enum, :string] | [:enums, :string] | [:commune_enum, :string] | [:epci_enum, :string] | [:departement_enum, :string] | [:address, :string]
in [:enum, :string] | [:enums, :string] | [:commune_enum, :string] | [:epci_enum, :string] | [:departement_enum, :string] | [:address, :string] | [:integer, :number] | [:decimal, :number]
true
else
false
Expand Down Expand Up @@ -126,6 +127,8 @@ def constant(value) = Logic::Constant.new(value)

def champ_value(stable_id) = Logic::ChampValue.new(stable_id)

def column_value(column) = Logic::ColumnValue.new(column)

def empty = Logic::Empty.new

def empty_operator(left, right) = Logic::EmptyOperator.new(left, right)
Expand Down
6 changes: 3 additions & 3 deletions app/models/logic/champ_value.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ class Logic::ChampValue < Logic::Term
:drop_down_list,
:multiple_drop_down_list,
:address,
:communes,
:epci,
:communes, # inject departement sous forme de chiffre ?
:epci, # ne marche pas
:departements,
:regions,
:pays
:pays # a faire n'injecte pas encore ses valeurs
)

MANAGED_TYPE_DE_CHAMP_BY_CATEGORY = MANAGED_TYPE_DE_CHAMP.keys.map(&:to_sym)
Expand Down
47 changes: 47 additions & 0 deletions app/models/logic/column_value.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

class Logic::ColumnValue < Logic::Term
delegate :stable_id, to: :@champ_column

def initialize(champ_column)
@champ_column = champ_column
end

def sources = [stable_id]

def compute(champs)
targeted_champ = champs.find { |champ| champ.stable_id == stable_id }
@champ_column.value(targeted_champ)
end

def type(_type_de_champs) = @champ_column.type

def options(_type_de_champs, _other = nil)
result = @champ_column.options_for_select
if result.present? && result.first.is_a?(String)
result.map { |option| [option, option] }
else
result
end
end

def errors(type_de_champs)
if !type_de_champs.map(&:stable_id).include?(stable_id)
[{ type: :not_available }]
else
[]
end
end

def to_h
{
"term" => self.class.name,
"column_id" => @champ_column.id
}
end

def self.from_h(h)
column = Column.find(JSON.parse(h['column_id'], symbolize_names: true))
self.new(column)
end
end
7 changes: 7 additions & 0 deletions app/models/types_de_champ/address_type_de_champ.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class TypesDeChamp::AddressTypeDeChamp < TypesDeChamp::TextTypeDeChamp
include AddressableColumnConcern

def libelles_for_export
path = paths.first
[[path[:libelle], path[:path]]]
Expand Down Expand Up @@ -36,6 +38,11 @@ def champ_value_for_export(champ, path = :value)
end
end

def columns(procedure:, displayable: true, prefix: nil)
super
.concat(addressable_columns(procedure:, displayable:, prefix:))
end

private

def paths
Expand Down
29 changes: 29 additions & 0 deletions spec/models/logic/column_value_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

describe Logic::ColumnValue do
include Logic

let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :yes_no, libelle: 'yes' }]) }
let(:column) { procedure.find_column(label: 'yes') }
let(:column_value) { Logic::ColumnValue.new(column) }

describe '#compute' do
let(:dossier) { create(:dossier, procedure:) }
let(:champ) { dossier.champs.first }

before { champ.update(value: 'true') }

it { expect(column_value.compute([champ])).to be(true) }
end

describe '#sources' do
it { expect(column_value.sources).to eq([column.stable_id]) }
end

describe '#errors' do
it do
expect(column_value.errors(procedure.active_revision.types_de_champ)).to eq([])
expect(column_value.errors([])).to eq([{ type: :not_available }])
end
end
end
Loading