demographic 0.8.6.RKM.89602.beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +479 -0
- data/Rakefile +22 -0
- data/app/controllers/demographic/application_controller.rb +87 -0
- data/app/controllers/demographic/custom_parameter_values_controller.rb +25 -0
- data/app/controllers/demographic/optionals_bulk_controller.rb +33 -0
- data/app/controllers/demographic/optionals_controller.rb +68 -0
- data/app/controllers/demographic/optionals_types_controller.rb +17 -0
- data/app/controllers/demographic/user_optionals_controller.rb +12 -0
- data/app/jobs/demographic/application_job.rb +4 -0
- data/app/mailers/demographic/application_mailer.rb +6 -0
- data/app/serializers/demographic/optionals/filter_list_serializer.rb +34 -0
- data/app/serializers/demographic/optionals/list_serializer.rb +17 -0
- data/app/serializers/demographic/optionals/optional_serializer.rb +20 -0
- data/app/serializers/demographic/optionals/value_serializer.rb +5 -0
- data/app/services/demographic/custom_parameter_values/index.rb +53 -0
- data/app/services/demographic/helpers/association_localizer.rb +13 -0
- data/app/services/demographic/helpers/import/bulk/build_optionals.rb +54 -0
- data/app/services/demographic/helpers/import/bulk/create_optional_values.rb +32 -0
- data/app/services/demographic/helpers/import/bulk/create_or_update_user_optionals.rb +110 -0
- data/app/services/demographic/helpers/import/create_optionals_list.rb +60 -0
- data/app/services/demographic/helpers/import/create_or_update_custom_parameter_values.rb +97 -0
- data/app/services/demographic/helpers/import/create_or_update_user_values.rb +161 -0
- data/app/services/demographic/helpers/import/create_or_update_values.rb +124 -0
- data/app/services/demographic/optional_values/create_list.rb +61 -0
- data/app/services/demographic/optional_values/update_list.rb +85 -0
- data/app/services/demographic/optionals/bulk_create.rb +115 -0
- data/app/services/demographic/optionals/bulk_create_validations.rb +122 -0
- data/app/services/demographic/optionals/create.rb +90 -0
- data/app/services/demographic/optionals/list.rb +51 -0
- data/app/services/demographic/optionals/optional_values.rb +52 -0
- data/app/services/demographic/optionals/update.rb +100 -0
- data/app/services/demographic/parse/data_serializer.rb +87 -0
- data/app/services/demographic/parse/types/values.rb +99 -0
- data/app/services/demographic/user_optionals/list.rb +60 -0
- data/app/services/import/templates/create_optionals.rb +26 -0
- data/app/services/import/templates/xlsx.rb +44 -0
- data/config/initializers/custom_classes/string.rb +11 -0
- data/config/routes.rb +38 -0
- data/db/migrate/20201207181535_create_demographic_optionals.rb +18 -0
- data/db/migrate/20201207184210_create_users.rb +12 -0
- data/db/migrate/20201211204926_create_demographic_demographic_optional_values.rb +15 -0
- data/db/migrate/20201215193056_create_demographic_user_optional_values.rb +11 -0
- data/db/migrate/20220427163444_add_token_to_optionals.rb +6 -0
- data/db/migrate/20220427163507_add_token_to_optional_values.rb +6 -0
- data/lib/demographic/engine.rb +17 -0
- data/lib/demographic/version.rb +5 -0
- data/lib/demographic.rb +78 -0
- data/lib/generators/init/USAGE +8 -0
- data/lib/generators/init/init_generator.rb +11 -0
- data/lib/generators/init/templates/init_demographic.rb +14 -0
- data/lib/generators/init/templates/policy_demographic.rb +70 -0
- data/lib/generators/init_manual_update/USAGE +8 -0
- data/lib/generators/init_manual_update/init_manual_update_generator.rb +12 -0
- data/lib/generators/init_manual_update/templates/20220427163444_add_token_to_optionals.rb +6 -0
- data/lib/generators/init_manual_update/templates/20220427163507_add_token_to_optional_values.rb +6 -0
- data/lib/generators/init_manual_update/templates/demographic_update_tokens.rake +13 -0
- data/lib/generators/init_manual_update/templates/demographic_update_tokens_by_tenants.rake +24 -0
- data/lib/generators/init_manual_update_v2/init_manual_update_generator.rb +10 -0
- data/lib/generators/init_manual_update_v2/templates/20240206120304_create_custom_parameter_values.rb +10 -0
- data/lib/generators/init_manual_update_v2/templates/custom_parameter_value.rb +5 -0
- data/lib/generators/init_model/USAGE +8 -0
- data/lib/generators/init_model/init_model_generator.rb +12 -0
- data/lib/generators/init_model/templates/optional.rb +5 -0
- data/lib/generators/init_model/templates/optional_value.rb +4 -0
- data/lib/generators/init_model/templates/user.rb +5 -0
- data/lib/generators/init_model/templates/user_optional.rb +5 -0
- data/lib/tasks/demographic_tasks.rake +4 -0
- metadata +346 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
module Demographic
|
|
2
|
+
module Optionals
|
|
3
|
+
class Create
|
|
4
|
+
attr_accessor :adjustable, :data, :optional
|
|
5
|
+
|
|
6
|
+
def initialize(adjustable:, data:)
|
|
7
|
+
@adjustable = adjustable
|
|
8
|
+
@data = data
|
|
9
|
+
@optional = Optional.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call
|
|
13
|
+
ActiveRecord::Base.transaction do
|
|
14
|
+
validation_optional
|
|
15
|
+
add_adjustable
|
|
16
|
+
create_optional
|
|
17
|
+
create_values_list
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
optional
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def validation_optional
|
|
26
|
+
unless data[:input_type].present?
|
|
27
|
+
optional.errors.add(:input_type, 'input_type is empty')
|
|
28
|
+
raise ActiveRecord::RecordInvalid, optional
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
if !data[:name_translate].present? || !data[:name_translate].values.any? { |v| v.present? }
|
|
32
|
+
optional.errors.add(:name_translate, 'name_translate is empty')
|
|
33
|
+
raise ActiveRecord::RecordInvalid, optional
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
if data[:input_type] == 'list' && !any_valid?
|
|
37
|
+
optional.errors.add(:values, 'values is empty')
|
|
38
|
+
raise ActiveRecord::RecordInvalid, optional
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def create_optional
|
|
43
|
+
optional.adjustable_id = adjustable.id
|
|
44
|
+
optional.adjustable_type = adjustable.class.name
|
|
45
|
+
optional.name = name
|
|
46
|
+
optional.code = code
|
|
47
|
+
optional.token = Demographic.generate_token
|
|
48
|
+
optional.input_type = data[:input_type]
|
|
49
|
+
optional.min_value = data[:min_value]
|
|
50
|
+
optional.max_value = data[:max_value]
|
|
51
|
+
optional.name_translate = data[:name_translate]
|
|
52
|
+
optional.order = data[:order_num] || 1
|
|
53
|
+
optional.save!
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def add_adjustable
|
|
57
|
+
return unless optional.attributes.key?('enterprise_process_id')
|
|
58
|
+
|
|
59
|
+
optional.enterprise_process_id = adjustable.try(:enterprise_process_id).presence || adjustable.id
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def create_values_list
|
|
63
|
+
::Demographic::OptionalValues::CreateList.new(adjustable: adjustable,
|
|
64
|
+
values: data[:values],
|
|
65
|
+
optional: optional).call
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def name
|
|
69
|
+
return data[:name_translate]['es'] if data[:name_translate]['es'].present?
|
|
70
|
+
|
|
71
|
+
data[:name_translate].values.detect { |v| v.present? }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def any_valid?
|
|
75
|
+
return false if data[:values].blank?
|
|
76
|
+
data[:values].any? { |value| value[:is_valid].to_d == 1 }
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def code
|
|
82
|
+
if data[:code].is_a?(String) && data[:code].parameterize.str_slug.present?
|
|
83
|
+
data[:code].parameterize.str_slug
|
|
84
|
+
else
|
|
85
|
+
name.parameterize.str_slug
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Demographic
|
|
2
|
+
module Optionals
|
|
3
|
+
class List
|
|
4
|
+
attr_accessor :adjustable, :page, :term, :per_page
|
|
5
|
+
|
|
6
|
+
def initialize(adjustable:, page:, term:, per_page:)
|
|
7
|
+
@adjustable = adjustable
|
|
8
|
+
@page = page || 1
|
|
9
|
+
@term = term.try(:downcase)
|
|
10
|
+
@per_page = per_page || 20
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_json
|
|
14
|
+
search(is_json: true)
|
|
15
|
+
rescue ActiveRecord::StatementInvalid
|
|
16
|
+
search(is_json: false)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def search(is_json:)
|
|
22
|
+
optionals = adjustable ? adjustable.optionals : Optional
|
|
23
|
+
optionals = search_term(optionals, is_json)
|
|
24
|
+
optionals = optionals.page(page).per(per_page)
|
|
25
|
+
struct_json(optionals)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def search_term(optionals, is_json = true)
|
|
29
|
+
return optionals unless term.present?
|
|
30
|
+
return optionals.where("name LIKE ?", "%#{term}%") unless is_json
|
|
31
|
+
|
|
32
|
+
optionals.where("LOWER(name_translate->>'#{I18n.locale.to_s}') ILIKE LOWER(?) OR name ILIKE LOWER(?)", "%#{term}%", "%#{term}%")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def struct_json(optionals)
|
|
36
|
+
{
|
|
37
|
+
limit_value: optionals.limit_value,
|
|
38
|
+
current_page: optionals.current_page,
|
|
39
|
+
total_pages: optionals.total_pages,
|
|
40
|
+
total_objects: optionals.total_count,
|
|
41
|
+
optionals: serializer(optionals)
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def serializer(optionals)
|
|
46
|
+
ActiveModelSerializers::SerializableResource.new(optionals,
|
|
47
|
+
each_serializer: ::Demographic::Optionals::ListSerializer)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Demographic
|
|
2
|
+
module Optionals
|
|
3
|
+
class OptionalValues
|
|
4
|
+
attr_accessor :adjustable, :optional, :page, :term, :per_page
|
|
5
|
+
|
|
6
|
+
def initialize(adjustable:, optional:, page:, term:, per_page:)
|
|
7
|
+
@adjustable = adjustable
|
|
8
|
+
@optional = optional
|
|
9
|
+
@page = page || 1
|
|
10
|
+
@term = term.try(:downcase)
|
|
11
|
+
@per_page = per_page || 20
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call
|
|
15
|
+
search(is_json: true)
|
|
16
|
+
rescue ActiveRecord::StatementInvalid
|
|
17
|
+
search(is_json: false)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def search(is_json:)
|
|
23
|
+
values = optional.optional_values
|
|
24
|
+
values = search_term(values, is_json)
|
|
25
|
+
values = values.page(page).per(per_page)
|
|
26
|
+
struct_json(values)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def search_term(values, is_json = true)
|
|
30
|
+
return values unless term.present?
|
|
31
|
+
return values.where("value LIKE ?", "%#{term}%") unless is_json
|
|
32
|
+
|
|
33
|
+
values.where("LOWER(value) ILIKE LOWER(?)", "%#{term}%")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def struct_json(values)
|
|
37
|
+
{
|
|
38
|
+
limit_value: values.limit_value,
|
|
39
|
+
current_page: values.current_page,
|
|
40
|
+
total_pages: values.total_pages,
|
|
41
|
+
total_objects: values.total_count,
|
|
42
|
+
values: serializer(values)
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def serializer(values)
|
|
47
|
+
ActiveModelSerializers::SerializableResource.new(values,
|
|
48
|
+
each_serializer: ::Demographic::Optionals::ValueSerializer)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
module Demographic
|
|
2
|
+
module Optionals
|
|
3
|
+
class Update
|
|
4
|
+
|
|
5
|
+
attr_accessor :optional, :data, :adjustable
|
|
6
|
+
|
|
7
|
+
def initialize(adjustable:, optional:, data:)
|
|
8
|
+
@data = data
|
|
9
|
+
@optional = optional
|
|
10
|
+
@adjustable = adjustable
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call
|
|
14
|
+
ActiveRecord::Base.transaction do
|
|
15
|
+
validation_optional
|
|
16
|
+
validation_type
|
|
17
|
+
update_optional
|
|
18
|
+
update_values_list
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
optional
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def validation_optional
|
|
27
|
+
unless data[:input_type].present?
|
|
28
|
+
optional.errors.add(:input_type, 'input_type is empty')
|
|
29
|
+
raise ActiveRecord::RecordInvalid.new(optional)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
if !data[:name_translate].present? || !data[:name_translate].values.any?{ |v| v.present? }
|
|
33
|
+
optional.errors.add(:name_translate, 'name_translate is empty')
|
|
34
|
+
raise ActiveRecord::RecordInvalid.new(optional)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
if data[:input_type] == 'list' && !any_valid?
|
|
38
|
+
optional.errors.add(:values, 'values is empty')
|
|
39
|
+
raise ActiveRecord::RecordInvalid, optional
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def validation_type
|
|
44
|
+
if Demographic.simple_inputs.include?(optional.input_type)
|
|
45
|
+
unless Demographic.simple_inputs.include?(data[:input_type])
|
|
46
|
+
optional.errors.add(:input_type, 'input_type error, must be simple_input')
|
|
47
|
+
raise ActiveRecord::RecordInvalid.new(optional)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
if Demographic.multiples_inputs.include?(optional.input_type)
|
|
52
|
+
unless Demographic.multiples_inputs.include?(data[:input_type])
|
|
53
|
+
optional.errors.add(:input_type, 'input_type error, must be multiple_input')
|
|
54
|
+
raise ActiveRecord::RecordInvalid.new(optional)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def update_optional
|
|
60
|
+
optional.name = name
|
|
61
|
+
optional.code = code
|
|
62
|
+
optional.input_type = data[:input_type]
|
|
63
|
+
optional.min_value = data[:min_value]
|
|
64
|
+
optional.max_value = data[:max_value]
|
|
65
|
+
optional.name_translate = data[:name_translate]
|
|
66
|
+
optional.order = data[:order_num] || 1
|
|
67
|
+
optional.save!
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def update_values_list
|
|
72
|
+
Demographic::OptionalValues::UpdateList.new(adjustable: adjustable,
|
|
73
|
+
values: data[:values],
|
|
74
|
+
optional: optional).call
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def name
|
|
78
|
+
return data[:name_translate]['es'] if data[:name_translate]['es'].present?
|
|
79
|
+
|
|
80
|
+
data[:name_translate].values.detect{|v| v.present? }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def any_valid?
|
|
84
|
+
return false if data[:values].blank?
|
|
85
|
+
data[:values].any? { |value| value[:is_valid].to_d == 1 }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
private
|
|
89
|
+
|
|
90
|
+
def code
|
|
91
|
+
if data[:code].is_a?(String)
|
|
92
|
+
data[:code].parameterize.str_slug
|
|
93
|
+
else
|
|
94
|
+
name.parameterize.str_slug
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
module Demographic
|
|
2
|
+
module Parse
|
|
3
|
+
class DataSerializer
|
|
4
|
+
attr_reader :users_data, :adjustable, :optionals_by_code, :initialize_error, :user_ids_by_token
|
|
5
|
+
|
|
6
|
+
KEY_REGEX = /^optional_/
|
|
7
|
+
|
|
8
|
+
def initialize(users_data:, parent_module:, reference_id:)
|
|
9
|
+
@users_data = users_data
|
|
10
|
+
@adjustable = find_adjustable(parent_module, reference_id)
|
|
11
|
+
@optionals_by_code ||= @adjustable.optionals.all.index_by(&:code)
|
|
12
|
+
@user_ids_by_token = build_user_ids_by_token(@users_data)
|
|
13
|
+
rescue => e
|
|
14
|
+
@initialize_error = e
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def call
|
|
18
|
+
return response_instance(success: false, message: initialize_error, data: []) if initialize_error.present?
|
|
19
|
+
|
|
20
|
+
data = users_data.reduce([]) do |formatted_optional_values, user_data|
|
|
21
|
+
next formatted_optional_values if user_data['token'].blank?
|
|
22
|
+
next formatted_optional_values if user_ids_by_token[user_data['token']].blank?
|
|
23
|
+
|
|
24
|
+
optionals = user_data.select { |key, _value| KEY_REGEX.match?(key) }
|
|
25
|
+
|
|
26
|
+
next formatted_optional_values if optionals.blank?
|
|
27
|
+
|
|
28
|
+
formatted_optional_values + get_optionals_values(optionals, user_data['token'])
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
response_instance(success: true, message: '', data: data)
|
|
32
|
+
rescue => error
|
|
33
|
+
response_instance(success: false, message: error, data: [])
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def find_adjustable(parent_module, reference_id)
|
|
39
|
+
parent_model(parent_module).to_s.capitalize.classify.constantize.find_by!(id: reference_id)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def parent_model(parent_module)
|
|
43
|
+
parent = Demographic.parent_model[parent_module.to_sym]
|
|
44
|
+
raise 'init Demographic parent_model error param :module!!!' unless parent.present?
|
|
45
|
+
|
|
46
|
+
parent
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def get_optionals_values(optionals, user_token)
|
|
50
|
+
optionals.reduce([]) do |optional_values, (key, value)|
|
|
51
|
+
optional_code = key.to_s.gsub('optional_', '')
|
|
52
|
+
optional = optionals_by_code[optional_code]
|
|
53
|
+
|
|
54
|
+
next optional_values unless optional.present?
|
|
55
|
+
|
|
56
|
+
format_value = ::Demographic::Parse::Types::Values.new(optional: optional,
|
|
57
|
+
value: value,
|
|
58
|
+
user_id: user_ids_by_token[user_token]).call
|
|
59
|
+
next optional_values unless format_value.is_valid?
|
|
60
|
+
|
|
61
|
+
optional_values << format_value.value
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def response_instance(success:, message:, data:)
|
|
66
|
+
Struct.new(:success, :message, :data)
|
|
67
|
+
.new(success, message, data)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def build_user_ids_by_token(users_data)
|
|
71
|
+
user_ids = {}
|
|
72
|
+
users_data.each_slice(1000).map do |users_data_slice|
|
|
73
|
+
users_tokens = users_data_slice.map { |user_data| user_data['token'] }.compact.uniq
|
|
74
|
+
|
|
75
|
+
user_ids.merge!(get_user_ids_by_token(users_tokens))
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
user_ids
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def get_user_ids_by_token(users_tokens)
|
|
82
|
+
return adjustable.users.where(token: users_tokens).pluck(:token, :id).to_h if adjustable.respond_to?(:users)
|
|
83
|
+
User.where(token: users_tokens).pluck(:token, :id).to_h
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
module Demographic
|
|
2
|
+
module Parse
|
|
3
|
+
module Types
|
|
4
|
+
class Values
|
|
5
|
+
attr_reader :optional, :value, :user_id
|
|
6
|
+
|
|
7
|
+
STRUCT = Struct.new(:is_valid?, :value)
|
|
8
|
+
DATE_FORMATS = %w[%d-%m-%Y %d/%m/%Y %Y-%m-%d %Y/%m/%d]
|
|
9
|
+
BOOL_HASH = { '0' => 'false', '1' => 'true' }
|
|
10
|
+
|
|
11
|
+
def initialize(optional:, value:, user_id:)
|
|
12
|
+
@optional = optional
|
|
13
|
+
@value = value
|
|
14
|
+
@user_id = user_id
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def call
|
|
18
|
+
build_value
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def build_value
|
|
24
|
+
return struct_instance unless struct_instance.is_valid?
|
|
25
|
+
|
|
26
|
+
parse_value
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def struct_instance
|
|
30
|
+
@struct_instance ||= build_struct
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def build_struct
|
|
34
|
+
return STRUCT.new(false, value.to_s) unless value.to_s.present?
|
|
35
|
+
|
|
36
|
+
return build_text_or_list_struct if optional.input_type.eql?('list') || optional.input_type.eql?('text')
|
|
37
|
+
|
|
38
|
+
return build_number_struct if optional.input_type.eql?('number')
|
|
39
|
+
|
|
40
|
+
return build_date_struct if optional.input_type.eql?('date')
|
|
41
|
+
|
|
42
|
+
return build_bool_struct if optional.input_type.eql?('bool')
|
|
43
|
+
|
|
44
|
+
STRUCT.new(false, value.to_s)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def build_text_or_list_struct
|
|
48
|
+
STRUCT.new(true, value)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def build_number_struct
|
|
52
|
+
STRUCT.new(value.to_s.is_numeric?, value)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def build_date_struct
|
|
56
|
+
DATE_FORMATS.each do |date_format|
|
|
57
|
+
date = format_date(date_format)
|
|
58
|
+
return STRUCT.new(true, date) if date != false
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
STRUCT.new(false, value.to_s)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def format_date(date_format)
|
|
65
|
+
date = Date.strptime(value, date_format)
|
|
66
|
+
return false if date.year.to_s.length != 4
|
|
67
|
+
date.strftime
|
|
68
|
+
rescue StandardError => e
|
|
69
|
+
false
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def build_bool_struct
|
|
73
|
+
bool = BOOL_HASH[value.to_i.to_s]
|
|
74
|
+
|
|
75
|
+
STRUCT.new(bool.present?, bool)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def parse_value
|
|
79
|
+
struct_value = struct_instance.value.to_s
|
|
80
|
+
slug = struct_value.str_slug
|
|
81
|
+
code = Demographic.generate_code(optional.id, slug)
|
|
82
|
+
|
|
83
|
+
parsed_value = {
|
|
84
|
+
user_id: user_id,
|
|
85
|
+
optional_id: optional.id,
|
|
86
|
+
token: Demographic.generate_token,
|
|
87
|
+
value: struct_value,
|
|
88
|
+
value_translate: { es: struct_value },
|
|
89
|
+
code: code,
|
|
90
|
+
slug: slug
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
struct_instance.value = parsed_value
|
|
94
|
+
struct_instance
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Demographic
|
|
4
|
+
module UserOptionals
|
|
5
|
+
class List
|
|
6
|
+
attr_accessor :user, :adjustable
|
|
7
|
+
|
|
8
|
+
def initialize(user:, adjustable:)
|
|
9
|
+
@user = user
|
|
10
|
+
@adjustable = adjustable
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def perform
|
|
14
|
+
{ optionals: list_optionals }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def list_optionals
|
|
20
|
+
optionals = adjustable.optionals.includes(:optional_values)
|
|
21
|
+
optionals.map do |optional|
|
|
22
|
+
hash = {
|
|
23
|
+
id: optional.id,
|
|
24
|
+
code: optional.code,
|
|
25
|
+
token: optional.token,
|
|
26
|
+
name: optional.name_translate[I18n.locale.to_s] || optional.name,
|
|
27
|
+
input_type: optional.input_type,
|
|
28
|
+
selected_text: '',
|
|
29
|
+
values: []
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
hash[:selected_text] = selected_text(optional) if Demographic.simple_inputs.include?(optional.input_type)
|
|
33
|
+
hash[:values] = selected_values(optional) if Demographic.multiples_inputs.include?(optional.input_type)
|
|
34
|
+
hash
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def selected_text(optional)
|
|
39
|
+
result = user_optionals[optional.id]
|
|
40
|
+
result&.optional_value&.value_translate&.dig(I18n.locale.to_s) || result&.value
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def selected_values(optional)
|
|
44
|
+
optional.optional_values.map do |value|
|
|
45
|
+
{
|
|
46
|
+
id: value.id,
|
|
47
|
+
slug: value.slug,
|
|
48
|
+
code: value.code,
|
|
49
|
+
value: value.value_translate[I18n.locale.to_s],
|
|
50
|
+
selected: user_optionals[optional.id]&.optional_value_id == value.id
|
|
51
|
+
}
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def user_optionals
|
|
56
|
+
@user_optionals ||= user.user_optionals.index_by(&:optional_id)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Import
|
|
2
|
+
module Templates
|
|
3
|
+
class CreateOptionals
|
|
4
|
+
FILE_NAME = 'create_optionals_template.xlsx'
|
|
5
|
+
HEADERS = %w[name type module code].freeze
|
|
6
|
+
|
|
7
|
+
def call
|
|
8
|
+
xlsx_service.create_temp_file
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def xlsx_service
|
|
14
|
+
@xlsx_service ||= Import::Templates::Xlsx.new(sheets: sheets, file_name: FILE_NAME)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def sheets
|
|
18
|
+
[{ name: 'optionals', headers: HEADERS, style_headers: { b: true, sz: 14, bg_color: "E2F0D9" }, rows: rows }]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def rows
|
|
22
|
+
[%w[Antigüedad list position antigüedad-001], %w[edad number master edad-001], ['fecha de ingreso', 'date', 'master', 'fecha-ingreso-001']]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Import
|
|
2
|
+
module Templates
|
|
3
|
+
class Xlsx
|
|
4
|
+
attr_reader :sheets, :xlsx, :workbook, :file_name
|
|
5
|
+
|
|
6
|
+
def initialize(sheets:, file_name:)
|
|
7
|
+
@sheets = sheets
|
|
8
|
+
@file_name = file_name
|
|
9
|
+
@xlsx = Axlsx::Package.new
|
|
10
|
+
@workbook = xlsx.workbook
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def create_temp_file
|
|
14
|
+
add_worksheets
|
|
15
|
+
|
|
16
|
+
temp_file
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def add_worksheets
|
|
22
|
+
sheets.each do |sheet_data|
|
|
23
|
+
workbook.add_worksheet(name: sheet_data[:name]) do |sheet|
|
|
24
|
+
sheet.add_row(sheet_data[:headers], style: workbook.styles.add_style(sheet_data[:style_headers]), height: 17)
|
|
25
|
+
|
|
26
|
+
sheet_data[:rows].each do |row|
|
|
27
|
+
sheet.add_row row
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def temp_file
|
|
34
|
+
return @temp_file if @temp_file.present?
|
|
35
|
+
|
|
36
|
+
@temp_file = Tempfile.new(file_name)
|
|
37
|
+
xlsx.use_shared_strings = true
|
|
38
|
+
xlsx.serialize(temp_file.path)
|
|
39
|
+
|
|
40
|
+
@temp_file
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
Demographic::Engine.routes.draw do
|
|
2
|
+
resources :optionals, path: '', only: [] do
|
|
3
|
+
collection do
|
|
4
|
+
get 'optionals/list' => 'optionals#index', defaults: { adjustable_id: nil }
|
|
5
|
+
get ':module/optionals/list/:adjustable_id' => 'optionals#index'
|
|
6
|
+
get 'optionals/options' => 'optionals#options'
|
|
7
|
+
get ':module/optionals/:optional_id/show/:adjustable_id' => 'optionals#show'
|
|
8
|
+
post ':module/optionals/create/:adjustable_id' => 'optionals#create'
|
|
9
|
+
put ':module/optionals/:optional_id/update/:adjustable_id' => 'optionals#update'
|
|
10
|
+
delete ':module/optionals/:optional_id/update/:adjustable_id' => 'optionals#destroy'
|
|
11
|
+
get ':module/optionals/filterList/:adjustable_id' => 'optionals#filter_list'
|
|
12
|
+
get ':module/optionals/:optional_token/optionalValues/:adjustable_id' => 'optionals#optional_values'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
scope path: ':module' do
|
|
17
|
+
scope path: 'optionals_bulk' do
|
|
18
|
+
scope path: ':adjustable_id' do
|
|
19
|
+
resources :optionals_bulk, path: '', only: [] do
|
|
20
|
+
collection do
|
|
21
|
+
get 'create_template' => 'optionals_bulk#create_template'
|
|
22
|
+
post 'create' => 'optionals_bulk#create'
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
resources :optionals_types, path: 'optionalTypes', only: [:index]
|
|
30
|
+
|
|
31
|
+
resources :user_optionals, path: '', only: [] do
|
|
32
|
+
collection do
|
|
33
|
+
get ':module/userOptionals/list/:adjustable_id' => 'user_optionals#index'
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
get ':module/customParameterValues/index/:adjustable_id' => 'custom_parameter_values#index'
|
|
38
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class CreateDemographicOptionals < ActiveRecord::Migration[6.0]
|
|
2
|
+
def change
|
|
3
|
+
create_table :optionals do |t|
|
|
4
|
+
t.integer :adjustable_id, null: false
|
|
5
|
+
t.string :adjustable_type, null: false
|
|
6
|
+
t.string :name
|
|
7
|
+
t.json :name_translate, default: {}
|
|
8
|
+
t.string :code, null: false
|
|
9
|
+
t.string :input_type, default: 'list'
|
|
10
|
+
t.integer :order, default: 1
|
|
11
|
+
t.string :min_value
|
|
12
|
+
t.string :max_value
|
|
13
|
+
t.timestamps
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
add_index :optionals, [:adjustable_id, :adjustable_type], :name => 'index_adjustable_type_and_adjustable_id'
|
|
17
|
+
end
|
|
18
|
+
end
|