aboutsummaryrefslogtreecommitdiffstats
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/chouette/area_type.rb8
-rw-r--r--app/models/chouette/purchase_window.rb9
-rw-r--r--app/models/chouette/route.rb2
-rw-r--r--app/models/chouette/routing_constraint_zone.rb7
-rw-r--r--app/models/chouette/stop_point.rb2
-rw-r--r--app/models/chouette/vehicle_journey.rb3
-rw-r--r--app/models/compliance_check_message_export.rb2
-rw-r--r--app/models/import/message_export.rb2
-rw-r--r--app/models/import/netex.rb11
-rw-r--r--app/models/merge.rb98
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