diff --git a/app/controllers/spree/admin/products_controller_decorator.rb b/app/controllers/spree/admin/products_controller_decorator.rb deleted file mode 100644 index 01058e6..0000000 --- a/app/controllers/spree/admin/products_controller_decorator.rb +++ /dev/null @@ -1,26 +0,0 @@ -module Spree - module Admin - ProductsController.class_eval do - def variant_prices - id = session[:current_price_book_id] - session.delete(:current_price_book_id) - - @current_price_book = id.present? ? PriceBook.find(id) : PriceBook.default - - # need every variant/price(for the current price book) pair - # I had to do this ridiculous sort to get the master first since the scope orders by position, - # but for some reason the position is screwed up for master (it's not first) - @variants = @product.variants_including_master.partition {|v| v.is_master?}.flatten - - @prices = {} - - @variants.each do |variant| - @prices[variant.id] = variant.prices.detect {|price| price.price_book_id == @current_price_book.id} # possibly nil - end - - @price_books = PriceBook.order('priority') - @default_price_book = @price_books.detect {|pb| pb.default?} - end - end - end -end diff --git a/app/controllers/spree/admin/spree_price_books/products_controller_decorator.rb b/app/controllers/spree/admin/spree_price_books/products_controller_decorator.rb new file mode 100644 index 0000000..c24c570 --- /dev/null +++ b/app/controllers/spree/admin/spree_price_books/products_controller_decorator.rb @@ -0,0 +1,30 @@ +module Spree + module Admin + module SpreePriceBooks + module ProductsControllerDecorator + def variant_prices + id = session[:current_price_book_id] + session.delete(:current_price_book_id) + + @current_price_book = id.present? ? PriceBook.find(id) : PriceBook.default + + # need every variant/price(for the current price book) pair + # I had to do this ridiculous sort to get the master first since the scope orders by position, + # but for some reason the position is screwed up for master (it's not first) + @variants = @product.variants_including_master.partition {|v| v.is_master?}.flatten + + @prices = {} + + @variants.each do |variant| + @prices[variant.id] = variant.prices.detect {|price| price.price_book_id == @current_price_book.id} # possibly nil + end + + @price_books = PriceBook.order('priority') + @default_price_book = @price_books.detect {|pb| pb.default?} + end + end + end + end +end + +Spree::Admin::ProductsController.prepend Spree::Admin::SpreePriceBooks::ProductsControllerDecorator diff --git a/app/helpers/spree/base_helper_decorator.rb b/app/helpers/spree/base_helper_decorator.rb deleted file mode 100644 index cf63ad4..0000000 --- a/app/helpers/spree/base_helper_decorator.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Spree - BaseHelper.class_eval do - def display_price(product_or_variant) - product_or_variant.price_in(current_currency, current_store.id, spree_current_user.try(:price_book_role_ids)).display_price.to_html - end - end -end diff --git a/app/helpers/spree/spree_price_books/base_helper_decorator.rb b/app/helpers/spree/spree_price_books/base_helper_decorator.rb new file mode 100644 index 0000000..55b2263 --- /dev/null +++ b/app/helpers/spree/spree_price_books/base_helper_decorator.rb @@ -0,0 +1,11 @@ +module Spree + module SpreePriceBooks + module BaseHelperDecorator + def display_price(product_or_variant) + product_or_variant.price_in(current_currency, current_store.id, spree_current_user.try(:price_book_role_ids)).display_price.to_html + end + end + end +end + +Spree::BaseHelper.prepend Spree::SpreePriceBooks::BaseHelperDecorator diff --git a/app/models/spree/order/currency_updater_decorator.rb b/app/models/spree/order/currency_updater_decorator.rb deleted file mode 100644 index 185eacd..0000000 --- a/app/models/spree/order/currency_updater_decorator.rb +++ /dev/null @@ -1,33 +0,0 @@ -module Spree - class Order < Spree::Base - CurrencyUpdater.class_eval do - - # Returns the price object from given item - def list_price_from_line_item(line_item) - line_item.variant.list_price_in(currency, store_id, user.try(:price_book_role_ids)) - end - - # Returns the price object from given item - def price_from_line_item(line_item) - line_item.variant.price_in(currency, store_id, user.try(:price_book_role_ids)) - end - - # Updates price from given line item - def update_line_item_price!(line_item) - list_price = list_price_from_line_item(line_item) - price = price_from_line_item(line_item) - - if price - line_item.update_attributes!( - currency: price.currency, - list_price: list_price.price, - price: price.price - ) - else - raise RuntimeError, "no #{currency} price found for #{line_item.product.name} (#{line_item.variant.sku})" - end - end - - end - end -end diff --git a/app/models/spree/order/spree_price_books/currency_updater_decorator.rb b/app/models/spree/order/spree_price_books/currency_updater_decorator.rb new file mode 100644 index 0000000..f23aa52 --- /dev/null +++ b/app/models/spree/order/spree_price_books/currency_updater_decorator.rb @@ -0,0 +1,35 @@ +module Spree + class Order + module SpreePriceBooks + module CurrencyUpdaterDecorator + # Returns the price object from given item + def list_price_from_line_item(line_item) + line_item.variant.list_price_in(currency, store_id, user.try(:price_book_role_ids)) + end + + # Returns the price object from given item + def price_from_line_item(line_item) + line_item.variant.price_in(currency, store_id, user.try(:price_book_role_ids)) + end + + # Updates price from given line item + def update_line_item_price!(line_item) + list_price = list_price_from_line_item(line_item) + price = price_from_line_item(line_item) + + if price + line_item.update_attributes!( + currency: price.currency, + list_price: list_price.price, + price: price.price + ) + else + raise RuntimeError, "no #{currency} price found for #{line_item.product.name} (#{line_item.variant.sku})" + end + end + end + end + end +end + +Spree::Order::CurrencyUpdater.prepend Spree::Order::SpreePriceBooks::CurrencyUpdaterDecorator diff --git a/app/models/spree/price_decorator.rb b/app/models/spree/price_decorator.rb deleted file mode 100644 index a02defe..0000000 --- a/app/models/spree/price_decorator.rb +++ /dev/null @@ -1,53 +0,0 @@ -Spree::Price.class_eval do - - belongs_to :price_book - - has_many :store_price_books, through: :price_book - - validate :ensure_proper_currency - validates :price_book_id, presence: true - - before_validation :ensure_price_book - - after_create :populate_children - after_update :update_children - - delegate :product, to: :variant - - scope :by_currency, -> (currency_iso) { where(currency: currency_iso) } - scope :by_role, -> (role_ids) { prioritized.where(spree_price_books: { role_id: role_ids }) } - scope :by_store, -> (store_id) { joins(:store_price_books).where(spree_store_price_books: { store_id: store_id }) } - scope :list, -> { prioritized.where(spree_price_books: { discount: false }) } - scope :prioritized, -> { includes(:price_book).order('spree_price_books.priority DESC, spree_prices.amount ASC') } - - private - - def ensure_price_book - self.price_book ||= Spree::PriceBook.default - end - - def ensure_proper_currency - unless currency == price_book.currency - errors.add(:currency, :match_price_book) - end - end - - def populate_children - price_book.children.each do |book| - if price = book.prices.find_by_variant_id(self.variant_id) - price.update_attribute :amount, self.amount * book.price_adjustment_factor - else - book.prices.create amount: (self.amount * book.price_adjustment_factor), currency: book.currency, variant_id: self.variant_id - end - end - end - - def update_children - price_book.children.each do |book| - if price = book.prices.find_by_variant_id(self.variant_id) - price.update_attribute :amount, self.amount * book.price_adjustment_factor - end - end - end - -end diff --git a/app/models/spree/role_decorator.rb b/app/models/spree/role_decorator.rb deleted file mode 100644 index 60e4f1b..0000000 --- a/app/models/spree/role_decorator.rb +++ /dev/null @@ -1,6 +0,0 @@ -module Spree - Role.class_eval do - has_many :price_books - scope :with_price_book, -> { where(id: Spree::PriceBook.pluck(:role_id).uniq) } - end -end diff --git a/app/models/spree/spree_price_books/price_decorator.rb b/app/models/spree/spree_price_books/price_decorator.rb new file mode 100644 index 0000000..47883b1 --- /dev/null +++ b/app/models/spree/spree_price_books/price_decorator.rb @@ -0,0 +1,55 @@ +module Spree::SpreePriceBooks::PriceDecorator + def self.prepended(base) + base.belongs_to :price_book + + base.has_many :store_price_books, through: :price_book + + base.validate :ensure_proper_currency + base.validates :price_book_id, presence: true + + base.before_validation :ensure_price_book + + base.after_create :populate_children + base.after_update :update_children + + base.delegate :product, to: :variant + + base.scope :by_currency, -> (currency_iso) { where(currency: currency_iso) } + base.scope :by_role, -> (role_ids) { prioritized.where(spree_price_books: { role_id: role_ids }) } + base.scope :by_store, -> (store_id) { joins(:store_price_books).where(spree_store_price_books: { store_id: store_id }) } + base.scope :list, -> { prioritized.where(spree_price_books: { discount: false }) } + base.scope :prioritized, -> { includes(:price_book).order('spree_price_books.priority DESC, spree_prices.amount ASC') } + end + + private + + def ensure_price_book + self.price_book ||= Spree::PriceBook.default + end + + def ensure_proper_currency + unless currency == price_book.currency + errors.add(:currency, :match_price_book) + end + end + + def populate_children + price_book.children.each do |book| + if price = book.prices.find_by_variant_id(self.variant_id) + price.update_attribute :amount, self.amount * book.price_adjustment_factor + else + book.prices.create amount: (self.amount * book.price_adjustment_factor), currency: book.currency, variant_id: self.variant_id + end + end + end + + def update_children + price_book.children.each do |book| + if price = book.prices.find_by_variant_id(self.variant_id) + price.update_attribute :amount, self.amount * book.price_adjustment_factor + end + end + end +end + +Spree::Price.prepend Spree::SpreePriceBooks::PriceDecorator diff --git a/app/models/spree/product_decorator.rb b/app/models/spree/spree_price_books/product_decorator.rb similarity index 61% rename from app/models/spree/product_decorator.rb rename to app/models/spree/spree_price_books/product_decorator.rb index 4fc681e..0708f24 100644 --- a/app/models/spree/product_decorator.rb +++ b/app/models/spree/spree_price_books/product_decorator.rb @@ -1,6 +1,7 @@ -Spree::Product.class_eval do - - has_many :price_books, through: :master +module Spree::SpreePriceBooks::ProductDecorator + def self.prepended(base) + base.has_many :price_books, through: :master + end def master_price_for(price_book) Spree::Price.where( @@ -13,5 +14,6 @@ def display_master_price_for(price_book) price = master_price_for(price_book) Spree::Money.new(price.amount, currency: price_book.currency) end - end + +Spree::Product.prepend Spree::SpreePriceBooks::ProductDecorator diff --git a/app/models/spree/spree_price_books/role_decorator.rb b/app/models/spree/spree_price_books/role_decorator.rb new file mode 100644 index 0000000..9c167fb --- /dev/null +++ b/app/models/spree/spree_price_books/role_decorator.rb @@ -0,0 +1,8 @@ +module Spree::SpreePriceBooks::RoleDecorator + def self.prepended(base) + base.has_many :price_books + base.scope :with_price_book, -> { where(id: Spree::PriceBook.pluck(:role_id).uniq) } + end +end + +Spree::Role.prepend Spree::SpreePriceBooks::RoleDecorator diff --git a/app/models/spree/spree_price_books/store_decorator.rb b/app/models/spree/spree_price_books/store_decorator.rb new file mode 100644 index 0000000..5c25812 --- /dev/null +++ b/app/models/spree/spree_price_books/store_decorator.rb @@ -0,0 +1,12 @@ +module Spree::SpreePriceBooks::StoreDecorator + def self.prepended(base) + base.has_many :price_books, -> { + select("DISTINCT (#{table_name}.id), #{table_name}.*, #{Spree::StorePriceBook.table_name}.priority"). + order("#{Spree::StorePriceBook.table_name}.priority DESC") + }, through: :store_price_books + + base.has_many :store_price_books + end +end + +Spree::Store.prepend Spree::SpreePriceBooks::StoreDecorator diff --git a/app/models/spree/user_decorator.rb b/app/models/spree/spree_price_books/user_decorator.rb similarity index 59% rename from app/models/spree/user_decorator.rb rename to app/models/spree/spree_price_books/user_decorator.rb index 0cc5885..3c9d770 100644 --- a/app/models/spree/user_decorator.rb +++ b/app/models/spree/spree_price_books/user_decorator.rb @@ -1,8 +1,8 @@ -Spree.user_class.class_eval do - +module Spree::SpreePriceBooks::UserDecorator # When prices are determined based on the user role we must also include nil. def price_book_role_ids [nil, spree_roles.pluck(:id)].flatten end - end + +Spree::user_class.prepend Spree::SpreePriceBooks::UserDecorator diff --git a/app/models/spree/variant_decorator.rb b/app/models/spree/spree_price_books/variant_decorator.rb similarity index 61% rename from app/models/spree/variant_decorator.rb rename to app/models/spree/spree_price_books/variant_decorator.rb index 7d5939c..319a60b 100644 --- a/app/models/spree/variant_decorator.rb +++ b/app/models/spree/spree_price_books/variant_decorator.rb @@ -1,22 +1,17 @@ -Spree::Variant.class_eval do - - ## Associations - - has_one :default_price, - -> { where currency: Spree::Config[:currency], price_book_id: Spree::PriceBook.default.id }, - class_name: 'Spree::Price', - dependent: :destroy - - has_many :prices, - class_name: 'Spree::Price', - dependent: :destroy, - inverse_of: :variant - - has_many :price_books, -> { active.order('spree_prices.amount ASC, spree_price_books.priority DESC') }, through: :prices - - ## Class Methods - - ## Instance Methods +module Spree::SpreePriceBooks::VariantDecorator + def self.prepended(base) + base.has_one :default_price, + -> { where currency: Spree::Config[:currency], price_book_id: Spree::PriceBook.default.id }, + class_name: 'Spree::Price', + dependent: :destroy + + base.has_many :prices, + class_name: 'Spree::Price', + dependent: :destroy, + inverse_of: :variant + + base.has_many :price_books, -> { active.order('spree_prices.amount ASC, spree_price_books.priority DESC') }, through: :prices + end def display_list_price(currency = Spree::Config[:currency], store_id = Spree::Store.default.id, role_ids = nil) lp = list_price_in(currency, store_id) @@ -39,5 +34,6 @@ def price_in(currency = Spree::Config[:currency], store_id = Spree::Store.defaul prices.by_currency(currency).by_role(role_ids).first end end - end + +Spree::Variant.prepend Spree::SpreePriceBooks::VariantDecorator diff --git a/app/models/spree/store_decorator.rb b/app/models/spree/store_decorator.rb deleted file mode 100644 index 1e4ec91..0000000 --- a/app/models/spree/store_decorator.rb +++ /dev/null @@ -1,10 +0,0 @@ -Spree::Store.class_eval do - - has_many :price_books, -> { - select("DISTINCT (#{table_name}.id), #{table_name}.*, #{Spree::StorePriceBook.table_name}.priority"). - order("#{Spree::StorePriceBook.table_name}.priority DESC") - }, through: :store_price_books - - has_many :store_price_books - -end diff --git a/lib/spree_price_books/engine.rb b/lib/spree_price_books/engine.rb index 1998b97..e54a74a 100644 --- a/lib/spree_price_books/engine.rb +++ b/lib/spree_price_books/engine.rb @@ -17,8 +17,10 @@ def self.activate config.to_prepare &method(:activate).to_proc - initializer "spree_active_shipping.register.calculators" do |app| - app.config.spree.calculators.shipping_methods << Spree::Calculator::Shipping::FlatMultiCurrencyRate + initializer "spree_price_books.register.calculators", after: "spree.register.calculators" do |app| + Rails.application.config.after_initialize do + app.config.spree.calculators.shipping_methods << Spree::Calculator::Shipping::FlatMultiCurrencyRate + end end end end