From ef3942099583f86d3f355a1bac8d99ce16cd2de3 Mon Sep 17 00:00:00 2001
From: Zog
Date: Mon, 8 Jan 2018 11:06:20 +0100
Subject: Refs #5493 @1h; Use local time in the Journeys editor
We store UTC times in the database though
---
 app/controllers/vehicle_journeys_controller.rb     |  1 +
 app/javascript/helpers/stop_area_header_manager.js |  9 ++++++-
 .../vehicle_journeys/components/VehicleJourneys.js |  2 +-
 app/models/chouette/stop_area.rb                   |  6 +++++
 app/models/chouette/vehicle_journey.rb             |  6 ++++-
 app/models/chouette/vehicle_journey_at_stop.rb     | 30 ++++++++++++++++++++--
 app/views/vehicle_journeys/show.rabl               |  8 +++---
 spec/factories/chouette_vehicle_journey_at_stop.rb |  2 +-
 .../chouette/vehicle_journey_at_stop_spec.rb       | 24 +++++++++++++++++
 spec/models/chouette/vehicle_journey_spec.rb       | 30 +++++++++++++++++++---
 10 files changed, 104 insertions(+), 14 deletions(-)
diff --git a/app/controllers/vehicle_journeys_controller.rb b/app/controllers/vehicle_journeys_controller.rb
index e3e067782..c5466abe5 100644
--- a/app/controllers/vehicle_journeys_controller.rb
+++ b/app/controllers/vehicle_journeys_controller.rb
@@ -59,6 +59,7 @@ class VehicleJourneysController < ChouetteController
             :for_boarding => sp.try(:for_boarding),
             :for_alighting => sp.try(:for_alighting),
             :name => sp.stop_area.try(:name),
+            :time_zone_formatted_offset => sp.stop_area.try(:time_zone_formatted_offset),
             :zip_code => sp.stop_area.try(:zip_code),
             :city_name => sp.stop_area.try(:city_name),
             :comment => sp.stop_area.try(:comment),
diff --git a/app/javascript/helpers/stop_area_header_manager.js b/app/javascript/helpers/stop_area_header_manager.js
index 54d957be9..c9f397dee 100644
--- a/app/javascript/helpers/stop_area_header_manager.js
+++ b/app/javascript/helpers/stop_area_header_manager.js
@@ -21,7 +21,14 @@ export default class StopAreaHeaderManager {
         data-headline={showHeadline}
         title={sp.city_name + ' (' + sp.zip_code +')'}
       >
-        {sp.name}
+        
+          
+            {sp.name}
+            {sp.time_zone_formatted_offset && 
+               ({sp.time_zone_formatted_offset})
+            }
+          
+        
       
     )
   }
