smartkiosk-client 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/Gemfile +5 -0
  2. data/Gemfile.lock +176 -0
  3. data/Rakefile +4 -0
  4. data/app/controllers/banners.rb +14 -0
  5. data/app/controllers/collections.rb +10 -0
  6. data/app/controllers/config.rb +23 -0
  7. data/app/controllers/payments.rb +30 -0
  8. data/app/controllers/receipts.rb +13 -0
  9. data/app/controllers/terminal.rb +104 -0
  10. data/app/models/admin.rb +3 -0
  11. data/app/models/banner.rb +5 -0
  12. data/app/models/collection.rb +53 -0
  13. data/app/models/customer.rb +3 -0
  14. data/app/models/group.rb +37 -0
  15. data/app/models/order.rb +25 -0
  16. data/app/models/payment.rb +80 -0
  17. data/app/models/phone_range.rb +3 -0
  18. data/app/models/promotion.rb +11 -0
  19. data/app/models/provider.rb +42 -0
  20. data/app/models/receipt.rb +21 -0
  21. data/app/models/receipt_template.rb +5 -0
  22. data/app/models/terminal.rb +152 -0
  23. data/app/uploaders/icon_uploader.rb +9 -0
  24. data/app/views/banners.haml +50 -0
  25. data/app/workers/orders/acknowledge_worker.rb +22 -0
  26. data/app/workers/orders/complete_worker.rb +20 -0
  27. data/app/workers/orders/disable_worker.rb +16 -0
  28. data/app/workers/orders/enable_worker.rb +16 -0
  29. data/app/workers/orders/reboot_worker.rb +18 -0
  30. data/app/workers/orders/reload_worker.rb +18 -0
  31. data/app/workers/orders/upgrade_worker.rb +108 -0
  32. data/app/workers/payments/check_worker.rb +35 -0
  33. data/app/workers/payments/collect_worker.rb +23 -0
  34. data/app/workers/payments/pay_worker.rb +21 -0
  35. data/app/workers/ping_worker.rb +180 -0
  36. data/app/workers/startup_worker.rb +11 -0
  37. data/app/workers/sync/icons_worker.rb +20 -0
  38. data/app/workers/sync/receipt_templates_worker.rb +27 -0
  39. data/config/boot.rb +104 -0
  40. data/config/services/application.yml +4 -0
  41. data/config/services/database.yml +17 -0
  42. data/config/services/database.yml.sample +33 -0
  43. data/config/services/smartware.yml +28 -0
  44. data/config/services/smartware.yml.sample +13 -0
  45. data/config/sidekiq.yml +12 -0
  46. data/db/development.sqlite3 +0 -0
  47. data/db/migrate/20121230080152_create_customers.rb +8 -0
  48. data/db/migrate/20121230080159_create_admins.rb +11 -0
  49. data/db/migrate/20130106150707_create_orders.rb +14 -0
  50. data/db/migrate/20130106155321_create_providers.rb +19 -0
  51. data/db/migrate/20130106160834_create_groups.rb +11 -0
  52. data/db/migrate/20130106181512_create_receipt_templates.rb +9 -0
  53. data/db/migrate/20130106181548_create_payments.rb +26 -0
  54. data/db/migrate/20130106181729_create_collections.rb +10 -0
  55. data/db/migrate/20130106181803_create_receipts.rb +15 -0
  56. data/db/migrate/20130106181844_create_phone_ranges.rb +14 -0
  57. data/db/migrate/20130108110546_create_promotions.rb +9 -0
  58. data/db/migrate/20130110025256_create_banners.rb +12 -0
  59. data/init.rb +1 -0
  60. data/lib/pinger.rb +22 -0
  61. data/lib/sidekiq.rb +20 -0
  62. data/lib/smartkiosk/client/version.rb +7 -0
  63. data/lib/smartkiosk/client.rb +1 -0
  64. data/lib/smartkiosk/config/chunk.rb +7 -0
  65. data/lib/smartkiosk/config/yaml.rb +26 -0
  66. data/lib/tasks/db.rb +15 -0
  67. data/lib/tasks/pack.rb +27 -0
  68. data/lib/tasks/scheduler.rb +27 -0
  69. data/lib/tasks/services.rb +20 -0
  70. data/server.rb +11 -0
  71. data/smartkiosk-client.gemspec +55 -0
  72. data/tmp/pids/.gitkeep +0 -0
  73. data/tmp/pids/sidekiq.pid +1 -0
  74. data/vendor/assets/javascripts/jquery.js +9555 -0
  75. metadata +444 -0
