diff --git a/app/controllers/spree/admin/promotion_batches_controller.rb b/app/controllers/spree/admin/promotion_batches_controller.rb index d60e3e83b5..6f3ceec1dc 100644 --- a/app/controllers/spree/admin/promotion_batches_controller.rb +++ b/app/controllers/spree/admin/promotion_batches_controller.rb @@ -1,62 +1,46 @@ module Spree module Admin class PromotionBatchesController < ResourceController - def update - if @object.template_promotion_id - flash[:error] = Spree.t(:template_promotion_already_assigned) - respond_with(@object) do |format| - format.html { render action: :edit, status: :unprocessable_entity } - format.js { render layout: false, status: :unprocessable_entity } - end - return - end - super - end - - def destroy - result = Spree::PromotionBatches::Destroy.call(promotion_batch: @promotion_batch) - - if result.success? - flash[:success] = flash_message_for(@promotion_batch, :successfully_removed) - else - flash[:error] = @promotion_batch.errors.full_messages.join(', ') - end - - respond_with(@promotion_batch) do |format| - format.html { redirect_to location_after_destroy } - format.js { render_js_for_destroy } - end - end - - def csv_export - send_data Spree::PromotionBatches::PromotionCodesExporter.new(params).call, - filename: "promo_codes_from_batch_id_#{params[:id]}.csv", - disposition: :attachment, - type: 'text/csv' - end - - def csv_import - file = params[:file] - Spree::PromotionBatches::PromotionCodesImporter.new(file: file, promotion_batch_id: params[:id]).call - redirect_back fallback_location: admin_promotions_path, notice: Spree.t('code_upload') - rescue Spree::PromotionBatches::PromotionCodesImporter::Error => e - redirect_back fallback_location: admin_promotions_path, alert: e.message - end - - def populate - batch_id = params[:id] - options = { - batch_size: params[:batch_size].to_i, - affix: params.dig(:code, :affix)&.to_sym, - content: params[:affix_content], - deny_list: params[:forbidden_phrases].split, - random_part_bytes: params[:random_part_bytes].to_i - } - - Spree::Promotions::PopulatePromotionBatch.new(batch_id, options).call - - flash[:success] = Spree.t('promotion_batch_populated') - redirect_to spree.edit_admin_promotion_batch_url(@promotion_batch) + before_action :set_template_promotion + + def index + @promotion_batches = Spree::PromotionBatch.where(template_promotion: @template_promotion) + end + + def new + @promotion_batch = @template_promotion.promotion_batches.build + end + + def create + Spree::PromotionBatches::CreateWithRandomCodes.new.call(template_promotion: @template_promotion, amount: params[:amount].to_i, random_characters: params[:random_characters].to_i, prefix: params[:prefix], suffix: params[:suffix]) + end + + def import; end + + def process_import + file = params[:file].read + Spree::PromotionBatches::CreateWithCodes.new.call(template_promotion: @template_promotion, codes: file.split("\n")) + redirect_to(admin_template_promotion_promotion_batches_path(template_promotion_id: @template_promotion.id)) + end + + def export + @promotion_batch = @template_promotion.promotion_batches.find(params[:promotion_batch_id]) + csv = Spree::PromotionBatches::Export.new.call(promotion_batch: @promotion_batch) + send_data csv, filename: "codes_#{@promotion_batch}.csv" + end + + private + + def collection_url + admin_template_promotion_promotion_batches_url(@template_promotion) + end + + def new_object_url(options = nil) + new_admin_template_promotion_promotion_batch_url(@template_promotion) + end + + def set_template_promotion + @template_promotion = Spree::Promotion.templates.find(params[:template_promotion_id]) end end end diff --git a/app/controllers/spree/admin/promotions_controller.rb b/app/controllers/spree/admin/promotions_controller.rb index 4b66698654..18a81a3329 100644 --- a/app/controllers/spree/admin/promotions_controller.rb +++ b/app/controllers/spree/admin/promotions_controller.rb @@ -40,7 +40,7 @@ def collection params[:q][:s] ||= 'id desc' @collection = super - @collection = @collection.non_batched + # @collection = @collection.where(template: false) @search = @collection.ransack(params[:q]) @collection = @search.result(distinct: true). includes(promotion_includes). diff --git a/app/controllers/spree/admin/template_promotions_controller.rb b/app/controllers/spree/admin/template_promotions_controller.rb new file mode 100644 index 0000000000..f8a5c92459 --- /dev/null +++ b/app/controllers/spree/admin/template_promotions_controller.rb @@ -0,0 +1,82 @@ +module Spree + module Admin + class TemplatePromotionsController < ResourceController + before_action :load_data + + def create + invoke_callbacks(:create, :before) + @object.attributes = permitted_resource_params + @object.template = true + if @object.save + invoke_callbacks(:create, :after) + flash[:success] = flash_message_for(@object, :successfully_created) + respond_with(@object) do |format| + format.turbo_stream if create_turbo_stream_enabled? + format.html { redirect_to location_after_save } + format.js { render layout: false } + end + else + invoke_callbacks(:create, :fails) + respond_with(@object) do |format| + format.html { render action: :new, status: :unprocessable_entity } + format.js { render layout: false, status: :unprocessable_entity } + end + end + end + + private + + def new_object_url(options = {}) + spree.new_admin_template_promotion_url(options) + end + + def collection_url(options = {}) + spree.admin_template_promotions_url(options) + end + + def resource + return @resource if @resource + + parent_model_name = parent_data[:model_name] if parent_data + @resource = Spree::Admin::Resource.new 'admin/spree', 'template_promotions', parent_model_name, object_name + end + + def load_data + @actions = Rails.application.config.spree.promotions.actions + + @calculators = Rails.application.config.spree.calculators.promotion_actions_create_adjustments + @promotion_categories = Spree::PromotionCategory.order(:name) + @promotion = @object + end + + def collection + return @collection if defined?(@collection) + + params[:q] ||= HashWithIndifferentAccess.new + params[:q][:s] ||= 'id desc' + + @collection = super + @collection = @collection.templates + @search = @collection.ransack(params[:q]) + @collection = @search.result(distinct: true). + includes(promotion_includes). + page(params[:page]). + per(params[:per_page] || Spree::Backend::Config[:admin_promotions_per_page]) + + @promotions = @collection + end + + def promotion_includes + [:promotion_actions] + end + + def model_class + Spree::Promotion + end + + def permitted_resource_params + params.require(:promotion).permit! + end + end + end +end diff --git a/app/helpers/spree/admin/navigation_helper.rb b/app/helpers/spree/admin/navigation_helper.rb index 7b6c81a7b8..6dac1de9af 100644 --- a/app/helpers/spree/admin/navigation_helper.rb +++ b/app/helpers/spree/admin/navigation_helper.rb @@ -378,12 +378,16 @@ def product_properties_actions Rails.application.config.spree_backend.actions[:product_properties] end + def template_promotion_actions + Rails.application.config.spree_backend.actions[:template_promotion] + end + def promotion_batch_actions - Rails.application.config.spree_backend.actions[:promotion_batch_actions] + Rails.application.config.spree_backend.actions[:promotion_batch] end def promotion_batches_actions - Rails.application.config.spree_backend.actions[:promotion_batches_actions] + Rails.application.config.spree_backend.actions[:promotion_batches] end # rubocop:enable Metrics/ModuleLength end diff --git a/app/models/spree/admin/actions/promotion_batch_default_actions_builder.rb b/app/models/spree/admin/actions/promotion_batch_default_actions_builder.rb deleted file mode 100644 index f9c7979b9d..0000000000 --- a/app/models/spree/admin/actions/promotion_batch_default_actions_builder.rb +++ /dev/null @@ -1,27 +0,0 @@ -module Spree - module Admin - module Actions - class PromotionBatchDefaultActionsBuilder - include Spree::Core::Engine.routes.url_helpers - - def build - root = Root.new - export_codes_to_csv_action(root) - root - end - - private - - def export_codes_to_csv_action(root) - action = - ActionBuilder.new('csv_export', ->(resource) { csv_export_admin_promotion_batch_path(resource) }). - with_icon_key('download.svg'). - with_style(::Spree::Admin::Actions::ActionStyle::PRIMARY). - build - - root.add(action) - end - end - end - end -end diff --git a/app/models/spree/admin/actions/promotion_batches_default_actions_builder.rb b/app/models/spree/admin/actions/promotion_batches_default_actions_builder.rb index 79a6ea955f..03021bb42e 100644 --- a/app/models/spree/admin/actions/promotion_batches_default_actions_builder.rb +++ b/app/models/spree/admin/actions/promotion_batches_default_actions_builder.rb @@ -6,22 +6,49 @@ class PromotionBatchesDefaultActionsBuilder def build root = Root.new - add_new_promotion_batch_action(root) + add_view_promotions_action(root) + add_import_promotion_batch_action(root) + add_generate_promotion_batch_action(root) root end private - def add_new_promotion_batch_action(root) + def add_generate_promotion_batch_action(root) action = - ActionBuilder.new('new_promotion_batch', new_admin_promotion_batch_path). + ActionBuilder.new('generate_codes', ->(template_promotion) { new_admin_template_promotion_promotion_batch_path(template_promotion_id: template_promotion.id) }). + with_label_translation_key('admin.promotion_batches.generate_codes'). with_icon_key('add.svg'). - with_style(::Spree::Admin::Actions::ActionStyle::PRIMARY). - with_create_ability_check(::Spree::PromotionBatch). + with_style(Spree::Admin::Actions::ActionStyle::PRIMARY). + with_create_ability_check(Spree::PromotionBatch). build root.add(action) end + + def add_import_promotion_batch_action(root) + action = + ActionBuilder.new('import_csv', ->(template_promotion) { import_admin_template_promotion_promotion_batches_path(template_promotion_id: template_promotion.id) }). + with_label_translation_key('admin.promotion_batches.import_csv'). + with_icon_key('file-earmark-arrow-up.svg'). + with_style(Spree::Admin::Actions::ActionStyle::LIGHT). + with_create_ability_check(Spree::PromotionBatch). + build + + root.add(action) + end + + def add_view_promotions_action(root) + action = + ActionBuilder.new('view_promotions', ->(template_promotion) { admin_promotions_path(q: { for_template_promotion_id: template_promotion.id }) }). + with_label_translation_key('admin.promotion_batches.view_promotions'). + with_icon_key('list.svg'). + with_style(Spree::Admin::Actions::ActionStyle::LIGHT). + with_manage_ability_check(Spree::Promotion). + build + + root.add(action) + end end end end diff --git a/app/models/spree/admin/actions/template_promotion_default_actions_builder.rb b/app/models/spree/admin/actions/template_promotion_default_actions_builder.rb new file mode 100644 index 0000000000..f452c72310 --- /dev/null +++ b/app/models/spree/admin/actions/template_promotion_default_actions_builder.rb @@ -0,0 +1,55 @@ +module Spree + module Admin + module Actions + class TemplatePromotionDefaultActionsBuilder + include Spree::Core::Engine.routes.url_helpers + + def build + root = Root.new + add_view_promotion_batches_action(root) + add_import_promotion_batch_action(root) + add_generate_promotion_batch_action(root) + root + end + + private + + def add_generate_promotion_batch_action(root) + action = + ActionBuilder.new('generate_codes', ->(template_promotion) { new_admin_template_promotion_promotion_batch_path(template_promotion_id: template_promotion.id) }). + with_label_translation_key('admin.promotion_batches.generate_codes'). + with_icon_key('add.svg'). + with_style(Spree::Admin::Actions::ActionStyle::PRIMARY). + with_create_ability_check(Spree::PromotionBatch). + build + + root.add(action) + end + + def add_import_promotion_batch_action(root) + action = + ActionBuilder.new('import_csv', ->(template_promotion) { import_admin_template_promotion_promotion_batches_path(template_promotion_id: template_promotion.id) }). + with_label_translation_key('admin.promotion_batches.import_csv'). + with_icon_key('file-earmark-arrow-up.svg'). + with_style(Spree::Admin::Actions::ActionStyle::LIGHT). + with_create_ability_check(Spree::PromotionBatch). + build + + root.add(action) + end + + def add_view_promotion_batches_action(root) + action = + ActionBuilder.new('view_promotion_batches', ->(template_promotion) { admin_template_promotion_promotion_batches_path(template_promotion) }). + with_label_translation_key('admin.promotion_batches.view_promotions'). + with_icon_key('list.svg'). + with_style(Spree::Admin::Actions::ActionStyle::LIGHT). + with_manage_ability_check(Spree::Promotion). + build + + root.add(action) + end + end + end + end +end diff --git a/app/models/spree/admin/main_menu/default_configuration_builder.rb b/app/models/spree/admin/main_menu/default_configuration_builder.rb index b524eaada3..5cb2fda22d 100644 --- a/app/models/spree/admin/main_menu/default_configuration_builder.rb +++ b/app/models/spree/admin/main_menu/default_configuration_builder.rb @@ -19,7 +19,6 @@ def build add_integrations_section(root) add_oauth_section(root) add_settings_section(root) - add_promotion_batches_section(root) root end @@ -138,6 +137,10 @@ def add_promotions_section(root) ItemBuilder.new('promotion_categories', admin_promotion_categories_path). with_admin_ability_check(Spree::PromotionCategory). with_label_translation_key('admin.tab.promotion_categories'). + build, + ItemBuilder.new('bulk_promo_codes', admin_template_promotions_path). + with_admin_ability_check(Spree::Promotion, Spree::PromotionBatch). + with_label_translation_key('admin.tab.bulk_promo_codes'). build ] @@ -256,13 +259,6 @@ def add_settings_section(root) build root.add(section) end - - def add_promotion_batches_section(root) - root.add(ItemBuilder.new('promotion_batches', admin_promotion_batches_path). - with_icon_key('stack.svg'). - with_admin_ability_check(Spree::PromotionBatch). - build) - end # rubocop:enable Metrics/AbcSize end # rubocop:enable Metrics/ClassLength diff --git a/app/views/spree/admin/promotion_batches/_form.html.erb b/app/views/spree/admin/promotion_batches/_form.html.erb index c831fea953..279ea2810a 100644 --- a/app/views/spree/admin/promotion_batches/_form.html.erb +++ b/app/views/spree/admin/promotion_batches/_form.html.erb @@ -1,6 +1,26 @@ -
- <%= f.field_container :template_promotion do %> - <%= f.label :template_promotion_id, Spree.t(:template_promotion) %> - <%= f.collection_select :template_promotion_id, Spree::Promotion.non_batched, :id, ->(promotion) { "#{promotion.name} # #{promotion.id}" }, { include_blank: true }, { class: 'select2-clear w-100' } %> - <% end %> +
+
+

