Skip to content

Commit

Permalink
Make all specs pass, fix the csv scrubber
Browse files Browse the repository at this point in the history
  • Loading branch information
manveru committed Feb 25, 2012
1 parent 2f40cfe commit 6c36281
Show file tree
Hide file tree
Showing 14 changed files with 163 additions and 131 deletions.
1 change: 1 addition & 0 deletions .gems
Expand Up @@ -11,6 +11,7 @@ name_parse -v0.0.5
nokogiri -v1.5.0
pg -v0.12.2
rack -v1.4.1
rack-test -v0.6.1
rake -v0.9.2.2
ramaze -v2011.12.28
sequel -v3.31.0
Expand Down
24 changes: 9 additions & 15 deletions app.rb
Expand Up @@ -2,19 +2,15 @@
require 'ramaze'

require_relative 'options'
require_relative 'model/init'
require_relative 'lib/tiny_dialer'

module TinyDialer
require MODEL_ROOT/:init
require LIBROOT/:tiny_dialer/:csv_scrub
require LIBROOT/:tiny_dialer/:zip_scrub
require LIBROOT/:tiny_dialer/:state_scrub
require LIBROOT/:tiny_dialer/:dialer
require LIBROOT/:tiny_dialer/:hopper
require LIBROOT/:tiny_dialer/:phone_number
require LIBROOT/:tiny_dialer/:tcc_helper if TinyDialer.options.direct_listener.tcc_root
end

require_relative 'lib/tiny_dialer/lead_scrub'
require_relative 'lib/tiny_dialer/state_scrub'
require_relative 'lib/tiny_dialer/zip_scrub'
require_relative 'lib/tiny_dialer/dialer'
require_relative 'lib/tiny_dialer/hopper'
require_relative 'lib/tiny_dialer/phone_number'
require_relative 'lib/tiny_dialer/tcc_helper' if TinyDialer.options.direct_listener.tcc_root
require_relative 'controller/init'

