# frozen_string_literal: true module Decidim module Conferences # This command is executed when the user joins a conference. class JoinConference < Decidim::Command # Initializes a JoinConference Command. # # conference - The current instance of the conference to be joined. # registration_type - The registration type selected to attend the conference # user - The user joining the conference. def initialize(conference, registration_type, user) @conference = conference @registration_type = registration_type @user = user end # Creates a conference registration if the conference has registrations enabled # and there are available slots. # # Broadcasts :ok if successful, :invalid otherwise. def call return broadcast(:invalid) unless can_join_conference? return broadcast(:ok) if already_joined_conference? conference.with_lock do create_registration create_meetings_registrations accept_invitation send_email_pending_validation send_notification_pending_validation notify_admin_over_percentage end broadcast(:ok) end private attr_reader :conference, :user def accept_invitation conference.conference_invites.find_by(user: user)&.accept! end def create_registration Decidim::Conferences::ConferenceRegistration.create!(conference: conference, user: user, registration_type: @registration_type) end def create_meetings_registrations published_meeting_components = Decidim::Component.where(participatory_space: conference).where(manifest_name: "meetings").published meetings = Decidim::Meetings::Meeting.where(component: published_meeting_components).where(id: @registration_type.conference_meetings.pluck(:id)) meetings.each do |meeting| Decidim::Meetings::Registration.create!(meeting: meeting, user: user) end end def can_join_conference? conference.registrations_enabled? && conference.has_available_slots? end def already_joined_conference? conference.conference_registrations.where(user: user).any? end def send_email_pending_validation Decidim::Conferences::ConferenceRegistrationMailer.pending_validation(user, conference, @registration_type).deliver_later end def send_notification_pending_validation Decidim::EventsManager.publish( event: "decidim.events.conferences.conference_registration_validation_pending", event_class: Decidim::Conferences::ConferenceRegistrationNotificationEvent, resource: @conference, affected_users: [@user] ) end def participatory_space_admins @conference.admins end 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 send_notification_over(percentage) Decidim::EventsManager.publish( event: "decidim.events.conferences.conference_registrations_over_percentage", event_class: Decidim::Conferences::ConferenceRegistrationsOverPercentageEvent, resource: @conference, followers: participatory_space_admins, extra: { percentage: percentage } ) end def occupied_slots_over?(percentage) @conference.remaining_slots == (@conference.available_slots * (1 - percentage)).round end end end end