diff options
Diffstat (limited to 'app/models')
| -rw-r--r-- | app/models/chouette/area_type.rb | 8 | ||||
| -rw-r--r-- | app/models/chouette/purchase_window.rb | 9 | ||||
| -rw-r--r-- | app/models/chouette/route.rb | 2 | ||||
| -rw-r--r-- | app/models/chouette/routing_constraint_zone.rb | 7 | ||||
| -rw-r--r-- | app/models/chouette/stop_point.rb | 2 | ||||
| -rw-r--r-- | app/models/chouette/vehicle_journey.rb | 3 | ||||
| -rw-r--r-- | app/models/compliance_check_message_export.rb | 2 | ||||
| -rw-r--r-- | app/models/import/message_export.rb | 2 | ||||
| -rw-r--r-- | app/models/import/netex.rb | 11 | ||||
| -rw-r--r-- | app/models/merge.rb | 98 |
10 files changed, 124 insertions, 20 deletions
diff --git a/app/models/chouette/area_type.rb b/app/models/chouette/area_type.rb index e17d2ee8d..4feb5c914 100644 --- a/app/models/chouette/area_type.rb +++ b/app/models/chouette/area_type.rb @@ -34,9 +34,9 @@ class Chouette::AreaType @@options = {} end - def self.options(kind=:all) + def self.options(kind=:all, locale=nil) @@options ||= {} - @@options[kind] ||= self.send(kind).map { |c| find(c) }.map { |t| [ t.label, t.code ] } + @@options[kind] ||= self.send(kind).map { |c| find(c) }.map { |t| [ t.label(locale), t.code ] } end attr_reader :code @@ -48,8 +48,8 @@ class Chouette::AreaType all.index(code) <=> all.index(other.code) end - def label - I18n.translate code, scope: 'area_types.label' + def label locale=nil + I18n.translate code, scope: 'area_types.label', locale: locale end end diff --git a/app/models/chouette/purchase_window.rb b/app/models/chouette/purchase_window.rb index d22674637..bd7cbb41e 100644 --- a/app/models/chouette/purchase_window.rb +++ b/app/models/chouette/purchase_window.rb @@ -21,6 +21,13 @@ module Chouette scope :overlap_dates, ->(date_range) { where('daterange(?, ?) && any (date_ranges)', date_range.first, date_range.last + 1.day) } scope :matching_dates, ->(date_range) { where('ARRAY[daterange(?, ?)] = date_ranges', date_range.first, date_range.last + 1.day) } + # VehicleJourneys include PurchaseWindow checksums in their checksums + # OPTIMIZEME + def update_vehicle_journey_checksums + vehicle_journeys.find_each(&:update_checksum!) + end + after_commit :update_vehicle_journey_checksums + def self.ransackable_scopes(auth_object = nil) [:contains_date] end @@ -35,7 +42,7 @@ module Chouette def checksum_attributes attrs = ['name', 'color', 'referential_id'] - ranges_attrs = date_ranges.map{|r| [r.first, r.last]}.flatten.sort + ranges_attrs = date_ranges.map{|r| [r.min, r.max]}.flatten.sort self.slice(*attrs).values + ranges_attrs end diff --git a/app/models/chouette/route.rb b/app/models/chouette/route.rb index b7f1e722b..928b65f13 100644 --- a/app/models/chouette/route.rb +++ b/app/models/chouette/route.rb @@ -148,7 +148,7 @@ module Chouette values = self.slice(*['name', 'published_name', 'wayback']).values values.tap do |attrs| attrs << self.stop_points.sort_by(&:position).map{|sp| [sp.stop_area.user_objectid, sp.for_boarding, sp.for_alighting]} - attrs << self.routing_constraint_zones.map(&:checksum) + attrs << self.routing_constraint_zones.map(&:checksum).sort end end diff --git a/app/models/chouette/routing_constraint_zone.rb b/app/models/chouette/routing_constraint_zone.rb index 886eadc6c..2cfb60bdd 100644 --- a/app/models/chouette/routing_constraint_zone.rb +++ b/app/models/chouette/routing_constraint_zone.rb @@ -1,6 +1,6 @@ module Chouette class RoutingConstraintZone < Chouette::TridentActiveRecord - has_metadata + # has_metadata include ChecksumSupport include ObjectidSupport @@ -30,6 +30,11 @@ module Chouette ] end + def update_route_checksum + route.update_checksum! + end + after_commit :update_route_checksum + def stop_points_belong_to_route return unless route diff --git a/app/models/chouette/stop_point.rb b/app/models/chouette/stop_point.rb index 6f2d89578..b0906d65f 100644 --- a/app/models/chouette/stop_point.rb +++ b/app/models/chouette/stop_point.rb @@ -26,7 +26,7 @@ module Chouette scope :default_order, -> { order("position") } - delegate :name, :kind, :area_type, to: :stop_area + delegate :name, :registration_number, :kind, :area_type, to: :stop_area before_destroy :remove_dependent_journey_pattern_stop_points def remove_dependent_journey_pattern_stop_points diff --git a/app/models/chouette/vehicle_journey.rb b/app/models/chouette/vehicle_journey.rb index c269d478e..814eeb388 100644 --- a/app/models/chouette/vehicle_journey.rb +++ b/app/models/chouette/vehicle_journey.rb @@ -140,9 +140,12 @@ module Chouette attrs << self.published_journey_identifier attrs << self.try(:company).try(:get_objectid).try(:local_id) attrs << self.footnotes.map(&:checksum).sort + vjas = self.vehicle_journey_at_stops vjas += VehicleJourneyAtStop.where(vehicle_journey_id: self.id) unless self.new_record? attrs << vjas.uniq.sort_by { |s| s.stop_point&.position }.map(&:checksum).sort + + attrs << self.purchase_windows.map(&:checksum).sort if purchase_windows.present? end end diff --git a/app/models/compliance_check_message_export.rb b/app/models/compliance_check_message_export.rb index bbaaa8e3f..9b7f90fac 100644 --- a/app/models/compliance_check_message_export.rb +++ b/app/models/compliance_check_message_export.rb @@ -22,7 +22,7 @@ class ComplianceCheckMessageExport end def column_names - ["criticity", "message key", "resource objectid", "link", "message"] + ["criticity", "message_key", "resource_objectid", "link", "message"].map {|c| ComplianceCheckMessage.tmf(c)} end def to_csv(options = {}) diff --git a/app/models/import/message_export.rb b/app/models/import/message_export.rb index 7a7add08c..7d03783ed 100644 --- a/app/models/import/message_export.rb +++ b/app/models/import/message_export.rb @@ -22,7 +22,7 @@ class Import::MessageExport end def column_names - ["criticity", "message key", "message", "file name", "line", "column"] + ["criticity", "message_key", "message", "filename", "line", "column"].map {|c| Import::Message.tmf(c)} end def to_csv(options = {}) diff --git a/app/models/import/netex.rb b/app/models/import/netex.rb index 93604c5f9..f19fde435 100644 --- a/app/models/import/netex.rb +++ b/app/models/import/netex.rb @@ -10,7 +10,7 @@ class Import::Netex < Import::Base validates_presence_of :parent - def create_referential! + def create_with_referential! self.referential = Referential.new( name: self.name, @@ -19,15 +19,16 @@ class Import::Netex < Import::Base metadatas: [referential_metadata] ) self.referential.save - unless self.referential.valid? + if self.referential.invalid? Rails.logger.info "Can't create referential for import #{self.id}: #{referential.inspect} #{referential.metadatas.inspect} #{referential.errors.messages}" - if referential.metadatas.all?{|m| m.line_ids.empty?} + if referential.metadatas.all?{|m| m.line_ids.present? && m.line_ids.empty?} parent.messages.create criticity: :error, message_key: "referential_creation_missing_lines", message_attributes: {referential_name: referential.name} else parent.messages.create criticity: :error, message_key: "referential_creation", message_attributes: {referential_name: referential.name} end + else + save! end - save! end private @@ -45,7 +46,7 @@ class Import::Netex < Import::Base def referential_metadata metadata = ReferentialMetadata.new - if self.file + if self.file && self.file.path netex_file = STIF::NetexFile.new(self.file.path) frame = netex_file.frames.first diff --git a/app/models/merge.rb b/app/models/merge.rb index 8d661f209..7df7aa590 100644 --- a/app/models/merge.rb +++ b/app/models/merge.rb @@ -135,6 +135,12 @@ class Merge < ApplicationModel referential_stop_points_by_route = referential_stop_points.group_by(&:route_id) + referential_routes_constraint_zones = referential.switch do + referential.routing_constraint_zones.each_with_object(Hash.new { |h,k| h[k] = [] }) do |routing_constraint_zone, hash| + hash[routing_constraint_zone.route_id] << routing_constraint_zone + end + end + new.switch do referential_routes.each do |route| existing_route = new.routes.find_by line_id: route.line_id, checksum: route.checksum @@ -164,6 +170,36 @@ class Merge < ApplicationModel new_route.stop_points.build attributes end + # We need to create StopPoints to known new primary keys + new_route.save! + + old_stop_point_ids = route_stop_points.sort_by(&:position).map(&:id) + new_stop_point_ids = new_route.stop_points.sort_by(&:position).map(&:id) + + stop_point_ids_mapping = Hash[[old_stop_point_ids, new_stop_point_ids].transpose] + + # RoutingConstraintZones + routes_constraint_zones = referential_routes_constraint_zones[route.id] + + routes_constraint_zones.each do |routing_constraint_zone| + objectid = new.routing_constraint_zones.where(objectid: routing_constraint_zone.objectid).exists? ? nil : routing_constraint_zone.objectid + stop_point_ids = routing_constraint_zone.stop_point_ids.map { |id| stop_point_ids_mapping[id] }.compact + + if stop_point_ids.size != routing_constraint_zone.stop_point_ids.size + raise "Can't find all required StopPoints for RoutingConstraintZone #{routing_constraint_zone.inspect}" + end + + attributes = routing_constraint_zone.attributes.merge( + id: nil, + route_id: nil, + objectid: objectid, + stop_point_ids: stop_point_ids, + ) + new_route.routing_constraint_zones.build attributes + + # No checksum check. RoutingConstraintZones are always recreated + end + new_route.save! if new_route.checksum != route.checksum @@ -224,7 +260,7 @@ class Merge < ApplicationModel new_journey_pattern = new.journey_patterns.create! attributes if new_journey_pattern.checksum != journey_pattern.checksum - raise "Checksum has changed for #{journey_pattern.inspect}: \"#{journey_pattern.checksum_source}\" -> \"#{new_journey_pattern.checksum_source}\"" + raise "Checksum has changed for #{journey_pattern.inspect} (to #{new_journey_pattern.inspect}): \"#{journey_pattern.checksum_source}\" -> \"#{new_journey_pattern.checksum_source}\"" end end end @@ -236,17 +272,36 @@ class Merge < ApplicationModel referential.vehicle_journeys.includes(:vehicle_journey_at_stops).all.to_a end + referential_purchase_windows_by_checksum, referential_vehicle_journey_purchase_window_checksums = referential.switch do + purchase_windows_by_checksum = referential.purchase_windows.each_with_object({}) do |purchase_window, hash| + hash[purchase_window.checksum] = purchase_window + end + + vehicle_journey_purchase_window_checksums = Hash.new { |h,k| h[k] = [] } + referential.purchase_windows.joins(:vehicle_journeys).pluck("vehicle_journeys.id", :checksum).each do |vehicle_journey_id, checksum| + vehicle_journey_purchase_window_checksums[vehicle_journey_id] << checksum + end + + [purchase_windows_by_checksum, vehicle_journey_purchase_window_checksums] + end + + new_vehicle_journey_ids = {} + new.switch do referential_vehicle_journeys.each do |vehicle_journey| # find parent journey pattern by checksum # TODO add line_id for security + associated_route_checksum = referential_routes_checksums[vehicle_journey.route_id] associated_journey_pattern_checksum = referential_journey_patterns_checksums[vehicle_journey.journey_pattern_id] - existing_associated_journey_pattern = new.journey_patterns.find_by checksum: associated_journey_pattern_checksum + + existing_associated_route = new.routes.find_by checksum: associated_route_checksum + existing_associated_journey_pattern = existing_associated_route.journey_patterns.find_by checksum: associated_journey_pattern_checksum existing_vehicle_journey = new.vehicle_journeys.find_by journey_pattern_id: existing_associated_journey_pattern.id, checksum: vehicle_journey.checksum if existing_vehicle_journey existing_vehicle_journey.merge_metadata_from vehicle_journey + new_vehicle_journey_ids[vehicle_journey.id] = existing_vehicle_journey.id else objectid = Chouette::VehicleJourney.where(objectid: vehicle_journey.objectid).exists? ? nil : vehicle_journey.objectid attributes = vehicle_journey.attributes.merge( @@ -269,11 +324,39 @@ class Merge < ApplicationModel new_vehicle_journey.vehicle_journey_at_stops.build at_stop_attributes end + # Associate (and create if needed) PurchaseWindows + + referential_vehicle_journey_purchase_window_checksums[vehicle_journey.id].each do |purchase_window_checksum| + associated_purchase_window = new.purchase_windows.find_by(checksum: purchase_window_checksum) + + unless associated_purchase_window + purchase_window = referential_purchase_windows_by_checksum[purchase_window_checksum] + + objectid = new.purchase_windows.where(objectid: purchase_window.objectid).exists? ? nil : purchase_window.objectid + attributes = purchase_window.attributes.merge( + id: nil, + objectid: objectid + ) + new_purchase_window = new.purchase_windows.build attributes + new_purchase_window.save! + + if new_purchase_window.checksum != purchase_window.checksum + raise "Checksum has changed: #{purchase_window.checksum_source} #{new_purchase_window.checksum_source}" + end + + associated_purchase_window = new_purchase_window + end + + new_vehicle_journey.purchase_windows << associated_purchase_window + end + new_vehicle_journey.save! if new_vehicle_journey.checksum != vehicle_journey.checksum raise "Checksum has changed: #{vehicle_journey.checksum_source} #{new_vehicle_journey.checksum_source}" end + + new_vehicle_journey_ids[vehicle_journey.id] = new_vehicle_journey.id end end @@ -285,14 +368,14 @@ class Merge < ApplicationModel time_tables_by_id = Hash[referential.time_tables.includes(:dates, :periods).all.to_a.map { |t| [t.id, t] }] time_tables_with_associated_lines = - referential.time_tables.joins(vehicle_journeys: {route: :line}).pluck("lines.id", :id, "vehicle_journeys.checksum") + referential.time_tables.joins(vehicle_journeys: {route: :line}).pluck("lines.id", :id, "vehicle_journeys.id") # Because TimeTables will be modified according metadata periods # we're loading timetables per line (line is associated to a period list) # # line_id: [ { time_table.id, vehicle_journey.checksum } ] time_tables_by_lines = time_tables_with_associated_lines.inject(Hash.new { |h,k| h[k] = [] }) do |hash, row| - hash[row.shift] << {id: row.first, vehicle_journey_checksum: row.second} + hash[row.shift] << {id: row.first, vehicle_journey_id: row.second} hash end @@ -362,7 +445,12 @@ class Merge < ApplicationModel # associate VehicleJourney - associated_vehicle_journey = line.vehicle_journeys.find_by!(checksum: properties[:vehicle_journey_checksum]) + new_vehicle_journey_id = new_vehicle_journey_ids[properties[:vehicle_journey_id]] + unless new_vehicle_journey_id + raise "TimeTable #{existing_time_table.inspect} associated to a not-merged VehicleJourney: #{properties[:vehicle_journey_id]}" + end + + associated_vehicle_journey = line.vehicle_journeys.find(new_vehicle_journey_id) associated_vehicle_journey.time_tables << existing_time_table end end |
