Merge pull request #1752 from MariaCheca/1725-census_local_copy_user_verification

Allow users to verify their account against a local copy of the Census
This commit is contained in:
BertoCQ
2017-07-21 11:36:29 +02:00
committed by GitHub
14 changed files with 226 additions and 16 deletions

View File

@@ -0,0 +1,6 @@
class LocalCensusRecord < ActiveRecord::Base
validates :document_number, presence: true
validates :document_type, presence: true
validates :date_of_birth, presence: true
validates :postal_code, presence: true
end

View File

@@ -4,7 +4,7 @@ class Officing::Residence
attr_accessor :user, :officer, :document_number, :document_type, :year_of_birth
before_validation :call_census_api
before_validation :retrieve_census_data
validates :document_number, presence: true
validates :document_type, presence: true
@@ -101,8 +101,8 @@ class Officing::Residence
private
def call_census_api
@census_api_response = CensusApi.new.call(document_type, document_number)
def retrieve_census_data
@census_api_response = CensusCaller.new.call(document_type, document_number)
end
def residency_valid?

View File

@@ -35,7 +35,7 @@ class Poll
end
def census_api_response
@census_api_response ||= CensusApi.new.call(document_type, document_number)
@census_api_response ||= CensusCaller.new.call(document_type, document_number)
end
def fill_stats_fields

View File

@@ -69,7 +69,7 @@ class Signature < ActiveRecord::Base
def in_census?
document_types.detect do |document_type|
response = CensusApi.new.call(document_type, document_number)
response = CensusCaller.new.call(document_type, document_number)
if response.valid?
@census_api_response = response
true
@@ -94,4 +94,4 @@ class Signature < ActiveRecord::Base
%w(1 2 3 4)
end
end
end

View File

@@ -18,7 +18,7 @@ class Verification::Management::Document
end
def in_census?
response = CensusApi.new.call(document_type, document_number)
response = CensusCaller.new.call(document_type, document_number)
response.valid? && valid_age?(response)
end

View File

@@ -5,7 +5,7 @@ class Verification::Residence
attr_accessor :user, :document_number, :document_type, :date_of_birth, :postal_code, :terms_of_service
before_validation :call_census_api
before_validation :retrieve_census_data
validates :document_number, presence: true
validates :document_type, presence: true
@@ -61,23 +61,23 @@ class Verification::Residence
end
def district_code
@census_api_response.district_code
@census_data.district_code
end
def gender
@census_api_response.gender
@census_data.gender
end
private
def call_census_api
@census_api_response = CensusApi.new.call(document_type, document_number)
def retrieve_census_data
@census_data = CensusCaller.new.call(document_type, document_number)
end
def residency_valid?
@census_api_response.valid? &&
@census_api_response.postal_code == postal_code &&
@census_api_response.date_of_birth == date_of_birth
@census_data.valid? &&
@census_data.postal_code == postal_code &&
@census_data.date_of_birth == date_of_birth
end
def clean_document_number

View File

@@ -0,0 +1,15 @@
class CreateLocalCensusRecords < ActiveRecord::Migration
def change
create_table :local_census_records do |t|
t.string :document_number, null: false
t.string :document_type, null: false
t.date :date_of_birth, null: false
t.string :postal_code, null: false
t.integer :user_id
t.timestamps null: false
end
add_foreign_key :local_census_records, :users, column: :user_id
end
end

View File

@@ -0,0 +1,5 @@
class RemoveLocalCensusRecordUserId < ActiveRecord::Migration
def change
remove_column :local_census_records, :user_id
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170708225159) do
ActiveRecord::Schema.define(version: 20170713110317) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -484,6 +484,15 @@ ActiveRecord::Schema.define(version: 20170708225159) do
add_index "legislation_questions", ["hidden_at"], name: "index_legislation_questions_on_hidden_at", using: :btree
add_index "legislation_questions", ["legislation_process_id"], name: "index_legislation_questions_on_legislation_process_id", using: :btree
create_table "local_census_records", force: :cascade do |t|
t.string "document_number", null: false
t.string "document_type", null: false
t.date "date_of_birth", null: false
t.string "postal_code", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "locks", force: :cascade do |t|
t.integer "user_id"
t.integer "tries", default: 0

9
lib/census_caller.rb Normal file
View File

@@ -0,0 +1,9 @@
class CensusCaller
def call(document_type, document_number)
response = CensusApi.new.call(document_type, document_number)
response = LocalCensus.new.call(document_type, document_number) unless response.valid?
response
end
end

66
lib/local_census.rb Normal file
View File

