feat: Add bulk imports API for contacts (#1724)

This commit is contained in:
Sojan Jose
2021-02-03 19:24:51 +05:30
committed by GitHub
parent 7748e0c56e
commit c61edff189
20 changed files with 278 additions and 14 deletions

26
spec/assets/contacts.csv Normal file
View File

@@ -0,0 +1,26 @@
id,first_name,last_name,email,gender,ip_address,identifier
1,Clarice,Uzzell,cuzzell0@mozilla.org,Genderfluid,70.61.11.201,bb4e11cd-0f23-49da-a123-dcc1fec6852c
2,Marieann,Creegan,mcreegan1@cornell.edu,Genderfluid,168.186.4.241,e60bab4c-9fbb-47eb-8f75-42025b789c47
3,Nancey,Windibank,nwindibank2@bluehost.com,Agender,73.44.41.59,f793e813-4210-4bf3-a812-711418de25d2
4,Sibel,Stennine,sstennine3@yellowbook.com,Genderqueer,115.249.27.155,d6e35a2d-d093-4437-a577-7df76316b937
5,Tina,O'Lunney,tolunney4@si.edu,Bigender,219.181.212.8,3540d40a-5567-4f28-af98-5583a7ddbc56
6,Quinn,Neve,qneve5@army.mil,Genderfluid,231.210.115.166,ba0e1bf0-c74b-41ce-8a2d-0b08fa0e5aa5
7,Karylin,Gaunson,kgaunson6@tripod.com,Polygender,160.189.41.11,d24cac79-c81b-4b84-a33e-0441b7c6a981
8,Jamison,Shenton,jshenton7@upenn.edu,Agender,53.94.18.201,29a7a8c0-c7f7-4af9-852f-761b1a784a7a
9,Gavan,Threlfall,gthrelfall8@spotify.com,Genderfluid,18.87.247.249,847d4943-ddb5-47cc-8008-ed5092c675c5
10,Katina,Hemmingway,khemmingway9@ameblo.jp,Non-binary,25.191.96.124,8f0b5efd-b6a8-4f1e-a1e3-b0ea8c9e3048
11,Jillian,Deinhard,jdeinharda@canalblog.com,Female,11.211.174.93,bd952787-1b05-411f-9975-b916ec0950cc
12,Blake,Finden,bfindenb@wsj.com,Female,47.26.205.153,12c95613-e49d-4fa2-86fb-deabb6ebe600
13,Liane,Maxworthy,lmaxworthyc@un.org,Non-binary,157.196.34.166,36b68e4c-40d6-4e09-bf59-7db3b27b18f0
14,Martynne,Ledley,mledleyd@sourceforge.net,Polygender,109.231.152.148,1856bceb-cb36-415c-8ffc-0527f3f750d8
15,Katharina,Ruffli,krufflie@huffingtonpost.com,Genderfluid,20.43.146.179,604de5c9-b154-4279-8978-41fb71f0f773
16,Tucker,Simmance,tsimmancef@bbc.co.uk,Bigender,179.76.226.171,0a8fc3a7-4986-4a51-a503-6c7f974c90ad
17,Wenona,Martinson,wmartinsong@census.gov,Genderqueer,92.243.194.160,0e5ea6e3-6824-4e78-a6f5-672847eafa17
18,Gretna,Vedyasov,gvedyasovh@lycos.com,Female,25.22.86.101,6becf55b-a7b5-48f6-8788-b89cae85b066
19,Lurline,Abdon,labdoni@archive.org,Genderqueer,150.249.116.118,afa9429f-9034-4b06-9efa-980e01906ebf
20,Fiann,Norcliff,fnorcliffj@istockphoto.com,Female,237.167.197.197,59f72dec-14ba-4d6e-b17c-0d962e69ffac
21,Zed,Linn,zlinnk@phoca.cz,Genderqueer,88.102.64.113,95f7bc56-be92-4c9c-ad58-eff3e63c7bea
22,Averyl,Simyson,asimysonl@livejournal.com,Agender,141.248.89.29,bde1fe59-c9bd-440c-bb39-79fe61dac1d1
23,Camella,Blackadder,cblackadderm@nifty.com,Polygender,118.123.138.115,0c981752-5857-487c-b9b5-5d0253df740a
24,Aurie,Spatig,aspatign@printfriendly.com,Polygender,157.45.102.235,4cf22bfb-2c3f-41d1-9993-6e3758e457ba
25,Adrienne,Bellard,abellardo@cnn.com,Male,170.73.198.47,f10f9b8d-38ac-4e17-8a7d-d2e6a055f944
1 id first_name last_name email gender ip_address identifier
2 1 Clarice Uzzell cuzzell0@mozilla.org Genderfluid 70.61.11.201 bb4e11cd-0f23-49da-a123-dcc1fec6852c
3 2 Marieann Creegan mcreegan1@cornell.edu Genderfluid 168.186.4.241 e60bab4c-9fbb-47eb-8f75-42025b789c47
4 3 Nancey Windibank nwindibank2@bluehost.com Agender 73.44.41.59 f793e813-4210-4bf3-a812-711418de25d2
5 4 Sibel Stennine sstennine3@yellowbook.com Genderqueer 115.249.27.155 d6e35a2d-d093-4437-a577-7df76316b937
6 5 Tina O'Lunney tolunney4@si.edu Bigender 219.181.212.8 3540d40a-5567-4f28-af98-5583a7ddbc56
7 6 Quinn Neve qneve5@army.mil Genderfluid 231.210.115.166 ba0e1bf0-c74b-41ce-8a2d-0b08fa0e5aa5
8 7 Karylin Gaunson kgaunson6@tripod.com Polygender 160.189.41.11 d24cac79-c81b-4b84-a33e-0441b7c6a981
9 8 Jamison Shenton jshenton7@upenn.edu Agender 53.94.18.201 29a7a8c0-c7f7-4af9-852f-761b1a784a7a
10 9 Gavan Threlfall gthrelfall8@spotify.com Genderfluid 18.87.247.249 847d4943-ddb5-47cc-8008-ed5092c675c5
11 10 Katina Hemmingway khemmingway9@ameblo.jp Non-binary 25.191.96.124 8f0b5efd-b6a8-4f1e-a1e3-b0ea8c9e3048
12 11 Jillian Deinhard jdeinharda@canalblog.com Female 11.211.174.93 bd952787-1b05-411f-9975-b916ec0950cc
13 12 Blake Finden bfindenb@wsj.com Female 47.26.205.153 12c95613-e49d-4fa2-86fb-deabb6ebe600
14 13 Liane Maxworthy lmaxworthyc@un.org Non-binary 157.196.34.166 36b68e4c-40d6-4e09-bf59-7db3b27b18f0
15 14 Martynne Ledley mledleyd@sourceforge.net Polygender 109.231.152.148 1856bceb-cb36-415c-8ffc-0527f3f750d8
16 15 Katharina Ruffli krufflie@huffingtonpost.com Genderfluid 20.43.146.179 604de5c9-b154-4279-8978-41fb71f0f773
17 16 Tucker Simmance tsimmancef@bbc.co.uk Bigender 179.76.226.171 0a8fc3a7-4986-4a51-a503-6c7f974c90ad
18 17 Wenona Martinson wmartinsong@census.gov Genderqueer 92.243.194.160 0e5ea6e3-6824-4e78-a6f5-672847eafa17
19 18 Gretna Vedyasov gvedyasovh@lycos.com Female 25.22.86.101 6becf55b-a7b5-48f6-8788-b89cae85b066
20 19 Lurline Abdon labdoni@archive.org Genderqueer 150.249.116.118 afa9429f-9034-4b06-9efa-980e01906ebf
21 20 Fiann Norcliff fnorcliffj@istockphoto.com Female 237.167.197.197 59f72dec-14ba-4d6e-b17c-0d962e69ffac
22 21 Zed Linn zlinnk@phoca.cz Genderqueer 88.102.64.113 95f7bc56-be92-4c9c-ad58-eff3e63c7bea
23 22 Averyl Simyson asimysonl@livejournal.com Agender 141.248.89.29 bde1fe59-c9bd-440c-bb39-79fe61dac1d1
24 23 Camella Blackadder cblackadderm@nifty.com Polygender 118.123.138.115 0c981752-5857-487c-b9b5-5d0253df740a
25 24 Aurie Spatig aspatign@printfriendly.com Polygender 157.45.102.235 4cf22bfb-2c3f-41d1-9993-6e3758e457ba
26 25 Adrienne Bellard abellardo@cnn.com Male 170.73.198.47 f10f9b8d-38ac-4e17-8a7d-d2e6a055f944

View File

@@ -3,7 +3,7 @@ require 'rails_helper'
RSpec.describe '/api/v1/accounts/{account.id}/contacts/:id/contact_inboxes', type: :request do
let(:account) { create(:account) }
let(:contact) { create(:contact, account: account) }
let(:inbox_1) { create(:inbox, account: account) }
let(:channel_twilio_sms) { create(:channel_twilio_sms, account: account) }
let(:channel_api) { create(:channel_api, account: account) }
let(:user) { create(:user, account: account) }
@@ -28,10 +28,10 @@ RSpec.describe '/api/v1/accounts/{account.id}/contacts/:id/contact_inboxes', typ
expect(contact.reload.contact_inboxes.map(&:inbox_id)).to include(channel_api.inbox.id)
end
it 'throws error when its not an api inbox' do
it 'throws error for invalid source id' do
expect do
post "/api/v1/accounts/#{account.id}/contacts/#{contact.id}/contact_inboxes",
params: { inbox_id: inbox_1.id },
params: { inbox_id: channel_twilio_sms.inbox.id },
headers: user.create_new_auth_token,
as: :json
end.to change(ContactInbox, :count).by(0)

View File

@@ -43,6 +43,43 @@ RSpec.describe 'Contacts API', type: :request do
end
end
describe 'POST /api/v1/accounts/{account.id}/contacts/import' do
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
post "/api/v1/accounts/#{account.id}/contacts/import"
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user with out permission' do
let(:agent) { create(:user, account: account, role: :agent) }
it 'returns unauthorized' do
post "/api/v1/accounts/#{account.id}/contacts/import",
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
let(:admin) { create(:user, account: account, role: :administrator) }
it 'creates a data import' do
file = fixture_file_upload(Rails.root.join('spec/assets/contacts.csv'), 'text/csv')
post "/api/v1/accounts/#{account.id}/contacts/import",
headers: admin.create_new_auth_token,
params: { import_file: file }
expect(response).to have_http_status(:success)
expect(account.data_imports.count).to eq(1)
expect(account.data_imports.first.import_file.attached?).to eq(true)
end
end
end
describe 'GET /api/v1/accounts/{account.id}/contacts/active' do
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do

View File

@@ -4,7 +4,9 @@ FactoryBot.define do
account_sid { SecureRandom.uuid }
sequence(:phone_number) { |n| "+123456789#{n}1" }
medium { :sms }
inbox
account
after(:build) do |channel|
channel.inbox ||= create(:inbox, account: channel.account)
end
end
end

View File

@@ -4,6 +4,18 @@ FactoryBot.define do
factory :contact_inbox do
contact
inbox
source_id { SecureRandom.uuid }
after(:build) { |contact_inbox| contact_inbox.source_id ||= generate_source_id(contact_inbox) }
end
end
def generate_source_id(contact_inbox)
case contact_inbox.inbox.channel_type
when 'Channel::TwilioSms'
contact_inbox.inbox.channel.medium == 'sms' ? Faker::PhoneNumber.cell_phone_in_e164 : "whatsapp:#{Faker::PhoneNumber.cell_phone_in_e164}"
when 'Channel::Email'
"#{SecureRandom.uuid}@acme.inc"
else
SecureRandom.uuid
end
end

View File

@@ -0,0 +1,7 @@
FactoryBot.define do
factory :data_import do
data_type { 'contacts' }
import_file { Rack::Test::UploadedFile.new(Rails.root.join('spec/assets/contacts.csv'), 'text/csv') }
account
end
end

View File

@@ -0,0 +1,24 @@
require 'rails_helper'
RSpec.describe DataImportJob, type: :job do
subject(:job) { described_class.perform_later(data_import) }
let!(:data_import) { create(:data_import) }
it 'queues the job' do
expect { job }.to have_enqueued_job(described_class)
.with(data_import)
.on_queue('low')
end
it 'imports data into the account' do
csv_length = CSV.parse(data_import.import_file.download, headers: true).length
described_class.perform_now(data_import)
expect(data_import.account.contacts.count).to eq(csv_length)
expect(data_import.reload.total_records).to eq(csv_length)
expect(data_import.reload.processed_records).to eq(csv_length)
# should generate pubsub tokens for contacts
expect(data_import.account.contacts.last.pubsub_token).present?
end
end

View File

@@ -0,0 +1,13 @@
require 'rails_helper'
RSpec.describe DataImport, type: :model do
describe 'associations' do
it { is_expected.to belong_to(:account) }
end
describe 'validations' do
it 'returns false for invalid data type' do
expect(build(:data_import, data_type: 'Xyc').valid?).to eq false
end
end
end