supplier.rb 4.79 KB
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
  belongs_to :consumer, class_name: 'Profile'
  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? and 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? and 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? and not self.dont_destroy_dummy and self.supplier and self.supplier.dummy?
      self.supplier.destroy
    end
    self.destroy_without_dummy
  end
  alias_method_chain :destroy, :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? or self.consumer.person? or 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 or Profile.new.respond_to? method, include_private
  end
  alias_method_chain :respond_to?, :profile

end