apidae 0.10.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1e5d13058f65857b20c5eb5ebcb31933047d458d
4
- data.tar.gz: 57c158bf11ea28f28c25094e2e2b732289cd1b47
3
+ metadata.gz: 0603f295a6946a070d13d9a70813840de04bc155
4
+ data.tar.gz: 9e15a59b156bad347b5d0cec0625fdb6ddca2c38
5
5
  SHA512:
6
- metadata.gz: '039e3d10fa484d795ad731c1a178b567f7c793b2a339ea835370f0a3c59318734ecb5bc9cd818073da9d4c16cdaf03d9d833f83c507d8589f39fe41d56c32657'
7
- data.tar.gz: 188194787706a94cf7b04854bdd92266095ee95607b24a764ad2ccadda0fec50f076bb9d0631b7bb3454c02c80c74334bb5f313832d10ac012b86ec4ad3c3e23
6
+ metadata.gz: 960c0cc9dcbbca0b5a290b4d44b60ca10b81271b55050d27ac6d279680d77233221720e117f5b2d7193824856e75d8cf842880625cda9d6b7a29fc94bde2b05b
7
+ data.tar.gz: 4dacb5596fad4f0824c76e1a2f4fd9f124f12399fbd753401e5ff3deea084b12ca087e83985dea9e7c5e9e3ee0725a315af69417a205ae7d8f9a186734b1e871
@@ -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,399 @@
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
+ openings_extra: lists_ids(openings_hash[:ouverturesComplementaires])
215
+ }
216
+ end
217
+ end
218
+
219
+ def self.parse_rates(rates_hash, *locales)
220
+ if rates_hash
221
+ desc = rates_hash[:gratuit] ? {DEFAULT_LOCALE => 'gratuit'} : node_value(rates_hash, :tarifsEnClair, *locales)
222
+ values = rates_hash[:periodes].blank? ? [] : rates_hash[:periodes].map {|p| build_rate(p)}
223
+ methods = rates_hash[:modesPaiement].blank? ? [] : rates_hash[:modesPaiement].map {|p| p[:id]}
224
+ {
225
+ rates_desc: desc, rates: values, payment_methods: methods,
226
+ rates_desc_mode: rates_hash[:tarifsEnClairGenerationMode] == 'AUTOMATIQUE' ? MODE_AUTO : MODE_MANUAL,
227
+ includes: node_value(rates_hash, :leTarifComprend, *locales),
228
+ excludes: node_value(rates_hash, :leTarifNeComprendPas, *locales)
229
+ }
230
+ end
231
+ end
232
+
233
+ def self.parse_type_data(apidae_obj, type_hash, presta_hash, business_hash, *locales)
234
+ data_hash = type_hash || {}
235
+ prestations_hash = presta_hash || {}
236
+ apidae_obj.apidae_subtype = lists_ids(data_hash[:typesManifestation]).first if apidae_obj.apidae_type == Obj::FEM
237
+ apidae_obj.apidae_subtype = node_id(data_hash, :rubrique) if apidae_obj.apidae_type == Obj::EQU
238
+ apidae_obj.apidae_subtype = lists_ids(data_hash[:typesHebergement]).first if apidae_obj.apidae_type == Obj::SPA
239
+ {
240
+ categories: lists_ids(data_hash[:categories], data_hash[:typesDetailles], data_hash[:activiteCategories]),
241
+ themes: lists_ids(data_hash[:themes]),
242
+ capacity: (data_hash[:capacite] || {})
243
+ .merge(presta_hash ? {group_min: presta_hash[:tailleGroupeMin], group_max: presta_hash[:tailleGroupeMax],
244
+ age_min: presta_hash[:ageMin], age_max: presta_hash[:ageMax]} : {}),
245
+ classification: nodes_ids(data_hash[:classement], data_hash[:classementPrefectoral], data_hash[:classification]) +
246
+ lists_ids(data_hash[:classementsGuides]) + lists_ids(data_hash[:classements]),
247
+ labels: lists_ids(data_hash[:labels], data_hash[:labelsChartesQualite], prestations_hash[:labelsTourismeHandicap]) +
248
+ (node_id(data_hash, :typeLabel) ? [node_id(data_hash, :typeLabel)] : []),
249
+ chains: lists_ids(data_hash[:chaines]) + nodes_ids(data_hash[:chaineEtLabel]),
250
+ area: apidae_obj.apidae_type == Obj::DOS ? data_hash.except(:classification) : node_value(data_hash, :lieuDePratique),
251
+ track: apidae_obj.apidae_type == Obj::EQU ? data_hash[:itineraire] : nil,
252
+ products: lists_ids(data_hash[:typesProduit], data_hash[:aopAocIgps], data_hash[:specialites]),
253
+ audience: lists_ids(prestations_hash[:typesClientele]),
254
+ animals: {allowed: prestations_hash[:animauxAcceptes] == 'ACCEPTES', desc: node_value(prestations_hash, :descriptifAnimauxAcceptes, *locales),
255
+ fee: prestations_hash[:animauxAcceptesSupplement] == 'AVEC_SUPPLEMENT'},
256
+ extra: apidae_obj.apidae_type == Obj::SPA ? node_value(data_hash, :formuleHebergement, *locales) : node_value(prestations_hash, :complementAccueil, *locales),
257
+ duration: apidae_obj.apidae_type == Obj::SPA ? {days: data_hash[:nombreJours], nights: data_hash[:nombreNuits]} : data_hash[:dureeSeance],
258
+ certifications: data_hash[:agrements].blank? ? [] : data_hash[:agrements].map {|a| {id: a[:type][:id], identifier: a[:numero]}},
259
+ business: business_hash
260
+ }
261
+ end
262
+
263
+ def self.parse_service_data(data_hash, type_data_hash)
264
+ if data_hash
265
+ {
266
+ services: lists_ids(data_hash[:services]),
267
+ equipments: lists_ids(data_hash[:equipements]),
268
+ comfort: lists_ids(data_hash[:conforts]),
269
+ activities: lists_ids(data_hash[:activites], type_data_hash ? type_data_hash[:activites] : [],
270
+ type_data_hash ? type_data_hash[:activitesSportives] : [],
271
+ type_data_hash ? type_data_hash[:activitesCulturelles] : []),
272
+ challenged: lists_ids(data_hash[:tourismesAdaptes]),
273
+ languages: lists_ids(data_hash[:languesParlees])
274
+ }
275
+ end
276
+ end
277
+
278
+ def self.parse_tags_data(pres_data_hash, crit_data_hash, linked_data_hash)
279
+ tags = {}
280
+ if pres_data_hash
281
+ tags[:promo] = lists_ids(pres_data_hash[:typologiesPromoSitra])
282
+ end
283
+ unless crit_data_hash.blank?
284
+ tags[:internal] = crit_data_hash.map {|c| c[:id]}
285
+ end
286
+ unless linked_data_hash.blank? || linked_data_hash[:liensObjetsTouristiquesTypes].blank?
287
+ tags[:linked] = linked_data_hash[:liensObjetsTouristiquesTypes]
288
+ .map {|l| {apidae_id: l[:objetTouristique][:id], apidae_type: l[:objetTouristique][:type], category: l[:type]}}
289
+ end
290
+ tags
291
+ end
292
+
293
+ def self.parse_booking(reservation_hash, *locales)
294
+ if reservation_hash
295
+ {
296
+ booking_desc: node_value(reservation_hash, :complement, *locales),
297
+ booking_entities: reservation_hash[:organismes]
298
+ }
299
+ end
300
+ end
301
+
302
+ def self.parse_town(location_hash)
303
+ if location_hash
304
+ address_hash = location_hash[:adresse]
305
+ (!address_hash.blank? && address_hash[:commune]) ? Town.find_by_apidae_id(address_hash[:commune][:id]) : nil
306
+ else
307
+ nil
308
+ end
309
+ end
310
+
311
+ def self.parse_entity_fields(information_hash, type_data_hash)
312
+ if information_hash && information_hash[:structureGestion]
313
+ {entity_id: information_hash[:structureGestion][:id], service_provider_id: node_id(type_data_hash, :prestataireActivites)}
314
+ end
315
+ end
316
+
317
+ def self.node_id(node, key)
318
+ node[key][:id] if node && node[key]
319
+ end
320
+
321
+ private
322
+
323
+ def self.build_rate(rate_period)
324
+ {
325
+ id: rate_period[:identifiant], start_date: rate_period[:dateDebut], end_date: rate_period[:dateFin],
326
+ 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)}}
327
+ }
328
+ end
329
+
330
+ def self.build_openings(openings_data, *locales)
331
+ openings_list = openings_data[:periodesOuvertures]
332
+ closing_days = openings_data[:fermeturesExceptionnelles]
333
+ if openings_list.blank?
334
+ []
335
+ else
336
+ openings_list.map do |o|
337
+ {
338
+ id: o[:identifiant],
339
+ external_id: o[:identifiantTechnique],
340
+ start_date: o[:dateDebut],
341
+ end_date: o[:dateFin],
342
+ closing_days: closing_days.blank? ? [] : closing_days.map {|d| d[:dateSpeciale]},
343
+ details: node_value(o, :complementHoraire, *locales),
344
+ time_periods: [
345
+ {
346
+ type: 'opening',
347
+ weekdays: compute_weekdays(o),
348
+ time_frames: (o[:horaireOuverture].blank? && o[:horaireFermeture].blank?) ? [] : [{start_time: o[:horaireOuverture], end_time: o[:horaireFermeture], recurrence: nil}]
349
+ }
350
+ ]
351
+ }
352
+ end
353
+ end
354
+ end
355
+
356
+ def self.compute_weekdays(opening_data)
357
+ if opening_data[:type] == 'OUVERTURE_TOUS_LES_JOURS'
358
+ ALL_DAYS
359
+ elsif opening_data[:type] == 'OUVERTURE_SAUF' && opening_data[:ouverturesJournalieres]
360
+ closed_weekdays = opening_data[:ouverturesJournalieres].map {|d| WEEKDAYS_MAP[d[:jour]]}
361
+ ALL_DAYS - closed_weekdays
362
+ elsif opening_data[:type] == 'OUVERTURE_SEMAINE' && opening_data[:ouverturesJournalieres]
363
+ opening_data[:ouverturesJournalieres].map {|d| WEEKDAYS_MAP[d[:jour]]}
364
+ else
365
+ []
366
+ end
367
+ end
368
+
369
+ def self.node_value(node, key, *locales)
370
+ l = locales.blank? ? [DEFAULT_LOCALE] : locales
371
+ locales_map = Hash[l.map {|loc| [localized_key(loc), loc]}]
372
+ if node && node[key]
373
+ node[key].slice(*locales_map.keys).transform_keys {|k| locales_map[k]}
374
+ else
375
+ {}
376
+ end
377
+ end
378
+
379
+ def self.localized_value(node, key, loc)
380
+ if node && node[key]
381
+ node[key][localized_key(loc)]
382
+ else
383
+ ''
384
+ end
385
+ end
386
+
387
+ def self.lists_ids(*lists)
388
+ lists.blank? ? [] : lists.map {|l| l.blank? ? [] : l.map {|elt| elt[:id]}}.flatten.uniq
389
+ end
390
+
391
+ def self.nodes_ids(*nodes)
392
+ nodes.blank? ? [] : nodes.select {|n| !n.blank?}.map {|n| n[:id]}
393
+ end
394
+
395
+ def self.localized_key(loc = DEFAULT_LOCALE)
396
+ "libelle#{loc.camelize.gsub('-', '')}".to_sym
397
+ end
398
+ end
399
+ end