Ramaze::Response.options.headers.merge!(
Expand All @@ -25,6 +21,4 @@ module TinyDialer

FSR.load_all_commands

if $0 == __FILE__
Ramaze.start port: 7575
end
Ramaze.start port: 7575 if $0 == __FILE__
3 changes: 2 additions & 1 deletion controller/admin.rb
Expand Up @@ -18,7 +18,8 @@ def upload_csv
FileUtils.mkdir_p(File.dirname(path))
File.open(path, 'wb+'){|out| out.print(upload[:tempfile].read) }

CsvScrubber.new(path, clear_leads).scrub_csv
TinyDialer::Lead.destroy if request[:clear_leads]
LeadScrubber.import_leads(path)

flash[:INFO] = "Loaded #{filename} : #{upload[:tempfile].size} bytes"
redirect_referrer
Expand Down
44 changes: 0 additions & 44 deletions lib/tiny_dialer/csv_scrub.rb

This file was deleted.

47 changes: 47 additions & 0 deletions lib/tiny_dialer/lead_scrub.rb
@@ -0,0 +1,47 @@
require_relative '../tiny_dialer'
require 'csv'
require 'name_parse'

module TinyDialer
module LeadScrubber
MAP = {
balance: 'BALANCE',
fullname: 'NAME1',
phone: 'RES-PHONE',
reference_number: 'REFNUMBER',
state: 'STATE',
zip: 'ZIP',
}

module_function

def each_lead(res)
return to_enum(__method__, res) unless block_given?

CSV.open res, headers: true do |csv|
csv.each do |entry|
yield(entry)
end
end
end

def import_leads(res)
each_lead res do |lead|
hash = lead.to_hash
name = NameParse[hash.fetch('NAME1')]
TinyDialer::Lead.create(
first_name: name.first,
last_name: name.last,
suffix: name.suffix,
prefix: name.prefix,
balance: hash.fetch('INIT-BALANCE'),
phone: hash.fetch('RES-PHONE'),
reference_number: hash.fetch('REFNUMBER'),
state: hash.fetch('STATE'),
status: 'NEW',
zip: hash.fetch('ZIP'),
)
end
end
end
end
18 changes: 9 additions & 9 deletions lib/tiny_dialer/menu_listener.rb
Expand Up @@ -25,23 +25,23 @@ def session_initiated

def play_message
lead.update(:status => 'ANSWER', :timestamp => Time.now)
@record = TinyDialer::Record.create(:timestamp => Time.now, :status => "CALLING", :debtor_id => lead.debtor_id.to_s, :first_name => lead.first_name.to_s, :last_name => lead.last_name.to_s, :phone => lead.phone.to_s, :zip => lead.zip.to_s)
@record = TinyDialer::Record.create(:timestamp => Time.now, :status => "CALLING", :reference_number => lead.reference_number.to_s, :first_name => lead.first_name.to_s, :last_name => lead.last_name.to_s, :phone => lead.phone.to_s, :zip => lead.zip.to_s)
playback(WELCOME_WAV) do
update_session do
Log.info "#{Time.now} - #{session.headers[:variable_amd_status].to_s} answered (#{session.headers[:variable_amd_result]}) - #{lead.first_name} #{lead.last_name} #{lead.debtor_id}"
Log.info "#{Time.now} - #{session.headers[:variable_amd_status].to_s} answered (#{session.headers[:variable_amd_result]}) - #{lead.first_name} #{lead.last_name} #{lead.reference_number}"
if session.headers[:variable_amd_status].to_s != "machine"
@record.update(:status => "ANSWERED")
Log.info "A person answered, playing initial first/last name question: #{lead.first_name} #{lead.last_name} #{lead.debtor_id}"
Log.info "A person answered, playing initial first/last name question: #{lead.first_name} #{lead.last_name} #{lead.reference_number}"
speak("#{lead.first_name.to_s} #{lead.last_name.to_s}", {:voice => 'diane', :engine => 'cepstral'}) do
Log.info "getting input: #{lead.first_name} #{lead.last_name} #{lead.debtor_id}"
Log.info "getting input: #{lead.first_name} #{lead.last_name} #{lead.reference_number}"
get_input
end
else
@record.update(:status => "MACHINE_ANSWERED")
set("first_name", "#{lead.first_name}") do
set("last_name", "#{lead.last_name}") do
set("debtor_id", "#{lead.debtor_id.to_s.split(%r{\s*}).join(' ')}") do
Log.info "#{Time.now} - Leaving a message for #{lead.first_name} #{lead.last_name} #{lead.debtor_id}"
set("reference_number", "#{lead.reference_number.to_s.split(%r{\s*}).join(' ')}") do
Log.info "#{Time.now} - Leaving a message for #{lead.first_name} #{lead.last_name} #{lead.reference_number}"
lead.update(:status => 'ANS_MACH_LMTC', :timestamp => Time.now)
@record.update(:status => 'ANS_MACH_LMTC')
lead.write_status
Expand Down Expand Up @@ -96,12 +96,12 @@ def case_input(input)
end

def direct_xfer
Log.info "#{Time.now} - ##{lead.debtor_id} #{lead.first_name} #{lead.last_name} transfered to queue"
Log.info "#{Time.now} - ##{lead.reference_number} #{lead.first_name} #{lead.last_name} transfered to queue"
timestamp = Time.now
lead.update(:status => 'DIRECT_XFER', :timestamp => timestamp)
@record.update(:status => 'DIRECT_XFER')
lead.write_status
set("effective_caller_id_number", "Acct#{lead.debtor_id}") do
set("effective_caller_id_number", "Acct#{lead.reference_number}") do
set("effective_caller_id_name", "#{@lead.first_name} #{@lead.last_name}") do
transfer("9999 XML default") { close_connection }
end
Expand All @@ -116,7 +116,7 @@ def leave_msg
lead.write_status
set("first_name", "#{lead.first_name}") do
set("last_name", "#{lead.last_name}") do
set("debtor_id", "#{lead.debtor_id.to_s.split(%r{\s*}).join(' ')}") do
set("reference_number", "#{lead.reference_number.to_s.split(%r{\s*}).join(' ')}") do
lead.write_status
transfer("7001 XML default") { close_connection }
end
Expand Down
48 changes: 25 additions & 23 deletions model/lead.rb
Expand Up @@ -3,18 +3,21 @@

class TinyDialer::Lead < Sequel::Model
set_dataset :leads
attr_reader :rej

def phone_num
phone.gsub('-', '') # Return phone number without hyphens, i.e. "-"
end

def write_status
File.open(File.join(TinyDialer::ROOT, "results", "#{self.debtor_id}.tsv"), 'wb', 0664) do |f|
f.puts "#{self.debtor_id}\t#{self.status}\t#{self.phone}\t#{self.timestamp.year}-#{self.timestamp.month}-#{self.timestamp.day}\t#{self.timestamp.hour}:#{self.timestamp.min}\tBD_IC"
File.open write_status_path, 'wb+', 0664 do |f|
f.puts [reference_number, status, phone, timestamp.strftime("%Y-%m-%d\t%H:%M"), 'BD_IC'].join("\t")
end
end

def write_status_path
"#{TinyDialer::ROOT}/results/#{reference_number}.tsv"
end

def postal
@zip ||= TinyDialer::Zip[:zip => zip[0..4]] if zip
@zip
Expand All @@ -35,48 +38,47 @@ def timezone
#
# Resorted to using postgres for the time comparison, because it Just Works
def call?
if rejection_reason
TinyDialer::Log.info "Rejected #{phone}: #{rejection_reason}"
return
if reason = rejection_reason
TinyDialer::Log.info "Rejected #{phone}: #{reason}"
return false
end

# Make sure (now, now) overlaps (start, stop)
now = (Time.now.utc + (3600*(timezone)).to_i).strftime('%H:%M')
unless TinyDialer.db.fetch("select ('#{now}'::text::time, '#{now}'::text::time) OVERLAPS ('#{state.start}'::text::time, '#{state.stop}'::text::time)").first[:overlaps]
if TinyDialer.db.fetch("select ('#{now}'::text::time, '#{now}'::text::time) OVERLAPS ('#{state.start}'::text::time, '#{state.stop}'::text::time)").first[:overlaps]
return true
else
TinyDialer::Log.info "Rejected #{phone}: Outside of calling times #{state.start} and #{state.stop}"
return false
end
true
rescue => e
TinyDialer::Log.error e
return
false
end

def dnc?
TinyDialer::Dnc[:number => self.phone_num]
TinyDialer::Dnc[number: phone_num]
end

def called_today?
return unless timestamp
begin
Time.now.to_date == timestamp.to_date
rescue => e
TinyDialer::Log.error e
return
end
timestamp && Date.today == timestamp.to_date
rescue => e
TinyDialer::Log.error e
false
end

private

def rejection_reason
return @rej = :no_zip unless zip
return @rej = :no_state unless state
#return @rej = :called_today if called_today?
return @rej = :do_not_call if dnc?
@rej = false
return :no_zip unless zip
return :no_state unless state
return :called_today if called_today?
return :do_not_call if dnc?
false
end

def before_create
self[:created_at] = DateTime.now
self[:status] ||= "NEW"
end

end
Empty file added results/.keep
Empty file.
14 changes: 14 additions & 0 deletions spec/csv_test.csv
@@ -0,0 +1,14 @@
"REFNUMBER","NAME1","NAME2","INIT-BALANCE","BALANCE","RES-PHONE","STATE","ZIP"
1819039,"Vanderpoel, Tj","",320.0,320.0,"4719395828","CA","95202"
1234567,"Blank, Paul",,320.0,320.0,"8123955950","TX","75202"
1234568,"Smith, Yolandia",,320.0,320.0,"8123766817","NY","05202"
1234569,"Dempsey, Rita",,320.0,320.0,"8124040546","TX","75202"
1234570,"Bacon, Dennis",,320.0,320.0,"8128860850","TX","75202"
1234571,"Harper, Tonya",,320.0,320.0,"8127247873","TX","75202"
1234572,"Rogers, Sudeshna",,320.0,320.0,"2878310431","TX","75202"
1234573,"Tate, Ronnie",,320.0,320.0,"2875693801","TX","75202"
1234574,"Gibson, Gary",,320.0,320.0,"2875791072","TX","75202"
1234575,"Tyler, Steve",,320.0,320.0,"8725406060","TX","75202"
1234576,"Hanks, Candace",,320.0,320.0,"2879647478","TX","75202"
1234577,"Berry, Thunder",,320.0,320.0,"8123340088","TX","75202"
1234578,"Wayne, Roy",,320.0,320.0,"8122052049","TX","75202"
34 changes: 16 additions & 18 deletions spec/model/lead.rb
Expand Up @@ -3,9 +3,9 @@
describe 'TinyDialer::Lead' do

before do
@u = TinyDialer::Lead.create(:first_name => "jayson", :last_name => "vaughn",
:phone => "817-690-7937", :status => "NEW",
:debtor_id => '1234567', :zip => '75202')
@u = TinyDialer::Lead.create(:first_name => "jayson", :last_name => "vaughn",
:phone => "817-690-7937", :status => "NEW",
:reference_number => '1234567', :zip => '75202')
@tz = TinyDialer::Zip.create(:zip => '75202', :gmt => '-6.0', :state => 'TX')
@state = TinyDialer::State.create(:state => 'TX', :start => "09:00", :stop => "21:00")
end
Expand All @@ -18,21 +18,19 @@

it 'should allow creation of a lead' do
@u.id.should.not == nil
@u.debtor_id.should == "1234567"
@u.reference_number.should == "1234567"
@u.phone.should == "817-690-7937"
@u.first_name.should == "jayson"
end

it 'should write lead status to a file in /tmp' do
@u.update(:status => 'LTMC', :timestamp => Time.now)
@u.update(:status => 'LTMC', :timestamp => Time.at(1330205728))
@u.write_status
status_file = File.join(TinyDialer::ROOT, "results", "#{@u.debtor_id}.tsv")
File.exists?(status_file).should == true
file = File.open(status_file).each do |record|
entry = record.strip.split("\t")
entry[0].should == "1234567"
entry[1].should == "LTMC"
entry[2].should == "817-690-7937"

File.open @u.write_status_path do |file|
file.each_line do |record|
record.scan(/[^\t]+/).first(3).should == %w[1234567 LTMC 817-690-7937]
end
end
end

Expand Down Expand Up @@ -61,11 +59,11 @@
end

it 'should not allow a call to be placed twice in the same day' do
@state.update(:start => '00:00', :stop => '23:59') # So the first spec will always pass
@u.update(:timestamp => Time.now - 36000)
@u.call?.should == true
@u.update(:timestamp => Time.now, :status => 'ANSWERED')
@u.call?.should != true
@state.update(start: '00:00', stop: '23:59') # So the first spec will always pass
@u.update(status: 'NEW', timestamp: Date.today - 1)
@u.timestamp.to_date.should.not == Date.today
@u.should.be.call
@u.update(status: 'ANSWERED', timestamp: Time.now)
@u.should.not.be.call
end

end
16 changes: 0 additions & 16 deletions spec/tiny_dialer/csv_scrub.rb

This file was deleted.

0 comments on commit 6c36281

Please sign in to comment.