diff --git a/Gemfile b/Gemfile index e6a5578..bc27e11 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,4 @@ -source 'https://rubygems.org' +source 'http://rubygems.org' gem 'rails', '4.1.8' gem 'mysql2' diff --git a/Gemfile.lock b/Gemfile.lock index 5117513..954599c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,5 +1,5 @@ GEM - remote: https://rubygems.org/ + remote: http://rubygems.org/ specs: actionmailer (4.1.8) actionpack (= 4.1.8) diff --git a/app/services/evacancy/ev_connect_service.rb b/app/services/evacancy/ev_connect_service.rb index cc92b49..d764e2b 100644 --- a/app/services/evacancy/ev_connect_service.rb +++ b/app/services/evacancy/ev_connect_service.rb @@ -1,5 +1,10 @@ module Evacancy class EvConnectService + EV_CHARGERS_OF_50_CHANNEL_ID = 'CBJNVA87R'.freeze + # Currently we only have one building so the channel ID can be hard coded + # eventually when we have more buildings we may need a Locations model containing + # attributes like channel_id, webhook_url, and has_many StationPorts + AVAILABLE = 'AVAILABLE'.freeze class << self @@ -17,9 +22,23 @@ def check_ports end if previously_open === 0 and currently_open > 0 - SlackWebhookService.send_message('A spot is available!') + next_in_queue_id = ChannelQueues::NextInQueue.new(channel_id: EV_CHARGERS_OF_50_CHANNEL_ID).user_id + next_in_queue = next_in_queue_id ? "<@#{next_in_queue_id}>" : "No one" + + message = <<~MESSAGE + A spot is available! + #{next_in_queue} is next in line! + Please dequeue with `/queue charging` after you plug in! + MESSAGE + + SlackWebhookService.send_message(message) elsif previously_open > 0 and currently_open === 0 - SlackWebhookService.send_message('All spots have been taken!') + message = <<~MESSAGE + All spots have been taken! + Please dequeue with `/queue charging` if you just plugged in! + MESSAGE + + SlackWebhookService.send_message(message) end end diff --git a/config/environments/development.rb b/config/environments/development.rb index f624b8e..efef775 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -38,6 +38,6 @@ # ENV variables ENV['ATTR_ENCRYPTION_KEY'] = 'DUMMY_ENCRYPTION_KEY_ABCDEFGHIJKLMNOPQRSTUVWXYZ' ENV['SLACK_WEBHOOKS'] = 'hook1, hook2' - ENV['EV_CONNECT_EMAIL'] = 'example@email.com' - ENV['EV_CONNECT_PASSWORD'] = 'password' + ENV['EVCONNECT_EMAIL'] = 'example@email.com' + ENV['EVCONNECT_PASSWORD'] = 'password' end diff --git a/config/environments/test.rb b/config/environments/test.rb index 8b7302b..e288da0 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -40,6 +40,6 @@ # ENV variables ENV['ATTR_ENCRYPTION_KEY'] = 'DUMMY_ENCRYPTION_KEY_ABCDEFGHIJKLMNOPQRSTUVWXYZ' ENV['SLACK_WEBHOOKS'] = 'hook1, hook2' - ENV['EV_CONNECT_EMAIL'] = 'example@email.com' - ENV['EV_CONNECT_PASSWORD'] = 'password' + ENV['EVCONNECT_EMAIL'] = 'example@email.com' + ENV['EVCONNECT_PASSWORD'] = 'password' end diff --git a/db/migrate/20200320175734_update_ev_connect_token_type.rb b/db/migrate/20200320175734_update_ev_connect_token_type.rb new file mode 100644 index 0000000..d1d196f --- /dev/null +++ b/db/migrate/20200320175734_update_ev_connect_token_type.rb @@ -0,0 +1,11 @@ +class UpdateEvConnectTokenType < ActiveRecord::Migration + def up + change_column :ev_connect_tokens, :access_token, :text + change_column :ev_connect_tokens, :refresh_token, :text + end + + def down + change_column :ev_connect_tokens, :access_token, :string + change_column :ev_connect_tokens, :refresh_token, :string + end +end diff --git a/db/migrate/20200320185718_update_station_names.rb b/db/migrate/20200320185718_update_station_names.rb new file mode 100644 index 0000000..e466880 --- /dev/null +++ b/db/migrate/20200320185718_update_station_names.rb @@ -0,0 +1,15 @@ +class UpdateStationNames < ActiveRecord::Migration + def up + EvConnectStationPort.find_by(qr_code: 'TBWS05').update!(qr_code: 'TWBS05') + EvConnectStationPort.find_by(qr_code: 'TBWS06').update!(qr_code: 'TWBS06') + EvConnectStationPort.find_by(qr_code: 'TBWS07').update!(qr_code: 'TWBS07') + EvConnectStationPort.find_by(qr_code: 'TBWS08').update!(qr_code: 'TWBS08') + end + + def down + EvConnectStationPort.find_by(qr_code: 'TWBS05').update!(qr_code: 'TBWS05') + EvConnectStationPort.find_by(qr_code: 'TWBS06').update!(qr_code: 'TBWS06') + EvConnectStationPort.find_by(qr_code: 'TWBS07').update!(qr_code: 'TBWS07') + EvConnectStationPort.find_by(qr_code: 'TWBS08').update!(qr_code: 'TBWS08') + end +end diff --git a/db/schema.rb b/db/schema.rb index e7b47eb..b5b78ee 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20200221185935) do +ActiveRecord::Schema.define(version: 20200320185718) do create_table "channel_queue_memberships", force: true do |t| t.integer "user_id", null: false @@ -35,8 +35,8 @@ end create_table "ev_connect_tokens", force: true do |t| - t.string "access_token", null: false - t.string "refresh_token", null: false + t.text "access_token", null: false + t.text "refresh_token", null: false t.datetime "expires_at", null: false t.datetime "created_at" t.datetime "updated_at" diff --git a/test/services/evacancy/ev_connect_service_test.rb b/test/services/evacancy/ev_connect_service_test.rb index e5f85b7..778e46d 100644 --- a/test/services/evacancy/ev_connect_service_test.rb +++ b/test/services/evacancy/ev_connect_service_test.rb @@ -2,11 +2,15 @@ module Evacancy class EvConnectServiceTest < ActiveSupport::TestCase + EV_CHARGERS_OF_50_CHANNEL_ID = 'CBJNVA87R'.freeze + setup do travel_to(Time.now) @token = EvConnectToken.create!(access_token: 'access_token', refresh_token: 'refresh_token', expires_at: Time.now + 30) @station1 = EvConnectStationPort.create!(qr_code: 'a1', port_status: 'AVAILABLE') @station2 = EvConnectStationPort.create!(qr_code: 'a2', port_status: 'AVAILABLE') + + @channel_queue = ChannelQueue.create(slack_channel_id: EV_CHARGERS_OF_50_CHANNEL_ID, slack_channel_name: 'test') end def test_check_ports @@ -19,13 +23,16 @@ def test_check_ports RestClient.expects(:get).with("https://api.evconnect.com/rest/v6/networks/ev-connect/stationPorts?qrCode=#{@station1.qr_code}", { 'EVC-API-TOKEN' => @token.access_token }).returns(response) RestClient.expects(:get).with("https://api.evconnect.com/rest/v6/networks/ev-connect/stationPorts?qrCode=#{@station2.qr_code}", { 'EVC-API-TOKEN' => @token.access_token }).returns(response) + ChannelQueues::NextInQueue.expects(:new).never + SlackWebhookService.expects(:send_message).never + Evacancy::EvConnectService.check_ports assert_equal @station1.reload.port_status, 'AVAILABLE' assert_equal @station2.reload.port_status, 'AVAILABLE' end - def test_check_ports__one_spot_opens + def test_check_ports__one_spot_opens__someone_in_line @station1.update!(port_status: 'CHARGING') @station2.update!(port_status: 'CHARGING') @@ -44,7 +51,50 @@ def test_check_ports__one_spot_opens RestClient.expects(:get).with("https://api.evconnect.com/rest/v6/networks/ev-connect/stationPorts?qrCode=#{@station1.qr_code}", { 'EVC-API-TOKEN' => @token.access_token }).returns(available_response) RestClient.expects(:get).with("https://api.evconnect.com/rest/v6/networks/ev-connect/stationPorts?qrCode=#{@station2.qr_code}", { 'EVC-API-TOKEN' => @token.access_token }).returns(charging_response) - SlackWebhookService.expects(:send_message).with('A spot is available!') + mock_next_in_queue = mock + ChannelQueues::NextInQueue.expects(:new).with(channel_id: EV_CHARGERS_OF_50_CHANNEL_ID).returns(mock_next_in_queue) + mock_next_in_queue.expects(:user_id).returns('dummy user id') + + message = <<~MESSAGE + A spot is available! + <@dummy user id> is next in line! + Please dequeue with `/queue charging` after you plug in! + MESSAGE + + SlackWebhookService.expects(:send_message).with(message) + + Evacancy::EvConnectService.check_ports + + assert_equal @station1.reload.port_status, 'AVAILABLE' + assert_equal @station2.reload.port_status, 'CHARGING' + end + + def test_check_ports__one_spot_opens__no_one_in_line + @station1.update!(port_status: 'CHARGING') + @station2.update!(port_status: 'CHARGING') + + available_response = mock + available_body = { + portStatus: 'AVAILABLE' + }.to_json + available_response.expects(:body).returns(available_body) + + charging_response = mock + charging_body = { + portStatus: 'CHARGING' + }.to_json + charging_response.expects(:body).returns(charging_body) + + RestClient.expects(:get).with("https://api.evconnect.com/rest/v6/networks/ev-connect/stationPorts?qrCode=#{@station1.qr_code}", { 'EVC-API-TOKEN' => @token.access_token }).returns(available_response) + RestClient.expects(:get).with("https://api.evconnect.com/rest/v6/networks/ev-connect/stationPorts?qrCode=#{@station2.qr_code}", { 'EVC-API-TOKEN' => @token.access_token }).returns(charging_response) + + message = <<~MESSAGE + A spot is available! + No one is next in line! + Please dequeue with `/queue charging` after you plug in! + MESSAGE + + SlackWebhookService.expects(:send_message).with(message) Evacancy::EvConnectService.check_ports @@ -62,7 +112,14 @@ def test_check_ports__all_spots_close RestClient.expects(:get).with("https://api.evconnect.com/rest/v6/networks/ev-connect/stationPorts?qrCode=#{@station1.qr_code}", { 'EVC-API-TOKEN' => @token.access_token }).returns(response) RestClient.expects(:get).with("https://api.evconnect.com/rest/v6/networks/ev-connect/stationPorts?qrCode=#{@station2.qr_code}", { 'EVC-API-TOKEN' => @token.access_token }).returns(response) - SlackWebhookService.expects(:send_message).with('All spots have been taken!') + ChannelQueues::NextInQueue.expects(:new).never + + message = <<~MESSAGE + All spots have been taken! + Please dequeue with `/queue charging` if you just plugged in! + MESSAGE + + SlackWebhookService.expects(:send_message).with(message) @station1.update!(port_status: 'AVAILABLE')