1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
module Chouette
class JourneyPattern < Chouette::TridentActiveRecord
has_paper_trail
include ChecksumSupport
include JourneyPatternRestrictions
include ObjectidSupport
# FIXME http://jira.codehaus.org/browse/JRUBY-6358
self.primary_key = "id"
belongs_to :route
has_many :vehicle_journeys, :dependent => :destroy
has_many :vehicle_journey_at_stops, :through => :vehicle_journeys
has_and_belongs_to_many :stop_points, -> { order("stop_points.position") }, :before_add => :vjas_add, :before_remove => :vjas_remove, :after_add => :shortcuts_update_for_add, :after_remove => :shortcuts_update_for_remove
has_many :stop_areas, through: :stop_points
validates_presence_of :route
validates_presence_of :name
#validates :stop_points, length: { minimum: 2, too_short: :minimum }, on: :update
enum section_status: { todo: 0, completed: 1, control: 2 }
attr_accessor :control_checked
def local_id
"IBOO-#{self.referential.id}-#{self.route.line.get_objectid.local_id}-#{self.id}"
end
def checksum_attributes
values = self.slice(*['name', 'published_name', 'registration_number']).values
values << self.stop_points.sort_by(&:position).map(&:stop_area).map(&:user_objectid)
values.flatten
end
def self.state_update route, state
transaction do
state.each do |item|
item.delete('errors')
jp = find_by(objectid: item['object_id']) || state_create_instance(route, item)
next if item['deletable'] && jp.persisted? && jp.destroy
# Update attributes and stop_points associations
jp.update_attributes(state_permited_attributes(item)) unless item['new_record']
jp.state_stop_points_update(item) if !jp.errors.any? && jp.persisted?
item['errors'] = jp.errors if jp.errors.any?
item['checksum'] = jp.checksum
end
if state.any? {|item| item['errors']}
state.map {|item| item.delete('object_id') if item['new_record']}
raise ::ActiveRecord::Rollback
end
end
state.map {|item| item.delete('new_record')}
state.delete_if {|item| item['deletable']}
end
def self.state_permited_attributes item
{
name: item['name'],
published_name: item['published_name'],
registration_number: item['registration_number'],
costs: item['costs']
}
end
def self.state_create_instance route, item
# Flag new record, so we can unset object_id if transaction rollback
jp = route.journey_patterns.create(state_permited_attributes(item))
# FIXME
# DefaultAttributesSupport will trigger some weird validation on after save
# wich will call to valid?, wich will populate errors
# In this case, we mark jp to be valid if persisted? return true
jp.errors.clear if jp.persisted?
item['object_id'] = jp.objectid
item['new_record'] = true
jp
end
def state_stop_points_update item
item['stop_points'].each do |sp|
exist = stop_area_ids.include?(sp['id'])
next if exist && sp['checked']
stop_point = route.stop_points.find_by(stop_area_id: sp['id'])
if !exist && sp['checked']
stop_points << stop_point
end
if exist && !sp['checked']
stop_points.delete(stop_point)
end
end
end
# TODO: this a workarround
# otherwise, we loose the first stop_point
# when creating a new journey_pattern
def special_update
bck_sp = self.stop_points.map {|s| s}
self.update_attributes :stop_points => []
self.update_attributes :stop_points => bck_sp
end
def departure_stop_point
return unless departure_stop_point_id
Chouette::StopPoint.find( departure_stop_point_id)
end
def arrival_stop_point
return unless arrival_stop_point_id
Chouette::StopPoint.find( arrival_stop_point_id)
end
def shortcuts_update_for_add( stop_point)
stop_points << stop_point unless stop_points.include?( stop_point)
ordered_stop_points = stop_points
ordered_stop_points = ordered_stop_points.sort { |a,b| a.position <=> b.position} unless ordered_stop_points.empty?
self.update_attributes( :departure_stop_point_id => (ordered_stop_points.first && ordered_stop_points.first.id),
:arrival_stop_point_id => (ordered_stop_points.last && ordered_stop_points.last.id))
end
def shortcuts_update_for_remove( stop_point)
stop_points.delete( stop_point) if stop_points.include?( stop_point)
ordered_stop_points = stop_points
ordered_stop_points = ordered_stop_points.sort { |a,b| a.position <=> b.position} unless ordered_stop_points.empty?
self.update_attributes( :departure_stop_point_id => (ordered_stop_points.first && ordered_stop_points.first.id),
:arrival_stop_point_id => (ordered_stop_points.last && ordered_stop_points.last.id))
end
def vjas_add( stop_point)
return if new_record?
vehicle_journeys.each do |vj|
vjas = vj.vehicle_journey_at_stops.create :stop_point_id => stop_point.id
end
end
def vjas_remove( stop_point)
return if new_record?
vehicle_journey_at_stops.where( :stop_point_id => stop_point.id).each do |vjas|
vjas.destroy
end
end
def costs
read_attribute(:costs) || {}
end
end
end
|