From 0d44f298fe008d1f3651cb13911cef22ea98ed6b Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Mon, 11 Nov 2019 16:40:53 +0000 Subject: [PATCH] Merge spree/admin/products_controller with its decorator --- .../spree/admin/products_controller.rb | 246 ++++++++++++++---- .../admin/products_controller_decorator.rb | 201 -------------- 2 files changed, 201 insertions(+), 246 deletions(-) delete mode 100644 app/controllers/spree/admin/products_controller_decorator.rb diff --git a/app/controllers/spree/admin/products_controller.rb b/app/controllers/spree/admin/products_controller.rb index 59f2aae4d0..a767295d88 100644 --- a/app/controllers/spree/admin/products_controller.rb +++ b/app/controllers/spree/admin/products_controller.rb @@ -1,30 +1,86 @@ +require 'open_food_network/spree_api_key_loader' +require 'open_food_network/referer_parser' +require 'open_food_network/permissions' + module Spree module Admin class ProductsController < ResourceController helper 'spree/products' + include OpenFoodNetwork::SpreeApiKeyLoader + include OrderCyclesHelper + include EnterprisesHelper before_filter :load_data, :except => :index create.before :create_before update.before :update_before + before_filter :load_data + before_filter :load_form_data, only: [:index, :new, :create, :edit, :update] + before_filter :load_spree_api_key, only: [:index, :variant_overrides] + before_filter :strip_new_properties, only: [:create, :update] + + respond_override create: { html: { + success: lambda { + if params[:button] == "add_another" + redirect_to new_admin_product_path + else + redirect_to admin_products_path + end + }, + failure: lambda { + render :new + } + } } + + def new + @object.shipping_category = DefaultShippingCategory.find_or_create + super + end + + def create + delete_stock_params_and_set_after do + super + end + rescue Paperclip::Errors::NotIdentifiedByImageMagickError + invoke_callbacks(:create, :fails) + @object.errors.add(:base, t('spree.admin.products.image_upload_error')) + respond_with(@object) + end + def show session[:return_to] ||= request.referer redirect_to( :action => :edit ) end def index - session[:return_to] = request.url - respond_with(@collection) + @current_user = spree_current_user + @show_latest_import = params[:latest_import] || false end def update - if params[:product][:taxon_ids].present? - params[:product][:taxon_ids] = params[:product][:taxon_ids].split(',') + original_supplier_id = @product.supplier_id + + delete_stock_params_and_set_after do + super + ExchangeVariantDeleter.new.delete(@product) if original_supplier_id != @product.supplier_id end - if params[:product][:option_type_ids].present? - params[:product][:option_type_ids] = params[:product][:option_type_ids].split(',') + end + + def bulk_update + product_set = product_set_from_params(params) + + # Ensure we're authorised to update all products + product_set.collection.each { |p| authorize! :update, p } + + if product_set.save + redirect_to main_app.bulk_products_api_products_path( bulk_index_query(params) ) + else + if product_set.errors.present? + render json: { errors: product_set.errors }, status: :bad_request + else + render nothing: true, status: :internal_server_error + end end - super end def destroy @@ -63,59 +119,159 @@ module Spree protected - def find_resource - Product.find_by_permalink!(params[:id]) + def find_resource + Product.find_by_permalink!(params[:id]) + end + + def location_after_save + spree.edit_admin_product_url(@product) + end + + def load_data + @taxons = Taxon.order(:name) + @option_types = OptionType.order(:name) + @tax_categories = TaxCategory.order(:name) + @shipping_categories = ShippingCategory.order(:name) + end + + def collection + # This method is copied directly from the spree product controller + # except where we narrow the search below with the managed_by search to support + # enterprise users. + # TODO: There has to be a better way!!! + return @collection if @collection.present? + params[:q] ||= {} + params[:q][:deleted_at_null] ||= "1" + + params[:q][:s] ||= "name asc" + # The next line is modified. + # Hit Spree::Product instead of super, avoiding cancan error for fetching + # records with block permissions via accessible_by. + @collection = Spree::Product + @collection = @collection.with_deleted if params[:q].delete(:deleted_at_null).blank? + # @search needs to be defined as this is passed to search_form_for + @search = @collection.ransack(params[:q]) + @collection = @search.result. + managed_by(spree_current_user). # this line is added to the original spree code!!!!! + group_by_products_id. + includes(product_includes). + page(params[:page]). + per(Spree::Config[:admin_products_per_page]) + + if params[:q][:s].include?("master_default_price_amount") + # PostgreSQL compatibility + @collection = @collection.group("spree_prices.amount") end + @collection + end - def location_after_save - spree.edit_admin_product_url(@product) - end + def create_before + return if params[:product][:prototype_id].blank? + @prototype = Spree::Prototype.find(params[:product][:prototype_id]) + end - def load_data - @taxons = Taxon.order(:name) - @option_types = OptionType.order(:name) - @tax_categories = TaxCategory.order(:name) - @shipping_categories = ShippingCategory.order(:name) - end + def update_before + # note: we only reset the product properties if we're receiving a post from the form on that tab + return unless params[:clear_product_properties] + params[:product] ||= {} + end - def collection - return @collection if @collection.present? - params[:q] ||= {} - params[:q][:deleted_at_null] ||= "1" + def product_includes + [{:variants => [:images, {:option_values => :option_type}]}, {:master => [:images, :default_price]}] + end - params[:q][:s] ||= "name asc" - @collection = super - @collection = @collection.with_deleted if params[:q].delete(:deleted_at_null).blank? - # @search needs to be defined as this is passed to search_form_for - @search = @collection.ransack(params[:q]) - @collection = @search.result. - group_by_products_id. - includes(product_includes). - page(params[:page]). - per(Spree::Config[:admin_products_per_page]) + def collection_actions + [:index, :bulk_update] + end - if params[:q][:s].include?("master_default_price_amount") - # PostgreSQL compatibility - @collection = @collection.group("spree_prices.amount") + private + + def product_set_from_params(params) + collection_hash = Hash[params[:products].each_with_index.map { |p, i| [i, p] }] + Spree::ProductSet.new(collection_attributes: collection_hash) + end + + def bulk_index_query(params) + params[:filters].to_h.merge(page: params[:page], per_page: params[:per_page]) + end + + def load_form_data + @producers = OpenFoodNetwork::Permissions.new(spree_current_user). + managed_product_enterprises.is_primary_producer.by_name + @taxons = Spree::Taxon.order(:name) + @import_dates = product_import_dates.uniq.to_json + end + + def product_import_dates + options = [{ id: '0', name: '' }] + product_import_dates_query.collect(&:import_date). + map { |i| options.push(id: i.to_date, name: i.to_date.to_formatted_s(:long)) } + + options + end + + def product_import_dates_query + Spree::Variant. + select('DISTINCT spree_variants.import_date'). + joins(:product). + where('spree_products.supplier_id IN (?)', editable_enterprises.collect(&:id)). + where('spree_variants.import_date IS NOT NULL'). + where(spree_variants: { is_master: false }). + where(spree_variants: { deleted_at: nil }). + order('spree_variants.import_date DESC') + end + + def strip_new_properties + return if spree_current_user.admin? || params[:product][:product_properties_attributes].nil? + names = Spree::Property.pluck(:name) + params[:product][:product_properties_attributes].each do |key, property| + unless names.include? property[:property_name] + params[:product][:product_properties_attributes].delete key end - @collection end + end - def create_before - return if params[:product][:prototype_id].blank? - @prototype = Spree::Prototype.find(params[:product][:prototype_id]) + def delete_stock_params_and_set_after + on_demand = params[:product].delete(:on_demand) + on_hand = params[:product].delete(:on_hand) + + yield + + set_stock_levels(@product, on_hand, on_demand) if @product.valid? + end + + def set_stock_levels(product, on_hand, on_demand) + variant = product_variant(product) + + begin + variant.on_demand = on_demand if on_demand.present? + variant.on_hand = on_hand.to_i if on_hand.present? + rescue StandardError => error + notify_bugsnag(error, product, variant) + raise error end + end - def update_before - # note: we only reset the product properties if we're receiving a post from the form on that tab - return unless params[:clear_product_properties] - params[:product] ||= {} + def notify_bugsnag(error, product, variant) + Bugsnag.notify(error) do |report| + report.add_tab(:product, product.attributes) + report.add_tab(:product_error, product.errors.first) unless product.valid? + report.add_tab(:variant, variant.attributes) + report.add_tab(:variant_error, variant.errors.first) unless variant.valid? end + end - def product_includes - [{:variants => [:images, {:option_values => :option_type}]}, {:master => [:images, :default_price]}] + def product_variant(product) + if product.variants.any? + product.variants.first + else + product.master end + end + def set_product_master_variant_price_to_zero + @product.price = 0 if @product.price.nil? + end end end end 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 9302a6696a..0000000000 --- a/app/controllers/spree/admin/products_controller_decorator.rb +++ /dev/null @@ -1,201 +0,0 @@ -require 'open_food_network/spree_api_key_loader' -require 'open_food_network/referer_parser' -require 'open_food_network/permissions' - -Spree::Admin::ProductsController.class_eval do - include OpenFoodNetwork::SpreeApiKeyLoader - include OrderCyclesHelper - include EnterprisesHelper - - before_filter :load_data - before_filter :load_form_data, only: [:index, :new, :create, :edit, :update] - before_filter :load_spree_api_key, only: [:index, :variant_overrides] - before_filter :strip_new_properties, only: [:create, :update] - - respond_override create: { html: { - success: lambda { - if params[:button] == "add_another" - redirect_to new_admin_product_path - else - redirect_to admin_products_path - end - }, - failure: lambda { - render :new - } - } } - - def index - @current_user = spree_current_user - @show_latest_import = params[:latest_import] || false - end - - def new - @object.shipping_category = DefaultShippingCategory.find_or_create - super - end - - def create - delete_stock_params_and_set_after do - super - end - rescue Paperclip::Errors::NotIdentifiedByImageMagickError - invoke_callbacks(:create, :fails) - @object.errors.add(:base, t('spree.admin.products.image_upload_error')) - respond_with(@object) - end - - def update - original_supplier_id = @product.supplier_id - - delete_stock_params_and_set_after do - super - ExchangeVariantDeleter.new.delete(@product) if original_supplier_id != @product.supplier_id - end - end - - def bulk_update - product_set = product_set_from_params(params) - - # Ensure we're authorised to update all products - product_set.collection.each { |p| authorize! :update, p } - - if product_set.save - redirect_to main_app.bulk_products_api_products_path( bulk_index_query(params) ) - else - if product_set.errors.present? - render json: { errors: product_set.errors }, status: :bad_request - else - render nothing: true, status: :internal_server_error - end - end - end - - protected - - def collection - # This method is copied directly from the spree product controller - # except where we narrow the search below with the managed_by search to support - # enterprise users. - # TODO: There has to be a better way!!! - return @collection if @collection.present? - - params[:q] ||= {} - params[:q][:deleted_at_null] ||= "1" - - params[:q][:s] ||= "name asc" - # The next line is modified. - # Hit Spree::Product instead of super, avoiding cancan error for fetching - # records with block permissions via accessible_by. - @collection = Spree::Product - @collection = @collection.with_deleted if params[:q].delete(:deleted_at_null).blank? - # @search needs to be defined as this is passed to search_form_for - @search = @collection.ransack(params[:q]) - @collection = @search.result. - managed_by(spree_current_user). # this line is added to the original spree code!!!!! - group_by_products_id. - includes(product_includes). - page(params[:page]). - per(Spree::Config[:admin_products_per_page]) - - if params[:q][:s].include?("master_default_price_amount") - # PostgreSQL compatibility - @collection = @collection.group("spree_prices.amount") - end - @collection - end - - def collection_actions - [:index, :bulk_update] - end - - private - - def product_set_from_params(params) - collection_hash = Hash[params[:products].each_with_index.map { |p, i| [i, p] }] - Spree::ProductSet.new(collection_attributes: collection_hash) - end - - def bulk_index_query(params) - params[:filters].to_h.merge(page: params[:page], per_page: params[:per_page]) - end - - def load_form_data - @producers = OpenFoodNetwork::Permissions.new(spree_current_user). - managed_product_enterprises.is_primary_producer.by_name - @taxons = Spree::Taxon.order(:name) - @import_dates = product_import_dates.uniq.to_json - end - - def product_import_dates - options = [{ id: '0', name: '' }] - product_import_dates_query.collect(&:import_date). - map { |i| options.push(id: i.to_date, name: i.to_date.to_formatted_s(:long)) } - - options - end - - def product_import_dates_query - Spree::Variant. - select('DISTINCT spree_variants.import_date'). - joins(:product). - where('spree_products.supplier_id IN (?)', editable_enterprises.collect(&:id)). - where('spree_variants.import_date IS NOT NULL'). - where(spree_variants: { is_master: false }). - where(spree_variants: { deleted_at: nil }). - order('spree_variants.import_date DESC') - end - - def strip_new_properties - return if spree_current_user.admin? || params[:product][:product_properties_attributes].nil? - - names = Spree::Property.pluck(:name) - params[:product][:product_properties_attributes].each do |key, property| - unless names.include? property[:property_name] - params[:product][:product_properties_attributes].delete key - end - end - end - - def delete_stock_params_and_set_after - on_demand = params[:product].delete(:on_demand) - on_hand = params[:product].delete(:on_hand) - - yield - - set_stock_levels(@product, on_hand, on_demand) if @product.valid? - end - - def set_stock_levels(product, on_hand, on_demand) - variant = product_variant(product) - - begin - variant.on_demand = on_demand if on_demand.present? - variant.on_hand = on_hand.to_i if on_hand.present? - rescue StandardError => e - notify_bugsnag(e, product, variant) - raise e - end - end - - def notify_bugsnag(error, product, variant) - Bugsnag.notify(error) do |report| - report.add_tab(:product, product.attributes) - report.add_tab(:product_error, product.errors.first) unless product.valid? - report.add_tab(:variant, variant.attributes) - report.add_tab(:variant_error, variant.errors.first) unless variant.valid? - end - end - - def product_variant(product) - if product.variants.any? - product.variants.first - else - product.master - end - end - - def set_product_master_variant_price_to_zero - @product.price = 0 if @product.price.nil? - end -end