module Eco module API class MicroCases # Unique access point to set the `supervisor_id` value on a person. # @note # - It prevents the basic cyclic supervisor case (supervisor to be supervisor of themselves) # @param person [Ecoportal::API::V1::Person] the person we want to update, carrying the changes to be done. # @param sup_id [nil, String] the **supervisor id** we should set on the `person`. # @param people [Eco::API::Organization::People] _People_ involved in the current update. # @param options [Hash] the options. # @yield [supervisor_id] callback when the supervisor_id is **unknown** (not `nil` nor any one's in `people`). # @yieldparam supervisor_id [String] the **unknown** `supervisor_id`. def set_supervisor(person, sup_id, people, options) return false if options.dig(:exclude, :core) || options.dig(:exclude, :supervisor) return false if sup_id && ((person.id == sup_id) || (person.external_id == sup_id)) cur_id = person.supervisor_id cur_super = cur_id && with_supervisor(cur_id, people) micro.with_supervisor(sup_id, people) do |new_super| if !sup_id person.supervisor_id = nil descrease_subordinates(cur_super) elsif new_super && (id = new_super.id) set_supervisor(new_super, nil, people, options) if new_super_direct_cyclic?(person, new_super) person.supervisor_id = id descrease_subordinates(cur_super) increase_subordinates(new_super) elsif !block_given? descrease_subordinates(cur_super) person.supervisor_id = sup_id elsif block_given? yield(sup_id) end end end private def new_super_direct_cyclic?(person, new_super) return false unless new_super.is_a?(Ecoportal::API::V1::Person) return false if new_super.supervisor_id.nil? return true if person.id == new_super.id return true if new_super.supervisor_id == person.id return true if new_super.supervisor_id == person.external_id false end def descrease_subordinates(person, by = 1) return unless person.is_a?(Ecoportal::API::V1::Person) person.subordinates -= by end def increase_subordinates(person, by = 1) return unless person.is_a?(Ecoportal::API::V1::Person) person.subordinates += by end end end end