diff --git a/app/controllers/officing/base_controller.rb b/app/controllers/officing/base_controller.rb index 271f62daa..97ef23d30 100644 --- a/app/controllers/officing/base_controller.rb +++ b/app/controllers/officing/base_controller.rb @@ -7,6 +7,6 @@ class Officing::BaseController < ApplicationController skip_authorization_check def verify_officer - raise CanCan::AccessDenied unless current_user.try(:poll_officer?) || current_user.try(:administrator?) - end + raise CanCan::AccessDenied unless current_user.try(:poll_officer?) || current_user.try(:administrator?) + end end \ No newline at end of file diff --git a/app/controllers/officing/residence_controller.rb b/app/controllers/officing/residence_controller.rb new file mode 100644 index 000000000..768bac21f --- /dev/null +++ b/app/controllers/officing/residence_controller.rb @@ -0,0 +1,21 @@ +class Officing::ResidenceController < Officing::BaseController + + def new + @residence = Officing::Residence.new + end + + def create + @residence = Officing::Residence.new(residence_params) + if @residence.save + redirect_to new_officing_voter_path(id: @residence.user.id), notice: t("officing.residence.flash.create") + else + render :new + end + end + + private + + def residence_params + params.require(:residence).permit(:document_number, :document_type, :date_of_birth) + end +end \ No newline at end of file diff --git a/app/controllers/officing/voters_controller.rb b/app/controllers/officing/voters_controller.rb index 6cf321beb..bb16a1412 100644 --- a/app/controllers/officing/voters_controller.rb +++ b/app/controllers/officing/voters_controller.rb @@ -1,6 +1,25 @@ class Officing::VotersController < Officing::BaseController + respond_to :html, :js def new + @user = User.find(params[:id]) + @polls = Poll.current # fix and use answerable_by(@user) end + def create + @poll = Poll.find(voter_params[:poll_id]) + @user = User.find(voter_params[:user_id]) + @voter = Poll::Voter.new(document_type: @user.document_type, + document_number: @user.document_number, + user: @user, + poll: @poll) + @voter.save! + end + + private + + def voter_params + params.require(:voter).permit(:poll_id, :user_id) + end + end \ No newline at end of file diff --git a/app/models/officing/residence.rb b/app/models/officing/residence.rb new file mode 100644 index 000000000..2a8cca51d --- /dev/null +++ b/app/models/officing/residence.rb @@ -0,0 +1,107 @@ +class Officing::Residence + include ActiveModel::Model + include ActiveModel::Dates + include ActiveModel::Validations::Callbacks + + attr_accessor :user, :officer, :document_number, :document_type, :date_of_birth + + before_validation :call_census_api + + validates_presence_of :document_number + validates_presence_of :document_type + validates_presence_of :date_of_birth + + validate :allowed_age + validate :residence_in_madrid + + def initialize(attrs={}) + self.date_of_birth = parse_date('date_of_birth', attrs) + attrs = remove_date('date_of_birth', attrs) + super + clean_document_number + end + + def save + return false unless valid? + + if user_exists? + self.user = find_user_by_document + else + user_params = { + document_number: document_number, + document_type: document_type, + geozone: self.geozone, + date_of_birth: date_of_birth.to_datetime, + gender: gender, + residence_verified_at: Time.current, + verified_at: Time.current, + erased_at: Time.current, + password: random_password, + terms_of_service: '1', + email: nil + } + self.user = User.create!(user_params) + end + end + + def user_exists? + find_user_by_document.present? + end + + def find_user_by_document + User.where(document_number: document_number, + document_type: document_type).first + end + + def residence_in_madrid + return if errors.any? + + unless residency_valid? + errors.add(:residence_in_madrid, false) + end + end + + def allowed_age + return if errors[:date_of_birth].any? + + unless allowed_age? + errors.add(:date_of_birth, I18n.t('verification.residence.new.error_not_allowed_age')) + end + end + + def allowed_age? + self.date_of_birth <= User.minimum_required_age.years.ago + end + + def geozone + Geozone.where(census_code: district_code).first + end + + def district_code + @census_api_response.district_code + end + + def gender + @census_api_response.gender + end + + private + + def call_census_api + @census_api_response = CensusApi.new.call(document_type, document_number) + end + + def residency_valid? + @census_api_response.valid? && + @census_api_response.date_of_birth == date_of_birth + end + + def clean_document_number + self.document_number = self.document_number.gsub(/[^a-z0-9]+/i, "").upcase unless self.document_number.blank? + end + + def random_password + (0...20).map { ('a'..'z').to_a[rand(26)] }.join + end + +end diff --git a/app/models/poll.rb b/app/models/poll.rb index c5da9dcd0..761a4561f 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -44,6 +44,10 @@ class Poll < ActiveRecord::Base current.joins(:geozones).where('geozone_restricted = ? or geozones.id = ?', false, user.geozone_id) end + def votable_by?(user) + !document_has_voted?(user.document_number, user.document_type) + end + def document_has_voted?(document_number, document_type) voters.where(document_number: document_number, document_type: document_type).exists? end diff --git a/app/models/poll/answer.rb b/app/models/poll/answer.rb index 84359e330..52fb11469 100644 --- a/app/models/poll/answer.rb +++ b/app/models/poll/answer.rb @@ -14,6 +14,6 @@ class Poll::Answer < ActiveRecord::Base scope :by_question, -> (question_id) { where(question_id: question_id) } def record_voter_participation - Poll::Voter.create_from_user(author, {poll_id: poll_id}) + Poll::Voter.create!(user: author, poll: poll) end end \ No newline at end of file diff --git a/app/models/poll/voter.rb b/app/models/poll/voter.rb index 087771a02..1cb8083c2 100644 --- a/app/models/poll/voter.rb +++ b/app/models/poll/voter.rb @@ -1,45 +1,54 @@ class Poll class Voter < ActiveRecord::Base belongs_to :poll + belongs_to :user + belongs_to :geozone belongs_to :booth_assignment belongs_to :officer_assignment - validates :poll, presence: true + validates :poll_id, presence: true + validates :user_id, presence: true + validates :geozone_id, presence: true + validates :gender, presence: true + validates :age, presence: true + validates :document_number, presence: true, uniqueness: { scope: [:poll_id, :document_type], message: :has_voted } - def census_api_response - @census_api_response ||= CensusApi.new.call(document_type, document_number) + before_validation :set_demographic_info, :set_document_info + + def set_demographic_info + return unless user.present? + + self.gender = user.gender + self.age = user.age + self.geozone = user.geozone end - def in_census? - census_api_response.valid? - end + def set_document_info + return unless user.present? - def fill_stats_fields - if in_census? - self.gender = census_api_response.gender - self.geozone_id = Geozone.select(:id).where(census_code: census_api_response.district_code).first.try(:id) - self.age = voter_age(census_api_response.date_of_birth) - end - end - - def self.create_from_user(user, options = {}) - poll_id = options[:poll_id] - booth_assignment_id = options[:booth_assignment_id] - - Voter.create( - document_type: user.document_type, - document_number: user.document_number, - poll_id: poll_id, - booth_assignment_id: booth_assignment_id, - gender: user.gender, - geozone_id: user.geozone_id, - age: user.age - ) + self.document_type = user.document_type + self.document_number = user.document_number end private + def in_census? + census_api_response.valid? + end + + def census_api_response + @census_api_response ||= CensusApi.new.call(document_type, document_number) + end + + def fill_stats_fields + if in_census? + self.gender = census_api_response.gender + self.geozone_id = Geozone.select(:id).where(census_code: census_api_response.district_code).first.try(:id) + self.age = voter_age(census_api_response.date_of_birth) + end + end + def voter_age(dob) if dob.blank? nil diff --git a/app/views/officing/_menu.html.erb b/app/views/officing/_menu.html.erb index d999fc06b..40484a90a 100644 --- a/app/views/officing/_menu.html.erb +++ b/app/views/officing/_menu.html.erb @@ -2,7 +2,7 @@