apidae 0.9.26 → 1.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b655d3179ca371fef82c07047d90d697237f1865
4
- data.tar.gz: ff4982ec6b58a36f49cf8f370cf4fea62d637af4
3
+ metadata.gz: b71bd513f58e234253653471aa9a71ac9d0c2128
4
+ data.tar.gz: 7564dab0a718de8e97f06bdba7373513265a1031
5
5
  SHA512:
6
- metadata.gz: 9cdc066df96e9ca1980e07eb9b6f1b95d8cc7e8c1cd43e9943d69cf454f8a47f49870daafdf5db472c3ffcd4a2bb2ac01004c13106713b93a0670f8390d6cff0
7
- data.tar.gz: 016220b014fcbc5f2be9e4b3392f379dcd8555500c8c7f7057cdfd23fa61cf61c115f32f404a2cfdff87067c27d68e831dfe25c496b432f3293b02e1122d9cbb
6
+ metadata.gz: ee5d3cbb3aa547a36f7131ee07819b0daf560808a977facfc62bf9ade35f04909400b2a9ca2279b50d8b452de3bb72c6f24ebc289c0e5425c6f22d37a5d2407b
7
+ data.tar.gz: 7b4466705605f967acb6026c0887c1ec00a448196d478b1ca47187701f833cb94367b338b45199a480e2f20374337ed54f4ff23e43e3a8509e29da5162bd9391
@@ -2,5 +2,24 @@ module Apidae
2
2
  class ApplicationController < ActionController::Base
3
3
  protect_from_forgery with: :exception
4
4
  before_action Rails.application.config.apidae_auth
5
+ before_action :check_user_data!
6
+
7
+ def apidae_user
8
+ send(Rails.application.config.apidae_user) if Rails.application.config.respond_to?(:apidae_user)
9
+ end
10
+
11
+ def user_is_admin?
12
+ apidae_user && Rails.application.config.respond_to?(:apidae_admin) && Rails.application.config.apidae_admin.call(apidae_user)
13
+ end
14
+
15
+ def user_has_data?
16
+ apidae_user && apidae_user.respond_to?(:apidae_projects_ids) && !apidae_user.apidae_projects_ids.blank?
17
+ end
18
+
19
+ def check_user_data!
20
+ unless user_has_data? || user_is_admin?
21
+ redirect_to main_app.root_path, alert: "Il n'y a aucun projet Apidae associé à votre compte."
22
+ end
23
+ end
5
24
  end
6
25
  end
@@ -3,11 +3,20 @@ require_dependency "apidae/application_controller"
3
3
  module Apidae
4
4
  class DashboardController < ApplicationController
5
5
  def index
6
- @objects = Obj.count
7
- @selections = Selection.count
8
- @projects = Project.count
6
+ if user_is_admin?
7
+ @objects = Obj.count
8
+ @selections = Selection.count
9
+ @projects = Project.count
10
+ @last_imports = FileImport.order(id: :desc).take(100)
11
+ else
12
+ projects = Project.where(apidae_id: apidae_user.apidae_projects_ids)
13
+ selections = Selection.where(apidae_project_id: projects.select(:id).map {|p| p.id})
14
+ @projects = projects.count
15
+ @selections = selections.uniq.count
16
+ @objects = SelectionObject.where(apidae_selection_id: selections.map {|s| s.id}.uniq).map {|so| so.apidae_object_id}.uniq.count
17
+ @last_imports = FileImport.where(apidae_id: apidae_user.apidae_projects_ids).order(id: :desc).take(100)
18
+ end
9
19
  @references = Reference.count
10
- @last_imports = FileImport.order(id: :desc).take(100)
11
20
  end
12
21
  end
13
22
  end
@@ -6,6 +6,7 @@ module Apidae
6
6
  class ImportController < ApplicationController
7
7
  skip_before_action :verify_authenticity_token
8
8
  skip_before_action Rails.application.config.apidae_auth
9
+ skip_before_action :check_user_data!
9
10
 
10
11
  # Callback endpoint for Apidae exports
11
12
  #
@@ -10,8 +10,13 @@ module Apidae
10
10
  if params[:selection_id]
11
11
  @selection = Selection.find(params[:selection_id])
12
12
  @objects = @selection.objects.select(:id, :apidae_id, :title_data, :apidae_type, :updated_at)
13
- else
13
+ elsif user_is_admin?
14
14
  @objects = Obj.all.select(:id, :apidae_id, :title_data, :apidae_type, :updated_at)
