aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stif/reflex_synchronization.rb
blob: eab86caf16c0e9298a818c6216b457c203e4dbdb (plain)
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
module Stif
  module ReflexSynchronization
    class << self
      def defaut_referential
        StopAreaReferential.find_by(name: "Reflex")
      end

      # Todo remove dummy objectid
      def find_by_object_id objectid
        Chouette::StopArea.find_by(objectid: "dummy:StopArea:#{objectid.tr(':', '')}")
      end

      def synchronize
        tstart     = Time.now
        begin
          client     = Reflex::API.new
          processed  = []

          ['getOR', 'getOP'].each do |method|
            start   = Time.now
            results = client.process method
            Rails.logger.info "Reflex:sync - Process #{method} done in #{Time.now - start} seconds"
            results.each do |type, entries|
              Rails.logger.info "Reflex:sync - #{entries.count} #{type} retrieved"
            end

            # Create or update stop_area for every quay, stop_place
            stop_areas = results[:Quay].merge(results[:StopPlace])
            start = Time.now
            stop_areas.each do |id, entry|
              processed << self.create_or_update_stop_area(entry).objectid
            end
            Rails.logger.info "Reflex:sync - Create or update StopArea done in #{Time.now - start} seconds"

            # Walk through every entry and set parent stop_area
            start = Time.now
            stop_areas.each do |id, entry|
              self.stop_area_set_parent entry
            end
            Rails.logger.info "Reflex:sync - StopArea set parent done in #{Time.now - start} seconds"
          end

          # Purge deleted stop_area
          deleted = self.set_deleted_stop_area processed.uniq
          self.defaut_referential.stop_area_referential_sync.record_status :ok, I18n.t('synchronization.reflex.message.success', time: Time.now - tstart, imported: processed.uniq.size, deleted: deleted.size)
        rescue Exception => e
          Rails.logger.error "Reflex:sync - Error: #{e}, ended after #{Time.now - tstart} seconds"
          LineReferential.first.line_referential_sync.record_status :ko, I18n.t('synchronization.reflex.message.failure', time: Time.now - tstart)
        end
      end

      def set_deleted_stop_area processed
        start   = Time.now
        deleted = Chouette::StopArea.where(deleted_at: nil).pluck(:objectid).uniq - processed
        deleted.each_slice(50) do |object_ids|
          Chouette::StopArea.where(objectid: object_ids).update_all(deleted_at: Time.now)
        end
        Rails.logger.info "Reflex:sync - StopArea #{deleted.size} stop_area deleted since last sync in #{Time.now - start} seconds"
        deleted
      end

      def stop_area_set_parent entry
        return false unless entry.try(:parent_site_ref) || entry.try(:quays)
        stop = self.find_by_object_id entry.id
        return false unless stop

        if entry.try(:parent_site_ref)
          stop.parent = self.find_by_object_id entry.parent_site_ref
          stop.save if stop.changed
        end

        if entry.try(:quays)
          entry.quays.each do |quay|
            children = self.find_by_object_id(quay[:ref])
            next unless children
            children.parent = stop
            children.save if children.changed?
          end
        end
      end

      def create_or_update_access_point entry, stop_area
        access = Chouette::AccessPoint.find_or_create_by(objectid: "dummy:AccessPoint:#{entry.id.tr(':', '')}")
        entry.version = entry.version.to_i + 1  if access.persisted?
        access.stop_area = stop_area
        {
          :name           => :name,
          :access_type    => :area_type,
          :object_version => :version,
          :zip_code       => :postal_code,
          :city_name      => :city,
          :import_xml     => :xml
        }.each do |k, v| access[k] = entry.try(v) end
        access.save if access.changed?
      end

      def create_or_update_stop_area entry
        stop = Chouette::StopArea.find_or_create_by(objectid: "dummy:StopArea:#{entry.id.tr(':', '')}")
        # Hack, on save object_version will be incremented by 1
        entry.version = entry.version.to_i + 1  if stop.persisted?
        stop.deleted_at            = nil
        stop.stop_area_referential = self.defaut_referential
        {
          :name           => :name,
          :creation_time  => :created,
          :area_type      => :area_type,
          :object_version => :version,
          :zip_code       => :postal_code,
          :city_name      => :city,
          :import_xml     => :xml
        }.each do |k, v| stop[k] = entry.try(v) end
        stop.save if stop.changed?
        # Create AccessPoint from StopPlaceEntrance
        if entry.try(:entrances)
          entry.entrances.each do |entrance|
            self.create_or_update_access_point entrance, stop
          end
        end
        stop
      end
    end
  end
end