apidae 0.7.3 → 0.7.4
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 +4 -4
- data/MIT-LICENSE +20 -20
- data/README.rdoc +2 -2
- data/Rakefile +38 -38
- data/app/assets/images/apidae/logo-apidae-grey.svg +84 -84
- data/app/assets/javascripts/apidae/application.js +13 -13
- data/app/assets/stylesheets/apidae/application.css +15 -15
- data/app/controllers/apidae/api_controller.rb +25 -25
- data/app/controllers/apidae/application_controller.rb +6 -6
- data/app/controllers/apidae/dashboard_controller.rb +13 -13
- data/app/controllers/apidae/import_controller.rb +68 -68
- data/app/controllers/apidae/objects_controller.rb +59 -59
- data/app/controllers/apidae/projects_controller.rb +35 -35
- data/app/controllers/apidae/references_controller.rb +9 -9
- data/app/controllers/apidae/selections_controller.rb +53 -53
- data/app/helpers/apidae/api_helper.rb +4 -4
- data/app/helpers/apidae/application_helper.rb +4 -4
- data/app/helpers/apidae/dashboard_helper.rb +4 -4
- data/app/helpers/apidae/import_helper.rb +4 -4
- data/app/helpers/apidae/objects_helper.rb +4 -4
- data/app/helpers/apidae/references_helper.rb +4 -4
- data/app/helpers/apidae/selections_helper.rb +4 -4
- data/app/models/apidae/application_record.rb +5 -5
- data/app/models/apidae/export.rb +13 -13
- data/app/models/apidae/file_import.rb +161 -161
- data/app/models/apidae/obj.rb +351 -351
- data/app/models/apidae/project.rb +4 -4
- data/app/models/apidae/reference.rb +45 -45
- data/app/models/apidae/selection.rb +160 -160
- data/app/models/apidae/selection_object.rb +6 -6
- data/app/models/apidae/town.rb +28 -27
- data/app/views/apidae/dashboard/index.html.erb +41 -41
- data/app/views/apidae/import/callback.html.erb +2 -2
- data/app/views/apidae/objects/_form.html.erb +73 -73
- data/app/views/apidae/objects/edit.html.erb +6 -6
- data/app/views/apidae/objects/index.html.erb +34 -34
- data/app/views/apidae/objects/index.json.jbuilder +6 -6
- data/app/views/apidae/objects/new.html.erb +5 -5
- data/app/views/apidae/objects/show.html.erb +74 -74
- data/app/views/apidae/projects/edit.html.erb +32 -32
- data/app/views/apidae/projects/index.html.erb +34 -34
- data/app/views/apidae/references/index.html.erb +34 -34
- data/app/views/apidae/selections/_form.html.erb +29 -29
- data/app/views/apidae/selections/edit.html.erb +6 -6
- data/app/views/apidae/selections/index.html.erb +34 -34
- data/app/views/apidae/selections/new.html.erb +5 -5
- data/app/views/apidae/selections/show.html.erb +19 -19
- data/app/views/layouts/apidae/application.html.erb +14 -14
- data/config/locales/apidae.fr.yml +6 -6
- data/config/routes.rb +14 -14
- data/db/migrate/20170512212941_create_apidae_selections.rb +11 -11
- data/db/migrate/20170512214641_create_apidae_objects.rb +22 -22
- data/db/migrate/20170512221525_create_apidae_objects_apidae_selections.rb +8 -8
- data/db/migrate/20170513114002_create_apidae_towns.rb +15 -15
- data/db/migrate/20170513114409_add_town_insee_code_to_objects.rb +5 -5
- data/db/migrate/20170513115401_add_pictures_data_to_objects.rb +5 -5
- data/db/migrate/20170513121215_create_apidae_attached_files.rb +13 -13
- data/db/migrate/20170513205932_rename_objects_selections_table.rb +5 -5
- data/db/migrate/20170720161134_add_entity_data_to_objects.rb +5 -5
- data/db/migrate/20170730102424_create_apidae_file_imports.rb +13 -13
- data/db/migrate/20171025075304_create_apidae_exports.rb +15 -15
- data/db/migrate/20180217222410_create_apidae_selection_objects.rb +10 -10
- data/db/migrate/20180218172704_change_text_columns_to_json.rb +10 -10
- data/db/migrate/20180218231319_add_service_data_to_apidae_objects.rb +5 -5
- data/db/migrate/20180222104915_add_rates_data_to_apidae_objects.rb +6 -6
- data/db/migrate/20180222105302_rename_openings_to_openings_data.rb +5 -5
- data/db/migrate/20180307164936_add_attachments_data_to_apidae_objects.rb +5 -5
- data/db/migrate/20180307170349_create_apidae_references.rb +12 -12
- data/db/migrate/20180314093512_add_tags_data_to_apidae_objects.rb +5 -5
- data/db/migrate/20180314132631_add_meta_data_to_apidae_objects.rb +5 -5
- data/db/migrate/20180319143954_remove_apidae_id_unicity.rb +6 -6
- data/db/migrate/20180417164604_add_location_data_to_apidae_objects.rb +5 -5
- data/db/migrate/20180417165744_remove_address_from_apidae_objects.rb +5 -5
- data/db/migrate/20180417171344_remove_lat_lng_from_apidae_objects.rb +6 -6
- data/db/migrate/20180418141248_add_description_data_to_apidae_objects.rb +5 -5
- data/db/migrate/20180418141305_remove_desc_columns_from_apidae_objects.rb +6 -6
- data/db/migrate/20180424141656_add_meta_data_to_apidae_references.rb +5 -5
- data/db/migrate/20180519170210_remove_insee_code_unicity.rb +7 -7
- data/db/migrate/20180521211735_destroy_attached_files.rb +5 -5
- data/db/migrate/20180625050400_rename_objects_to_obj.rb +5 -5
- data/db/migrate/20181024072424_add_project_id_to_selections.rb +5 -5
- data/db/migrate/20181024072843_create_apidae_projects.rb +10 -10
- data/db/migrate/20190328122424_add_description_to_apidae_towns.rb +5 -0
- data/lib/apidae.rb +4 -4
- data/lib/apidae/engine.rb +10 -10
- data/lib/apidae/version.rb +3 -3
- data/lib/tasks/apidae_tasks.rake +4 -4
- data/test/apidae_test.rb +7 -7
- data/test/controllers/apidae/api_controller_test.rb +23 -23
- data/test/controllers/apidae/dashboard_controller_test.rb +15 -15
- data/test/controllers/apidae/import_controller_test.rb +15 -15
- data/test/controllers/apidae/objects_controller_test.rb +52 -52
- data/test/controllers/apidae/references_controller_test.rb +13 -13
- data/test/controllers/apidae/selections_controller_test.rb +52 -52
- data/test/data/selections.json +14 -14
- data/test/data/structure.json +64 -64
- data/test/data/update_selections.json +18 -18
- data/test/dummy/README.rdoc +28 -28
- data/test/dummy/Rakefile +6 -6
- data/test/dummy/app/assets/javascripts/application.js +13 -13
- data/test/dummy/app/assets/stylesheets/application.css +15 -15
- data/test/dummy/app/controllers/application_controller.rb +5 -5
- data/test/dummy/app/helpers/application_helper.rb +2 -2
- data/test/dummy/app/views/layouts/application.html.erb +14 -14
- data/test/dummy/bin/bundle +3 -3
- data/test/dummy/bin/rails +4 -4
- data/test/dummy/bin/rake +4 -4
- data/test/dummy/bin/setup +29 -29
- data/test/dummy/config.ru +4 -4
- data/test/dummy/config/application.rb +24 -24
- data/test/dummy/config/boot.rb +5 -5
- data/test/dummy/config/database.yml +20 -20
- data/test/dummy/config/environment.rb +5 -5
- data/test/dummy/config/environments/development.rb +41 -41
- data/test/dummy/config/environments/production.rb +79 -79
- data/test/dummy/config/environments/test.rb +42 -42
- data/test/dummy/config/initializers/apidae.rb +18 -18
- data/test/dummy/config/initializers/assets.rb +11 -11
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -7
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -3
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -4
- data/test/dummy/config/initializers/inflections.rb +16 -16
- data/test/dummy/config/initializers/mime_types.rb +4 -4
- data/test/dummy/config/initializers/session_store.rb +3 -3
- data/test/dummy/config/initializers/to_time_preserves_timezone.rb +10 -10
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -14
- data/test/dummy/config/locales/en.yml +23 -23
- data/test/dummy/config/routes.rb +4 -4
- data/test/dummy/config/secrets.yml +22 -22
- data/test/dummy/db/schema.rb +104 -104
- data/test/dummy/public/404.html +67 -67
- data/test/dummy/public/422.html +67 -67
- data/test/dummy/public/500.html +66 -66
- data/test/fixtures/apidae/exports.yml +15 -15
- data/test/fixtures/apidae/objects.yml +33 -33
- data/test/fixtures/apidae/references.yml +11 -11
- data/test/fixtures/apidae/selection_objects.yml +9 -9
- data/test/fixtures/apidae/selections.yml +11 -11
- data/test/fixtures/apidae/towns.yml +15 -15
- data/test/integration/navigation_test.rb +8 -8
- data/test/models/apidae/export_test.rb +9 -9
- data/test/models/apidae/file_import_test.rb +88 -88
- data/test/models/apidae/object_test.rb +9 -9
- data/test/models/apidae/reference_test.rb +9 -9
- data/test/models/apidae/selection_object_test.rb +9 -9
- data/test/models/apidae/selection_test.rb +9 -9
- data/test/models/apidae/town_test.rb +9 -9
- data/test/test_helper.rb +22 -22
- metadata +49 -50
- data/test/dummy/log/test.log +0 -2109
@@ -1,4 +1,4 @@
|
|
1
|
-
module Apidae
|
2
|
-
module ApiHelper
|
3
|
-
end
|
4
|
-
end
|
1
|
+
module Apidae
|
2
|
+
module ApiHelper
|
3
|
+
end
|
4
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Apidae
|
2
|
-
module ApplicationHelper
|
3
|
-
end
|
4
|
-
end
|
1
|
+
module Apidae
|
2
|
+
module ApplicationHelper
|
3
|
+
end
|
4
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Apidae
|
2
|
-
module DashboardHelper
|
3
|
-
end
|
4
|
-
end
|
1
|
+
module Apidae
|
2
|
+
module DashboardHelper
|
3
|
+
end
|
4
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Apidae
|
2
|
-
module ImportHelper
|
3
|
-
end
|
4
|
-
end
|
1
|
+
module Apidae
|
2
|
+
module ImportHelper
|
3
|
+
end
|
4
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Apidae
|
2
|
-
module ObjectsHelper
|
3
|
-
end
|
4
|
-
end
|
1
|
+
module Apidae
|
2
|
+
module ObjectsHelper
|
3
|
+
end
|
4
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Apidae
|
2
|
-
module ReferencesHelper
|
3
|
-
end
|
4
|
-
end
|
1
|
+
module Apidae
|
2
|
+
module ReferencesHelper
|
3
|
+
end
|
4
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Apidae
|
2
|
-
module SelectionsHelper
|
3
|
-
end
|
4
|
-
end
|
1
|
+
module Apidae
|
2
|
+
module SelectionsHelper
|
3
|
+
end
|
4
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
module Apidae
|
2
|
-
class ApplicationRecord < ActiveRecord::Base
|
3
|
-
self.abstract_class = true
|
4
|
-
end
|
5
|
-
end
|
1
|
+
module Apidae
|
2
|
+
class ApplicationRecord < ActiveRecord::Base
|
3
|
+
self.abstract_class = true
|
4
|
+
end
|
5
|
+
end
|
data/app/models/apidae/export.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
module Apidae
|
2
|
-
class Export < ActiveRecord::Base
|
3
|
-
|
4
|
-
PENDING = 'pending'
|
5
|
-
COMPLETE = 'complete'
|
6
|
-
CANCELLED = 'cancelled'
|
7
|
-
|
8
|
-
# Note : handle reset case
|
9
|
-
def self.pending
|
10
|
-
where(remote_status: 'SUCCESS', status: PENDING).order(:id)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
1
|
+
module Apidae
|
2
|
+
class Export < ActiveRecord::Base
|
3
|
+
|
4
|
+
PENDING = 'pending'
|
5
|
+
COMPLETE = 'complete'
|
6
|
+
CANCELLED = 'cancelled'
|
7
|
+
|
8
|
+
# Note : handle reset case
|
9
|
+
def self.pending
|
10
|
+
where(remote_status: 'SUCCESS', status: PENDING).order(:id)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -1,161 +1,161 @@
|
|
1
|
-
require 'zip'
|
2
|
-
|
3
|
-
module Apidae
|
4
|
-
class FileImport < ActiveRecord::Base
|
5
|
-
|
6
|
-
STATUS_PENDING = 'pending'
|
7
|
-
STATUS_COMPLETE = 'complete'
|
8
|
-
STATUS_CANCELLED = 'cancelled'
|
9
|
-
|
10
|
-
TOWNS_FILE = 'communes.json'
|
11
|
-
INTERNAL_FILE = 'criteres_internes.json'
|
12
|
-
REFERENCES_FILE = 'elements_reference.json'
|
13
|
-
MODIFIED_DIR = 'objets_modifies'
|
14
|
-
DELETED_FILE = 'objets_supprimes.json'
|
15
|
-
SELECTIONS_FILE = 'selections.json'
|
16
|
-
|
17
|
-
def self.import(zip_file, project_id)
|
18
|
-
Zip::File.open(zip_file) do |zfile|
|
19
|
-
result = {created: 0, updated: 0, deleted: 0, selections: []}
|
20
|
-
Reference.import(zfile.read(REFERENCES_FILE))
|
21
|
-
Reference.import_internal(zfile.read(INTERNAL_FILE))
|
22
|
-
logger.info "Completed #{Reference.count} references update"
|
23
|
-
Town.import(zfile.read(TOWNS_FILE))
|
24
|
-
logger.info "Completed #{Town.count} towns update"
|
25
|
-
zfile.each do |file|
|
26
|
-
if file.file? && file.name.end_with?('.json')
|
27
|
-
logger.info "Processing file : #{file.name}"
|
28
|
-
if file.name.include?(MODIFIED_DIR)
|
29
|
-
add_or_update_objects(zfile.read(file.name), result)
|
30
|
-
elsif file.name.include?(DELETED_FILE)
|
31
|
-
delete_objects(zfile.read(file.name), result)
|
32
|
-
elsif file.name.include?(SELECTIONS_FILE)
|
33
|
-
add_or_update_selections(project_id, zfile.read(file.name), result)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
create(result.except(:selections).merge({remote_file: (zip_file.is_a?(File) ? zip_file.path : zip_file), status: STATUS_COMPLETE}))
|
38
|
-
logger.info "Import results : #{result}"
|
39
|
-
result
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.import_dir(project_id, dir)
|
44
|
-
result = {created: 0, updated: 0, deleted: 0, selections: []}
|
45
|
-
import_updates(File.join(dir, MODIFIED_DIR), result)
|
46
|
-
import_deletions(File.join(dir, DELETED_FILE), result)
|
47
|
-
import_selections(project_id, File.join(dir, SELECTIONS_FILE), result)
|
48
|
-
logger.info "Import results : #{result}"
|
49
|
-
result
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.import_updates(json_dir, result)
|
53
|
-
if Dir.exist?(json_dir)
|
54
|
-
Dir.foreach(json_dir) do |f|
|
55
|
-
if f.end_with?('.json')
|
56
|
-
json_file = File.join(json_dir, f)
|
57
|
-
objects_json = File.read(json_file)
|
58
|
-
add_or_update_objects(objects_json, result)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.add_or_update_objects(objects_json, result)
|
65
|
-
objects_hashes = JSON.parse(objects_json, symbolize_names: true)
|
66
|
-
objects_hashes.each do |object_data|
|
67
|
-
begin
|
68
|
-
existing = Obj.find_by_apidae_id(object_data[:id])
|
69
|
-
if existing
|
70
|
-
Obj.update_object(existing, object_data)
|
71
|
-
result[:updated] += 1
|
72
|
-
else
|
73
|
-
Obj.add_object(object_data)
|
74
|
-
result[:created] += 1
|
75
|
-
end
|
76
|
-
rescue Exception => e
|
77
|
-
puts "Failed to import object #{object_data[:id]}"
|
78
|
-
puts e.message
|
79
|
-
puts e.backtrace[0..5].join("\n")
|
80
|
-
raise e
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def self.import_deletions(json_file, result)
|
86
|
-
if File.exist?(json_file)
|
87
|
-
deleted_json = File.read(json_file)
|
88
|
-
delete_objects(deleted_json, result)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.delete_objects(deleted_json, result)
|
93
|
-
deleted_ids = JSON.parse(deleted_json)
|
94
|
-
deleted_ids.each do |id|
|
95
|
-
obj = Obj.find_by_apidae_id(id)
|
96
|
-
if obj
|
97
|
-
obj.destroy!
|
98
|
-
result[:deleted] += 1
|
99
|
-
else
|
100
|
-
logger.info "skipping object deletion : #{id}"
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def self.update_fields(json_dir)
|
106
|
-
result = false
|
107
|
-
if Dir.exist?(json_dir)
|
108
|
-
Dir.foreach(json_dir) do |f|
|
109
|
-
if f.end_with?('.json')
|
110
|
-
json_file = File.join(json_dir, f)
|
111
|
-
objects_json = File.read(json_file)
|
112
|
-
objects_hashes = JSON.parse(objects_json, symbolize_names: true)
|
113
|
-
objects_hashes.each do |object_data|
|
114
|
-
obj = Obj.find_by_apidae_id(object_data[:id])
|
115
|
-
if obj
|
116
|
-
yield(obj, object_data)
|
117
|
-
obj.save!
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
result = true
|
122
|
-
end
|
123
|
-
result
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
# def self.load_pictures
|
128
|
-
# Apidae::Object.all.each do |obj|
|
129
|
-
# if obj.apidae_attached_files.blank? && obj.pictures.any?
|
130
|
-
# obj.pictures.each do |pic|
|
131
|
-
# begin
|
132
|
-
# attached = Apidae::AttachedFile.new(apidae_object_id: id, name: pic[:name], picture: URI.parse(pic[:url]),
|
133
|
-
# description: pic[:description], credits: pic[:credits])
|
134
|
-
# attached.save
|
135
|
-
# rescue OpenURI::HTTPError => e
|
136
|
-
# logger.error "Could not retrieve attached picture for object #{title} - Error is #{e.message}"
|
137
|
-
# end
|
138
|
-
# end
|
139
|
-
# end
|
140
|
-
# end
|
141
|
-
# end
|
142
|
-
|
143
|
-
def self.import_selections(project_id, json_file, result)
|
144
|
-
selections_json = File.read(json_file)
|
145
|
-
add_or_update_selections(project_id, selections_json, result)
|
146
|
-
end
|
147
|
-
|
148
|
-
def self.add_or_update_selections(project_id, selections_json, result)
|
149
|
-
selections_hashes = JSON.parse(selections_json, symbolize_names: true)
|
150
|
-
project = Project.find_or_create_by(apidae_id: project_id)
|
151
|
-
deleted_ids = Selection.where(apidae_project_id: project.id).collect {|sel| sel.apidae_id}.uniq - selections_hashes.collect {|sel| sel[:id]}
|
152
|
-
Selection.where(apidae_id: deleted_ids).delete_all
|
153
|
-
selections_hashes.each do |selection_data|
|
154
|
-
logger.info "Updating selection #{selection_data[:id]}"
|
155
|
-
Selection.add_or_update(selection_data, project.id)
|
156
|
-
end
|
157
|
-
result[:selections] = Selection.where(apidae_project_id: project_id)
|
158
|
-
.collect {|sel| {apidae_id: sel.apidae_id, reference: sel.reference, objects: sel.objects.count}}
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
1
|
+
require 'zip'
|
2
|
+
|
3
|
+
module Apidae
|
4
|
+
class FileImport < ActiveRecord::Base
|
5
|
+
|
6
|
+
STATUS_PENDING = 'pending'
|
7
|
+
STATUS_COMPLETE = 'complete'
|
8
|
+
STATUS_CANCELLED = 'cancelled'
|
9
|
+
|
10
|
+
TOWNS_FILE = 'communes.json'
|
11
|
+
INTERNAL_FILE = 'criteres_internes.json'
|
12
|
+
REFERENCES_FILE = 'elements_reference.json'
|
13
|
+
MODIFIED_DIR = 'objets_modifies'
|
14
|
+
DELETED_FILE = 'objets_supprimes.json'
|
15
|
+
SELECTIONS_FILE = 'selections.json'
|
16
|
+
|
17
|
+
def self.import(zip_file, project_id)
|
18
|
+
Zip::File.open(zip_file) do |zfile|
|
19
|
+
result = {created: 0, updated: 0, deleted: 0, selections: []}
|
20
|
+
Reference.import(zfile.read(REFERENCES_FILE))
|
21
|
+
Reference.import_internal(zfile.read(INTERNAL_FILE))
|
22
|
+
logger.info "Completed #{Reference.count} references update"
|
23
|
+
Town.import(zfile.read(TOWNS_FILE))
|
24
|
+
logger.info "Completed #{Town.count} towns update"
|
25
|
+
zfile.each do |file|
|
26
|
+
if file.file? && file.name.end_with?('.json')
|
27
|
+
logger.info "Processing file : #{file.name}"
|
28
|
+
if file.name.include?(MODIFIED_DIR)
|
29
|
+
add_or_update_objects(zfile.read(file.name), result)
|
30
|
+
elsif file.name.include?(DELETED_FILE)
|
31
|
+
delete_objects(zfile.read(file.name), result)
|
32
|
+
elsif file.name.include?(SELECTIONS_FILE)
|
33
|
+
add_or_update_selections(project_id, zfile.read(file.name), result)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
create(result.except(:selections).merge({remote_file: (zip_file.is_a?(File) ? zip_file.path : zip_file), status: STATUS_COMPLETE}))
|
38
|
+
logger.info "Import results : #{result}"
|
39
|
+
result
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.import_dir(project_id, dir)
|
44
|
+
result = {created: 0, updated: 0, deleted: 0, selections: []}
|
45
|
+
import_updates(File.join(dir, MODIFIED_DIR), result)
|
46
|
+
import_deletions(File.join(dir, DELETED_FILE), result)
|
47
|
+
import_selections(project_id, File.join(dir, SELECTIONS_FILE), result)
|
48
|
+
logger.info "Import results : #{result}"
|
49
|
+
result
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.import_updates(json_dir, result)
|
53
|
+
if Dir.exist?(json_dir)
|
54
|
+
Dir.foreach(json_dir) do |f|
|
55
|
+
if f.end_with?('.json')
|
56
|
+
json_file = File.join(json_dir, f)
|
57
|
+
objects_json = File.read(json_file)
|
58
|
+
add_or_update_objects(objects_json, result)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.add_or_update_objects(objects_json, result)
|
65
|
+
objects_hashes = JSON.parse(objects_json, symbolize_names: true)
|
66
|
+
objects_hashes.each do |object_data|
|
67
|
+
begin
|
68
|
+
existing = Obj.find_by_apidae_id(object_data[:id])
|
69
|
+
if existing
|
70
|
+
Obj.update_object(existing, object_data)
|
71
|
+
result[:updated] += 1
|
72
|
+
else
|
73
|
+
Obj.add_object(object_data)
|
74
|
+
result[:created] += 1
|
75
|
+
end
|
76
|
+
rescue Exception => e
|
77
|
+
puts "Failed to import object #{object_data[:id]}"
|
78
|
+
puts e.message
|
79
|
+
puts e.backtrace[0..5].join("\n")
|
80
|
+
raise e
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.import_deletions(json_file, result)
|
86
|
+
if File.exist?(json_file)
|
87
|
+
deleted_json = File.read(json_file)
|
88
|
+
delete_objects(deleted_json, result)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.delete_objects(deleted_json, result)
|
93
|
+
deleted_ids = JSON.parse(deleted_json)
|
94
|
+
deleted_ids.each do |id|
|
95
|
+
obj = Obj.find_by_apidae_id(id)
|
96
|
+
if obj
|
97
|
+
obj.destroy!
|
98
|
+
result[:deleted] += 1
|
99
|
+
else
|
100
|
+
logger.info "skipping object deletion : #{id}"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.update_fields(json_dir)
|
106
|
+
result = false
|
107
|
+
if Dir.exist?(json_dir)
|
108
|
+
Dir.foreach(json_dir) do |f|
|
109
|
+
if f.end_with?('.json')
|
110
|
+
json_file = File.join(json_dir, f)
|
111
|
+
objects_json = File.read(json_file)
|
112
|
+
objects_hashes = JSON.parse(objects_json, symbolize_names: true)
|
113
|
+
objects_hashes.each do |object_data|
|
114
|
+
obj = Obj.find_by_apidae_id(object_data[:id])
|
115
|
+
if obj
|
116
|
+
yield(obj, object_data)
|
117
|
+
obj.save!
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
result = true
|
122
|
+
end
|
123
|
+
result
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# def self.load_pictures
|
128
|
+
# Apidae::Object.all.each do |obj|
|
129
|
+
# if obj.apidae_attached_files.blank? && obj.pictures.any?
|
130
|
+
# obj.pictures.each do |pic|
|
131
|
+
# begin
|
132
|
+
# attached = Apidae::AttachedFile.new(apidae_object_id: id, name: pic[:name], picture: URI.parse(pic[:url]),
|
133
|
+
# description: pic[:description], credits: pic[:credits])
|
134
|
+
# attached.save
|
135
|
+
# rescue OpenURI::HTTPError => e
|
136
|
+
# logger.error "Could not retrieve attached picture for object #{title} - Error is #{e.message}"
|
137
|
+
# end
|
138
|
+
# end
|
139
|
+
# end
|
140
|
+
# end
|
141
|
+
# end
|
142
|
+
|
143
|
+
def self.import_selections(project_id, json_file, result)
|
144
|
+
selections_json = File.read(json_file)
|
145
|
+
add_or_update_selections(project_id, selections_json, result)
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.add_or_update_selections(project_id, selections_json, result)
|
149
|
+
selections_hashes = JSON.parse(selections_json, symbolize_names: true)
|
150
|
+
project = Project.find_or_create_by(apidae_id: project_id)
|
151
|
+
deleted_ids = Selection.where(apidae_project_id: project.id).collect {|sel| sel.apidae_id}.uniq - selections_hashes.collect {|sel| sel[:id]}
|
152
|
+
Selection.where(apidae_id: deleted_ids).delete_all
|
153
|
+
selections_hashes.each do |selection_data|
|
154
|
+
logger.info "Updating selection #{selection_data[:id]}"
|
155
|
+
Selection.add_or_update(selection_data, project.id)
|
156
|
+
end
|
157
|
+
result[:selections] = Selection.where(apidae_project_id: project_id)
|
158
|
+
.collect {|sel| {apidae_id: sel.apidae_id, reference: sel.reference, objects: sel.objects.count}}
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/app/models/apidae/obj.rb
CHANGED
@@ -1,351 +1,351 @@
|
|
1
|
-
module Apidae
|
2
|
-
class Obj < ActiveRecord::Base
|
3
|
-
|
4
|
-
belongs_to :town, class_name: 'Apidae::Town', foreign_key: :town_insee_code, primary_key: :insee_code
|
5
|
-
has_many :apidae_selection_objects, class_name: 'Apidae::SelectionObject', foreign_key: :apidae_object_id
|
6
|
-
has_many :selections, class_name: 'Apidae::Selection', source: :apidae_selection, through: :apidae_selection_objects
|
7
|
-
|
8
|
-
store_accessor :description_data, :short_desc, :long_desc, :theme_desc, :private_desc
|
9
|
-
store_accessor :pictures_data, :pictures
|
10
|
-
store_accessor :attachments_data, :attachments
|
11
|
-
store_accessor :type_data, :categories, :themes, :capacity, :classification, :labels, :chains, :area, :track,
|
12
|
-
:products, :audience, :animals, :extra, :duration, :certifications
|
13
|
-
store_accessor :entity_data, :entity_id, :entity_name, :service_provider_id
|
14
|
-
store_accessor :contact, :telephone, :email, :website
|
15
|
-
store_accessor :location_data, :address, :place, :latitude, :longitude, :access, :territories, :environments
|
16
|
-
store_accessor :openings_data, :openings_desc, :openings, :time_periods
|
17
|
-
store_accessor :rates_data, :rates_desc, :rates, :payment_methods, :includes, :excludes
|
18
|
-
store_accessor :service_data, :services, :equipments, :comfort, :activities, :challenged, :languages
|
19
|
-
store_accessor :tags_data, :promo, :internal, :linked
|
20
|
-
|
21
|
-
ACT = 'ACTIVITE'
|
22
|
-
COS = 'COMMERCE_ET_SERVICE'
|
23
|
-
DEG = 'DEGUSTATION'
|
24
|
-
DOS = 'DOMAINE_SKIABLE'
|
25
|
-
EQU = 'EQUIPEMENT'
|
26
|
-
FEM = 'FETE_ET_MANIFESTATION'
|
27
|
-
HCO = 'HEBERGEMENT_COLLECTIF'
|
28
|
-
HLO = 'HEBERGEMENT_LOCATIF'
|
29
|
-
HOT = 'HOTELLERIE'
|
30
|
-
HPA = 'HOTELLERIE_PLEIN_AIR'
|
31
|
-
PCU = 'PATRIMOINE_CULTUREL'
|
32
|
-
PNA = 'PATRIMOINE_NATUREL'
|
33
|
-
RES = 'RESTAURATION'
|
34
|
-
SPA = 'SEJOUR_PACKAGE'
|
35
|
-
STR = 'STRUCTURE'
|
36
|
-
TER = 'TERRITOIRE'
|
37
|
-
|
38
|
-
TYPES_DATA = {
|
39
|
-
ACT => {node: :informationsActivite, subtype: :activiteType},
|
40
|
-
COS => {node: :informationsCommerceEtService, subtype: :commerceEtServiceType},
|
41
|
-
DEG => {node: :informationsDegustation, subtype: :degustationType},
|
42
|
-
DOS => {node: :informationsDomaineSkiable, subtype: :domaineSkiableType},
|
43
|
-
EQU => {node: :informationsEquipement, subtype: :equipementType},
|
44
|
-
FEM => {node: :informationsFeteEtManifestation, subtype: :feteEtManifestationType},
|
45
|
-
HCO => {node: :informationsHebergementCollectif, subtype: :hebergementCollectifType},
|
46
|
-
HLO => {node: :informationsHebergementLocatif, subtype: :hebergementLocatifType},
|
47
|
-
HOT => {node: :informationsHotellerie, subtype: :hotellerieType},
|
48
|
-
HPA => {node: :informationsHotelleriePleinAir, subtype: :hotelleriePleinAirType},
|
49
|
-
PCU => {node: :informationsPatrimoineCulturel, subtype: :patrimoineCulturelType},
|
50
|
-
PNA => {node: :informationsPatrimoineNaturel, subtype: :patrimoineNaturelType},
|
51
|
-
RES => {node: :informationsRestauration, subtype: :restaurationType},
|
52
|
-
SPA => {node: :informationsSejourPackage, subtype: :sejourPackageType},
|
53
|
-
STR => {node: :informationsStructure, subtype: :structureType},
|
54
|
-
TER => {node: :informationsTerritoire, subtype: :territoireType}
|
55
|
-
}
|
56
|
-
|
57
|
-
PHONE = 201
|
58
|
-
EMAIL = 204
|
59
|
-
WEBSITE = 205
|
60
|
-
|
61
|
-
def self.add_object(object_data)
|
62
|
-
apidae_obj = Obj.new(apidae_id: object_data[:id])
|
63
|
-
update_object(apidae_obj, object_data)
|
64
|
-
end
|
65
|
-
|
66
|
-
def self.update_object(apidae_obj, object_data)
|
67
|
-
populate_fields(apidae_obj, object_data)
|
68
|
-
|
69
|
-
if Rails.application.config.respond_to?(:apidae_aspect) && !object_data[:aspects].blank?
|
70
|
-
apidae_aspect = object_data[:aspects].find {|a| a[:aspect] == Rails.application.config.apidae_aspect}
|
71
|
-
if apidae_aspect
|
72
|
-
apidae_aspect[:type] = apidae_obj.apidae_type
|
73
|
-
aspect_obj = Obj.new
|
74
|
-
populate_fields(aspect_obj, apidae_aspect)
|
75
|
-
merge_fields(apidae_obj, aspect_obj)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
apidae_obj.save!
|
80
|
-
end
|
81
|
-
|
82
|
-
def self.populate_fields(apidae_obj, object_data)
|
83
|
-
type_fields = TYPES_DATA[object_data[:type]]
|
84
|
-
apidae_obj.apidae_type = object_data[:type]
|
85
|
-
apidae_obj.apidae_subtype = node_id(object_data[type_fields[:node]], type_fields[:subtype])
|
86
|
-
apidae_obj.title = node_value(object_data, :nom)
|
87
|
-
apidae_obj.description_data = parse_desc_data(object_data[:presentation], object_data[:donneesPrivees])
|
88
|
-
apidae_obj.contact = contact(object_data[:informations])
|
89
|
-
apidae_obj.location_data = parse_location_data(object_data[:localisation], object_data[type_fields[:node]],
|
90
|
-
object_data[:territoires])
|
91
|
-
apidae_obj.town = town(object_data[:localisation])
|
92
|
-
apidae_obj.openings_data = parse_openings(object_data[:ouverture])
|
93
|
-
apidae_obj.rates_data = parse_rates(object_data[:descriptionTarif])
|
94
|
-
apidae_obj.reservation = parse_reservation(object_data[:reservation])
|
95
|
-
apidae_obj.type_data = parse_type_data(apidae_obj, object_data[type_fields[:node]], object_data[:prestations])
|
96
|
-
apidae_obj.pictures_data = pictures_urls(object_data[:illustrations])
|
97
|
-
apidae_obj.attachments_data = attachments_urls(object_data[:multimedias])
|
98
|
-
apidae_obj.entity_data = entity_fields(object_data[:informations], object_data[type_fields[:node]])
|
99
|
-
apidae_obj.service_data = parse_service_data(object_data[:prestations], object_data[type_fields[:node]])
|
100
|
-
apidae_obj.tags_data = parse_tags_data(object_data[:presentation], object_data[:criteresInternes], object_data[:liens])
|
101
|
-
apidae_obj.meta_data = object_data[:metadonnees]
|
102
|
-
end
|
103
|
-
|
104
|
-
def self.merge_fields(apidae_obj, aspect_obj)
|
105
|
-
apidae_obj.description_data.merge!(non_empty(aspect_obj.description_data)) if aspect_obj.description_data
|
106
|
-
apidae_obj.contact.merge!(non_empty(aspect_obj.contact)) if aspect_obj.contact
|
107
|
-
apidae_obj.location_data.merge!(non_empty(aspect_obj.location_data)) if aspect_obj.location_data
|
108
|
-
apidae_obj.openings_data.merge!(non_empty(aspect_obj.openings_data)) if aspect_obj.openings_data
|
109
|
-
apidae_obj.rates_data.merge!(non_empty(aspect_obj.rates_data)) if aspect_obj.rates_data
|
110
|
-
apidae_obj.reservation = aspect_obj.reservation unless aspect_obj.reservation.blank?
|
111
|
-
apidae_obj.type_data.merge!(non_empty(aspect_obj.type_data)) if aspect_obj.type_data
|
112
|
-
apidae_obj.pictures_data.merge!(non_empty(aspect_obj.pictures_data)) if aspect_obj.pictures_data
|
113
|
-
apidae_obj.attachments_data.merge!(non_empty(aspect_obj.attachments_data)) if aspect_obj.attachments_data
|
114
|
-
apidae_obj.service_data.merge!(non_empty(aspect_obj.service_data)) if aspect_obj.service_data
|
115
|
-
apidae_obj.tags_data.merge!(non_empty(aspect_obj.tags_data)) if aspect_obj.tags_data
|
116
|
-
apidae_obj.meta_data.merge!(non_empty(aspect_obj.meta_data)) if aspect_obj.meta_data
|
117
|
-
end
|
118
|
-
|
119
|
-
def self.non_empty(data_hash)
|
120
|
-
data_hash.keep_if {|k, v| !v.blank?}
|
121
|
-
end
|
122
|
-
|
123
|
-
def self.parse_desc_data(data_hash, private_data)
|
124
|
-
unless data_hash.blank?
|
125
|
-
{
|
126
|
-
short_desc: node_value(data_hash, :descriptifCourt),
|
127
|
-
long_desc: node_value(data_hash, :descriptifDetaille),
|
128
|
-
theme_desc: data_hash[:descriptifsThematises].blank? ? {} : Hash[data_hash[:descriptifsThematises].map {|th| [node_id(th, :theme), node_value(th, :description)]}],
|
129
|
-
private_desc: private_data.blank? ? {} : Hash[private_data.map {|d| [d[:nomTechnique], node_value(d, :descriptif)]}]
|
130
|
-
}
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def self.pictures_urls(pictures_array)
|
135
|
-
pics_data = []
|
136
|
-
unless pictures_array.blank?
|
137
|
-
pictures_array.select { |p| p.is_a?(Hash) && !p[:traductionFichiers].blank? }.each do |pic|
|
138
|
-
pics_data << {
|
139
|
-
name: node_value(pic, :nom),
|
140
|
-
url: pic[:traductionFichiers][0][:url],
|
141
|
-
description: node_value(pic, :legende),
|
142
|
-
credits: node_value(pic, :copyright)
|
143
|
-
}
|
144
|
-
end
|
145
|
-
end
|
146
|
-
{pictures: pics_data}
|
147
|
-
end
|
148
|
-
|
149
|
-
def self.attachments_urls(attachments_array)
|
150
|
-
atts_data = []
|
151
|
-
unless attachments_array.blank?
|
152
|
-
attachments_array.select { |att| att.is_a?(Hash) && !att[:traductionFichiers].blank? }.each do |att|
|
153
|
-
atts_data << {
|
154
|
-
name: node_value(att, :nom),
|
155
|
-
url: att[:traductionFichiers][0][:url]
|
156
|
-
}
|
157
|
-
end
|
158
|
-
end
|
159
|
-
{attachments: atts_data}
|
160
|
-
end
|
161
|
-
|
162
|
-
def self.contact(information_hash)
|
163
|
-
contact_details = {}
|
164
|
-
unless information_hash.blank?
|
165
|
-
contact_entries = information_hash[:moyensCommunication] || []
|
166
|
-
contact_entries.each do |c|
|
167
|
-
case c[:type][:id]
|
168
|
-
when PHONE
|
169
|
-
contact_details[:telephone] ||= []
|
170
|
-
contact_details[:telephone] << c[:coordonnees][:fr]
|
171
|
-
when EMAIL
|
172
|
-
contact_details[:email] ||= []
|
173
|
-
contact_details[:email] << c[:coordonnees][:fr]
|
174
|
-
when WEBSITE
|
175
|
-
contact_details[:website] ||= []
|
176
|
-
contact_details[:website] << c[:coordonnees][:fr]
|
177
|
-
else
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
contact_details
|
182
|
-
end
|
183
|
-
|
184
|
-
def self.parse_location_data(location_hash, type_data_hash, territories)
|
185
|
-
loc_data = {}
|
186
|
-
unless location_hash.blank?
|
187
|
-
address_hash = location_hash[:adresse]
|
188
|
-
computed_address = []
|
189
|
-
unless address_hash.blank?
|
190
|
-
computed_address << address_hash[:adresse1] unless address_hash[:adresse1].blank?
|
191
|
-
computed_address << address_hash[:adresse2] unless address_hash[:adresse2].blank?
|
192
|
-
computed_address << address_hash[:adresse3] unless address_hash[:adresse3].blank?
|
193
|
-
end
|
194
|
-
loc_data.merge!({address: computed_address})
|
195
|
-
loc_data.merge!({place: type_data_hash[:nomLieu]}) if type_data_hash
|
196
|
-
geoloc_details = location_hash[:geolocalisation]
|
197
|
-
if geoloc_details && geoloc_details[:valide] && geoloc_details[:geoJson]
|
198
|
-
loc_data[:latitude] = geoloc_details[:geoJson][:coordinates][1]
|
199
|
-
loc_data[:longitude] = geoloc_details[:geoJson][:coordinates][0]
|
200
|
-
end
|
201
|
-
loc_data[:access] = node_value(geoloc_details, :complement) if geoloc_details
|
202
|
-
loc_data[:environments] = location_hash[:environnements].map {|e| e[:id]} if location_hash[:environnements]
|
203
|
-
end
|
204
|
-
loc_data[:territories] = territories.map {|t| t[:id]} unless territories.blank?
|
205
|
-
loc_data
|
206
|
-
end
|
207
|
-
|
208
|
-
def self.town(location_hash)
|
209
|
-
if location_hash
|
210
|
-
address_hash = location_hash[:adresse]
|
211
|
-
(!address_hash.blank? && address_hash[:commune]) ? Town.find_by_apidae_id(address_hash[:commune][:id]) : nil
|
212
|
-
else
|
213
|
-
nil
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
def self.parse_openings(openings_hash)
|
218
|
-
if openings_hash && openings_hash[:periodeEnClair]
|
219
|
-
{
|
220
|
-
openings_desc: openings_hash[:periodeEnClair][:libelleFr],
|
221
|
-
openings: openings_hash[:periodesOuvertures],
|
222
|
-
time_periods: lists_ids(openings_hash[:indicationsPeriode])
|
223
|
-
}
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
def self.parse_rates(rates_hash)
|
228
|
-
if rates_hash
|
229
|
-
desc = rates_hash[:gratuit] ? 'gratuit' : node_value(rates_hash, :tarifsEnClair)
|
230
|
-
values = rates_hash[:periodes].blank? ? [] : rates_hash[:periodes].map {|p| build_rate(p)}
|
231
|
-
methods = rates_hash[:modesPaiement].blank? ? [] : rates_hash[:modesPaiement].map {|p| p[:id]}
|
232
|
-
{rates_desc: desc, rates: values, payment_methods: methods, includes: node_value(rates_hash, :leTarifComprend), excludes: node_value(rates_hash, :leTarifNeComprendPas)}
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
def self.parse_type_data(apidae_obj, type_hash, presta_hash)
|
237
|
-
data_hash = type_hash || {}
|
238
|
-
prestations_hash = presta_hash || {}
|
239
|
-
apidae_obj.apidae_subtype = lists_ids(data_hash[:typesManifestation]).first if apidae_obj.apidae_type == FEM
|
240
|
-
apidae_obj.apidae_subtype = node_id(data_hash, :rubrique) if apidae_obj.apidae_type == EQU
|
241
|
-
apidae_obj.apidae_subtype = lists_ids(data_hash[:typesHebergement]).first if apidae_obj.apidae_type == SPA
|
242
|
-
{
|
243
|
-
categories: lists_ids(data_hash[:categories], data_hash[:typesDetailles], data_hash[:activiteCategories]),
|
244
|
-
themes: lists_ids(data_hash[:themes]),
|
245
|
-
capacity: (data_hash[:capacite] || {})
|
246
|
-
.merge(presta_hash ? {group_min: presta_hash[:tailleGroupeMin], group_max: presta_hash[:tailleGroupeMax],
|
247
|
-
age_min: presta_hash[:ageMin], age_max: presta_hash[:ageMax]} : {}),
|
248
|
-
classification: nodes_ids(data_hash[:classement], data_hash[:classementPrefectoral], data_hash[:classification]) +
|
249
|
-
lists_ids(data_hash[:classementsGuides]) + lists_ids(data_hash[:classements]),
|
250
|
-
labels: lists_ids(data_hash[:labels], prestations_hash[:labelsTourismeHandicap]) +
|
251
|
-
(node_id(data_hash, :typeLabel) ? [node_id(data_hash, :typeLabel)] : []),
|
252
|
-
chains: lists_ids(data_hash[:chaines]) + nodes_ids(data_hash[:chaineEtLabel]),
|
253
|
-
area: apidae_obj.apidae_type == DOS ? data_hash.except(:classification) : node_value(data_hash, :lieuDePratique),
|
254
|
-
track: apidae_obj.apidae_type == EQU ? data_hash[:itineraire] : nil,
|
255
|
-
products: lists_ids(data_hash[:typesProduit], data_hash[:aopAocIgps], data_hash[:specialites]),
|
256
|
-
audience: lists_ids(prestations_hash[:typesClientele]),
|
257
|
-
animals: prestations_hash[:animauxAcceptes] == 'ACCEPTES',
|
258
|
-
extra: apidae_obj.apidae_type == SPA ? node_value(data_hash, :formuleHebergement) : node_value(prestations_hash, :complementAccueil),
|
259
|
-
duration: apidae_obj.apidae_type == SPA ? {days: data_hash[:nombreJours], nights: data_hash[:nombreNuits]} : data_hash[:dureeSeance],
|
260
|
-
certifications: data_hash[:agrements].blank? ? [] : data_hash[:agrements].map {|a| {id: a[:type][:id], identifier: a[:numero]}}
|
261
|
-
}
|
262
|
-
end
|
263
|
-
|
264
|
-
def self.parse_service_data(data_hash, type_data_hash)
|
265
|
-
if data_hash
|
266
|
-
{
|
267
|
-
services: lists_ids(data_hash[:services]),
|
268
|
-
equipments: lists_ids(data_hash[:equipements]),
|
269
|
-
comfort: lists_ids(data_hash[:conforts]),
|
270
|
-
activities: lists_ids(data_hash[:activites], type_data_hash ? type_data_hash[:activites] : [],
|
271
|
-
type_data_hash ? type_data_hash[:activitesSportives] : [],
|
272
|
-
type_data_hash ? type_data_hash[:activitesCulturelles] : []),
|
273
|
-
challenged: lists_ids(data_hash[:tourismesAdaptes]),
|
274
|
-
languages: lists_ids(data_hash[:languesParlees])
|
275
|
-
}
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
def self.parse_tags_data(pres_data_hash, crit_data_hash, linked_data_hash)
|
280
|
-
tags = {}
|
281
|
-
if pres_data_hash
|
282
|
-
tags[:promo] = lists_ids(pres_data_hash[:typologiesPromoSitra])
|
283
|
-
end
|
284
|
-
unless crit_data_hash.blank?
|
285
|
-
tags[:internal] = crit_data_hash.map {|c| c[:id]}
|
286
|
-
end
|
287
|
-
unless linked_data_hash.blank? || linked_data_hash[:liensObjetsTouristiquesTypes].blank?
|
288
|
-
tags[:linked] = linked_data_hash[:liensObjetsTouristiquesTypes]
|
289
|
-
.map {|l| {apidae_id: l[:objetTouristique][:id], apidae_type: l[:objetTouristique][:type], category: l[:type]}}
|
290
|
-
end
|
291
|
-
tags
|
292
|
-
end
|
293
|
-
|
294
|
-
def self.parse_reservation(reservation_hash)
|
295
|
-
if reservation_hash
|
296
|
-
if reservation_hash[:complement]
|
297
|
-
reservation_hash[:complement][:libelleFr]
|
298
|
-
else
|
299
|
-
reservation_hash[:organismes]
|
300
|
-
end
|
301
|
-
end
|
302
|
-
end
|
303
|
-
|
304
|
-
def self.entity_fields(information_hash, type_data_hash)
|
305
|
-
if information_hash && information_hash[:structureGestion]
|
306
|
-
{entity_id: information_hash[:structureGestion][:id], service_provider_id: node_id(type_data_hash, :prestataireActivites)}
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
|
-
def contact_text
|
311
|
-
entries = []
|
312
|
-
JSON.parse(contact).each_pair do |k, v|
|
313
|
-
entries << "#{k}: #{v}"
|
314
|
-
end
|
315
|
-
entries.join("\n")
|
316
|
-
end
|
317
|
-
|
318
|
-
def main_picture
|
319
|
-
pictures.any? ? pictures[0]["url"] : "#{Rails.application.config.apidae_pictures_path}/default/logo.png"
|
320
|
-
end
|
321
|
-
|
322
|
-
def self.build_rate(rate_period)
|
323
|
-
{
|
324
|
-
id: rate_period[:identifiant], from: rate_period[:dateDebut], to: rate_period[:dateFin],
|
325
|
-
values: rate_period[:tarifs].blank? ? [] : rate_period[:tarifs].map {|t| {min: t[:minimum], max: t[:maximum], type: t[:type][:id], details: node_value(t, :precisionTarif)}}
|
326
|
-
}
|
327
|
-
end
|
328
|
-
|
329
|
-
private
|
330
|
-
|
331
|
-
def self.node_value(node, key)
|
332
|
-
if node && node[key]
|
333
|
-
node[key][:libelleFr]
|
334
|
-
else
|
335
|
-
''
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
def self.node_id(node, key)
|
340
|
-
node[key][:id] if node && node[key]
|
341
|
-
end
|
342
|
-
|
343
|
-
def self.lists_ids(*lists)
|
344
|
-
lists.blank? ? [] : lists.map {|l| l.blank? ? [] : l.map {|elt| elt[:id]}}.flatten.uniq
|
345
|
-
end
|
346
|
-
|
347
|
-
def self.nodes_ids(*nodes)
|
348
|
-
nodes.blank? ? [] : nodes.select {|n| !n.blank?}.map {|n| n[:id]}
|
349
|
-
end
|
350
|
-
end
|
351
|
-
end
|
1
|
+
module Apidae
|
2
|
+
class Obj < ActiveRecord::Base
|
3
|
+
|
4
|
+
belongs_to :town, class_name: 'Apidae::Town', foreign_key: :town_insee_code, primary_key: :insee_code
|
5
|
+
has_many :apidae_selection_objects, class_name: 'Apidae::SelectionObject', foreign_key: :apidae_object_id
|
6
|
+
has_many :selections, class_name: 'Apidae::Selection', source: :apidae_selection, through: :apidae_selection_objects
|
7
|
+
|
8
|
+
store_accessor :description_data, :short_desc, :long_desc, :theme_desc, :private_desc
|
9
|
+
store_accessor :pictures_data, :pictures
|
10
|
+
store_accessor :attachments_data, :attachments
|
11
|
+
store_accessor :type_data, :categories, :themes, :capacity, :classification, :labels, :chains, :area, :track,
|
12
|
+
:products, :audience, :animals, :extra, :duration, :certifications
|
13
|
+
store_accessor :entity_data, :entity_id, :entity_name, :service_provider_id
|
14
|
+
store_accessor :contact, :telephone, :email, :website
|
15
|
+
store_accessor :location_data, :address, :place, :latitude, :longitude, :access, :territories, :environments
|
16
|
+
store_accessor :openings_data, :openings_desc, :openings, :time_periods
|
17
|
+
store_accessor :rates_data, :rates_desc, :rates, :payment_methods, :includes, :excludes
|
18
|
+
store_accessor :service_data, :services, :equipments, :comfort, :activities, :challenged, :languages
|
19
|
+
store_accessor :tags_data, :promo, :internal, :linked
|
20
|
+
|
21
|
+
ACT = 'ACTIVITE'
|
22
|
+
COS = 'COMMERCE_ET_SERVICE'
|
23
|
+
DEG = 'DEGUSTATION'
|
24
|
+
DOS = 'DOMAINE_SKIABLE'
|
25
|
+
EQU = 'EQUIPEMENT'
|
26
|
+
FEM = 'FETE_ET_MANIFESTATION'
|
27
|
+
HCO = 'HEBERGEMENT_COLLECTIF'
|
28
|
+
HLO = 'HEBERGEMENT_LOCATIF'
|
29
|
+
HOT = 'HOTELLERIE'
|
30
|
+
HPA = 'HOTELLERIE_PLEIN_AIR'
|
31
|
+
PCU = 'PATRIMOINE_CULTUREL'
|
32
|
+
PNA = 'PATRIMOINE_NATUREL'
|
33
|
+
RES = 'RESTAURATION'
|
34
|
+
SPA = 'SEJOUR_PACKAGE'
|
35
|
+
STR = 'STRUCTURE'
|
36
|
+
TER = 'TERRITOIRE'
|
37
|
+
|
38
|
+
TYPES_DATA = {
|
39
|
+
ACT => {node: :informationsActivite, subtype: :activiteType},
|
40
|
+
COS => {node: :informationsCommerceEtService, subtype: :commerceEtServiceType},
|
41
|
+
DEG => {node: :informationsDegustation, subtype: :degustationType},
|
42
|
+
DOS => {node: :informationsDomaineSkiable, subtype: :domaineSkiableType},
|
43
|
+
EQU => {node: :informationsEquipement, subtype: :equipementType},
|
44
|
+
FEM => {node: :informationsFeteEtManifestation, subtype: :feteEtManifestationType},
|
45
|
+
HCO => {node: :informationsHebergementCollectif, subtype: :hebergementCollectifType},
|
46
|
+
HLO => {node: :informationsHebergementLocatif, subtype: :hebergementLocatifType},
|
47
|
+
HOT => {node: :informationsHotellerie, subtype: :hotellerieType},
|
48
|
+
HPA => {node: :informationsHotelleriePleinAir, subtype: :hotelleriePleinAirType},
|
49
|
+
PCU => {node: :informationsPatrimoineCulturel, subtype: :patrimoineCulturelType},
|
50
|
+
PNA => {node: :informationsPatrimoineNaturel, subtype: :patrimoineNaturelType},
|
51
|
+
RES => {node: :informationsRestauration, subtype: :restaurationType},
|
52
|
+
SPA => {node: :informationsSejourPackage, subtype: :sejourPackageType},
|
53
|
+
STR => {node: :informationsStructure, subtype: :structureType},
|
54
|
+
TER => {node: :informationsTerritoire, subtype: :territoireType}
|
55
|
+
}
|
56
|
+
|
57
|
+
PHONE = 201
|
58
|
+
EMAIL = 204
|
59
|
+
WEBSITE = 205
|
60
|
+
|
61
|
+
def self.add_object(object_data)
|
62
|
+
apidae_obj = Obj.new(apidae_id: object_data[:id])
|
63
|
+
update_object(apidae_obj, object_data)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.update_object(apidae_obj, object_data)
|
67
|
+
populate_fields(apidae_obj, object_data)
|
68
|
+
|
69
|
+
if Rails.application.config.respond_to?(:apidae_aspect) && !object_data[:aspects].blank?
|
70
|
+
apidae_aspect = object_data[:aspects].find {|a| a[:aspect] == Rails.application.config.apidae_aspect}
|
71
|
+
if apidae_aspect
|
72
|
+
apidae_aspect[:type] = apidae_obj.apidae_type
|
73
|
+
aspect_obj = Obj.new
|
74
|
+
populate_fields(aspect_obj, apidae_aspect)
|
75
|
+
merge_fields(apidae_obj, aspect_obj)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
apidae_obj.save!
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.populate_fields(apidae_obj, object_data)
|
83
|
+
type_fields = TYPES_DATA[object_data[:type]]
|
84
|
+
apidae_obj.apidae_type = object_data[:type]
|
85
|
+
apidae_obj.apidae_subtype = node_id(object_data[type_fields[:node]], type_fields[:subtype])
|
86
|
+
apidae_obj.title = node_value(object_data, :nom)
|
87
|
+
apidae_obj.description_data = parse_desc_data(object_data[:presentation], object_data[:donneesPrivees])
|
88
|
+
apidae_obj.contact = contact(object_data[:informations])
|
89
|
+
apidae_obj.location_data = parse_location_data(object_data[:localisation], object_data[type_fields[:node]],
|
90
|
+
object_data[:territoires])
|
91
|
+
apidae_obj.town = town(object_data[:localisation])
|
92
|
+
apidae_obj.openings_data = parse_openings(object_data[:ouverture])
|
93
|
+
apidae_obj.rates_data = parse_rates(object_data[:descriptionTarif])
|
94
|
+
apidae_obj.reservation = parse_reservation(object_data[:reservation])
|
95
|
+
apidae_obj.type_data = parse_type_data(apidae_obj, object_data[type_fields[:node]], object_data[:prestations])
|
96
|
+
apidae_obj.pictures_data = pictures_urls(object_data[:illustrations])
|
97
|
+
apidae_obj.attachments_data = attachments_urls(object_data[:multimedias])
|
98
|
+
apidae_obj.entity_data = entity_fields(object_data[:informations], object_data[type_fields[:node]])
|
99
|
+
apidae_obj.service_data = parse_service_data(object_data[:prestations], object_data[type_fields[:node]])
|
100
|
+
apidae_obj.tags_data = parse_tags_data(object_data[:presentation], object_data[:criteresInternes], object_data[:liens])
|
101
|
+
apidae_obj.meta_data = object_data[:metadonnees]
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.merge_fields(apidae_obj, aspect_obj)
|
105
|
+
apidae_obj.description_data.merge!(non_empty(aspect_obj.description_data)) if aspect_obj.description_data
|
106
|
+
apidae_obj.contact.merge!(non_empty(aspect_obj.contact)) if aspect_obj.contact
|
107
|
+
apidae_obj.location_data.merge!(non_empty(aspect_obj.location_data)) if aspect_obj.location_data
|
108
|
+
apidae_obj.openings_data.merge!(non_empty(aspect_obj.openings_data)) if aspect_obj.openings_data
|
109
|
+
apidae_obj.rates_data.merge!(non_empty(aspect_obj.rates_data)) if aspect_obj.rates_data
|
110
|
+
apidae_obj.reservation = aspect_obj.reservation unless aspect_obj.reservation.blank?
|
111
|
+
apidae_obj.type_data.merge!(non_empty(aspect_obj.type_data)) if aspect_obj.type_data
|
112
|
+
apidae_obj.pictures_data.merge!(non_empty(aspect_obj.pictures_data)) if aspect_obj.pictures_data
|
113
|
+
apidae_obj.attachments_data.merge!(non_empty(aspect_obj.attachments_data)) if aspect_obj.attachments_data
|
114
|
+
apidae_obj.service_data.merge!(non_empty(aspect_obj.service_data)) if aspect_obj.service_data
|
115
|
+
apidae_obj.tags_data.merge!(non_empty(aspect_obj.tags_data)) if aspect_obj.tags_data
|
116
|
+
apidae_obj.meta_data.merge!(non_empty(aspect_obj.meta_data)) if aspect_obj.meta_data
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.non_empty(data_hash)
|
120
|
+
data_hash.keep_if {|k, v| !v.blank?}
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.parse_desc_data(data_hash, private_data)
|
124
|
+
unless data_hash.blank?
|
125
|
+
{
|
126
|
+
short_desc: node_value(data_hash, :descriptifCourt),
|
127
|
+
long_desc: node_value(data_hash, :descriptifDetaille),
|
128
|
+
theme_desc: data_hash[:descriptifsThematises].blank? ? {} : Hash[data_hash[:descriptifsThematises].map {|th| [node_id(th, :theme), node_value(th, :description)]}],
|
129
|
+
private_desc: private_data.blank? ? {} : Hash[private_data.map {|d| [d[:nomTechnique], node_value(d, :descriptif)]}]
|
130
|
+
}
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.pictures_urls(pictures_array)
|
135
|
+
pics_data = []
|
136
|
+
unless pictures_array.blank?
|
137
|
+
pictures_array.select { |p| p.is_a?(Hash) && !p[:traductionFichiers].blank? }.each do |pic|
|
138
|
+
pics_data << {
|
139
|
+
name: node_value(pic, :nom),
|
140
|
+
url: pic[:traductionFichiers][0][:url],
|
141
|
+
description: node_value(pic, :legende),
|
142
|
+
credits: node_value(pic, :copyright)
|
143
|
+
}
|
144
|
+
end
|
145
|
+
end
|
146
|
+
{pictures: pics_data}
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.attachments_urls(attachments_array)
|
150
|
+
atts_data = []
|
151
|
+
unless attachments_array.blank?
|
152
|
+
attachments_array.select { |att| att.is_a?(Hash) && !att[:traductionFichiers].blank? }.each do |att|
|
153
|
+
atts_data << {
|
154
|
+
name: node_value(att, :nom),
|
155
|
+
url: att[:traductionFichiers][0][:url]
|
156
|
+
}
|
157
|
+
end
|
158
|
+
end
|
159
|
+
{attachments: atts_data}
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.contact(information_hash)
|
163
|
+
contact_details = {}
|
164
|
+
unless information_hash.blank?
|
165
|
+
contact_entries = information_hash[:moyensCommunication] || []
|
166
|
+
contact_entries.each do |c|
|
167
|
+
case c[:type][:id]
|
168
|
+
when PHONE
|
169
|
+
contact_details[:telephone] ||= []
|
170
|
+
contact_details[:telephone] << c[:coordonnees][:fr]
|
171
|
+
when EMAIL
|
172
|
+
contact_details[:email] ||= []
|
173
|
+
contact_details[:email] << c[:coordonnees][:fr]
|
174
|
+
when WEBSITE
|
175
|
+
contact_details[:website] ||= []
|
176
|
+
contact_details[:website] << c[:coordonnees][:fr]
|
177
|
+
else
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
contact_details
|
182
|
+
end
|
183
|
+
|
184
|
+
def self.parse_location_data(location_hash, type_data_hash, territories)
|
185
|
+
loc_data = {}
|
186
|
+
unless location_hash.blank?
|
187
|
+
address_hash = location_hash[:adresse]
|
188
|
+
computed_address = []
|
189
|
+
unless address_hash.blank?
|
190
|
+
computed_address << address_hash[:adresse1] unless address_hash[:adresse1].blank?
|
191
|
+
computed_address << address_hash[:adresse2] unless address_hash[:adresse2].blank?
|
192
|
+
computed_address << address_hash[:adresse3] unless address_hash[:adresse3].blank?
|
193
|
+
end
|
194
|
+
loc_data.merge!({address: computed_address})
|
195
|
+
loc_data.merge!({place: type_data_hash[:nomLieu]}) if type_data_hash
|
196
|
+
geoloc_details = location_hash[:geolocalisation]
|
197
|
+
if geoloc_details && geoloc_details[:valide] && geoloc_details[:geoJson]
|
198
|
+
loc_data[:latitude] = geoloc_details[:geoJson][:coordinates][1]
|
199
|
+
loc_data[:longitude] = geoloc_details[:geoJson][:coordinates][0]
|
200
|
+
end
|
201
|
+
loc_data[:access] = node_value(geoloc_details, :complement) if geoloc_details
|
202
|
+
loc_data[:environments] = location_hash[:environnements].map {|e| e[:id]} if location_hash[:environnements]
|
203
|
+
end
|
204
|
+
loc_data[:territories] = territories.map {|t| t[:id]} unless territories.blank?
|
205
|
+
loc_data
|
206
|
+
end
|
207
|
+
|
208
|
+
def self.town(location_hash)
|
209
|
+
if location_hash
|
210
|
+
address_hash = location_hash[:adresse]
|
211
|
+
(!address_hash.blank? && address_hash[:commune]) ? Town.find_by_apidae_id(address_hash[:commune][:id]) : nil
|
212
|
+
else
|
213
|
+
nil
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def self.parse_openings(openings_hash)
|
218
|
+
if openings_hash && openings_hash[:periodeEnClair]
|
219
|
+
{
|
220
|
+
openings_desc: openings_hash[:periodeEnClair][:libelleFr],
|
221
|
+
openings: openings_hash[:periodesOuvertures],
|
222
|
+
time_periods: lists_ids(openings_hash[:indicationsPeriode])
|
223
|
+
}
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def self.parse_rates(rates_hash)
|
228
|
+
if rates_hash
|
229
|
+
desc = rates_hash[:gratuit] ? 'gratuit' : node_value(rates_hash, :tarifsEnClair)
|
230
|
+
values = rates_hash[:periodes].blank? ? [] : rates_hash[:periodes].map {|p| build_rate(p)}
|
231
|
+
methods = rates_hash[:modesPaiement].blank? ? [] : rates_hash[:modesPaiement].map {|p| p[:id]}
|
232
|
+
{rates_desc: desc, rates: values, payment_methods: methods, includes: node_value(rates_hash, :leTarifComprend), excludes: node_value(rates_hash, :leTarifNeComprendPas)}
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def self.parse_type_data(apidae_obj, type_hash, presta_hash)
|
237
|
+
data_hash = type_hash || {}
|
238
|
+
prestations_hash = presta_hash || {}
|
239
|
+
apidae_obj.apidae_subtype = lists_ids(data_hash[:typesManifestation]).first if apidae_obj.apidae_type == FEM
|
240
|
+
apidae_obj.apidae_subtype = node_id(data_hash, :rubrique) if apidae_obj.apidae_type == EQU
|
241
|
+
apidae_obj.apidae_subtype = lists_ids(data_hash[:typesHebergement]).first if apidae_obj.apidae_type == SPA
|
242
|
+
{
|
243
|
+
categories: lists_ids(data_hash[:categories], data_hash[:typesDetailles], data_hash[:activiteCategories]),
|
244
|
+
themes: lists_ids(data_hash[:themes]),
|
245
|
+
capacity: (data_hash[:capacite] || {})
|
246
|
+
.merge(presta_hash ? {group_min: presta_hash[:tailleGroupeMin], group_max: presta_hash[:tailleGroupeMax],
|
247
|
+
age_min: presta_hash[:ageMin], age_max: presta_hash[:ageMax]} : {}),
|
248
|
+
classification: nodes_ids(data_hash[:classement], data_hash[:classementPrefectoral], data_hash[:classification]) +
|
249
|
+
lists_ids(data_hash[:classementsGuides]) + lists_ids(data_hash[:classements]),
|
250
|
+
labels: lists_ids(data_hash[:labels], prestations_hash[:labelsTourismeHandicap]) +
|
251
|
+
(node_id(data_hash, :typeLabel) ? [node_id(data_hash, :typeLabel)] : []),
|
252
|
+
chains: lists_ids(data_hash[:chaines]) + nodes_ids(data_hash[:chaineEtLabel]),
|
253
|
+
area: apidae_obj.apidae_type == DOS ? data_hash.except(:classification) : node_value(data_hash, :lieuDePratique),
|
254
|
+
track: apidae_obj.apidae_type == EQU ? data_hash[:itineraire] : nil,
|
255
|
+
products: lists_ids(data_hash[:typesProduit], data_hash[:aopAocIgps], data_hash[:specialites]),
|
256
|
+
audience: lists_ids(prestations_hash[:typesClientele]),
|
257
|
+
animals: prestations_hash[:animauxAcceptes] == 'ACCEPTES',
|
258
|
+
extra: apidae_obj.apidae_type == SPA ? node_value(data_hash, :formuleHebergement) : node_value(prestations_hash, :complementAccueil),
|
259
|
+
duration: apidae_obj.apidae_type == SPA ? {days: data_hash[:nombreJours], nights: data_hash[:nombreNuits]} : data_hash[:dureeSeance],
|
260
|
+
certifications: data_hash[:agrements].blank? ? [] : data_hash[:agrements].map {|a| {id: a[:type][:id], identifier: a[:numero]}}
|
261
|
+
}
|
262
|
+
end
|
263
|
+
|
264
|
+
def self.parse_service_data(data_hash, type_data_hash)
|
265
|
+
if data_hash
|
266
|
+
{
|
267
|
+
services: lists_ids(data_hash[:services]),
|
268
|
+
equipments: lists_ids(data_hash[:equipements]),
|
269
|
+
comfort: lists_ids(data_hash[:conforts]),
|
270
|
+
activities: lists_ids(data_hash[:activites], type_data_hash ? type_data_hash[:activites] : [],
|
271
|
+
type_data_hash ? type_data_hash[:activitesSportives] : [],
|
272
|
+
type_data_hash ? type_data_hash[:activitesCulturelles] : []),
|
273
|
+
challenged: lists_ids(data_hash[:tourismesAdaptes]),
|
274
|
+
languages: lists_ids(data_hash[:languesParlees])
|
275
|
+
}
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def self.parse_tags_data(pres_data_hash, crit_data_hash, linked_data_hash)
|
280
|
+
tags = {}
|
281
|
+
if pres_data_hash
|
282
|
+
tags[:promo] = lists_ids(pres_data_hash[:typologiesPromoSitra])
|
283
|
+
end
|
284
|
+
unless crit_data_hash.blank?
|
285
|
+
tags[:internal] = crit_data_hash.map {|c| c[:id]}
|
286
|
+
end
|
287
|
+
unless linked_data_hash.blank? || linked_data_hash[:liensObjetsTouristiquesTypes].blank?
|
288
|
+
tags[:linked] = linked_data_hash[:liensObjetsTouristiquesTypes]
|
289
|
+
.map {|l| {apidae_id: l[:objetTouristique][:id], apidae_type: l[:objetTouristique][:type], category: l[:type]}}
|
290
|
+
end
|
291
|
+
tags
|
292
|
+
end
|
293
|
+
|
294
|
+
def self.parse_reservation(reservation_hash)
|
295
|
+
if reservation_hash
|
296
|
+
if reservation_hash[:complement]
|
297
|
+
reservation_hash[:complement][:libelleFr]
|
298
|
+
else
|
299
|
+
reservation_hash[:organismes]
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def self.entity_fields(information_hash, type_data_hash)
|
305
|
+
if information_hash && information_hash[:structureGestion]
|
306
|
+
{entity_id: information_hash[:structureGestion][:id], service_provider_id: node_id(type_data_hash, :prestataireActivites)}
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def contact_text
|
311
|
+
entries = []
|
312
|
+
JSON.parse(contact).each_pair do |k, v|
|
313
|
+
entries << "#{k}: #{v}"
|
314
|
+
end
|
315
|
+
entries.join("\n")
|
316
|
+
end
|
317
|
+
|
318
|
+
def main_picture
|
319
|
+
pictures.any? ? pictures[0]["url"] : "#{Rails.application.config.apidae_pictures_path}/default/logo.png"
|
320
|
+
end
|
321
|
+
|
322
|
+
def self.build_rate(rate_period)
|
323
|
+
{
|
324
|
+
id: rate_period[:identifiant], from: rate_period[:dateDebut], to: rate_period[:dateFin],
|
325
|
+
values: rate_period[:tarifs].blank? ? [] : rate_period[:tarifs].map {|t| {min: t[:minimum], max: t[:maximum], type: t[:type][:id], details: node_value(t, :precisionTarif)}}
|
326
|
+
}
|
327
|
+
end
|
328
|
+
|
329
|
+
private
|
330
|
+
|
331
|
+
def self.node_value(node, key)
|
332
|
+
if node && node[key]
|
333
|
+
node[key][:libelleFr]
|
334
|
+
else
|
335
|
+
''
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def self.node_id(node, key)
|
340
|
+
node[key][:id] if node && node[key]
|
341
|
+
end
|
342
|
+
|
343
|
+
def self.lists_ids(*lists)
|
344
|
+
lists.blank? ? [] : lists.map {|l| l.blank? ? [] : l.map {|elt| elt[:id]}}.flatten.uniq
|
345
|
+
end
|
346
|
+
|
347
|
+
def self.nodes_ids(*nodes)
|
348
|
+
nodes.blank? ? [] : nodes.select {|n| !n.blank?}.map {|n| n[:id]}
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|