15
+ else
16
+ projects_ids = Project.where(apidae_id: apidae_user.apidae_projects_ids).map {|p| p.id}
17
+ @objects = Obj.joins(:selections).where("apidae_selections.apidae_project_id IN (?)", projects_ids)
18
+ .select("apidae_objs.id, apidae_objs.apidae_id, apidae_objs.title_data, apidae_objs.apidae_type, apidae_objs.updated_at")
19
+ .distinct("apidae_objs.apidae_id").to_a
15
20
  end
16
21
  end
17
22
 
@@ -5,7 +5,11 @@ module Apidae
5
5
  before_action :set_project, only: [:edit, :update, :destroy]
6
6
 
7
7
  def index
8
- @projects = Project.all
8
+ if user_is_admin?
9
+ @projects = Project.all
10
+ else
11
+ @projects = Project.where(apidae_id: apidae_user.apidae_projects_ids)
12
+ end
9
13
  end
10
14
 
11
15
  def new
@@ -5,7 +5,12 @@ module Apidae
5
5
  before_action :set_selection, only: [:show, :edit, :update, :destroy, :refresh]
6
6
 
7
7
  def index
8
- @selections = Selection.all
8
+ if user_is_admin?
9
+ @selections = Selection.all
10
+ else
11
+ projects_ids = Project.where(apidae_id: apidae_user.apidae_projects_ids).map {|p| p.id}
12
+ @selections = Selection.where(apidae_project_id: projects_ids)
13
+ end
9
14
  end
10
15
 
11
16
  def show
@@ -1,5 +1,9 @@
1
1
  module Apidae
2
2
  module ApplicationHelper
3
3
  include Apidae::ApidaeHelper
4
+
5
+ def apidae_user
6
+ send(Rails.application.config.apidae_user) if Rails.application.config.respond_to?(:apidae_user)
7
+ end
4
8
  end
5
9
  end
