diff --git a/app/controllers/admin/signature_sheets_controller.rb b/app/controllers/admin/signature_sheets_controller.rb new file mode 100644 index 000000000..83d1e93ce --- /dev/null +++ b/app/controllers/admin/signature_sheets_controller.rb @@ -0,0 +1,33 @@ +class Admin::SignatureSheetsController < Admin::BaseController + + def index + @signature_sheets = SignatureSheet.all + end + + def new + @signature_sheet = SignatureSheet.new + end + + def create + @signature_sheet = SignatureSheet.new(signature_sheet_params) + @signature_sheet.author = current_user + if @signature_sheet.save + @signature_sheet.delay.verify_signatures + redirect_to [:admin, @signature_sheet] + else + render :new + end + end + + def show + @signature_sheet = SignatureSheet.find(params[:id]) + @invalid_signatures = @signature_sheet.invalid_signatures + end + + private + + def signature_sheet_params + params.require(:signature_sheet).permit(:signable_type, :signable_id, :document_numbers) + end + +end \ No newline at end of file diff --git a/app/helpers/signature_sheets_helper.rb b/app/helpers/signature_sheets_helper.rb new file mode 100644 index 000000000..14424639c --- /dev/null +++ b/app/helpers/signature_sheets_helper.rb @@ -0,0 +1,8 @@ +module SignatureSheetsHelper + + def signable_options + [[t("activerecord.models.proposal", count: 1), Proposal], + [t("activerecord.models.spending_proposal", count: 1), SpendingProposal]] + end + +end \ No newline at end of file diff --git a/app/models/proposal.rb b/app/models/proposal.rb index 7bd4b7a92..fd828c31e 100644 --- a/app/models/proposal.rb +++ b/app/models/proposal.rb @@ -122,9 +122,9 @@ class Proposal < ActiveRecord::Base retired_at.present? end - def register_vote(user, vote_value) + def register_vote(user, vote_value, signature=nil) if votable_by?(user) && !archived? - vote_by(voter: user, vote: vote_value) + vote_by(voter: user, vote: vote_value, vote_scope: signature) end end diff --git a/app/models/signature.rb b/app/models/signature.rb new file mode 100644 index 000000000..3a1d197eb --- /dev/null +++ b/app/models/signature.rb @@ -0,0 +1,72 @@ +class Signature < ActiveRecord::Base + belongs_to :signature_sheet + belongs_to :user + + validate :in_census + validate :not_already_voted + + scope :valid, -> { where(status: 'verified') } + scope :invalid, -> { where.not(status: 'verified') } + + def in_census + return true if user_exists? + errors.add(:document_number, :not_in_census) unless in_census? + end + + def not_already_voted + errors.add(:document_number, :already_voted) if already_voted? + end + + def verify + if valid? + assign_vote + update_attribute(:status, 'verified') + else + error = errors.messages[:document_number].first + update_attribute(:status, error) + end + end + + private + + def assign_vote + if user_exists? + assign_vote_to_user + else + create_user + assign_vote_to_user + end + end + + def assign_vote_to_user + signable.register_vote(user, "yes", "signature") + #Vote.create(votable: signable, voter: user, signature: self) + end + + def user_exists? + user = User.where(document_number: document_number).exists? + end + + def create_user + user = User.where(document_number: document_number, erased_at: Time.now).create + end + + def in_census? + document_types.any? do |document_type| + CensusApi.new.call(document_type, document_number).valid? + end + end + + def already_voted? + signable.voters.where(document_number: document_number).exists? + end + + def signable + signature_sheet.signable + end + + def document_types + %w(1 2 3 4) + end + +end \ No newline at end of file diff --git a/app/models/signature_sheet.rb b/app/models/signature_sheet.rb new file mode 100644 index 000000000..7829833a3 --- /dev/null +++ b/app/models/signature_sheet.rb @@ -0,0 +1,43 @@ +class SignatureSheet < ActiveRecord::Base + belongs_to :signable, polymorphic: true + belongs_to :author, class_name: 'User', foreign_key: 'author_id' + + VALID_SIGNABLES = %w( Proposal SpendingProposal ) + + has_many :signatures + + validates :author, presence: true + validates :signable_type, inclusion: {in: VALID_SIGNABLES} + validates :document_numbers, presence: true + validates :signable, presence: true + validate :signable_found + + def name + "#{signable_name} + #{signable_id}" + end + + def signable_name + I18n.t("activerecord.models.#{signable_type.underscore}", count: 1) + end + + def verify_signatures + parsed_document_numbers.each do |document_number| + signature = signatures.new(document_number: document_number) + signature.save(validate: false) + signature.verify + end + update(processed: true) + end + + def invalid_signatures + signatures.invalid.group_by(&:status) + end + + def parsed_document_numbers + document_numbers.split(",") + end + + def signable_found + errors.add(:signable_id, :not_found) if errors.messages[:signable].present? + end +end \ No newline at end of file diff --git a/app/models/spending_proposal.rb b/app/models/spending_proposal.rb index 223e9adfe..111f4c3dd 100644 --- a/app/models/spending_proposal.rb +++ b/app/models/spending_proposal.rb @@ -125,13 +125,17 @@ class SpendingProposal < ActiveRecord::Base return :organization if user.organization? end + def voters + User.active.where(id: votes_for.voters) + end + def votable_by?(user) reason_for_not_being_votable_by(user).blank? end - def register_vote(user, vote_value) + def register_vote(user, vote_value, signature=nil) if votable_by?(user) - vote_by(voter: user, vote: vote_value) + vote_by(voter: user, vote: vote_value, vote_scope: signature) end end diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb index 3d3e807c7..3cdb057fb 100644 --- a/app/views/admin/_menu.html.erb +++ b/app/views/admin/_menu.html.erb @@ -35,6 +35,14 @@ <% end %> + <% if feature?(:signature_sheets) %> +
| <%= t("admin.signature_sheet.name") %> | +<%= t("admin.signature_sheet.author") %> | +<%= t("admin.signature_sheet.created_at") %> | +
|---|---|---|
| + <%= link_to signature_sheet.name, [:admin, signature_sheet] %> + | ++ <%= signature_sheet.author.name %> + | ++ <%= l(signature_sheet.created_at, format: :short) %> + | +