dawarich/app/services/families/accept_invitation.rb

121 lines
3 KiB
Ruby

# frozen_string_literal: true
module Families
class AcceptInvitation
attr_reader :invitation, :user, :error_message
def initialize(invitation:, user:)
@invitation = invitation
@user = user
@error_message = nil
end
def call
return false unless can_accept?
if user.in_family?
@error_message = 'You must leave your current family before joining a new one.'
return false
end
ActiveRecord::Base.transaction do
create_membership
update_invitation
send_notifications
end
true
rescue ActiveRecord::RecordInvalid => e
handle_record_invalid_error(e)
false
rescue StandardError => e
handle_generic_error(e)
false
end
private
def can_accept?
return false unless validate_invitation
return false unless validate_email_match
return false unless validate_family_capacity
true
end
def validate_invitation
return true if invitation.can_be_accepted?
@error_message = 'This invitation is no longer valid or has expired.'
false
end
def validate_email_match
return true if invitation.email == user.email
@error_message = 'This invitation is not for your email address.'
false
end
def validate_family_capacity
return true unless invitation.family.full?
@error_message = 'This family has reached the maximum number of members.'
false
end
def create_membership
Family::Membership.create!(
family: invitation.family,
user: user,
role: :member
)
end
def update_invitation
invitation.update!(status: :accepted)
end
def send_notifications
send_user_notification
send_owner_notification
end
def send_user_notification
Notification.create!(
user: user,
kind: :info,
title: 'Welcome to Family',
content: "You've joined the family '#{invitation.family.name}'"
)
end
def send_owner_notification
return unless defined?(Notification)
Notification.create!(
user: invitation.family.creator,
kind: :info,
title: 'New Family Member',
content: "#{user.email} has joined your family"
)
rescue StandardError => e
# Don't fail the entire operation if notification fails
Rails.logger.warn "Failed to send family join notification: #{e.message}"
end
def handle_record_invalid_error(error)
@error_message = if error.record&.errors&.any?
error.record.errors.full_messages.first
else
"Failed to join family: #{error.message}"
end
end
def handle_generic_error(error)
Rails.logger.error "Unexpected error in Families::AcceptInvitation: #{error.message}"
Rails.logger.error error.backtrace.join("\n")
@error_message = 'An unexpected error occurred while joining the family. Please try again'
end
end
end