@@ -0,0 +1,398 @@
1
+ module Apidae
2
+ class ApidaeDataParser
3
+ PHONE = 201
4
+ ALT_PHONE = 206
5
+ EMAIL = 204
6
+ WEBSITE = 205
7
+ GOOGLE = 3789
8
+ FACEBOOK = 207
9
+ TWITTER = 3755
10
+ YELP = 4007
11
+ TRIP_ADVISOR = 4000
12
+
13
+ MODE_AUTO = 'auto'
14
+ MODE_MANUAL = 'manual'
15
+
16
+ MONDAY = 'MON'
17
+ TUESDAY = 'TUE'
18
+ WEDNESDAY = 'WED'
19
+ THURSDAY = 'THU'
20
+ FRIDAY = 'FRI'
21
+ SATURDAY = 'SAT'
22
+ SUNDAY = 'SUN'
23
+
24
+ ALL_DAYS = [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
25
+
26
+ WEEKDAYS_MAP = {
27
+ 'LUNDI' => MONDAY,
28
+ 'MARDI' => TUESDAY,
29
+ 'MERCREDI' => WEDNESDAY,
30
+ 'JEUD' => THURSDAY,
31
+ 'VENDREDI' => FRIDAY,
32
+ 'SAMEDI' => SATURDAY,
33
+ 'DIMANCHE' => SUNDAY
34
+ }
35
+
36
+ def self.parse_versioned_fields(data_hash)
37
+ version_fields = data_hash[:champsAspect] || []
38
+ matched_fields = []
39
+ version_fields.each do |f|
40
+ case f
41
+ when 'nom'
42
+ matched_fields << 'title'
43
+ when 'presentation.descriptifCourt'
44
+ matched_fields << 'short_desc'
45
+ when 'presentation.descriptifDetaille'
46
+ matched_fields << 'long_desc'
47
+ when 'illustrations'
48
+ matched_fields << 'pictures'
49
+ when 'multimedias'
50
+ matched_fields << 'attachments'
51
+ when 'informations.moyensCommunication'
52
+ matched_fields << 'contact'
53
+ when 'descriptifsThematises'
54
+ matched_fields << 'theme_desc'
55
+ when 'ouverture.periodesOuvertures', 'ouverture.periodeEnClair'
56
+ matched_fields << 'openings_desc'
57
+ matched_fields << 'openings'
58
+ when 'ouverture.periodeEnClairAutomatique'
59
+ matched_fields << 'openings_desc_mode'
60
+ when 'descriptionTarif.tarifsEnClair', 'descriptionTarif.periodes'
61
+ matched_fields << 'rates_desc'
62
+ matched_fields << 'rates'
63
+ when 'descriptionTarif.tarifsEnClairAutomatique'
64
+ matched_fields << 'rates_desc_mode'
65
+ when 'prestations.equipements'
66
+ matched_fields << 'equipments'
67
+ when 'prestations.activites'
68
+ matched_fields << 'activities'
69
+ when 'prestations.services'
70
+ matched_fields << 'services'
71
+ when 'localisation.environnements'
72
+ matched_fields << 'environments'
73
+ when 'prestations.complementAccueil'
74
+ matched_fields << 'extra'
75
+ when 'localisation.geolocalisation.complement'
76
+ matched_fields << 'access'
77
+ else
78
+ end
79
+ end
80
+ matched_fields.uniq
81
+ end
82
+
83
+ def self.parse_title(data_hash, *locales)
84
+ {title: node_value(data_hash, :nom, *locales)}
85
+ end
86
+
87
+ def self.parse_owner_data(data_hash)
88
+ unless data_hash.blank?
89
+ {owner_name: data_hash[:nom], owner_id: data_hash[:id]}
90
+ end
91
+ end
92
+
93
+ def self.parse_desc_data(data_hash, private_data, *locales)
94
+ unless data_hash.blank?
95
+ {
96
+ short_desc: node_value(data_hash, :descriptifCourt, *locales),
97
+ long_desc: node_value(data_hash, :descriptifDetaille, *locales),
98
+ theme_desc: data_hash[:descriptifsThematises].blank? ? {} : Hash[data_hash[:descriptifsThematises].map {|th| [node_id(th, :theme), node_value(th, :description, *locales)]}],
99
+ private_desc: private_data.blank? ? {} : Hash[private_data.map {|d| [d[:nomTechnique], node_value(d, :descriptif, *locales)]}]
100
+ }
101
+ end
102
+ end
103
+
104
+ def self.parse_pictures_data(pictures_array, *locales)
105
+ pics_data = {}
106
+ unless pictures_array.blank?
107
+ l = locales.blank? ? [DEFAULT_LOCALE] : locales
108
+ l.each do |locale|
109
+ pics_data[locale] = []
110
+ pictures_array.select { |p| p.is_a?(Hash) && !p[:traductionFichiers].blank? }.each do |pic|
111
+ pics_data[locale] << {
112
+ id: pic[:identifiant],
113
+ name: localized_value(pic, :nom, locale),
114
+ url: pic[:traductionFichiers][0][:url].gsub('http:', 'https:'),
115
+ description: localized_value(pic, :legende, locale),
116
+ credits: localized_value(pic, :copyright, locale),
117
+ expiration_date: pic[:dateLimiteDePublication]
118
+ }
119
+ end
120
+ end
121
+ end
122
+ {pictures: pics_data}
123
+ end
124
+
125
+ def self.parse_attachments_data(attachments_array, *locales)
126
+ atts_data = {}
127
+ unless attachments_array.blank?
128
+ l = locales.blank? ? [DEFAULT_LOCALE] : locales
129
+ l.each do |locale|
130
+ atts_data[locale] = []
131
+ attachments_array.select { |att| att.is_a?(Hash) && !att[:traductionFichiers].blank? }.each do |att|
132
+ atts_data[locale] << {
133
+ id: att[:identifiant],
134
+ name: localized_value(att, :nom, locale),
135
+ url: att[:traductionFichiers][0][:url].gsub('http:', 'https:'),
136
+ type: att[:type],
137
+ description: localized_value(att, :legende, locale)
138
+ }
139
+ end
140
+ end
141
+ end
142
+ {attachments: atts_data}
143
+ end
144
+
145
+ def self.parse_contact_data(information_hash, contacts_list)
146
+ contact_details = {contacts: contacts_list}
147
+ unless information_hash.blank?
148
+ contact_entries = information_hash[:moyensCommunication] || []
149
+ contact_entries.each do |c|
150
+ case c[:type][:id]
151
+ when PHONE, ALT_PHONE
152
+ contact_details[:telephone] ||= []
153
+ contact_details[:telephone] << c[:coordonnees][:fr]
154
+ when EMAIL
155
+ contact_details[:email] ||= []
156
+ contact_details[:email] << c[:coordonnees][:fr]
157
+ when WEBSITE
158
+ contact_details[:website] ||= []
159
+ contact_details[:website] << c[:coordonnees][:fr]
160
+ when GOOGLE
161
+ contact_details[:google] ||= []
162
+ contact_details[:google] << c[:coordonnees][:fr]
163
+ when FACEBOOK
164
+ contact_details[:facebook] ||= []
165
+ contact_details[:facebook] << c[:coordonnees][:fr]
166
+ when TWITTER
167
+ contact_details[:twitter] ||= []
168
+ contact_details[:twitter] << c[:coordonnees][:fr]
169
+ when YELP
170
+ contact_details[:yelp] ||= []
171
+ contact_details[:yelp] << c[:coordonnees][:fr]
172
+ when TRIP_ADVISOR
173
+ contact_details[:trip_advisor] ||= []
174
+ contact_details[:trip_advisor] << c[:coordonnees][:fr]
175
+ else
176
+ end
177
+ end
178
+ end
179
+ contact_details
180
+ end
181
+
182
+ def self.parse_location_data(location_hash, type_data_hash, territories)
183
+ loc_data = {}
184
+ unless location_hash.blank?
185
+ address_hash = location_hash[:adresse]
186
+ computed_address = []
187
+ unless address_hash.blank?
188
+ computed_address << address_hash[:adresse1] unless address_hash[:adresse1].blank?
189
+ computed_address << address_hash[:adresse2] unless address_hash[:adresse2].blank?
190
+ computed_address << address_hash[:adresse3] unless address_hash[:adresse3].blank?
191
+ end
192
+ loc_data.merge!({address: computed_address})
193
+ loc_data.merge!({place: type_data_hash[:nomLieu]}) if type_data_hash
194
+ geoloc_details = location_hash[:geolocalisation]
195
+ if geoloc_details && geoloc_details[:valide] && geoloc_details[:geoJson]
196
+ loc_data[:latitude] = geoloc_details[:geoJson][:coordinates][1]
197
+ loc_data[:longitude] = geoloc_details[:geoJson][:coordinates][0]
198
+ end
199
+ loc_data[:access] = node_value(geoloc_details, :complement) if geoloc_details
200
+ loc_data[:environments] = location_hash[:environnements].map {|e| e[:id]} if location_hash[:environnements]
201
+ end
202
+ loc_data[:territories] = territories.map {|t| t[:id]} unless territories.blank?
203
+ loc_data
204
+ end
205
+
206
+ # Note : use internal format for openings storage (ideally Apihours one, to merge data from both sources)
207
+ def self.parse_openings(openings_hash, *locales)
208
+ if openings_hash && openings_hash[:periodeEnClair]
209
+ {
210
+ openings_desc: node_value(openings_hash, :periodeEnClair, *locales),
211
+ openings_desc_mode: openings_hash[:periodeEnClairGenerationMode] == 'AUTOMATIQUE' ? MODE_AUTO : MODE_MANUAL,
212
+ openings: build_openings(openings_hash, *locales),
213
+ time_periods: lists_ids(openings_hash[:indicationsPeriode])
214
+ }
215
+ end
216
+ end
217
+
218
+ def self.parse_rates(rates_hash, *locales)
219
+ if rates_hash
220
+ desc = rates_hash[:gratuit] ? {DEFAULT_LOCALE => 'gratuit'} : node_value(rates_hash, :tarifsEnClair, *locales)
221
+ values = rates_hash[:periodes].blank? ? [] : rates_hash[:periodes].map {|p| build_rate(p)}
222
+ methods = rates_hash[:modesPaiement].blank? ? [] : rates_hash[:modesPaiement].map {|p| p[:id]}
223
+ {
224
+ rates_desc: desc, rates: values, payment_methods: methods,
225
+ rates_desc_mode: rates_hash[:tarifsEnClairGenerationMode] == 'AUTOMATIQUE' ? MODE_AUTO : MODE_MANUAL,
226
+ includes: node_value(rates_hash, :leTarifComprend, *locales),
227
+ excludes: node_value(rates_hash, :leTarifNeComprendPas, *locales)
228
+ }
229
+ end
230
+ end
231
+
232
+ def self.parse_type_data(apidae_obj, type_hash, presta_hash, business_hash, *locales)
233
+ data_hash = type_hash || {}
234
+ prestations_hash = presta_hash || {}
235
+ apidae_obj.apidae_subtype = lists_ids(data_hash[:typesManifestation]).first if apidae_obj.apidae_type == Obj::FEM
236
+ apidae_obj.apidae_subtype = node_id(data_hash, :rubrique) if apidae_obj.apidae_type == Obj::EQU
237
+ apidae_obj.apidae_subtype = lists_ids(data_hash[:typesHebergement]).first if apidae_obj.apidae_type == Obj::SPA
238
+ {
239
+ categories: lists_ids(data_hash[:categories], data_hash[:typesDetailles], data_hash[:activiteCategories]),
240
+ themes: lists_ids(data_hash[:themes]),
241
+ capacity: (data_hash[:capacite] || {})
242
+ .merge(presta_hash ? {group_min: presta_hash[:tailleGroupeMin], group_max: presta_hash[:tailleGroupeMax],
243
+ age_min: presta_hash[:ageMin], age_max: presta_hash[:ageMax]} : {}),
244
+ classification: nodes_ids(data_hash[:classement], data_hash[:classementPrefectoral], data_hash[:classification]) +
245
+ lists_ids(data_hash[:classementsGuides]) + lists_ids(data_hash[:classements]),
246
+ labels: lists_ids(data_hash[:labels], data_hash[:labelsChartesQualite], prestations_hash[:labelsTourismeHandicap]) +
247
+ (node_id(data_hash, :typeLabel) ? [node_id(data_hash, :typeLabel)] : []),
248
+ chains: lists_ids(data_hash[:chaines]) + nodes_ids(data_hash[:chaineEtLabel]),
249
+ area: apidae_obj.apidae_type == Obj::DOS ? data_hash.except(:classification) : node_value(data_hash, :lieuDePratique),
250
+ track: apidae_obj.apidae_type == Obj::EQU ? data_hash[:itineraire] : nil,
251
+ products: lists_ids(data_hash[:typesProduit], data_hash[:aopAocIgps], data_hash[:specialites]),
252
+ audience: lists_ids(prestations_hash[:typesClientele]),
253
+ animals: {allowed: prestations_hash[:animauxAcceptes] == 'ACCEPTES', desc: node_value(prestations_hash, :descriptifAnimauxAcceptes, *locales),
254
+ fee: prestations_hash[:animauxAcceptesSupplement] == 'AVEC_SUPPLEMENT'},
255
+ extra: apidae_obj.apidae_type == Obj::SPA ? node_value(data_hash, :formuleHebergement, *locales) : node_value(prestations_hash, :complementAccueil, *locales),
256
+ duration: apidae_obj.apidae_type == Obj::SPA ? {days: data_hash[:nombreJours], nights: data_hash[:nombreNuits]} : data_hash[:dureeSeance],
257
+ certifications: data_hash[:agrements].blank? ? [] : data_hash[:agrements].map {|a| {id: a[:type][:id], identifier: a[:numero]}},
258
+ business: business_hash
259
+ }
260
+ end
261
+
262
+ def self.parse_service_data(data_hash, type_data_hash)
263
+ if data_hash
264
+ {
265
+ services: lists_ids(data_hash[:services]),
266
+ equipments: lists_ids(data_hash[:equipements]),
267
+ comfort: lists_ids(data_hash[:conforts]),
268
+ activities: lists_ids(data_hash[:activites], type_data_hash ? type_data_hash[:activites] : [],
269
+ type_data_hash ? type_data_hash[:activitesSportives] : [],
270
+ type_data_hash ? type_data_hash[:activitesCulturelles] : []),
271
+ challenged: lists_ids(data_hash[:tourismesAdaptes]),
272
+ languages: lists_ids(data_hash[:languesParlees])
273
+ }
274
+ end
275
+ end
276
+
277
+ def self.parse_tags_data(pres_data_hash, crit_data_hash, linked_data_hash)
278
+ tags = {}
279
+ if pres_data_hash
280
+ tags[:promo] = lists_ids(pres_data_hash[:typologiesPromoSitra])
281
+ end
282
+ unless crit_data_hash.blank?
283
+ tags[:internal] = crit_data_hash.map {|c| c[:id]}
284
+ end
285
+ unless linked_data_hash.blank? || linked_data_hash[:liensObjetsTouristiquesTypes].blank?
286
+ tags[:linked] = linked_data_hash[:liensObjetsTouristiquesTypes]
287
+ .map {|l| {apidae_id: l[:objetTouristique][:id], apidae_type: l[:objetTouristique][:type], category: l[:type]}}
288
+ end
289
+ tags
290
+ end
291
+
292
+ def self.parse_booking(reservation_hash, *locales)
293
+ if reservation_hash
294
+ {
295
+ booking_desc: node_value(reservation_hash, :complement, *locales),
296
+ booking_entities: reservation_hash[:organismes]
297
+ }
298
+ end
299
+ end
300
+
301
+ def self.parse_town(location_hash)
302
+ if location_hash
303
+ address_hash = location_hash[:adresse]
304
+ (!address_hash.blank? && address_hash[:commune]) ? Town.find_by_apidae_id(address_hash[:commune][:id]) : nil
305
+ else
306
+ nil
307
+ end
308
+ end
309
+
310
+ def self.parse_entity_fields(information_hash, type_data_hash)
311
+ if information_hash && information_hash[:structureGestion]
312
+ {entity_id: information_hash[:structureGestion][:id], service_provider_id: node_id(type_data_hash, :prestataireActivites)}
313
+ end
314
+ end
315
+
316
+ def self.node_id(node, key)
317
+ node[key][:id] if node && node[key]
318
+ end
319
+
320
+ private
321
+
322
+ def self.build_rate(rate_period)
323
+ {
324
+ id: rate_period[:identifiant], start_date: rate_period[:dateDebut], end_date: 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
+ def self.build_openings(openings_data, *locales)
330
+ openings_list = openings_data[:periodesOuvertures]
331
+ closing_days = openings_data[:fermeturesExceptionnelles]
332
+ if openings_list.blank?
333
+ []
334
+ else
335
+ openings_list.map do |o|
336
+ {
337
+ id: o[:identifiant],
338
+ external_id: o[:identifiantTechnique],
339
+ start_date: o[:dateDebut],
340
+ end_date: o[:dateFin],
341
+ closing_days: closing_days.blank? ? [] : closing_days.map {|d| d[:dateSpeciale]},
342
+ details: node_value(o, :complementHoraire, *locales),
343
+ time_periods: [
344
+ {
345
+ type: 'opening',
346
+ weekdays: compute_weekdays(o),
347
+ time_frames: (o[:horaireOuverture].blank? && o[:horaireFermeture].blank?) ? [] : [{start_time: o[:horaireOuverture], end_time: o[:horaireFermeture], recurrence: nil}]
348
+ }
349
+ ]
350
+ }
351
+ end
352
+ end
353
+ end
354
+
355
+ def self.compute_weekdays(opening_data)
356
+ if opening_data[:type] == 'OUVERTURE_TOUS_LES_JOURS'
357
+ ALL_DAYS
358
+ elsif opening_data[:type] == 'OUVERTURE_SAUF' && opening_data[:ouverturesJournalieres]
359
+ closed_weekdays = opening_data[:ouverturesJournalieres].map {|d| WEEKDAYS_MAP[d[:jour]]}
360
+ ALL_DAYS - closed_weekdays
361
+ elsif opening_data[:type] == 'OUVERTURE_SEMAINE' && opening_data[:ouverturesJournalieres]
362
+ opening_data[:ouverturesJournalieres].map {|d| WEEKDAYS_MAP[d[:jour]]}
363
+ else
364
+ []
365
+ end
366
+ end
367
+
368
+ def self.node_value(node, key, *locales)
369
+ l = locales.blank? ? [DEFAULT_LOCALE] : locales
370
+ locales_map = Hash[l.map {|loc| [localized_key(loc), loc]}]
371
+ if node && node[key]
372
+ node[key].slice(*locales_map.keys).transform_keys {|k| locales_map[k]}
373
+ else
374
+ {}
375
+ end
376
+ end
377
+
378
+ def self.localized_value(node, key, loc)
379
+ if node && node[key]
380
+ node[key][localized_key(loc)]
381
+ else
382
+ ''
383
+ end
384
+ end
385
+
386
+ def self.lists_ids(*lists)
387
+ lists.blank? ? [] : lists.map {|l| l.blank? ? [] : l.map {|elt| elt[:id]}}.flatten.uniq
388
+ end
389
+
390
+ def self.nodes_ids(*nodes)
391
+ nodes.blank? ? [] : nodes.select {|n| !n.blank?}.map {|n| n[:id]}
392
+ end
393
+
394
+ def self.localized_key(loc = DEFAULT_LOCALE)
395
+ "libelle#{loc.camelize.gsub('-', '')}".to_sym
396
+ end
397
+ end
398
+ end