rework ChampColumn.value

This commit is contained in:
simon lehericey 2024-11-04 16:34:29 +01:00
parent ea57a97c06
commit c364be12f1
No known key found for this signature in database
GPG key ID: CDE670D827C7B3C5
2 changed files with 101 additions and 31 deletions

View file

@ -22,11 +22,11 @@ class Columns::ChampColumn < Column
def value(champ)
return if champ.nil?
value = typed_value(champ)
if default_column?
cast_value(value, from_type: champ.last_write_column_type, to_type: type)
# nominal case
if @tdc_type == champ.last_write_type_champ
typed_value(champ)
else
value
cast_value(champ)
end
end
@ -34,15 +34,11 @@ class Columns::ChampColumn < Column
def column_id = "type_de_champ/#{stable_id}"
def string_value(champ) = champ.public_send(value_column)
def typed_value(champ)
value = string_value(champ)
parse_value(value, type: champ.last_write_column_type)
end
def string_value(champ) = champ.public_send(value_column)
def default_column? = value_column.in?([:value, :external_id])
def parse_value(value, type:)
return if value.blank?
case type
@ -63,29 +59,30 @@ class Columns::ChampColumn < Column
end
end
def cast_value(value, from_type:, to_type:)
return if value.blank?
return value if from_type == to_type
def cast_value(champ)
value = string_value(champ)
case [from_type, to_type]
when [:integer, :decimal] # recast numbers automatically
return if value.blank?
case [champ.last_write_type_champ, @tdc_type]
when ['integer_number', 'decimal_number'] # recast numbers automatically
value.to_f
when [:decimal, :integer] # may lose some data, but who cares ?
when ['decimal_number', 'integer_number'] # may lose some data, but who cares ?
value.to_i
when [:integer, :text], [:decimal, :text] # number to text
value.to_s
when [:enum, :enums] # single list can become multi
[value]
when [:enum, :text] # single list can become text
when ['integer_number', 'text'], ['decimal_number', 'text'] # number to text
value
when [:enums, :enum] # multi list can become single list
value.first
when [:enums, :text] # multi list can become text
value.join(', ')
when [:date, :datetime] # date <=> datetime
value.to_datetime
when [:datetime, :date] # may lose some data, but who cares ?
value.to_date
when ['drop_down_list', 'multiple_drop_down_list'] # single list can become multi
[value]
when ['drop_down_list', 'text'] # single list can become text
value
when ['multiple_drop_down_list', 'drop_down_list'] # multi list can become single
parse_enums(value).first
when ['multiple_drop_down_list', 'text'] # single list can become text
parse_enums(value).join(', ')
when ['date', 'datetime'] # date <=> datetime
parse_datetime(value)&.to_datetime
when ['datetime', 'date'] # may lose some data, but who cares ?
parse_datetime(value)&.to_date
else
nil
end

View file

@ -2,8 +2,9 @@
describe Columns::ChampColumn do
describe '#value' do
context 'when champ columns' do
let(:procedure) { create(:procedure, :with_all_champs_mandatory) }
let(:procedure) { create(:procedure, :with_all_champs_mandatory) }
context 'without any cast' do
let(:dossier) { create(:dossier, :with_populated_champs, procedure:) }
let(:types_de_champ) { procedure.all_revisions_types_de_champ }
@ -43,6 +44,78 @@ describe Columns::ChampColumn do
expect_type_de_champ_values('expression_reguliere', [nil])
end
end
context 'with cast' do
def column(label) = procedure.find_column(label:)
context 'from a integer_number' do
let(:champ) { double(last_write_type_champ: 'integer_number', value: '42') }
it do
expect(column('decimal_number').value(champ)).to eq(42.0)
expect(column('text').value(champ)).to eq('42')
end
end
context 'from a decimal_number' do
let(:champ) { double(last_write_type_champ: 'decimal_number', value: '42.1') }
it do
expect(column('integer_number').value(champ)).to eq(42)
expect(column('text').value(champ)).to eq('42.1')
end
end
context 'from a date' do
let(:champ) { double(last_write_type_champ: 'date', value:) }
describe 'when the value is valid' do
let(:value) { '2019-07-10' }
it { expect(column('datetime').value(champ)).to eq(Time.zone.parse('2019-07-10')) }
end
describe 'when the value is invalid' do
let(:value) { 'invalid' }
it { expect(column('datetime').value(champ)).to be_nil }
end
end
context 'from a datetime' do
let(:champ) { double(last_write_type_champ: 'datetime', value:) }
describe 'when the value is valid' do
let(:value) { '1962-09-15T15:35:00+01:00' }
it { expect(column('date').value(champ)).to eq('1962-09-15'.to_date) }
end
describe 'when the value is invalid' do
let(:value) { 'invalid' }
it { expect(column('date').value(champ)).to be_nil }
end
end
context 'from a drop_down_list' do
let(:champ) { double(last_write_type_champ: 'drop_down_list', value: 'val1') }
it do
expect(column('multiple_drop_down_list').value(champ)).to eq(['val1'])
expect(column('text').value(champ)).to eq('val1')
end
end
context 'from a multiple_drop_down_list' do
let(:champ) { double(last_write_type_champ: 'multiple_drop_down_list', value: '["val1","val2"]') }
it do
expect(column('simple_drop_down_list').value(champ)).to eq('val1')
expect(column('text').value(champ)).to eq('val1, val2')
end
end
end
end
private