Noosfero/noosfero

View on GitHub
plugins/suppliers/models/suppliers_plugin/supplier.rb

Summary

Maintainability
A
25 mins
Test Coverage
class SuppliersPlugin::Supplier < ApplicationRecord
  attr_accessor :distribute_products_on_create, :dont_destroy_dummy, :identifier_from_name

  attr_accessible :profile_id, :profile, :consumer, :consumer_id, :name, :name_abbreviation, :description

  belongs_to :profile, optional: true
  belongs_to :consumer, class_name: "Profile", optional: true
  alias_method :supplier, :profile

  validates_presence_of :name, if: :dummy?
  validates_associated :profile, if: :dummy?
  validates_presence_of :profile
  validates_presence_of :consumer
  validates_uniqueness_of :consumer_id, scope: :profile_id, if: :profile_id

  scope :alphabetical, -> { order "name ASC" }

  scope :active, -> { where active: true }
  scope :dummy, -> { joins(:profile).where profiles: { visible: false } }

  scope :of_profile, ->(p) { where profile_id: p.id }
  scope :of_profile_id, ->(id) { where profile_id: id }
  scope :of_consumer, ->(c) { where consumer_id: c.id }
  scope :of_consumer_id, ->(id) { where consumer_id: id }

  scope :from_supplier_id, ->(supplier_id) { where "suppliers_plugin_suppliers.id = ?", supplier_id }

  scope :with_name, ->(name) { where "suppliers_plugin_suppliers.name ILIKE ?", "%#{name.downcase}%" if name }
  scope :by_active, ->(active) { where active: active if active }

  scope :except_people, -> { joins(:consumer).where "profiles.type <> ?", Person.name }
  scope :except_self, -> { where "profile_id <> consumer_id" }

  after_create :add_admins, if: :dummy?
  after_create :save_profile, if: :dummy?
  after_create :distribute_products_to_consumer
  before_validation :fill_identifier, if: :dummy?
  before_destroy :destroy_consumer_products

  def self.new_dummy(attributes)
    environment = attributes[:consumer].environment
    profile = environment.enterprises.build
    profile.enabled = false
    profile.visible = false
    profile.public_profile = false

    supplier = self.new
    supplier.profile = profile
    supplier.consumer = attributes.delete :consumer
    supplier.attributes = attributes
    supplier
  end

  def self.create_dummy(attributes)
    s = new_dummy attributes
    s.save!
    s
  end

  def self?
    self.profile_id == self.consumer_id
  end

  def person?
    self.consumer.person?
  end

  def dummy?
    !self.supplier.visible rescue false
  end

  def active?
    self.active
  end

  def name
    self.attributes["name"] || self.profile.name
  end

  def name=(value)
    self["name"] = value
    self.supplier.name = value if self.dummy? && (not self.supplier.frozen?)
  end

  def description
    self.attributes["description"] || self.profile.description
  end

  def description=(value)
    self["description"] = value
    self.supplier.description = value if self.dummy? && (not self.supplier.frozen?)
  end

  def abbreviation_or_name
    return self.profile.nickname || self.name if self.self?

    self.name_abbreviation.blank? ? self.name : self.name_abbreviation
  end

  def destroy_with_dummy
    if (not self.self?) && (not self.dont_destroy_dummy) && self.supplier && self.supplier.dummy?
      self.supplier.destroy
    end
    self.destroy_without_dummy
  end
  alias_method :destroy_without_dummy, :destroy
  alias_method :destroy, :destroy_with_dummy

  protected

    def set_identifier
      if self.identifier_from_name
        identifier = self.profile.identifier = self.profile.name.to_slug
        i = 0
        self.profile.identifier = "#{identifier}#{i += 1}" while Profile[self.profile.identifier].present?
      else
        self.profile.identifier = Digest::MD5.hexdigest rand.to_s
      end
    end

    def fill_identifier
      return if self.profile.identifier.present?

      set_identifier
    end

    def add_admins
      self.consumer.admins.to_a.each { |a| self.supplier.add_admin a }
    end

    # sync name, description, etc
    def save_profile
      self.supplier.save
    end

    def distribute_products_to_consumer
      self.distribute_products_on_create = true if self.distribute_products_on_create.nil?
      return if self.self? || self.consumer.person? || (not self.distribute_products_on_create)

      already_supplied = self.consumer.distributed_products.unarchived.from_supplier_id(self.id).all

      self.profile.products.unarchived.each do |source_product|
        next if already_supplied.find { |f| f.supplier_product == source_product }

        source_product.distribute_to_consumer self.consumer
      end
    end
    handle_asynchronously :distribute_products_to_consumer

    def destroy_consumer_products
      self.consumer.products.joins(:suppliers).from_supplier(self).destroy_all
    end

    # delegate missing methods to profile
    def method_missing(method, *args, &block)
      if self.profile.respond_to? method
        self.profile.send method, *args, &block
      else
        super method, *args, &block
      end
    end

    def respond_to_with_profile?(method, include_private = false)
      respond_to_without_profile?(method, include_private) || Profile.new.respond_to?(method, include_private)
    end
    alias_method :respond_to_without_profile?, :respond_to
    alias_method :respond_to, :respond_to_with_profile?
end