# frozen_string_literal: true module Decidim module Elections module Admin # This command gets called when a election is setup from the admin panel. class SetupElection < Rectify::Command # Public: Initializes the command. # # form - A SetupForm object with the information needed to setup the election def initialize(form) @form = form end # Public: Setup the Election. # # Broadcasts :ok if setup, :invalid otherwise. def call return broadcast(:invalid) if form.invalid? transaction do log_action update_election notify_trustee_about_election setup_election end broadcast(:ok, election) rescue StandardError => e broadcast(:invalid, e.message) end private attr_reader :form delegate :election, :bulletin_board, :current_organization, to: :form def questions @questions ||= election.questions end def answers Decidim::Elections::Answer.where(question: questions) end def trustees @trustees ||= Decidim::Elections::Trustee.where(id: form.trustee_ids).order(:id) end def update_election return if election.trustees.exists?(id: form.trustee_ids) election.trustees << trustees election.blocked_at = Time.current election.bb_created! end def election_data @election_data ||= begin ret = base_election_data election.participatory_space.try(:complete_election_data, election, ret) ret end end def base_election_data { trustees: trustees_data, default_locale: current_organization.default_locale, title: flatten_translations(election.title), start_date: election.start_time, end_date: election.end_time, questions: questions_data, answers: answers_data, ballot_styles: {} } end def trustees_data trustees.map do |trustee| { name: trustee.name, slug: trustee.bulletin_board_slug, public_key: JSON.parse(trustee.public_key) } end end def questions_data questions.map do |question| { slug: question.slug, weight: question.weight, max_selections: question.max_selections, title: flatten_translations(question.title), # the bulletin_board gem (ruby client) expects a description for the question # as development is in a separate repository, let's send an empty content for the moment description: {}, answers: question_answers_data(question) } end end def question_answers_data(question) question.answers.map do |answer| { slug: answer.slug, weight: answer.weight } end end def answers_data answers.map do |answer| { slug: answer.slug, title: flatten_translations(answer.title) } end end def setup_election bb_election = bulletin_board.create_election(election.id, election_data) raise StandardError, "Wrong status for the created election" if bb_election.status != "created" end def log_action Decidim.traceability.perform_action!( :setup, election, form.current_user, visibility: "all" ) end def notify_trustee_about_election trustee = trustees.collect(&:user) data = { event: "decidim.events.elections.trustees.new_election", event_class: Decidim::Elections::Trustees::NotifyTrusteeNewElectionEvent, resource: election, affected_users: trustee } Decidim::EventsManager.publish(**data) end # Since machine_translations return a nested hash but Electionguard and other # schemes expect the translations to be returned in a "simple" hash, we need to # flatten the translations. # { # "language": "en", # "value": "Jubilee Alliance" # } # You can read more about the Civics Common Standard Data Specification here: # https://developers.google.com/civics-data/reference/internationalized-text def flatten_translations(translated_attribute) translated_attribute.deep_symbolize_keys! machine_translations = translated_attribute.delete(:machine_translations) || {} machine_translations.merge(translated_attribute).reject { |_k, v| v.empty? } end end end end end