@@ -0,0 +1,66 @@
include DocumentParser
class LocalCensus
def call(document_type, document_number)
record = nil
get_document_number_variants(document_type, document_number).each do |variant|
record = Response.new(get_record(document_type, variant))
return record if record.valid?
end
record
end
class Response
def initialize(body)
@body = body
end
def valid?
@body.present? ? !@body.attributes.values.include?("" || nil) : false
end
def date_of_birth
@body.date_of_birth
end
def postal_code
@body.postal_code
end
def district_code
@body.district_code rescue nil
end
def gender
case @body.gender
when "Varón"
"male"
when "Mujer"
"female"
end
rescue NoMethodError
nil
end
def name
"#{@body.nombre} #{@body.apellido1}" rescue nil
end
private
def data
@body.attributes
end
end
private
def get_record(document_type, document_number)
LocalCensusRecord.find_by(document_type: document_type, document_number: document_number)
end
def is_dni?(document_type)
document_type.to_s == "1"
end
end

View File

@@ -1,4 +1,11 @@
FactoryGirl.define do
factory :local_census_record, class: 'LocalCensusRecord' do
document_number '12345678A'
document_type 1
date_of_birth Date.new(1970, 1, 31)
postal_code '28002'
end
sequence(:document_number) { |n| "#{n.to_s.rjust(8, '0')}X" }
factory :user do

View File

@@ -0,0 +1,38 @@
require 'rails_helper'
describe CensusCaller do
let(:api) { described_class.new }
describe '#call' do
it "returns data from local_census_records if census API is not available" do
census_api_response = CensusApi::Response.new({:get_habita_datos_response=>{:get_habita_datos_return=>{:datos_habitante=>{}, :datos_vivienda=>{}}}})
local_census_response = LocalCensus::Response.new(create(:local_census_record))
CensusApi.any_instance.stub(:call).and_return(census_api_response)
LocalCensus.any_instance.stub(:call).and_return(local_census_response)
allow(CensusApi).to receive(:call).with(1, "12345678A")
allow(LocalCensus).to receive(:call).with(1, "12345678A")
response = api.call(1, "12345678A")
expect(response).to eq(local_census_response)
end
it "returns data from census API if it's available and valid" do
census_api_response = CensusApi::Response.new({get_habita_datos_response: {get_habita_datos_return: {datos_habitante: {item: {fecha_nacimiento_string: "1-1-1980"}}}}})
local_census_response = LocalCensus::Response.new(create(:local_census_record))
CensusApi.any_instance.stub(:call).and_return(census_api_response)
LocalCensus.any_instance.stub(:call).and_return(local_census_response)
allow(CensusApi).to receive(:call).with(1, "12345678A")
allow(LocalCensus).to receive(:call).with(1, "12345678A")
response = api.call(1, "12345678A")
expect(response).to eq(census_api_response)
end
end
end

View File

@@ -0,0 +1,55 @@
require 'rails_helper'
describe LocalCensus do
let(:api) { described_class.new }
describe '#get_document_number_variants' do
it "trims and cleans up entry" do
expect(api.get_document_number_variants(2, ' 1 2@ 34')).to eq(['1234'])
end
it "returns only one try for passports & residence cards" do
expect(api.get_document_number_variants(2, '1234')).to eq(['1234'])
expect(api.get_document_number_variants(3, '1234')).to eq(['1234'])
end
it 'takes only the last 8 digits for dnis and resicence cards' do
expect(api.get_document_number_variants(1, '543212345678')).to eq(['12345678'])
end
it 'tries all the dni variants padding with zeroes' do
expect(api.get_document_number_variants(1, '0123456')).to eq(['123456', '0123456', '00123456'])
expect(api.get_document_number_variants(1, '00123456')).to eq(['123456', '0123456', '00123456'])
end
it 'adds upper and lowercase letter when the letter is present' do
expect(api.get_document_number_variants(1, '1234567A')).to eq(['1234567', '01234567', '1234567a', '1234567A', '01234567a', '01234567A'])
end
end
describe '#call' do
let(:invalid_body) { nil }
let(:valid_body) { create(:local_census_record) }
it "returns the response for the first valid variant" do
allow(api).to receive(:get_record).with(1, "00123456").and_return(invalid_body)
allow(api).to receive(:get_record).with(1, "123456").and_return(invalid_body)
expect(api).to receive(:get_record).with(1, "0123456").and_return(valid_body)
response = api.call(1, "123456")
expect(response).to be_valid
expect(response.date_of_birth).to eq(Date.new(1970, 1, 31))
end
it "returns the last failed response" do
expect(api).to receive(:get_record).with(1, "00123456").and_return(invalid_body)
expect(api).to receive(:get_record).with(1, "123456").and_return(invalid_body)
expect(api).to receive(:get_record).with(1, "0123456").and_return(invalid_body)
response = api.call(1, "123456")
expect(response).to_not be_valid
end
end
end