ofac 1.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +6 -0
- data/History.txt +72 -0
- data/LICENSE +20 -0
- data/PostInstall.txt +11 -0
- data/README.rdoc +123 -0
- data/Rakefile +60 -0
- data/VERSION.yml +4 -0
- data/generators/ofac_migration/ofac_migration_generator.rb +12 -0
- data/generators/ofac_migration/templates/migration.rb +31 -0
- data/lib/ofac.rb +9 -0
- data/lib/ofac/models/ofac.rb +177 -0
- data/lib/ofac/models/ofac_sdn.rb +5 -0
- data/lib/ofac/models/ofac_sdn_loader.rb +305 -0
- data/lib/ofac/ofac_match.rb +139 -0
- data/lib/ofac/ruby_string_extensions.rb +22 -0
- data/lib/tasks/ofac.rake +8 -0
- data/ofac.gemspec +104 -0
- data/test/files/test_address_data_load.pip +10 -0
- data/test/files/test_alt_data_load.pip +10 -0
- data/test/files/test_sdn_data_load.pip +9 -0
- data/test/files/valid_flattened_file.csv +19 -0
- data/test/mocks/test/ofac_sdn_loader.rb +20 -0
- data/test/ofac_sdn_loader_test.rb +40 -0
- data/test/ofac_test.rb +138 -0
- data/test/test_helper.rb +49 -0
- metadata +119 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
Ofac_SoundexChars = 'BPFVCSKGJQXZDTLMNR'
|
4
|
+
Ofac_SoundexNums = '111122222222334556'
|
5
|
+
Ofac_SoundexCharsEx = '^' + Ofac_SoundexChars
|
6
|
+
Ofac_SoundexCharsDel = '^A-Z'
|
7
|
+
|
8
|
+
# desc: http://en.wikipedia.org/wiki/Soundex
|
9
|
+
def ofac_soundex(census = true)
|
10
|
+
str = upcase.delete(Ofac_SoundexCharsDel).squeeze
|
11
|
+
|
12
|
+
str[0 .. 0] + str[1 .. -1].
|
13
|
+
delete(Ofac_SoundexCharsEx).
|
14
|
+
tr(Ofac_SoundexChars, Ofac_SoundexNums)[0 .. (census ? 2 : -1)].
|
15
|
+
ljust(3, '0') rescue ''
|
16
|
+
end
|
17
|
+
|
18
|
+
def ofac_sounds_like(other, census = true)
|
19
|
+
ofac_soundex(census) == other.ofac_soundex(census)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/lib/tasks/ofac.rake
ADDED
data/ofac.gemspec
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ofac}
|
8
|
+
s.version = "1.1.11"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Kevin Tyll"]
|
12
|
+
s.date = %q{2010-02-05}
|
13
|
+
s.description = %q{Attempts to find a hit on the Office of Foreign Assets Control's Specially Designated Nationals list.}
|
14
|
+
s.email = %q{kevintyll@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"History.txt",
|
23
|
+
"LICENSE",
|
24
|
+
"PostInstall.txt",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION.yml",
|
28
|
+
"generators/ofac_migration/.DS_Store",
|
29
|
+
"generators/ofac_migration/ofac_migration_generator.rb",
|
30
|
+
"generators/ofac_migration/templates/.DS_Store",
|
31
|
+
"generators/ofac_migration/templates/migration.rb",
|
32
|
+
"lib/ofac.rb",
|
33
|
+
"lib/ofac/models/ofac.rb",
|
34
|
+
"lib/ofac/models/ofac_sdn.rb",
|
35
|
+
"lib/ofac/models/ofac_sdn_loader.rb",
|
36
|
+
"lib/ofac/ofac_match.rb",
|
37
|
+
"lib/ofac/ruby_string_extensions.rb",
|
38
|
+
"lib/tasks/ofac.rake",
|
39
|
+
"nbproject/project.properties",
|
40
|
+
"nbproject/project.xml",
|
41
|
+
"ofac.gemspec",
|
42
|
+
"pkg/ofac-0.1.0.gem",
|
43
|
+
"pkg/ofac-1.0.0.gem",
|
44
|
+
"rdoc/classes/Ofac.html",
|
45
|
+
"rdoc/classes/OfacMatch.html",
|
46
|
+
"rdoc/classes/OfacSdn.html",
|
47
|
+
"rdoc/classes/OfacSdnLoader.html",
|
48
|
+
"rdoc/classes/String.html",
|
49
|
+
"rdoc/created.rid",
|
50
|
+
"rdoc/files/README_rdoc.html",
|
51
|
+
"rdoc/files/lib/ofac/models/ofac_rb.html",
|
52
|
+
"rdoc/files/lib/ofac/models/ofac_sdn_loader_rb.html",
|
53
|
+
"rdoc/files/lib/ofac/models/ofac_sdn_rb.html",
|
54
|
+
"rdoc/files/lib/ofac/ofac_match_rb.html",
|
55
|
+
"rdoc/files/lib/ofac/ruby_string_extensions_rb.html",
|
56
|
+
"rdoc/files/lib/ofac_rb.html",
|
57
|
+
"rdoc/fr_class_index.html",
|
58
|
+
"rdoc/fr_file_index.html",
|
59
|
+
"rdoc/fr_method_index.html",
|
60
|
+
"rdoc/index.html",
|
61
|
+
"rdoc/rdoc-style.css",
|
62
|
+
"test/files/test_address_data_load.pip",
|
63
|
+
"test/files/test_alt_data_load.pip",
|
64
|
+
"test/files/test_sdn_data_load.pip",
|
65
|
+
"test/files/valid_flattened_file.csv",
|
66
|
+
"test/mocks/test/ofac_sdn_loader.rb",
|
67
|
+
"test/ofac_sdn_loader_test.rb",
|
68
|
+
"test/ofac_test.rb",
|
69
|
+
"test/test_helper.rb"
|
70
|
+
]
|
71
|
+
s.homepage = %q{http://github.com/kevintyll/ofac}
|
72
|
+
s.post_install_message = %q{For more information on ofac, see http://kevintyll.github.com/ofac/
|
73
|
+
|
74
|
+
* To create the necessary db migration, from the command line, run:
|
75
|
+
script/generate ofac_migration
|
76
|
+
* Require the gem in your environment.rb file in the Rails::Initializer block:
|
77
|
+
config.gem 'kevintyll-ofac', :lib => 'ofac'
|
78
|
+
* To load your table with the current OFAC data, from the command line, run:
|
79
|
+
rake ofac:update_data
|
80
|
+
|
81
|
+
* The OFAC data is not updated with any regularity, but you can sign up for email notifications when the data changes at
|
82
|
+
http://www.treas.gov/offices/enforcement/ofac/sdn/index.shtml.}
|
83
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
84
|
+
s.require_paths = ["lib"]
|
85
|
+
s.rubygems_version = %q{1.3.5}
|
86
|
+
s.summary = %q{Attempts to find a hit on the Office of Foreign Assets Control's Specially Designated Nationals list.}
|
87
|
+
s.test_files = [
|
88
|
+
"test/mocks/test/ofac_sdn_loader.rb",
|
89
|
+
"test/ofac_sdn_loader_test.rb",
|
90
|
+
"test/ofac_test.rb",
|
91
|
+
"test/test_helper.rb"
|
92
|
+
]
|
93
|
+
|
94
|
+
if s.respond_to? :specification_version then
|
95
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
96
|
+
s.specification_version = 3
|
97
|
+
|
98
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
99
|
+
else
|
100
|
+
end
|
101
|
+
else
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
10|7|-0- |-0- |"Panama"|-0-
|
2
|
+
15|12|-0- |-0- |"Panama"|-0-
|
3
|
+
22|14|"123 Somewhere Ln"|"Clearwater"|"United States"|-0-
|
4
|
+
39|27|-0- |"Managua"|"Nicaragua"|-0-
|
5
|
+
39|29|"Bal Harbour Shopping Center, Via Italia"|"Panama City"|"Panama"|-0-
|
6
|
+
41|41|"Avenida de Concha, Espina 8, E-28036"|"Madrid"|"Spain"|-0-
|
7
|
+
41|102|-0- |-0- |-0- |-0-
|
8
|
+
66|111|-0- |-0- |"Italy"|-0-
|
9
|
+
66|117|-0- |-0- |"Panama"|-0-
|
10
|
+
66|125|"1840 West 49th Street"|-0- |"United States"|-0-
|
@@ -0,0 +1,10 @@
|
|
1
|
+
15|14|"aka"|"VIAJES GUAMA TOURS"|-0-
|
2
|
+
22|15|"aka"|"HERNANDEZ, Oscar Grouch"|-0-
|
3
|
+
22|16|"aka"|"Alternate Name"|-0-
|
4
|
+
25|57|"aka"|"AVIA IMPORT"|-0-
|
5
|
+
36|219|"aka"|"BNC"|-0-
|
6
|
+
36|220|"aka"|"NATIONAL BANK OF CUBA"|-0-
|
7
|
+
36|221|"aka"|"BNC"|-0-
|
8
|
+
41|222|"aka"|"NATIONAL BANK OF CUBA"|-0-
|
9
|
+
66|223|"aka"|"BNC"|-0-
|
10
|
+
66|224|"aka"|"NATIONAL BANK OF CUBA"|-0-
|
@@ -0,0 +1,9 @@
|
|
1
|
+
10|"ABASTECEDORA NAVAL Y INDUSTRIAL, S.A."|-0- |"CUBA"|-0- |-0- |-0- |-0- |-0- |-0- |-0- |-0-
|
2
|
+
15|"ABDELNUR| Nury de Jesus"|"individual"|"CUBA"|-0- |-0- |-0- |-0- |-0- |-0- |-0- |-0-
|
3
|
+
22|"HERNANDEZ, Oscar"|"individual"|"CUBA"|-0- |-0- |"Unknown vessel type"|-0- |-0- |-0- |"Acechilly Navigation Co., Malta"|-0-
|
4
|
+
24|"LOPEZ MENDEZ, Luis Eduardo"|"individual"|"CUBA"|-0- |-0- |"Unknown vessel type"|-0- |-0- |-0- |"Acefrosty Shipping Co., Malta"|-0-
|
5
|
+
25|"ACEFROSTY SHIPPING CO., LTD."|-0- |"CUBA"|-0- |-0- |-0- |-0- |-0- |-0- |-0- |-0-
|
6
|
+
36|"AEROCARIBBEAN AIRLINES"|-0- |"CUBA"|-0- |-0- |-0- |-0- |-0- |-0- |-0- |-0-
|
7
|
+
39|"AEROTAXI EJECUTIVO, S.A."|-0- |"CUBA"|-0- |-0- |-0- |-0- |-0- |-0- |-0- |-0-
|
8
|
+
41|"AGENCIA DE VIAJES GUAMA"|-0- |"CUBA"|-0- |-0- |-0- |-0- |-0- |-0- |-0- |-0-
|
9
|
+
66|"AGUIAR, Raul"|"individual"|"CUBA"|"Director, Banco Nacional de Cuba"|-0- |-0- |-0- |-0- |-0- |-0- |"; Director, Banco Nacional de Cuba."
|
@@ -0,0 +1,19 @@
|
|
1
|
+
``|`ABASTECEDORA NAVAL Y INDUSTRIAL, S.A.`|``|`CUBA`|``|``|``|``|``|``|``|``|``|``|`Panama`|``|``|``|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
2
|
+
``|`ABDELNUR`|` Nury de Jesus`|`individual`|`CUBA`|``|``|``|``|``|``|``|``|``|`Panama`|``|`aka`|`VIAJES GUAMA TOURS`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
3
|
+
``|`HERNANDEZ, Oscar`|`individual`|`CUBA`|``|``|`Unknown vessel type`|``|``|``|`Acechilly Navigation Co., Malta`|``|`123 Somewhere Ln`|`Clearwater`|`United States`|``|`aka`|`HERNANDEZ, Oscar Grouch`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
4
|
+
``|`HERNANDEZ, Oscar`|`individual`|`CUBA`|``|``|`Unknown vessel type`|``|``|``|`Acechilly Navigation Co., Malta`|``|`123 Somewhere Ln`|`Clearwater`|`United States`|``|`aka`|`Alternate Name`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
5
|
+
``|`LOPEZ MENDEZ, Luis Eduardo`|`individual`|`CUBA`|``|``|`Unknown vessel type`|``|``|``|`Acefrosty Shipping Co., Malta`|``|``|``|``|``|``|``|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
6
|
+
``|`ACEFROSTY SHIPPING CO., LTD.`|``|`CUBA`|``|``|``|``|``|``|``|``|``|``|``|``|`aka`|`AVIA IMPORT`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
7
|
+
``|`AEROCARIBBEAN AIRLINES`|``|`CUBA`|``|``|``|``|``|``|``|``|``|``|``|``|`aka`|`BNC`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
8
|
+
``|`AEROCARIBBEAN AIRLINES`|``|`CUBA`|``|``|``|``|``|``|``|``|``|``|``|``|`aka`|`NATIONAL BANK OF CUBA`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
9
|
+
``|`AEROCARIBBEAN AIRLINES`|``|`CUBA`|``|``|``|``|``|``|``|``|``|``|``|``|`aka`|`BNC`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
10
|
+
``|`AEROTAXI EJECUTIVO, S.A.`|``|`CUBA`|``|``|``|``|``|``|``|``|``|`Managua`|`Nicaragua`|``|``|``|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
11
|
+
``|`AEROTAXI EJECUTIVO, S.A.`|``|`CUBA`|``|``|``|``|``|``|``|``|`Bal Harbour Shopping Center, Via Italia`|`Panama City`|`Panama`|``|``|``|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
12
|
+
``|`AGENCIA DE VIAJES GUAMA`|``|`CUBA`|``|``|``|``|``|``|``|``|`Avenida de Concha, Espina 8, E-28036`|`Madrid`|`Spain`|``|`aka`|`NATIONAL BANK OF CUBA`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
13
|
+
``|`AGENCIA DE VIAJES GUAMA`|``|`CUBA`|``|``|``|``|``|``|``|``|``|``|``|``|`aka`|`NATIONAL BANK OF CUBA`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
14
|
+
``|`AGUIAR, Raul`|`individual`|`CUBA`|`Director, Banco Nacional de Cuba`|``|``|``|``|``|``|`; Director, Banco Nacional de Cuba.`|``|``|`Italy`|``|`aka`|`BNC`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
15
|
+
``|`AGUIAR, Raul`|`individual`|`CUBA`|`Director, Banco Nacional de Cuba`|``|``|``|``|``|``|`; Director, Banco Nacional de Cuba.`|``|``|`Italy`|``|`aka`|`NATIONAL BANK OF CUBA`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
16
|
+
``|`AGUIAR, Raul`|`individual`|`CUBA`|`Director, Banco Nacional de Cuba`|``|``|``|``|``|``|`; Director, Banco Nacional de Cuba.`|``|``|`Panama`|``|`aka`|`BNC`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
17
|
+
``|`AGUIAR, Raul`|`individual`|`CUBA`|`Director, Banco Nacional de Cuba`|``|``|``|``|``|``|`; Director, Banco Nacional de Cuba.`|``|``|`Panama`|``|`aka`|`NATIONAL BANK OF CUBA`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
18
|
+
``|`AGUIAR, Raul`|`individual`|`CUBA`|`Director, Banco Nacional de Cuba`|``|``|``|``|``|``|`; Director, Banco Nacional de Cuba.`|`1840 West 49th Street`|``|`United States`|``|`aka`|`BNC`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
19
|
+
``|`AGUIAR, Raul`|`individual`|`CUBA`|`Director, Banco Nacional de Cuba`|``|``|``|``|``|``|`; Director, Banco Nacional de Cuba.`|`1840 West 49th Street`|``|`United States`|``|`aka`|`NATIONAL BANK OF CUBA`|``|`2009-05-06 15:55:24`|`2009-05-06 15:55:24`
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'ofac/models/ofac_sdn_loader'
|
2
|
+
|
3
|
+
class OfacSdnLoader
|
4
|
+
|
5
|
+
def self.load_current_sdn_file
|
6
|
+
sdn = File.new(File.dirname(__FILE__) + '/../../files/test_sdn_data_load.pip')
|
7
|
+
address = File.new(File.dirname(__FILE__) + '/../../files/test_address_data_load.pip')
|
8
|
+
alt = File.new(File.dirname(__FILE__) + '/../../files/test_alt_data_load.pip')
|
9
|
+
active_record_file_load(sdn, address, alt)
|
10
|
+
sdn.close
|
11
|
+
address.close
|
12
|
+
alt.close
|
13
|
+
end
|
14
|
+
|
15
|
+
#Gives access to the private convert_to_flattened_csv method
|
16
|
+
def self.create_csv_file(sdn, address, alt)
|
17
|
+
convert_to_flattened_csv(sdn, address, alt)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class OfacSdnLoaderTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context '' do
|
6
|
+
setup do setup_ofac_sdn_table end
|
7
|
+
|
8
|
+
should "load table from files multiple times and always have the same record count" do
|
9
|
+
assert_equal(0,OfacSdn.count)
|
10
|
+
OfacSdnLoader.load_current_sdn_file #this method is mocked to load test files instead of the live files from the web.
|
11
|
+
assert_equal(19, OfacSdn.count)
|
12
|
+
OfacSdnLoader.load_current_sdn_file
|
13
|
+
assert_equal(19, OfacSdn.count)
|
14
|
+
end
|
15
|
+
|
16
|
+
should "create flattened_csv_file_for_mysql_import" do
|
17
|
+
#since, I'm using sqlight3 for it's in memory db, I can't test the mysql load
|
18
|
+
#but I can test the csv file creation.
|
19
|
+
sdn = File.new(File.dirname(__FILE__) + '/files/test_sdn_data_load.pip')
|
20
|
+
address = File.new(File.dirname(__FILE__) + '/files/test_address_data_load.pip')
|
21
|
+
alt = File.new(File.dirname(__FILE__) + '/files/test_alt_data_load.pip')
|
22
|
+
|
23
|
+
csv = OfacSdnLoader.create_csv_file(sdn, address, alt) #this method was created in the mock only to call the private convert_to_flattened_csv method
|
24
|
+
correctly_formatted_csv = File.open(File.dirname(__FILE__) + '/files/valid_flattened_file.csv')
|
25
|
+
|
26
|
+
csv.rewind
|
27
|
+
generated_file = csv.readlines
|
28
|
+
#compare the values of each csv line, with the correctly formated "control file"
|
29
|
+
correctly_formatted_csv.each_with_index do |line,i|
|
30
|
+
csv_line = generated_file[i]
|
31
|
+
correctly_formatted_record_array = line.split('|')
|
32
|
+
csv_record_array = csv_line.split('|')
|
33
|
+
(0..18).each do |i| #skip indices 19 and 20, they are the created_at and updated_at fields, they will never match.
|
34
|
+
assert_equal correctly_formatted_record_array[i], csv_record_array[i]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
data/test/ofac_test.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class OfacTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context '' do
|
6
|
+
setup do
|
7
|
+
setup_ofac_sdn_table
|
8
|
+
OfacSdnLoader.load_current_sdn_file #this method is mocked to load test files instead of the live files from the web.
|
9
|
+
end
|
10
|
+
|
11
|
+
should "give a score of 0 if no name is given" do
|
12
|
+
assert_equal 0, Ofac.new({:address => '123 somewhere'}).score
|
13
|
+
assert_equal 0, Ofac.new({:name => ''}).score
|
14
|
+
assert_equal 0, Ofac.new({:name => ' '}).score
|
15
|
+
assert_equal 0, Ofac.new({:name => nil}).score
|
16
|
+
assert_equal 0, Ofac.new({:name => {:first_name => '',:last_name => ' '}}).score
|
17
|
+
assert_equal 0, Ofac.new({:name => {:first_name => '',:last_name => ' '}}).score
|
18
|
+
assert_equal 0, Ofac.new({:name => 'P T'}).score
|
19
|
+
end
|
20
|
+
|
21
|
+
should "give a score of 0 if there is no name match" do
|
22
|
+
assert_equal 0, Ofac.new({:name => 'Kevin T P'}).score
|
23
|
+
assert_equal 0, Ofac.new({:name => "O'Brian"}).score
|
24
|
+
assert_equal 0, Ofac.new({:name => {:first_name => 'Matthew',:last_name => "O'Brian"}}).score
|
25
|
+
assert_equal 0, Ofac.new({:name => 'Kevin', :address => '123 somewhere ln', :city => 'Clearwater'}).score
|
26
|
+
end
|
27
|
+
|
28
|
+
should "give a score of 60 if there is a name match and deduct scores for non matches on address and city" do
|
29
|
+
assert_equal 60, Ofac.new({:name => 'Oscar Hernandez'}).score
|
30
|
+
assert_equal 60, Ofac.new({:name => {:first_name => 'Oscar', :last_name => 'Hernandez'}}).score
|
31
|
+
end
|
32
|
+
|
33
|
+
should "give a score of 30 if there is only a partial match" do
|
34
|
+
assert_equal 30, Ofac.new({:name => 'Oscar de la Hernandez'}).score
|
35
|
+
assert_equal 30, Ofac.new({:name => {:first_name => 'Oscar', :last_name => 'de la Hernandez'}}).score
|
36
|
+
end
|
37
|
+
|
38
|
+
should "handle first or last name not given" do
|
39
|
+
assert_equal 60, Ofac.new({:name => {:first_name => 'Oscar', :last_name => ''}}).score
|
40
|
+
assert_equal 60, Ofac.new({:name => {:first_name => 'Oscar', :last_name => nil}}).score
|
41
|
+
assert_equal 60, Ofac.new({:name => {:first_name => nil, :last_name => 'Oscar'}}).score
|
42
|
+
assert_equal 60, Ofac.new({:name => {:first_name => 'Oscar'}}).score
|
43
|
+
assert_equal 60, Ofac.new({:name => {:first_name => '', :last_name => 'Oscar'}}).score
|
44
|
+
assert_equal 60, Ofac.new({:name => {:last_name => 'Oscar'}}).score
|
45
|
+
end
|
46
|
+
|
47
|
+
should "deduct scores for non matches on address if data is in the database" do
|
48
|
+
#if there is data for address or city in the database, and that info is passed in, then 10%
|
49
|
+
#of the weight will be deducted if there is no match or sounds like match
|
50
|
+
|
51
|
+
#name and city match
|
52
|
+
assert_equal 89, Ofac.new({:name => 'Oscar Hernandez', :city => 'Clearwater', :address => 'no match'}).score
|
53
|
+
#the record is pulled because clear is like clearwater, but it's not a match
|
54
|
+
#score = 60 for name - (30 * .1) for Clear = 57
|
55
|
+
assert_equal 57, Ofac.new({:name => 'Oscar Hernandez', :city => 'Clear'}).score
|
56
|
+
end
|
57
|
+
|
58
|
+
should "not deduct from score if no data for city or address is in the database" do
|
59
|
+
assert_equal 60, Ofac.new({:name => 'Luis Lopez', :city => 'no match', :address => 'no match'}).score
|
60
|
+
end
|
61
|
+
|
62
|
+
should "give a score of 60 if there is a name match on alternate identity name" do
|
63
|
+
assert_equal 60, Ofac.new({:name => 'Alternate Name'}).score
|
64
|
+
end
|
65
|
+
|
66
|
+
should "give a partial score if there is a partial name match" do
|
67
|
+
assert_equal 40, Ofac.new({:name => 'Oscar middlename Hernandez'}).score
|
68
|
+
assert_equal 30, Ofac.new({:name => 'Oscar WrongLastName'}).score
|
69
|
+
assert_equal 70, Ofac.new({:name => 'Oscar middlename Hernandez',:city => 'Clearwater'}).score
|
70
|
+
end
|
71
|
+
|
72
|
+
should "give a score of 90 if there is a name and city match" do
|
73
|
+
assert_equal 90, Ofac.new({:name => 'Oscar Hernandez', :city => 'Clearwater'}).score
|
74
|
+
end
|
75
|
+
|
76
|
+
should "give a score of 100 if there is a name and city and address match" do
|
77
|
+
assert_equal 100, Ofac.new({:name => 'Oscar Hernandez', :city => 'Clearwater', :address => '123 somewhere ln'}).score
|
78
|
+
end
|
79
|
+
|
80
|
+
should "give partial scores for sounds like matches" do
|
81
|
+
|
82
|
+
#32456 summer lane sounds like 32456 Somewhere ln so is adds 75% of the address weight to the score, or 8.
|
83
|
+
assert_equal 98, Ofac.new({:name => 'Oscar Hernandez', :city => 'Clearwater', :address => '32456 summer lane'}).score
|
84
|
+
|
85
|
+
#Louis Eduardo Lopez Mendez sounds like Luis Eduardo Lopez Mendez:
|
86
|
+
#:name has a weight of 60, so a sounds like is worth 45
|
87
|
+
assert_equal 45, Ofac.new({:name => {:first_name => 'Louis Eduardo', :last_name => 'Lopez Mendez'}, :city => 'Las Vegas', :address => 'no match'}).score
|
88
|
+
end
|
89
|
+
|
90
|
+
should 'not give partial scores if sounds like does not match the entire string' do
|
91
|
+
#summer sounds like somewhere, and all numbers sound alike, so 2 of the 3 address elements match by sound
|
92
|
+
#but the whole thing does not make a sounds like match so only city matches, subtract 1 for no address match
|
93
|
+
assert_equal 89, Ofac.new({:name => 'Oscar Hernandez', :city => 'Clearwater', :address => '12358 summer blvd'}).score
|
94
|
+
end
|
95
|
+
|
96
|
+
should "return an array of possible hits" do
|
97
|
+
#it should not matter which order you call score or possible hits.
|
98
|
+
sdn = Ofac.new({:name => 'Oscar Hernandez', :city => 'Clearwater', :address => '123 somewhere ln'})
|
99
|
+
assert sdn.score > 0
|
100
|
+
assert !sdn.possible_hits.empty?
|
101
|
+
|
102
|
+
sdn = Ofac.new({:name => 'Oscar Hernandez', :city => 'Clearwater', :address => '123 somewhere ln'})
|
103
|
+
assert !sdn.possible_hits.empty?
|
104
|
+
assert sdn.score > 0
|
105
|
+
end
|
106
|
+
|
107
|
+
should "db_hit? should return true if name is an exact match in the database" do
|
108
|
+
|
109
|
+
sdn = Ofac.new({:name => {:first_name => 'Oscar', :last_name => 'Hernandez'}, :city => 'Clearwater', :address => '123 somewhere ln'})
|
110
|
+
assert sdn.db_hit?
|
111
|
+
|
112
|
+
sdn = Ofac.new({:name => 'Oscar Hernandez', :city => 'Clearwater', :address => '123 somewhere ln'})
|
113
|
+
assert sdn.db_hit?
|
114
|
+
|
115
|
+
#single initials are ignored
|
116
|
+
sdn = Ofac.new({:name => 'Oscar M Hernandez', :city => 'Clearwater', :address => '123 somewhere ln'})
|
117
|
+
assert sdn.db_hit?
|
118
|
+
|
119
|
+
#city and address are ignored
|
120
|
+
sdn = Ofac.new({:name => 'Oscar Hernandez', :city => 'bad city', :address => 'bad address'})
|
121
|
+
assert sdn.db_hit?
|
122
|
+
end
|
123
|
+
|
124
|
+
should "db_hit? should return false if name is not an exact match in the database" do
|
125
|
+
|
126
|
+
sdn = Ofac.new({:name => {:first_name => 'Oscar', :last_name => 'de la Hernandez'}, :city => 'Clearwater', :address => '123 somewhere ln'})
|
127
|
+
assert !sdn.db_hit?
|
128
|
+
|
129
|
+
sdn = Ofac.new({:name => 'Oscar Maria Hernandez', :city => 'Clearwater', :address => '123 somewhere ln'})
|
130
|
+
assert !sdn.db_hit?
|
131
|
+
|
132
|
+
#city and address are ignored
|
133
|
+
sdn = Ofac.new({:name => 'Oscar de la Hernandez', :city => 'bad city', :address => 'bad address'})
|
134
|
+
assert !sdn.db_hit?
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'mocks/test/ofac_sdn_loader'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
require 'ofac'
|
9
|
+
|
10
|
+
ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
|
11
|
+
|
12
|
+
class Test::Unit::TestCase
|
13
|
+
def setup_ofac_sdn_table
|
14
|
+
ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
|
15
|
+
create_ofac_sdn_table
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def create_ofac_sdn_table
|
21
|
+
silence_stream(STDOUT) do
|
22
|
+
ActiveRecord::Schema.define(:version => 1) do
|
23
|
+
create_table :ofac_sdns do |t|
|
24
|
+
t.text :name
|
25
|
+
t.string :sdn_type
|
26
|
+
t.string :program
|
27
|
+
t.string :title
|
28
|
+
t.string :vessel_call_sign
|
29
|
+
t.string :vessel_type
|
30
|
+
t.string :vessel_tonnage
|
31
|
+
t.string :gross_registered_tonnage
|
32
|
+
t.string :vessel_flag
|
33
|
+
t.string :vessel_owner
|
34
|
+
t.text :remarks
|
35
|
+
t.text :address
|
36
|
+
t.string :city
|
37
|
+
t.string :country
|
38
|
+
t.string :address_remarks
|
39
|
+
t.string :alternate_identity_type
|
40
|
+
t.text :alternate_identity_name
|
41
|
+
t.string :alternate_identity_remarks
|
42
|
+
t.timestamps
|
43
|
+
end
|
44
|
+
add_index :ofac_sdns, :sdn_type
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ofac
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.11
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kevin Tyll
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-02-05 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Attempts to find a hit on the Office of Foreign Assets Control's Specially Designated Nationals list.
|
17
|
+
email: kevintyll@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- .document
|
27
|
+
- .gitignore
|
28
|
+
- History.txt
|
29
|
+
- LICENSE
|
30
|
+
- PostInstall.txt
|
31
|
+
- README.rdoc
|
32
|
+
- Rakefile
|
33
|
+
- VERSION.yml
|
34
|
+
- generators/ofac_migration/.DS_Store
|
35
|
+
- generators/ofac_migration/ofac_migration_generator.rb
|
36
|
+
- generators/ofac_migration/templates/.DS_Store
|
37
|
+
- generators/ofac_migration/templates/migration.rb
|
38
|
+
- lib/ofac.rb
|
39
|
+
- lib/ofac/models/ofac.rb
|
40
|
+
- lib/ofac/models/ofac_sdn.rb
|
41
|
+
- lib/ofac/models/ofac_sdn_loader.rb
|
42
|
+
- lib/ofac/ofac_match.rb
|
43
|
+
- lib/ofac/ruby_string_extensions.rb
|
44
|
+
- lib/tasks/ofac.rake
|
45
|
+
- nbproject/project.properties
|
46
|
+
- nbproject/project.xml
|
47
|
+
- ofac.gemspec
|
48
|
+
- pkg/ofac-0.1.0.gem
|
49
|
+
- pkg/ofac-1.0.0.gem
|
50
|
+
- rdoc/classes/Ofac.html
|
51
|
+
- rdoc/classes/OfacMatch.html
|
52
|
+
- rdoc/classes/OfacSdn.html
|
53
|
+
- rdoc/classes/OfacSdnLoader.html
|
54
|
+
- rdoc/classes/String.html
|
55
|
+
- rdoc/created.rid
|
56
|
+
- rdoc/files/README_rdoc.html
|
57
|
+
- rdoc/files/lib/ofac/models/ofac_rb.html
|
58
|
+
- rdoc/files/lib/ofac/models/ofac_sdn_loader_rb.html
|
59
|
+
- rdoc/files/lib/ofac/models/ofac_sdn_rb.html
|
60
|
+
- rdoc/files/lib/ofac/ofac_match_rb.html
|
61
|
+
- rdoc/files/lib/ofac/ruby_string_extensions_rb.html
|
62
|
+
- rdoc/files/lib/ofac_rb.html
|
63
|
+
- rdoc/fr_class_index.html
|
64
|
+
- rdoc/fr_file_index.html
|
65
|
+
- rdoc/fr_method_index.html
|
66
|
+
- rdoc/index.html
|
67
|
+
- rdoc/rdoc-style.css
|
68
|
+
- test/files/test_address_data_load.pip
|
69
|
+
- test/files/test_alt_data_load.pip
|
70
|
+
- test/files/test_sdn_data_load.pip
|
71
|
+
- test/files/valid_flattened_file.csv
|
72
|
+
- test/mocks/test/ofac_sdn_loader.rb
|
73
|
+
- test/ofac_sdn_loader_test.rb
|
74
|
+
- test/ofac_test.rb
|
75
|
+
- test/test_helper.rb
|
76
|
+
has_rdoc: true
|
77
|
+
homepage: http://github.com/kevintyll/ofac
|
78
|
+
licenses: []
|
79
|
+
|
80
|
+
post_install_message: |-
|
81
|
+
For more information on ofac, see http://kevintyll.github.com/ofac/
|
82
|
+
|
83
|
+
* To create the necessary db migration, from the command line, run:
|
84
|
+
script/generate ofac_migration
|
85
|
+
* Require the gem in your environment.rb file in the Rails::Initializer block:
|
86
|
+
config.gem 'kevintyll-ofac', :lib => 'ofac'
|
87
|
+
* To load your table with the current OFAC data, from the command line, run:
|
88
|
+
rake ofac:update_data
|
89
|
+
|
90
|
+
* The OFAC data is not updated with any regularity, but you can sign up for email notifications when the data changes at
|
91
|
+
http://www.treas.gov/offices/enforcement/ofac/sdn/index.shtml.
|
92
|
+
rdoc_options:
|
93
|
+
- --charset=UTF-8
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: "0"
|
101
|
+
version:
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: "0"
|
107
|
+
version:
|
108
|
+
requirements: []
|
109
|
+
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 1.3.5
|
112
|
+
signing_key:
|
113
|
+
specification_version: 3
|
114
|
+
summary: Attempts to find a hit on the Office of Foreign Assets Control's Specially Designated Nationals list.
|
115
|
+
test_files:
|
116
|
+
- test/mocks/test/ofac_sdn_loader.rb
|
117
|
+
- test/ofac_sdn_loader_test.rb
|
118
|
+
- test/ofac_test.rb
|
119
|
+
- test/test_helper.rb
|