@@ -0,0 +1,152 @@
1
+ require 'smartware'
2
+ require 'socket'
3
+ require 'redis'
4
+ require 'redis/objects'
5
+
6
+ Application.load 'lib/smartkiosk/config/yaml'
7
+
8
+ class Terminal
9
+ include Redis::Objects
10
+
11
+ value :state, :global => true
12
+ value :started_at, :global => true, :marshal => true
13
+ value :modified_at, :global => true, :marshal => true
14
+ value :payment_in_progress, :global => true
15
+
16
+ value :support_phone, :global => true
17
+ value :providers_updates, :global => true, :marshal => true
18
+
19
+ def self.smartguard
20
+ DRbObject.new_with_uri(Terminal.config.smartguard_host)
21
+ end
22
+
23
+ #
24
+ # STATES
25
+ #
26
+ def self.enable
27
+ self.state = 'active'
28
+ end
29
+
30
+ def self.disable
31
+ self.state = 'disabled'
32
+ end
33
+
34
+ def self.payment_in_progress?
35
+ self.payment_in_progress.value == "true"
36
+ end
37
+
38
+ def self.actual_state
39
+ self.state.value || 'active'
40
+ end
41
+
42
+ def self.actual_modified_at
43
+ self.modified_at.value || DateTime.now
44
+ end
45
+
46
+ def self.providers_updated_at
47
+ self.providers_updates[self.config.host] rescue nil
48
+ end
49
+
50
+ def self.providers_updated_at=(value)
51
+ self.providers_updates = {self.config.host => value}
52
+ end
53
+
54
+ #
55
+ # ACTIONS
56
+ #
57
+ def self.ping
58
+ PingWorker.perform_async
59
+ end
60
+
61
+ def self.reload
62
+ smartguard.restart_async
63
+ end
64
+
65
+ def self.reboot
66
+ self.state = 'rebooting'
67
+ StartupWorker.perform_async self.name, :enable
68
+
69
+ smartguard.reboot_async
70
+ end
71
+
72
+ #
73
+ # CONDITON
74
+ #
75
+ def self.config
76
+ @config ||= Smartkiosk::Config::YAML.new(Application.root.join 'config/services/application.yml')
77
+ end
78
+
79
+ def self.keyword
80
+ config.keyword
81
+ end
82
+
83
+ def self.enabled?
84
+ self.actual_state == 'active'
85
+ end
86
+
87
+ def self.version
88
+ '0.1'
89
+ end
90
+
91
+ def self.ip
92
+ orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
93
+
94
+ UDPSocket.open do |s|
95
+ s.connect '64.233.187.99', 1
96
+ s.addr.last
97
+ end
98
+ rescue
99
+ '0.0.0.0'
100
+ ensure
101
+ Socket.do_not_reverse_lookup = orig
102
+ end
103
+
104
+ def self.as_json
105
+ {
106
+ :started_at => Terminal.started_at.value,
107
+ :modified_at => Terminal.actual_modified_at,
108
+ :keyword => Terminal.keyword,
109
+ :support_phone => Terminal.support_phone.value,
110
+ :groups => Group.all.map{|x| x.as_json},
111
+ :providers => Provider.active.map{|x| x.as_json},
112
+ :promotions => Promotion.order(:priority).limit(6).map{|x| x.provider_id}
113
+ }
114
+ end
115
+
116
+ def self.condition
117
+ {
118
+ :ip => ip,
119
+ :state => Terminal.actual_state,
120
+ :banknotes => Payment.merge_banknotes(Payment.uncollected),
121
+ :cash => Payment.merge_cash(Payment.uncollected),
122
+ :providers => {
123
+ :updated_at => Terminal.providers_updated_at,
124
+ :ids => Provider.select(:foreign_id).map{|x| x.foreign_id} || []
125
+ },
126
+ :queues => {
127
+ :payments => Sidekiq::Queue.new('payments').size,
128
+ :pings => Sidekiq::Queue.new('pings').size,
129
+ :orders => Sidekiq::Queue.new('orders').size,
130
+ :sync => Sidekiq::Queue.new('sync').size
131
+ },
132
+ :cash_acceptor => {
133
+ :error => Smartware.cash_acceptor.error,
134
+ :model => Smartware.cash_acceptor.model,
135
+ :version => Smartware.cash_acceptor.version
136
+ },
137
+ :printer => {
138
+ :error => Smartware.printer.error,
139
+ :model => Smartware.printer.model,
140
+ :version => Smartware.printer.version
141
+ },
142
+ :modem => {
143
+ :error => Smartware.modem.error,
144
+ :signal_level => Smartware.modem.signal_level,
145
+ :balance => Smartware.modem.balance,
146
+ :model => Smartware.modem.model,
147
+ :version => Smartware.modem.version
148
+ },
149
+ :version => Terminal.version
150
+ }
151
+ end
152
+ end
@@ -0,0 +1,9 @@
1
+ require 'carrierwave'
2
+
3
+ class IconUploader < CarrierWave::Uploader::Base
4
+ storage :file
5
+
6
+ def store_dir
7
+ "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
8
+ end
9
+ end
@@ -0,0 +1,50 @@
1
+ !!!
2
+ %html{:lang => "ru"}
3
+ %head
4
+ %meta{:charset => "utf-8"}
5
+ %meta{:content => "width=device-width, initial-scale=1.0", :name => "viewport"}
6
+ %title banners
7
+ %script{:type => 'text/javascript', :src => '/assets/jquery.js'}
8
+
9
+ :javascript
10
+ var playBanner;
11
+
12
+ playBanner = function(prev) {
13
+ if (prev == null) {
14
+ prev = 0;
15
+ }
16
+ return $.get("/banners/playlist?prev=" + prev, function(banner) {
17
+ var playNext,
18
+ _this = this;
19
+ if (banner.filename.substr(banner.filename.length-4) === '.swf') {
20
+ $('video').hide();
21
+ $('video').attr('src', '');
22
+ $('object').show();
23
+ $('object').attr('data', banner.filename);
24
+ $('object > embed').attr('src', banner.filename);
25
+ return playNext = setTimeout(function() {
26
+ return playBanner(banner.playorder);
27
+ }, parseInt(parseFloat(banner.duration) * 1000));
28
+ } else {
29
+ $('object').hide();
30
+ $('object').attr('data', '');
31
+ $('object > embed').attr('src', '');
32
+ $('video').show();
33
+ $('video').attr('src', banner.filename);
34
+ $('video')[0].play();
35
+ return playNext = setTimeout(function() {
36
+ $('video')[0].pause();
37
+ return playBanner(banner.playorder);
38
+ }, parseInt(parseFloat(banner.duration) * 1000));
39
+ }
40
+ });
41
+ };
42
+
43
+ playBanner();
44
+
45
+
46
+ %body{:style => 'margin: 0; padding: 0;'}
47
+ %video{:width => "1280", :height => "1024", :type => 'video/webm', :style => "max-height: 1019px; max-width: 1280px;" }
48
+ %object{:height => '1019', :width => '1280', :type => "application/x-shockwave-flash" }
49
+ %param{:name => "autoplay", :value => "true"}
50
+ %embed{:height => '1019', :width => '1280' }
@@ -0,0 +1,22 @@
1
+ require 'rest-client'
2
+
3
+ Application.load 'lib/sidekiq'
4
+
5
+ module Orders
6
+ class AcknowledgeWorker
7
+ include Sidekiq::Worker
8
+
9
+ sidekiq_options :queue => :orders
10
+
11
+ def perform(order_id, error=nil, percent=nil)
12
+ order = Order.find(order_id)
13
+
14
+ response = RestClient.post "#{Terminal.config.host}/terminal_orders/#{order.foreign_id}/acknowledge",
15
+ :terminal => Terminal.keyword,
16
+ :error => error,
17
+ :percent => percent
18
+
19
+ order.acknowledged!
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ require 'rest-client'
2
+
3
+ Application.load 'lib/sidekiq'
4
+
5
+ module Orders
6
+ class CompleteWorker
7
+ include Sidekiq::Worker
8
+
9
+ sidekiq_options :queue => :orders
10
+
11
+ def perform(order_id)
12
+ order = Order.find(order_id)
13
+
14
+ response = RestClient.post "#{Terminal.config.host}/terminal_orders/#{order.foreign_id}/complete",
15
+ :terminal => Terminal.keyword
16
+
17
+ Terminal.ping
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ Application.load 'lib/sidekiq'
2
+
3
+ module Orders
4
+ class DisableWorker
5
+ include Sidekiq::Worker
6
+
7
+ sidekiq_options :queue => :orders
8
+
9
+ def perform(order_id)
10
+ order = Order.find(order_id)
11
+
12
+ Terminal.disable
13
+ order.complete
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ Application.load 'lib/sidekiq'
2
+
3
+ module Orders
4
+ class EnableWorker
5
+ include Sidekiq::Worker
6
+
7
+ sidekiq_options :queue => :orders
8
+
9
+ def perform(order_id)
10
+ order = Order.find(order_id)
11
+
12
+ Terminal.enable
13
+ order.complete
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ Application.load 'lib/sidekiq'
2
+
3
+ module Orders
4
+ class RebootWorker
5
+ include Sidekiq::Worker
6
+
7
+ sidekiq_options :queue => :orders
8
+
9
+ def perform(order_id)
10
+ StartupWorker.perform_async self.class.name, :finish, [order_id]
11
+ Terminal.reboot
12
+ end
13
+
14
+ def self.finish(order_id)
15
+ Order.find(order_id).complete
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ Application.load 'lib/sidekiq'
2
+
3
+ module Orders
4
+ class ReloadWorker
5
+ include Sidekiq::Worker
6
+
7
+ sidekiq_options :queue => :orders
8
+
9
+ def perform(order_id)
10
+ StartupWorker.perform_async self.class.name, :finish, [order_id]
11
+ Terminal.reload
12
+ end
13
+
14
+ def self.finish(order_id)
15
+ Order.find(order_id).complete
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,108 @@
1
+ require 'pathname'
2
+ require 'rubygems'
3
+ require 'fileutils'
4
+
5
+ Application.load 'lib/sidekiq'
6
+
7
+ module Orders
8
+ class UpgradeWorker
9
+ include Sidekiq::Worker
10
+
11
+ sidekiq_options :queue => :orders
12
+
13
+ def perform(order_id)
14
+ order = Order.find(order_id)
15
+
16
+ @order_id = order_id
17
+ @build_version = Gem::Version.new order.args[1]
18
+ @build_id = order.args[0]
19
+ @base_url = URI.parse(order.args[3]).scheme.nil? ? "#{Terminal.config.host}#{order.args[3]}"
20
+ : order.args[3]
21
+
22
+ @releases_pathname = Terminal.smartguard.releases_path
23
+ @build_pathname = @releases_pathname.join @build_version.to_s
24
+
25
+ self.sync!
26
+ Terminal.smartguard.switch_release @build_version.to_s.to_sym do
27
+ order.complete
28
+ end
29
+ end
30
+
31
+ def files!
32
+ FileUtils.mkdir_p @releases_pathname
33
+
34
+ nearest_less_release = Dir.glob(@releases_pathname.join('*.*')).select do |v|
35
+ Gem::Version.new(File.basename(v)) < @build_version
36
+ end.max
37
+
38
+ if !File.directory?(@build_pathname)
39
+ if nearest_less_release.blank?
40
+ FileUtils.mkdir_p @build_pathname
41
+ else
42
+ FileUtils.cp_r nearest_less_release, @build_pathname
43
+ end
44
+ end
45
+
46
+ remotes = JSON.parse(RestClient.get "#{Terminal.config.host}/terminal_builds/#{@build_id}/hashes")
47
+ locals = Dir[File.join(@build_pathname, '**/**')].select{|x| File.file?(x)}.map{|x|
48
+ Pathname.new(x).relative_path_from(@build_pathname).to_s
49
+ }
50
+
51
+ download = {}
52
+ remove = []
53
+
54
+ remotes.each do |remote, data|
55
+ local = @build_pathname.join(remote)
56
+
57
+ if !File.file?(local) || Digest::MD5.file(local).hexdigest != data[0]
58
+ download[remote] = data[1]
59
+ end
60
+ end
61
+
62
+ locals.each do |local, hash|
63
+ remove << local if remotes[local].blank?
64
+ end
65
+
66
+ {:download => download, :remove => remove}
67
+ end
68
+
69
+ def sync!
70
+ diff = files!
71
+
72
+ total_transfer_size = diff[:download].values.inject(0){|sum,x|(sum+=x) unless x.nil?; sum }.to_f
73
+
74
+ diff[:download].each do |key, value|
75
+ uri = URI.parse(URI.encode("#{@base_url}/#{key}"))
76
+ path = @build_pathname.join key
77
+ FileUtils.mkdir_p File.dirname(path)
78
+
79
+ File.open(path, "wb") do |f|
80
+ Net::HTTP.start(uri.host, uri.port) do |http|
81
+ http.request_get(uri.path) do |resp|
82
+ resp.read_body do |segment|
83
+ f.write(segment)
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ diff[:download][key] = 0
90
+
91
+ delta_transfer_size = diff[:download].values.inject(0){|sum,x| (sum+=x) unless x.nil?; sum}.to_f
92
+
93
+ current_percentage = (100.0 - (delta_transfer_size / total_transfer_size * 100.0)).round(2)
94
+ if current_percentage > (@percentage ||= 0) + 5 || current_percentage == 100
95
+ @percentage = current_percentage
96
+ AcknowledgeWorker.perform_async(@order_id, nil, @percentage)
97
+ end
98
+
99
+ end
100
+
101
+ diff[:remove].each do |file|
102
+ fullpath = @build_pathname.join file
103
+ File.delete(fullpath) if File.exist?(fullpath)
104
+ end
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,35 @@
1
+ require 'rest-client'
2
+
3
+ Application.load 'lib/sidekiq'
4
+
5
+ module Payments
6
+ class CheckWorker
7
+ include Sidekiq::Worker
8
+
9
+ sidekiq_options :queue => :payments
10
+
11
+ def perform(payment_id)
12
+ payment = Payment.find(payment_id)
13
+ response = RestClient.post "#{Terminal.config.host}/payments",
14
+ :provider => payment.provider.keyword,
15
+ :terminal => Terminal.config.keyword,
16
+ :payment => {
17
+ :account => payment.account,
18
+ :fields => payment.fields,
19
+ :session_id => payment.id
20
+ }
21
+
22
+ answer = JSON.parse(response.to_s, :symbolize_names => true)
23
+
24
+ unless answer[:id].nil?
25
+ payment.update_attributes :foreign_id => answer[:id],
26
+ :limit => answer[:limits].sort_by(&:weight).last,
27
+ :commissions => (answer[:commissions].empty? ? nil : answer[:commissions]),
28
+ :receipt_template => answer[:receipt_template],
29
+ :checked => true
30
+ end
31
+ rescue => e
32
+ Payment.find(payment_id).update_attributes :error => true
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ Application.load 'lib/sidekiq'
2
+
3
+ module Payments
4
+ class CollectWorker
5
+ include Sidekiq::Worker
6
+
7
+ sidekiq_options :queue => :payments
8
+
9
+ def perform(collection_id)
10
+ collection = Collection.find(collection_id)
11
+
12
+ response = RestClient.post "#{Terminal.config.host}/collections",
13
+ :terminal => Terminal.config.keyword,
14
+ :collection => {
15
+ :banknotes => collection.banknotes,
16
+ :collected_at => collection.created_at,
17
+ :session_ids => collection.payment_ids
18
+ }
19
+
20
+ collection.update_attribute(:reported_at, DateTime.now)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ require 'rest-client'
2
+
3
+ Application.load 'lib/sidekiq'
4
+
5
+ module Payments
6
+ class PayWorker
7
+ include Sidekiq::Worker
8
+
9
+ sidekiq_options :queue => :payments
10
+
11
+ def perform(payment_id)
12
+ payment = Payment.find(payment_id)
13
+ response = RestClient.post "#{Terminal.config.host}/payments/#{payment.foreign_id}/pay",
14
+ :provider => payment.provider.keyword,
15
+ :terminal => Terminal.config.keyword,
16
+ :payment => { :paid_amount => payment.paid_amount }
17
+ Sidekiq::Logging.logger.debug "Pay response: #{response.to_s}"
18
+ payment.update_attributes(:processed => true) if response
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,180 @@
1
+ require 'rest-client'
2
+
3
+ Application.load 'lib/sidekiq'
4
+
5
+ class PingWorker
6
+ include Sidekiq::Worker
7
+
8
+ sidekiq_options :retry => false, :queue => :pings
9
+
10
+ SEMAPHORE = ConnectionPool.new(:size => 1, :timeout => 5) { true }
11
+
12
+ def perform
13
+ begin
14
+ SEMAPHORE.with do |glory|
15
+ condition = Terminal.condition
16
+
17
+ Sidekiq::Logging.logger.info "Requesting with updated_at: #{Terminal.providers_updated_at}"
18
+
19
+ begin
20
+ response = RestClient::Request.execute(
21
+ :method => :post,
22
+ :url => "#{Terminal.config.host}/terminal_pings",
23
+ :timeout => 40,
24
+ :open_timeout => 60,
25
+ :payload => {
26
+ :terminal => Terminal.keyword,
27
+ :terminal_ping => condition
28
+ }
29
+ )
30
+ rescue Exception => e
31
+ Sidekiq::Logging.logger.warn e.to_s
32
+ return
33
+ end
34
+
35
+ begin
36
+ response = JSON.parse(response.to_s, :symbolize_names => true)
37
+ rescue Exception => e
38
+ Sidekiq::Logging.logger.warn "Unable to parse JSON: #{e.to_s}"
39
+ return
40
+ end
41
+
42
+ unless Terminal.support_phone.value == response[:support_phone]
43
+ Terminal.support_phone = response[:support_phone]
44
+ Terminal.modified_at = DateTime.now
45
+ end
46
+
47
+ Sidekiq::Logging.logger.info "Response: #{response.inspect}"
48
+
49
+ #
50
+ # ORDERS
51
+ #
52
+ response[:orders].each do |order|
53
+ next unless Order.find_by_foreign_id(order[:id]).blank?
54
+
55
+ order[:foreign_id] = order.delete(:id)
56
+ order = Order.create!(order)
57
+
58
+ order.acknowledge
59
+ order.perform
60
+ end
61
+
62
+ #
63
+ # PROVIDERS
64
+ #
65
+ unless response[:providers].blank?
66
+ syncs = []
67
+
68
+ Provider.transaction do
69
+ #
70
+ # GROUPS
71
+ #
72
+ unless response[:providers][:groups].nil?
73
+ remote = response[:providers][:groups]
74
+ remote_ids = response[:providers][:groups].map{|x| x[:id]}
75
+ local = Group.all
76
+
77
+ local.select{|x| !remote_ids.include?(x.id)}.each do |x|
78
+ Sidekiq::Logging.logger.info "Group removal: ##{x.id}, #{x.title}"
79
+ x.destroy
80
+ end
81
+
82
+ remote.each do |r|
83
+ entry = local.find{|x| x.id == r[:id]}
84
+ entry ||= Group.new :foreign_id => r[:id]
85
+
86
+ entry.title = r[:title]
87
+ entry.priority = r[:priority]
88
+ entry.group_id = r[:parent_id]
89
+
90
+ Sidekiq::Logging.logger.info "Group replace: #{entry.title}"
91
+
92
+ entry.save!
93
+
94
+ unless r[:icon].blank?
95
+ syncs << ['Group', entry.id, r[:icon]]
96
+ end
97
+ end
98
+ end
99
+
100
+ #
101
+ # PROVIDERS REMOVAL
102
+ #
103
+ unless response[:providers][:remove].blank?
104
+ Sidekiq::Logging.logger.info "Providers removal: #{response[:providers][:remove]}"
105
+ Provider.where(:foreign_id => response[:providers][:remove]).destroy_all
106
+ end
107
+
108
+ #
109
+ # PROVIDERS UPDATES
110
+ #
111
+ unless response[:providers][:updated_at].blank?
112
+ response[:providers][:update].each do |provider|
113
+ local = Provider.find_or_initialize_by_foreign_id(provider[:id])
114
+
115
+ attributes = {
116
+ :title => provider[:title],
117
+ :keyword => provider[:keyword],
118
+ :priority => provider[:priority],
119
+ :fields => provider[:fields],
120
+ :group_id => provider[:group_id],
121
+ :requires_print => provider[:requires_print]
122
+ }
123
+
124
+ if provider[:icon].blank?
125
+ attributes[:icon] = nil
126
+ end
127
+
128
+ local.assign_attributes attributes
129
+
130
+ Sidekiq::Logging.logger.info "Provider replace: #{local.keyword}"
131
+
132
+ local.save!
133
+
134
+ unless provider[:icon].blank?
135
+ syncs << ['Provider', local.id, provider[:icon]]
136
+ end
137
+ end
138
+ end
139
+
140
+ #
141
+ # PROMOTIONS
142
+ #
143
+ unless response[:providers][:promotions].nil?
144
+ providers = Provider.to_hash(:foreign_id, response[:providers][:promotions], :invert => true)
145
+ remote = response[:providers][:promotions].map{|x| providers[x]}.compact
146
+ local = Promotion.all
147
+
148
+ local.select{|x| !remote.include?(x.provider_id)}.each do |x|
149
+ Sidekiq::Logging.logger.info "Promotion removal: #{x.provider_id}"
150
+ x.destroy
151
+ end
152
+
153
+ remote.each_with_index do |r, i|
154
+ entry = local.find{|x| x.provider_id == r}
155
+ entry ||= Promotion.new :provider_id => r
156
+
157
+ Sidekiq::Logging.logger.info "Promotion replace: #{r}"
158
+
159
+ entry.priority = i
160
+ entry.save!
161
+ end
162
+ end
163
+ end
164
+
165
+ unless response[:providers][:updated_at].blank?
166
+ Terminal.providers_updated_at = response[:providers][:updated_at]
167
+ end
168
+
169
+ Sidekiq::Logging.logger.info "Icons to sync: #{syncs}"
170
+
171
+ syncs.each do |args|
172
+ Sync::IconsWorker.perform_async *args
173
+ end
174
+ end
175
+ end
176
+ rescue Timeout::Error => e
177
+ Sidekiq::Logging.logger.warn "Semaphore timeout. #{e.to_s}"
178
+ end
179
+ end
180
+ end