# frozen_string_literal: true class EnterpriseRelationship < ApplicationRecord belongs_to :parent, class_name: 'Enterprise', touch: true belongs_to :child, class_name: 'Enterprise', touch: true has_many :permissions, class_name: 'EnterpriseRelationshipPermission', dependent: :destroy validates :child_id, uniqueness: { scope: :parent_id, message: I18n.t('validation_msg_relationship_already_established') } before_destroy :revoke_all_child_variant_overrides before_destroy :destroy_related_exchanges after_save :update_permissions_of_child_variant_overrides scope :with_enterprises, -> { joins(" LEFT JOIN enterprises AS parent_enterprises ON parent_enterprises.id = enterprise_relationships.parent_id"). joins(" LEFT JOIN enterprises AS child_enterprises ON child_enterprises.id = enterprise_relationships.child_id") } scope :involving_enterprises, ->(enterprises) { where('parent_id IN (?) OR child_id IN (?)', enterprises.select(&:id), enterprises.select(&:id)) } scope :permitting, ->(enterprise_ids) { where(child_id: enterprise_ids) } scope :permitted_by, ->(enterprise_ids) { where(parent_id: enterprise_ids) } scope :with_permission, ->(permission) { joins(:permissions). where(enterprise_relationship_permissions: { name: permission }) } scope :by_name, -> { with_enterprises.order('child_enterprises.name, parent_enterprises.name') } # Load an array of the relatives of each enterprise (ie. any enterprise related to it in # either direction). This array is split into distributors and producers, and has the format: # {enterprise_id => {distributors: [id, ...], producers: [id, ...]} } def self.relatives(activated_only = false) relationships = EnterpriseRelationship.includes(:child, :parent) relatives = {} Enterprise.is_primary_producer.pluck(:id).each do |enterprise_id| relatives[enterprise_id] ||= { distributors: Set.new, producers: Set.new } relatives[enterprise_id][:producers] << enterprise_id end Enterprise.is_distributor.pluck(:id).each do |enterprise_id| relatives[enterprise_id] ||= { distributors: Set.new, producers: Set.new } relatives[enterprise_id][:distributors] << enterprise_id end relationships.each do |r| relatives[r.parent_id] ||= { distributors: Set.new, producers: Set.new } relatives[r.child_id] ||= { distributors: Set.new, producers: Set.new } if !activated_only || r.child.activated? relatives[r.parent_id][:producers] << r.child_id if r.child.is_primary_producer relatives[r.parent_id][:distributors] << r.child_id if r.child.is_distributor end if !activated_only || r.parent.activated? relatives[r.child_id][:producers] << r.parent_id if r.parent.is_primary_producer relatives[r.child_id][:distributors] << r.parent_id if r.parent.is_distributor end end relatives end def permissions_list=(perms) if perms.nil? permissions.destroy_all else permissions.where.not(name: perms).destroy_all perms.map { |name| permissions.find_or_initialize_by name: } end end def has_permission?(name) permissions.reload.map(&:name).map(&:to_sym).include? name.to_sym end private def update_permissions_of_child_variant_overrides if has_permission?(:create_variant_overrides) allow_all_child_variant_overrides else revoke_all_child_variant_overrides end end def allow_all_child_variant_overrides child_variant_overrides.update_all(permission_revoked_at: nil) end def revoke_all_child_variant_overrides child_variant_overrides.update_all(permission_revoked_at: Time.zone.now) end def destroy_related_exchanges Exchange.where(sender: parent, receiver: child, incoming: true).destroy_all end def child_variant_overrides VariantOverride.unscoped.for_hubs(child) .joins(:variant).where(spree_variants: { supplier_id: parent } ) end end