aboutsummaryrefslogtreecommitdiffstats
path: root/app/models/merge.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/merge.rb')
-rw-r--r--app/models/merge.rb125
1 files changed, 110 insertions, 15 deletions
diff --git a/app/models/merge.rb b/app/models/merge.rb
index 62bf581d6..7df7aa590 100644
--- a/app/models/merge.rb
+++ b/app/models/merge.rb
@@ -1,4 +1,4 @@
-class Merge < ActiveRecord::Base
+class Merge < ApplicationModel
extend Enumerize
belongs_to :workbench
@@ -50,7 +50,7 @@ class Merge < ActiveRecord::Base
new =
if workbench.output.current
Rails.logger.debug "Clone current output"
- Referential.new_from(workbench.output.current, fixme_functional_scope).tap do |clone|
+ Referential.new_from(workbench.output.current, workbench.organisation).tap do |clone|
clone.inline_clone = true
end
else
@@ -135,10 +135,18 @@ class Merge < ActiveRecord::Base
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
- unless existing_route
+ if existing_route
+ existing_route.merge_metadata_from route
+ else
objectid = Chouette::Route.where(objectid: route.objectid).exists? ? nil : route.objectid
attributes = route.attributes.merge(
id: nil,
@@ -152,21 +160,50 @@ class Merge < ActiveRecord::Base
route_stop_points = referential_stop_points_by_route[route.id]
# Stop Points
- route_stop_points.each do |stop_point|
+ route_stop_points.sort_by(&:position).each do |stop_point|
objectid = Chouette::StopPoint.where(objectid: stop_point.objectid).exists? ? nil : stop_point.objectid
attributes = stop_point.attributes.merge(
id: nil,
route_id: nil,
objectid: objectid,
)
-
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
- raise "Checksum has changed: #{route.inspect} #{new_route.inspect}"
+ raise "Checksum has changed: \"#{route.checksum}\", \"#{route.checksum_source}\" -> \"#{new_route.checksum}\", \"#{new_route.checksum_source}\""
end
end
end
@@ -197,7 +234,9 @@ class Merge < ActiveRecord::Base
existing_journey_pattern = new.journey_patterns.find_by route_id: existing_associated_route.id, checksum: journey_pattern.checksum
- unless existing_journey_pattern
+ if existing_journey_pattern
+ existing_journey_pattern.merge_metadata_from journey_pattern
+ else
objectid = Chouette::JourneyPattern.where(objectid: journey_pattern.objectid).exists? ? nil : journey_pattern.objectid
attributes = journey_pattern.attributes.merge(
id: nil,
@@ -221,7 +260,7 @@ class Merge < ActiveRecord::Base
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
@@ -233,16 +272,37 @@ class Merge < ActiveRecord::Base
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
- unless existing_vehicle_journey
+ 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(
id: nil,
@@ -264,11 +324,39 @@ class Merge < ActiveRecord::Base
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
@@ -280,14 +368,14 @@ class Merge < ActiveRecord::Base
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
@@ -339,7 +427,9 @@ class Merge < ActiveRecord::Base
existing_time_table = line.time_tables.find_by checksum: candidate_time_table.checksum
- unless existing_time_table
+ if existing_time_table
+ existing_time_table.merge_metadata_from candidate_time_table
+ else
objectid = Chouette::TimeTable.where(objectid: time_table.objectid).exists? ? nil : time_table.objectid
candidate_time_table.objectid = objectid
@@ -355,7 +445,12 @@ class Merge < ActiveRecord::Base
# 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
@@ -364,7 +459,7 @@ class Merge < ActiveRecord::Base
def save_current
output.update current: new, new: nil
- output.current.update referential_suite: output
+ output.current.update referential_suite: output, ready: true
referentials.update_all merged_at: created_at, archived_at: created_at
end