class Decidim::Meetings::JoinMeeting

This command is executed when the user joins a meeting.

def accept_invitation

def accept_invitation
  meeting.invites.find_by(user: user)&.accept!
end

def answer_questionnaire

def answer_questionnaire
  return unless questionnaire?
  Decidim::Forms::AnswerQuestionnaire.call(registration_form, user, meeting.questionnaire) do
    on(:ok) do
      return :valid
    end
    on(:invalid) do
      return :invalid
    end
  end
end

def call

Broadcasts :ok if successful, :invalid otherwise.

and there are available slots.
Creates a meeting registration if the meeting has registrations enabled
def call
  return broadcast(:invalid) unless can_join_meeting?
  return broadcast(:invalid_form) unless registration_form.valid?
  return broadcast(:invalid) if answer_questionnaire == :invalid
  meeting.with_lock do
    create_registration
    accept_invitation
    send_email_confirmation
    send_notification_confirmation
    notify_admin_over_percentage
    increment_score
  end
  follow_meeting
  broadcast(:ok)
end

def can_join_meeting?

def can_join_meeting?
  meeting.registrations_enabled? && meeting.has_available_slots? &&
    !meeting.has_registration_for?(user)
end

def create_registration

def create_registration
  @registration = Decidim::Meetings::Registration.create!(
    meeting: meeting,
    user: user,
    user_group: user_group,
    public_participation: registration_form.public_participation
  )
end

def follow_form

def follow_form
  Decidim::FollowForm
    .from_params(followable_gid: meeting.to_signed_global_id.to_s)
    .with_context(current_user: user)
end

def follow_meeting

def follow_meeting
  Decidim::CreateFollow.call(follow_form, user)
end

def increment_score

def increment_score
  Decidim::Gamification.increment_score(user, :attended_meetings)
end

def initialize(meeting, user, registration_form)

registration_form - A form object with params; can be a questionnaire.
user - The user joining the meeting.
meeting - The current instance of the meeting to be joined.

Initializes a JoinMeeting Command.
def initialize(meeting, user, registration_form)
  @meeting = meeting
  @user = user
  @user_group = Decidim::UserGroup.find_by(id: registration_form.user_group_id)
  @registration_form = registration_form
end

def notify_admin_over_percentage

def notify_admin_over_percentage
  return send_notification_over(0.5) if occupied_slots_over?(0.5)
  return send_notification_over(0.8) if occupied_slots_over?(0.8)
  send_notification_over(1.0) if occupied_slots_over?(1.0)
end

def occupied_slots_over?(percentage)

def occupied_slots_over?(percentage)
  @meeting.remaining_slots == (@meeting.available_slots * (1 - percentage)).round
end

def participatory_space_admins

def participatory_space_admins
  @meeting.component.participatory_space.admins
end

def questionnaire?

def questionnaire?
  registration_form.model_name == "questionnaire"
end

def send_email_confirmation

def send_email_confirmation
  Decidim::Meetings::RegistrationMailer.confirmation(user, meeting, registration).deliver_later
end

def send_notification_confirmation

def send_notification_confirmation
  Decidim::EventsManager.publish(
    event: "decidim.events.meetings.meeting_registration_confirmed",
    event_class: Decidim::Meetings::MeetingRegistrationNotificationEvent,
    resource: @meeting,
    affected_users: [@user],
    extra: {
      registration_code: @registration.code
    }
  )
end

def send_notification_over(percentage)

def send_notification_over(percentage)
  Decidim::EventsManager.publish(
    event: "decidim.events.meetings.meeting_registrations_over_percentage",
    event_class: Decidim::Meetings::MeetingRegistrationsOverPercentageEvent,
    resource: @meeting,
    affected_users: participatory_space_admins,
    extra: {
      percentage: percentage
    }
  )
end