| Ruby on rails |
| 1 | class Shop::Product < ActiveRecord::Base include ::Shop::Product::SizeSetter include ::Shop::Product::Status |
| 2 | # >>>>>> Shop::Priceable behavior >>>>>>>>>> include Shop::Priceable price_attr_accessor [:feed_price, :feed_original_price, :feed_shipping_price, :price_value, :price_vat_value, :original_price_value, :original_price_vat_value, :shipping_price_value, :shipping_price_vat_value] # <<<<<< Shop::Priceable behavior <<<<<<<<<< |
| 3 | PRODUCTS_PER_PAGE_MODES = [32, 180].freeze INHERITED_MASTER_ATTRIBUTES = [:brand, :weight_value, :weight_unit, :price_value, :price_currency, :original_price_value, :shipping_price_value, :vat_included_value, :images, :attributes_hash, :categories] attr_accessible :retailer, :sku, :type, :title, :description, :brand, :weight, :ean, :pricing, :stock, :images, :category_ids, :categories, :status, :master_product_id, :attributes_hash, :country, :parameters_hash, :version, :supplier_category, :xml_digest |
| 4 | belongs_to :retailer belongs_to :brand belongs_to :version, class_name: 'Shop::ProductVersion', foreign_key: :product_version_id belongs_to :master_product, class_name: 'Shop::Product' has_many :variants, class_name: 'Shop::Product', foreign_key: :master_product_id has_many :products_categories, :dependent => :destroy has_many :categories, through: :products_categories has_many :cart_items, :dependent => :destroy has_many :disabled_carriers, class_name: Shop::CarrierDisabledProduct has_many :ordered_products, class_name: Shop::OrderedProduct has_many :questions |
| 5 | scope :by_country, ->(country) { where(country: country) } scope :by_category_brands, -> { joins(:products_categories).where('products_categories.category_id = category_brands.category_id') } scope :by_supplier_categories, ->(supplier_categories) do where("supplier_category && ARRAY[?]::VARCHAR[]", supplier_categories) end scope :simple_and_master, -> { where("products.type = 'simple' OR products.type = 'master'") } scope :master, -> { where(type: 'master') } scope :by_price_range, ->(min_price, max_price) do where(min_price.present? && max_price.present? && {price_value: min_price..max_price}) end scope :by_retailer_names, ->(retailer_names) { joins(:retailer).where(retailers: {name: retailer_names}) } scope :by_retailer, ->(retailer_ids) { where(retailer_id: retailer_ids) } scope :by_category, ->(category_ids) do joins(:categories).where({categories: {id: category_ids}}) if category_ids.present? end scope :by_top_level_category, ->(category_ids) do joins(:categories). where('categories.id IN (:category_ids) OR categories.parent_id IN (:category_ids)', category_ids: category_ids) if category_ids.present? end scope :in_stock, -> { where('products.stock > 0') } scope :without_disappeared, -> { where("products.statuses != 'all => disappeared'::hstore") } scope :of_mini_retailers, -> { where('retailer_id in (SELECT id from retailers WHERE mini is TRUE)') } scope :by_status, -> (status, carrier_id: 'all') { where("COALESCE(statuses -> '?', statuses -> 'all') = ?", carrier_id, status) } |
| 6 | serialize :images, Array serialize :attributes_hash, Hash serialize :parameters_hash, Hash |
| 7 | Pricing = Struct.new(:price, :price_vat, :original_price, :original_price_vat, :shipping_price, :shipping_price_vat, :currency, :vat_included, :rebate_percent) |
| 8 | Weight = Struct.new(:value, :unit) |
| 9 | composed_of :pricing, class_name: 'Shop::Product::Pricing', mapping: [ %w(price_value price), %w(price_vat_value price_vat), %w(original_price_value original_price), %w(original_price_vat_value original_price_vat), %w(shipping_price_value shipping_price), %w(shipping_price_vat_value shipping_price_vat), %w(price_currency currency), %w(vat_included_value vat_included), %w(rebate_percent rebate_percent) ] |
| 10 | composed_of :weight, class_name: 'Shop::Product::Weight', mapping: [ %w(weight_value value), %w(weight_unit unit) ] validates :sku, :type, :title, :description, :country, :presence => true delegate :name, to: :brand, prefix: true self.inheritance_column = '_type_disabled' |
| 11 | def self.get_price_range r = self.select('max(price_value) as maximum, min(price_value) as minimum').first OpenStruct.new minimum: r.minimum.to_f, maximum: r.maximum.to_f end |
| 12 | def self.set_to_zero_outdated_stocks countries_grouped_by_retailer_id, outdated_version_id countries_grouped_by_retailer_id.each do |retailer_id, countries| self.where(retailer_id: retailer_id, country: countries). where('product_version_id <= ?', outdated_version_id). where('stock != 0'). update_all(stock: 0) end end |
| 13 | def original_price? original_price_value? end # shipping price has to be 0 by default (according to https://stagingnowshop.com/retailer/setup/products) # but parser return nil for absent appropriate tag now def shipping_price? shipping_price_value? end |
| 14 | def vat_included? vat_included_value? end def weight? weight_value? end def increase_popularity self.popularity += 1 if save && type == 'variant' master_product.increase_popularity end end |
| 15 | # TODO: Define there getters at the bottom of this class definition # to provide ability to override (above) any attribute accessor by business necessity. INHERITED_MASTER_ATTRIBUTES.each do |attr_name| self.override_getter(attr_name) do |val| if self.simple? or val.present? val else master_product.public_send(attr_name) if master_product end end end |
| 16 | %w[simple master variant].each do |type_name| define_method("#{type_name}?") { type.to_s.downcase == type_name.to_s.downcase } end def variants self.variant? ? master_product.variants : super end def categories self.variant? ? master_product.categories : super end |
| 17 | def category_ids self.variant? ? master_product.category_ids : super end def brand self.variant? ? master_product.brand : super end def parameter_names return [] if self.simple? (self.variant? ? master_product : self).parameters_hash.try(:keys) end |
| 18 | def cover_image try(:images).try :first end def color parameters_hash['color'] end def size parameters_hash['size'] end |
| 19 | def in_stock? self.stock > 0 end def original_price original_price_value || price_value end def has_rebate? price_value != original_price end |
| 20 | def price_with_carrier_rebate carrier = nil (price_value * (1 - carrier.try(:rebate).to_f / 100)).round(2) end def total_rebate carrier = nil return 0 if original_price.zero? new_price = price_value * (1 - carrier.try(:rebate).to_f / 100) (100 * (1 - new_price / original_price)).round end |
| 21 | def disappear all_countries: false PRODUCT_LOG.log_block "disappear product \"#{title}\" (id = #{id}, sku = #{sku}, country = #{country}, retailer_id = #{retailer_id})" do Shop::Product.transaction do if master_product master_product.variants.delete(self) master_product.disappear if master_product.variants.empty? end set_status('disappeared') save! Shop::CacheTable::ProductCategoryBrand.new.drop([id]) if type.in? %w[simple master] Shop::ActiveCartItemRemover.new.remove_by_disabled_product([id]) end if all_countries Shop::Product.where(sku: sku, retailer_id: retailer_id).where.not(id: id).each(&:disappear) end true end rescue Exception => e false end |
| 22 | def editable_by? profile case profile when Shop::Retailer then self.retailer_id == profile.id && profile.can_edit_products? when Shop::Carrier then retailer.can_edit_products? && retailer.carrier_id == profile.id else false end end |
| 23 | # TODO: replace with status? def disabled_by? carrier self.disabled_carriers.any?{|c| c.carrier_id == carrier.try(:id)} end def self.reset_column_information super @inheritance_column = '_type_disabled' end def price_vat_without_carrier_rebate sale_with_vat? ? price_vat_value : 0 end |
| 24 | def shipping_price_vat_without_carrier_rebate sale_with_vat? ? shipping_price_vat_value : 0 end def commission retailer.commission(category_ids: category_ids) end def vat_tax retailer.vat_percent_by_country_code(country) end def sef_url self.class.product_url_params(brand_name, title, id) end |
| 25 | def self.product_url_params(brand_name, product_title, product_id) "#{ TextProcessor.urlify(brand_name) }/#{ TextProcessor.urlify(product_title) }_#{ product_id }" end def mini_retailer? retailer.mini? end def sibling_for(country_code) self.class.find_by(sku: sku, retailer_id: retailer_id, country: country_code) end def can_be_sold_to(country) self.country == country.sale_zone end end |
Комментарии