diff --git a/app/javascript/vehicle_journeys/components/VehicleJourneys.js b/app/javascript/vehicle_journeys/components/VehicleJourneys.js
index b188962c2..36721b55b 100644
--- a/app/javascript/vehicle_journeys/components/VehicleJourneys.js
+++ b/app/javascript/vehicle_journeys/components/VehicleJourneys.js
@@ -109,8 +109,8 @@ export default class VehicleJourneys extends Component {
                 
                   ID course
                   Nom course
-                  
ID mission
                   Transporteur
+                  
ID mission
                   Calendriers
                   { this.hasFeature('purchase_windows') && 
Calendriers Commerciaux
 }
                 
 
diff --git a/app/models/chouette/stop_area.rb b/app/models/chouette/stop_area.rb
index 52602be9f..b16bbb487 100644
--- a/app/models/chouette/stop_area.rb
+++ b/app/models/chouette/stop_area.rb
@@ -358,11 +358,17 @@ module Chouette
       update_attribute :deleted_at, Time.now
     end
 
+
     def country_name
       return unless country_code
 
       country = ISO3166::Country[country_code]
       country.translations[I18n.locale.to_s] || country.name
     end
+
+    def time_zone_formatted_offset
+      return nil unless time_zone.present?
+      ActiveSupport::TimeZone[time_zone].formatted_offset
+    end
   end
 end
diff --git a/app/models/chouette/vehicle_journey.rb b/app/models/chouette/vehicle_journey.rb
index 1904e1b92..67216e422 100644
--- a/app/models/chouette/vehicle_journey.rb
+++ b/app/models/chouette/vehicle_journey.rb
@@ -132,10 +132,14 @@ module Chouette
     def update_vjas_from_state state
       state.each do |vjas|
         next if vjas["dummy"]
+        stop_point = Chouette::StopPoint.find_by(objectid: vjas['stop_point_objectid'])
+        stop_area = stop_point&.stop_area
+        tz = stop_area&.time_zone
+        tz = tz && ActiveSupport::TimeZone[tz]
         params = {}.tap do |el|
           ['arrival_time', 'departure_time'].each do |field|
             time = "#{vjas[field]['hour']}:#{vjas[field]['minute']}"
-            el[field.to_sym] = Time.parse("2000-01-01 #{time}:00 UTC")
+            el[field.to_sym] = Time.parse("2000-01-01 #{time}:00 #{tz&.formatted_offset || "UTC"}")
           end
         end
         stop = create_or_find_vjas_from_state(vjas)
diff --git a/app/models/chouette/vehicle_journey_at_stop.rb b/app/models/chouette/vehicle_journey_at_stop.rb
index 6b3c1e7de..f1a3cdcaa 100644
--- a/app/models/chouette/vehicle_journey_at_stop.rb
+++ b/app/models/chouette/vehicle_journey_at_stop.rb
@@ -77,11 +77,37 @@ module Chouette
     end
 
     def departure
-      departure_time.utc.strftime "%H:%M" if departure_time
+      format_time departure_time.utc
     end
 
     def arrival
-      arrival_time.utc.strftime "%H:%M" if arrival_time
+      format_time arrival_time.utc
+    end
+
+    def departure_local_time
+      local_time departure_time
+    end
+
+    def arrival_local_time
+      local_time arrival_time
+    end
+
+    def departure_local
+      format_time departure_local_time
+    end
+
+    def arrival_local
+      format_time arrival_local_time
+    end
+
+    private
+    def local_time time
+      return time unless stop_point&.stop_area&.time_zone.present?
+      time + ActiveSupport::TimeZone[stop_point.stop_area.time_zone].utc_offset
+    end
+
+    def format_time time
+      time.strftime "%H:%M" if time
     end
 
   end
diff --git a/app/views/vehicle_journeys/show.rabl b/app/views/vehicle_journeys/show.rabl
index eeed79b34..df1eca016 100644
--- a/app/views/vehicle_journeys/show.rabl
+++ b/app/views/vehicle_journeys/show.rabl
@@ -59,11 +59,11 @@ child(:vehicle_journey_at_stops_matrix, :object_root => false) do |vehicle_stops
       vehicle_stop.stop_point.stop_area.city_name
     end
 
-    [:arrival_time, :departure_time].each do |att|
-      node(att) do |vs|
+    [:arrival, :departure].each do |att|
+      node("#{att}_time") do |vs|
         {
-          hour: vs.send(att).try(:strftime, '%H'),
-          minute: vs.send(att).try(:strftime, '%M')
+          hour: vs.send("#{att}_local_time").try(:strftime, '%H'),
+          minute: vs.send("#{att}_local_time").try(:strftime, '%M')
         }
       end
     end
diff --git a/spec/factories/chouette_vehicle_journey_at_stop.rb b/spec/factories/chouette_vehicle_journey_at_stop.rb
index 831e347d4..07a4ec557 100644
--- a/spec/factories/chouette_vehicle_journey_at_stop.rb
+++ b/spec/factories/chouette_vehicle_journey_at_stop.rb
@@ -1,9 +1,9 @@
 FactoryGirl.define do
   factory :vehicle_journey_at_stop, :class => Chouette::VehicleJourneyAtStop do
     association :vehicle_journey, :factory => :vehicle_journey
+    association :stop_point, :factory => :stop_point
     departure_day_offset { 0 }
     departure_time       { Time.now }
     arrival_time         { Time.now - 1.hour }
   end
 end
-
diff --git a/spec/models/chouette/vehicle_journey_at_stop_spec.rb b/spec/models/chouette/vehicle_journey_at_stop_spec.rb
index df8a630fe..4d4a1794e 100644
--- a/spec/models/chouette/vehicle_journey_at_stop_spec.rb
+++ b/spec/models/chouette/vehicle_journey_at_stop_spec.rb
@@ -40,6 +40,30 @@ RSpec.describe Chouette::VehicleJourneyAtStop, type: :model do
     end
   end
 
+  context "the different times" do
+    let (:at_stop) { build_stubbed(:vehicle_journey_at_stop) }
+
+    describe "without a TimeZone" do
+      it "should not offset times" do
+        expect(at_stop.departure).to eq at_stop.departure_local
+        expect(at_stop.arrival).to eq at_stop.arrival_local
+      end
+    end
+
+
+    describe "with a TimeZone" do
+      before(:each) do
+        stop = at_stop.stop_point.stop_area
+        stop.time_zone = "Mexico City"
+      end
+
+      it "should offset times" do
+        expect(at_stop.departure_local).to eq at_stop.send(:format_time, at_stop.departure_time - 6.hours)
+        expect(at_stop.arrival_local).to eq at_stop.send(:format_time, at_stop.arrival_time - 6.hours)
+      end
+    end
+  end
+
   describe "#validate" do
     it "displays the proper error message when day offset exceeds the max" do
       bad_offset = Chouette::VehicleJourneyAtStop::DAY_OFFSET_MAX + 1
diff --git a/spec/models/chouette/vehicle_journey_spec.rb b/spec/models/chouette/vehicle_journey_spec.rb
index 06cac6bc7..0beec2d81 100644
--- a/spec/models/chouette/vehicle_journey_spec.rb
+++ b/spec/models/chouette/vehicle_journey_spec.rb
@@ -64,10 +64,12 @@ describe Chouette::VehicleJourney, :type => :model do
         at_stop[att.to_s] = vjas.send(att) unless vjas.send(att).nil?
       end
 
-      [:arrival_time, :departure_time].map do |att|
-        at_stop[att.to_s] = {
-          'hour'   => vjas.send(att).strftime('%H'),
-          'minute' => vjas.send(att).strftime('%M'),
+      at_stop["stop_point_objectid"] = vjas&.stop_point&.objectid
+
+      [:arrival, :departure].map do |att|
+        at_stop["#{att}_time"] = {
+          'hour'   => vjas.send("#{att}_local_time").strftime('%H'),
+          'minute' => vjas.send("#{att}_local_time").strftime('%M'),
         }
       end
       at_stop
@@ -112,6 +114,26 @@ describe Chouette::VehicleJourney, :type => :model do
       expect(obj.published_journey_name).to eq 'dummy'
     end
 
+    it 'should expect local times' do
+      new_vj = build(:vehicle_journey, objectid: nil, published_journey_name: 'dummy', route: route, journey_pattern: journey_pattern)
+      stop_area = create(:stop_area, time_zone: "Mexico City")
+      stop_point = create(:stop_point, stop_area: stop_area)
+      new_vj.vehicle_journey_at_stops << build(:vehicle_journey_at_stop, vehicle_journey: vehicle_journey, stop_point: stop_point)
+      data = vehicle_journey_to_state(new_vj)
+      data['vehicle_journey_at_stops'][0]["departure_time"]["hour"] = "15"
+      data['vehicle_journey_at_stops'][0]["arrival_time"]["hour"] = "12"
+      collection << data
+      expect {
+        Chouette::VehicleJourney.state_update(route, collection)
+      }.to change {Chouette::VehicleJourney.count}.by(1)
+      created = Chouette::VehicleJourney.last.vehicle_journey_at_stops.last
+      expect(created.stop_point).to eq stop_point
+      expect(created.departure_local_time.hour).to_not eq created.departure_time.hour
+      expect(created.arrival_local_time.hour).to_not eq created.arrival_time.hour
+      expect(created.departure_local_time.hour).to eq 15
+      expect(created.arrival_local_time.hour).to eq 12
+    end
+
     it 'should save vehicle_journey_at_stops of newly created vj' do
       new_vj = build(:vehicle_journey, objectid: nil, published_journey_name: 'dummy', route: route, journey_pattern: journey_pattern)
       new_vj.vehicle_journey_at_stops << build(:vehicle_journey_at_stop,
-- 
cgit v1.2.3
From cb8b0a431944925885846966c45d7434e6618b8c Mon Sep 17 00:00:00 2001
From: Zog
Date: Thu, 11 Jan 2018 22:02:42 +0100
Subject: Refs #5493; Show Timezone on JPs editor
---
 app/controllers/journey_patterns_collections_controller.rb | 1 +
 app/models/chouette/stop_area.rb                           | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/app/controllers/journey_patterns_collections_controller.rb b/app/controllers/journey_patterns_collections_controller.rb
index b37ac6cd0..da567779e 100644
--- a/app/controllers/journey_patterns_collections_controller.rb
+++ b/app/controllers/journey_patterns_collections_controller.rb
@@ -44,6 +44,7 @@ class JourneyPatternsCollectionsController < ChouetteController
             :zip_code => sp.stop_area.try(:zip_code),
             :city_name => sp.stop_area.try(:city_name),
             :country_name => sp.stop_area.try(:country_name),
+            :time_zone_formatted_offset => sp.stop_area.try(:time_zone_formatted_offset),
             :comment => sp.stop_area.try(:comment),
             :area_type => sp.stop_area.try(:area_type),
             :registration_number => sp.stop_area.try(:registration_number),
diff --git a/app/models/chouette/stop_area.rb b/app/models/chouette/stop_area.rb
index b16bbb487..37d20ae02 100644
--- a/app/models/chouette/stop_area.rb
+++ b/app/models/chouette/stop_area.rb
@@ -368,7 +368,7 @@ module Chouette
 
     def time_zone_formatted_offset
       return nil unless time_zone.present?
-      ActiveSupport::TimeZone[time_zone].formatted_offset
+      ActiveSupport::TimeZone[time_zone]&.formatted_offset
     end
   end
 end
-- 
cgit v1.2.3