<%= Spree.t('admin.promotion_batches.general_settings') %>

+
+ <%= label_tag :amount, Spree.t('admin.promotion_batches.amount') %> + <%= number_field_tag :amount, nil, class: 'form-control' %> +
+ +
+

<%= Spree.t('admin.promotion_batches.generator_settings') %>

+
+ <%= label_tag :random_characters, Spree.t('admin.promotion_batches.random_characters') %> + <%= number_field_tag :random_characters, nil, class: 'form-control' %> +
+ +
+ <%= label_tag :prefix, Spree.t('admin.promotion_batches.prefix') %> + <%= text_field_tag :prefix, nil, class: 'form-control' %> +
+ +
+ <%= label_tag :suffix, Spree.t('admin.promotion_batches.suffix') %> + <%= text_field_tag :suffix, nil, class: 'form-control' %> +
+
diff --git a/app/views/spree/admin/promotion_batches/edit.html.erb b/app/views/spree/admin/promotion_batches/edit.html.erb deleted file mode 100644 index 8c1f21c7f7..0000000000 --- a/app/views/spree/admin/promotion_batches/edit.html.erb +++ /dev/null @@ -1,68 +0,0 @@ -<% content_for :page_title do %> - <%= link_to Spree.t(:promotion_batches), admin_promotion_batches_path %> / - <%= @promotion_batch.id %> -<% end %> - -<% if @promotion_batch.template_promotion_id%> -
-
- <%= form_tag csv_import_admin_promotion_batch_path, method: :post, multipart: true do %> - <%= file_field_tag :file, accept: ".csv" %> - <%= submit_tag Spree.t('promotion_batch_form.import_codes') %> - <% end %> -
-
-<% end %> - -<% unless @promotion_batch.template_promotion_id%> - <%= form_for @promotion_batch, url: object_url, method: :put do |f| %> -
-
- <%= render partial: 'form', locals: { f: f } %> - <%= render partial: 'spree/admin/shared/edit_resource_links' %> -
-
- <% end %> -<% end %> - -<% if @promotion_batch.template_promotion_id %> - <%= form_with url: populate_admin_promotion_batch_path(@promotion_batch), method: :post do %> -
- <%= label_tag :batch_size do %> - <%= number_field_tag(:batch_size) %> - <%= Spree.t('promotion_batch_form.batch_size') %> - <% end %> -
-
- <%= label_tag :prefix do %> - <%= radio_button :code, :affix, 'prefix' %> - <%= Spree.t('promotion_batch_form.prefix') %> - <% end %> -
-
- <%= label_tag :suffix do %> - <%= radio_button :code, :affix, 'suffix' %> - <%= Spree.t('promotion_batch_form.suffix') %> - <% end %> -
-
- <%= label_tag :affix_content do %> - <%= text_field_tag(:affix_content) %> - <%= Spree.t('promotion_batch_form.affix_content') %> - <% end %> -
-
- <%= label_tag :forbidden_phrases do %> - <%= text_area_tag(:forbidden_phrases) %> - <%= Spree.t('promotion_batch_form.forbidden_phrases') %> - <% end %> -
-
- <%= label_tag :random_part_bytes do %> - <%= number_field_tag(:random_part_bytes, value = 4) %> - <%= Spree.t('promotion_batch_form.random_part_bytes') %> - <% end %> -
- <%= submit_tag(Spree.t('promotion_batch_form.populate')) %> - <% end %> -<% end %> diff --git a/app/views/spree/admin/promotion_batches/import.html.erb b/app/views/spree/admin/promotion_batches/import.html.erb new file mode 100644 index 0000000000..39b0c52b47 --- /dev/null +++ b/app/views/spree/admin/promotion_batches/import.html.erb @@ -0,0 +1,24 @@ +<% content_for :page_title do %> + <%= link_to Spree.t(:template_promotions), admin_template_promotions_url %> / + <%= link_to @template_promotion.name, edit_admin_template_promotion_url(@template_promotion) %> / + <%= link_to Spree.t(:promotion_batches), admin_template_promotion_promotion_batches_url(@template_promotion) %> / + <%= Spree.t('admin.promotion_batches.import_csv') %> +<% end %> + + +
+
+ <%= form_tag process_import_admin_template_promotion_promotion_batches_path(@template_promotion), method: :post, multipart: true do %> +
+
+
+ <%= label_tag :file, Spree.t('admin.promotion_batches.csv_file'), class: 'form-control-file' %> + <%= file_field_tag :file, accept: '.csv' %> + <%= Spree.t('admin.promotion_batches.csv_file_notice') %> +
+ <%= render partial: 'spree/admin/shared/new_resource_links' %> +
+
+ <% end %> +
+
diff --git a/app/views/spree/admin/promotion_batches/index.html.erb b/app/views/spree/admin/promotion_batches/index.html.erb index 60b460ae49..a328042c9c 100644 --- a/app/views/spree/admin/promotion_batches/index.html.erb +++ b/app/views/spree/admin/promotion_batches/index.html.erb @@ -1,5 +1,7 @@ <% content_for :page_title do %> - <%= plural_resource_name(Spree::PromotionBatch) %> + <%= link_to Spree.t(:template_promotions), admin_template_promotions_url %> / + <%= link_to @template_promotion.name, edit_admin_template_promotion_url(@template_promotion) %> / + <%= Spree.t(:promotion_batches) %> <% end %> <% content_for :page_actions do %> @@ -7,7 +9,7 @@ <% next unless action.available?(current_ability) %> <%= button_link_to( Spree.t(action.label_translation_key), - action.url, + action.url(@template_promotion), class: action.classes, icon: action.icon_key ) %> @@ -20,26 +22,33 @@ <%= Spree.t(:id) %> - <%= Spree.t(:size) %> - <%= Spree.t(:template_promotion) %> + <%= Spree.t('admin.promotion_batches.generated_codes') %> + <%= Spree.t(:created_at) %> + <%= Spree.t(:state) %> <% @promotion_batches.each do |promotion_batch| %> - <%= link_to Spree::PromotionBatchPresenter.new(promotion_batch).call[:model_name_id], spree.admin_promotion_batch_path(promotion_batch) %> + <%= promotion_batch.id %> <%= promotion_batch.promotions.count %> - <%= link_to Spree::PromotionBatchPresenter.new(promotion_batch).call[:template_promotion_name_id], spree.edit_admin_promotion_path(promotion_batch.template_promotion) if promotion_batch.template_promotion %> - - - <%= link_to_edit promotion_batch, no_text: true if can?(:edit, promotion_batch) %> - <%= link_to_delete promotion_batch, no_text: true if can?(:delete, promotion_batch) %> - + <%= promotion_batch.created_at.strftime('%F %T %Z') %> + <%= promotion_batch.state %> + + <%= button_link_to('', admin_promotions_path({ q: { promotion_batch_id_eq: promotion_batch.id }}), icon: 'list.svg', class: 'btn btn-light btn-sm with-tip icon-link', data: { 'original-title' => Spree.t('admin.promotion_batches.view_promotions') }) %> + <%= button_link_to('', admin_template_promotion_promotion_batch_export_path(template_promotion_id: @template_promotion.id, promotion_batch_id: promotion_batch.id), icon: 'file-earmark-arrow-down.svg', class: 'btn btn-light btn-sm with-tip icon-link', data: { 'original-title' => Spree.t('admin.promotion_batches.export_csv')} ) %> <% end %>
-<% end %> \ No newline at end of file +<% else %> +
+ <%= Spree.t(:no_resource_found, resource: plural_resource_name(Spree::PromotionBatch)) %>, + <%= link_to Spree.t('admin.promotion_batches.generate_codes'), new_object_url if can?(:create, Spree::PromotionBatch) %> + <%= Spree.t(:or) %> + <%= link_to Spree.t('admin.promotion_batches.import_csv'), import_admin_template_promotion_promotion_batches_path(@template_promotion) if can?(:create, Spree::PromotionBatch) %>! +
+<% end %> diff --git a/app/views/spree/admin/promotion_batches/new.html.erb b/app/views/spree/admin/promotion_batches/new.html.erb index 328fe5e0c0..593775e52e 100644 --- a/app/views/spree/admin/promotion_batches/new.html.erb +++ b/app/views/spree/admin/promotion_batches/new.html.erb @@ -1,6 +1,8 @@ <% content_for :page_title do %> - <%= link_to Spree.t(:promotion_batches), admin_promotion_batches_path %> / - <%= Spree.t(:new_promotion_batch) %> + <%= link_to Spree.t(:template_promotions), admin_template_promotions_url %> / + <%= link_to @template_promotion.name, edit_admin_template_promotion_url(@template_promotion) %> / + <%= link_to Spree.t(:promotion_batches), admin_template_promotion_promotion_batches_url(@template_promotion) %> / + <%= Spree.t(:generate_codes) %> <% end %>
diff --git a/app/views/spree/admin/promotion_batches/show.html.erb b/app/views/spree/admin/promotion_batches/show.html.erb deleted file mode 100644 index 2bad5bdcfe..0000000000 --- a/app/views/spree/admin/promotion_batches/show.html.erb +++ /dev/null @@ -1,37 +0,0 @@ -<% content_for :page_title do %> - <%= link_to Spree.t(:promotion_batches), admin_promotion_batches_path %> / - <%= @promotion_batch.id %> -<% end %> - -<% content_for :page_actions do %> - <% promotion_batch_actions.items.each do |action| %> - <% next unless action.available?(current_ability) %> - <%= button_link_to( - Spree.t(action.label_translation_key), - action.url(@promotion_batch), - class: action.classes, - icon: action.icon_key - ) %> - <% end %> -<% end %> - - - - - - - - - - - - <% @promotion_batch.promotions.each do |promotion| %> - - - - - - - <% end %> - -
<%= Spree.t(:code) %><%= Spree.t(:description) %><%= Spree.t(:redeemed) %><%= Spree.t(:expiration) %>
<%= promotion.code %><%= promotion.description %><%= promotion.credits_count == promotion.usage_limit ? Spree.t(:say_yes) : Spree.t(:say_no) %><%= promotion.expires_at.to_date if promotion.expires_at %>
diff --git a/app/views/spree/admin/template_promotions/_form.html.erb b/app/views/spree/admin/template_promotions/_form.html.erb new file mode 100644 index 0000000000..73ea5f4fad --- /dev/null +++ b/app/views/spree/admin/template_promotions/_form.html.erb @@ -0,0 +1,77 @@ +<%= render partial: 'spree/admin/shared/error_messages', locals: { target: @promotion } %> + +
+
+ <%= f.field_container :name do %> + <%= f.label :name %> + <%= f.text_field :name, class: 'form-control' %> + <%= f.error_message_on :name %> + <% end %> + + <%= f.field_container :path do %> + <%= f.label :path %> + <%= f.text_field :path, class: 'form-control' %> + <% end %> + + <%= f.field_container :advertise, class: ['checkbox'] do %> + <%= f.label :advertise do %> + <%= f.check_box :advertise %> + <%= Spree.t(:advertise) %> + <% end %> + <% end %> +
+ +
+ <%= f.field_container :description do %> + <%= f.label :description %> + <%= f.text_area :description, rows: 7, class: 'form-control' %> + <% end %> + + <%= f.field_container :category do %> + <%= f.label :promotion_category %> + <%= f.collection_select(:promotion_category_id, @promotion_categories, :id, :name, { include_blank: Spree.t('match_choices.none') }, { class: 'select2 w-100' }) %> + <% end %> + + <% if @stores.count > 1 %> + <%= f.field_container :stores do %> + <%= f.label :promotion_stores, Spree.t(:stores) %> + <%= collection_select(:promotion, :store_ids, @stores, :id, :unique_name, {}, { multiple: true, class: 'select2' }) %> + <% end %> + <% end %> +
+ +
+
+ <%= f.label :starts_at %> +
+ <%= f.datetime_field :starts_at, + class: 'form-control', + placeholder: Spree.t('starting_from'), + 'data-input':'' %> + + <%= render partial: 'spree/admin/shared/cal_close' %> +
+
+ +
+ <%= f.label :expires_at %> +
+ <%= f.datetime_field :expires_at, + placeholder:Spree.t('ends_at'), + class: 'form-control', + 'data-input':'' %> + + <%= render partial: 'spree/admin/shared/cal_close' %> +
+
+ +
+
diff --git a/app/views/spree/admin/template_promotions/edit.html.erb b/app/views/spree/admin/template_promotions/edit.html.erb new file mode 100644 index 0000000000..2a09dc07bc --- /dev/null +++ b/app/views/spree/admin/template_promotions/edit.html.erb @@ -0,0 +1,42 @@ +<% content_for :page_title do %> + <%= link_to Spree.t(:template_promotions), admin_template_promotions_url %> / + <%= @promotion.name %> +<% end %> + +<% content_for :page_actions do %> + <% template_promotion_actions.items.each do |action| %> + <% next unless action.available?(current_ability) %> + <%= button_link_to( + Spree.t(action.label_translation_key), + action.url(@promotion), + class: action.classes, + icon: action.icon_key + ) %> + <% end %> +<% end %> + +<%= form_for @promotion, url: object_url, method: :put do |f| %> +
+
+ <%= render partial: 'form', locals: { f: f } %> + <%= render partial: 'spree/admin/shared/edit_resource_links' %> +
+
+ +<% end %> + +
+
+
+ <%= render partial: 'spree/admin/promotions/rules' %> +
+
+ +
+
+ <%= render partial: 'spree/admin/promotions/actions' %> +
+
+
+ +<%= render partial: "spree/admin/variants/autocomplete", formats: [:js] %> diff --git a/app/views/spree/admin/template_promotions/index.html.erb b/app/views/spree/admin/template_promotions/index.html.erb new file mode 100644 index 0000000000..d7fa9159a5 --- /dev/null +++ b/app/views/spree/admin/template_promotions/index.html.erb @@ -0,0 +1,71 @@ +<% content_for :page_title do %> + <%= Spree.t(:template_promotions) %> +<% end %> + +<% content_for :page_actions do %> + <%= button_link_to Spree.t('admin.template_promotions.new_template'), new_object_url, class: "btn-success", icon: 'add.svg' %> +<% end if can?(:create, Spree::Promotion) %> + +<% content_for :table_filter do %> +
+ <%= search_form_for [:admin, @search] do |f| %> +
+
+
+ <%= label_tag :q_name_cont, Spree.t(:name) %> + <%= f.text_field :name_cont, tabindex: 1, class: "form-control js-quick-search-target js-filterable" %> +
+
+ +
+
+ <%= label_tag :q_promotion_category_id_eq, Spree.t(:promotion_category) %> + <%= f.collection_select(:promotion_category_id_eq, @promotion_categories, :id, :name, { include_blank: Spree.t('match_choices.all') }, { class: 'select2 js-filterable' }) %> +
+
+
+ +
+ <%= button Spree.t(:filter_results), 'search.svg' %> +
+ <% end %> +
+<% end %> + +<% if @promotions.any? %> +
+ + + + + + + + + + + + <% @promotions.each do |template| %> + + + + + + + + <% end %> + +
<%= Spree.t(:name) %><%= Spree.t(:description) %><%= Spree.t('admin.template_promotions.generated_promotions') %><%= Spree.t(:expiration) %>
<%= link_to template.name, spree.edit_admin_template_promotion_path(template) %><%= template.description %><%= link_to template.promotion_from_template.count, admin_template_promotion_promotion_batches_path(template) %><%= template.expires_at.to_date if template.expires_at %> + + <%= link_to_edit template, no_text: true if can?(:edit, template) %> + <%= button_link_to '', admin_template_promotion_promotion_batches_path(template), class: 'btn btn-light btn-sm icon-link with-tip', icon: 'list.svg', data: { 'original-title' => Spree.t('admin.promotion_batches.view_promotions')} %> + +
+
+ <%= render 'spree/admin/shared/index_table_options', collection: @promotions, simple: true %> +<% else %> +
+ <%= Spree.t(:no_resource_found, resource: plural_resource_name(Spree::Promotion)) %>, + <%= link_to Spree.t(:add_one), new_object_url if can?(:create, Spree::Promotion) %>! +
+<% end %> diff --git a/app/views/spree/admin/template_promotions/new.html.erb b/app/views/spree/admin/template_promotions/new.html.erb new file mode 100644 index 0000000000..58086c09e8 --- /dev/null +++ b/app/views/spree/admin/template_promotions/new.html.erb @@ -0,0 +1,13 @@ +<% content_for :page_title do %> + <%= link_to Spree.t(:template_promotions), admin_template_promotions_url %> / + <%= Spree.t('admin.template_promotions.new_template') %> +<% end %> + +
+
+ <%= form_for :promotion, url: collection_url do |f| %> + <%= render partial: 'form', locals: { f: f } %> + <%= render partial: 'spree/admin/shared/new_resource_links' %> + <% end %> +
+
diff --git a/config/locales/en.yml b/config/locales/en.yml index 435aeeda45..4bd4bef8ed 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -116,6 +116,7 @@ en: physical: Physical digital: Digital tab: + bulk_promo_codes: Bulk Promo Codes configuration: Configuration content: Content option_types: Option Types @@ -171,6 +172,20 @@ en: scopes: Scopes documentation_message: 'To learn how to authenticate requests to the Platform API, ' documentation_cta: see the documentation + promotion_batches: + amount: Number of codes to generate + csv_file: Select a CSV file to import + csv_file_notice: The CSV file should include one promo code per line, without any additional columns + export_csv: Export CSV + generate_codes: Generate Codes + generated_codes: Generated Codes + general_settings: General Settings + generator_settings: Generator Settings + import_csv: Import CSV + prefix: (Optional) Prefix + random_characters: Number of random characters to generate for each code + suffix: (Optional) Suffix + view_promotions: View Promotions reports: for: For %{store_name} return_authorization: @@ -190,6 +205,9 @@ en: customer_support_email_help: "This email is visible to your Store visitors in the Footer section" new_order_notifications_email_help: "If you want to receive an email notification every time someone places an Order please provide an email address for that notification to be sent to" seo_robots: "Please check this page for more help" + template_promotions: + generated_promotions: Generated Promotions + new_template: New Template user: account: Account addresses: Addresses diff --git a/config/routes.rb b/config/routes.rb index c1ee28aa19..a469e83403 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,11 +10,14 @@ resources :promotion_categories, except: [:show] - resources :promotion_batches do - member do - get :csv_export, to: 'promotion_batches#csv_export' - post :csv_import, to: 'promotion_batches#csv_import' - post :populate + resources :template_promotions do + resources :promotion_batches, only: %i[index new create show] do + collection do + get :import + post :process_import, to: 'promotion_batches#process_import' + end + + get :export end end diff --git a/lib/spree/backend/engine.rb b/lib/spree/backend/engine.rb index 119358659a..752aea2bb5 100644 --- a/lib/spree/backend/engine.rb +++ b/lib/spree/backend/engine.rb @@ -48,10 +48,9 @@ class Engine < ::Rails::Engine Rails.application.config.spree_backend.actions[:payments] = Spree::Admin::Actions::PaymentsDefaultActionsBuilder.new.build Rails.application.config.spree_backend.actions[:variants] = Spree::Admin::Actions::VariantsDefaultActionsBuilder.new.build Rails.application.config.spree_backend.actions[:product_properties] = Spree::Admin::Actions::ProductPropertiesDefaultActionsBuilder.new.build - Rails.application.config.spree_backend.actions[:promotion_batch_actions] = - Spree::Admin::Actions::PromotionBatchDefaultActionsBuilder.new.build - Rails.application.config.spree_backend.actions[:promotion_batches_actions] = - Spree::Admin::Actions::PromotionBatchesDefaultActionsBuilder.new.build + Rails.application.config.spree_backend.actions[:template_promotion] = Spree::Admin::Actions::TemplatePromotionDefaultActionsBuilder.new.build + Rails.application.config.spree_backend.actions[:promotion_batch] = Spree::Admin::Actions::PromotionBatchDefaultActionsBuilder.new.build + Rails.application.config.spree_backend.actions[:promotion_batches] = Spree::Admin::Actions::PromotionBatchesDefaultActionsBuilder.new.build end end end diff --git a/spec/models/spree/admin/actions/promotion_batch_default_actions_builder_spec.rb b/spec/models/spree/admin/actions/promotion_batch_default_actions_builder_spec.rb deleted file mode 100644 index 2f45ca3460..0000000000 --- a/spec/models/spree/admin/actions/promotion_batch_default_actions_builder_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -require 'spec_helper' - -module Spree - module Admin - describe Actions::PromotionBatchDefaultActionsBuilder, type: :model do - let(:builder) { described_class.new } - let(:default_actions) do - %w(csv_export) - end - - describe '#build' do - subject { builder.build } - - it 'builds default tabs' do - expect(subject.items.map(&:key)).to match(default_actions) - end - end - end - end -end