Skip to content

Commit

Permalink
Add promotion code batch
Browse files Browse the repository at this point in the history
  • Loading branch information
vladstoick committed Oct 23, 2016
1 parent 3003e2a commit a3babeb
Show file tree
Hide file tree
Showing 24 changed files with 454 additions and 388 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module Spree
module Admin
class PromotionCodeBatchesController < ResourceController
belongs_to 'spree/promotion'

create.after :build_promotion_code_batch

def download
require "csv"

@promotion_code_batch = Spree::PromotionCodeBatch.find(
id: params[:promotion_code_batch_id]
)

respond_to do |format|
format.csv do
filename = "promotion-code-batch-list-#{@promotion_code_batch.id}.csv"
headers["Content-Type"] = "text/csv"
headers["Content-disposition"] = "attachment; filename=\"#{filename}\""
end
end
end

private

def build_promotion_code_batch
@promotion_code_batch.process
end
end
end
end
27 changes: 4 additions & 23 deletions backend/app/controllers/spree/admin/promotions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,24 @@ module Spree
module Admin
class PromotionsController < ResourceController
before_action :load_data
before_action :load_bulk_code_information, only: [:edit]

helper 'spree/promotion_rules'

def create
@promotion_builder = Spree::PromotionBuilder.new(
permitted_promo_builder_params.merge(user: try_spree_current_user),
permitted_resource_params
)
@promotion = @promotion_builder.promotion
@promotion = Spree::Promotion.new(permitted_resource_params)
@promotion.codes.new(value: params[:single_code]) if params[:single_code].present?

if @promotion_builder.perform
if @promotion.save
flash[:success] = Spree.t(:promotion_successfully_created)
redirect_to location_after_save
else
flash[:error] = @promotion_builder.errors.full_messages.join(", ")
flash[:error] = @promotion.errors.full_messages.join(", ")
render action: 'new'
end
end

private

def load_bulk_code_information
@promotion_builder = Spree::PromotionBuilder.new(
base_code: @promotion.codes.first.try!(:value),
number_of_codes: @promotion.codes.count
)
end

def location_after_save
spree.edit_admin_promotion_url(@promotion)
end
Expand Down Expand Up @@ -58,14 +47,6 @@ def collection
def promotion_includes
[:promotion_actions]
end

def permitted_promo_builder_params
if params[:promotion_builder]
params[:promotion_builder].permit(:base_code, :number_of_codes)
else
{}
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CSV.generate do |csv|
csv << ['Code']
@promotion_code_batch.promotion_codes.order(:id).pluck(:value).each do |value|
csv << [value]
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<% admin_breadcrumb(link_to plural_resource_name(Spree::Promotion), spree.admin_promotions_path) %>
<% admin_breadcrumb(link_to @promotion.name, spree.edit_admin_promotion_path(@promotion.id)) %>
<% admin_breadcrumb(plural_resource_name(Spree::PromotionCodeBatch)) %>

<% content_for :page_actions do %>
<li>
<% if can?(:create, Spree::PromotionCodeBatch) %>
<%= button_link_to Spree.t(:new_promotion_code_batch), new_object_url %>
<% end %>
</li>
<% end %>

<% if @promotion_code_batches.any? %>
<table>
<thead>
<tr>
<th><%= Spree.t("promotion_code_batches.base_code") %></th>
<th><%= Spree.t("promotion_code_batches.total_codes") %></th>
<th><%= Spree.t("promotion_code_batches.status") %></th>
<th><%= Spree.t("promotion_code_batches.email") %></th>
</tr>
</thead>
<tbody>
<% @promotion_code_batches.each do |promotion_code_batch| %>
<tr>
<td><%= promotion_code_batch.base_code %></td>
<td><%= promotion_code_batch.number_of_codes %></td>
<td>
<% if promotion_code_batch.error.present? %>
<%= Spree.t(
"promotion_code_batches.errored",
error: promotion_code_batch.error
) %>
<% elsif promotion_code_batch.finished? %>
<%= Spree.t(
"promotion_code_batches.finished",
number_of_codes: promotion_code_batch.number_of_codes
) %>
<%= link_to(
Spree.t(:download_promotion_code_list),
admin_promotion_promotion_code_batch_download_path(
promotion_code_batch_id: promotion_code_batch.id,
format: :csv
)
) %>
<% else %>
<%= Spree.t(
"promotion_code_batches.processing",
number_of_codes: promotion_code_batch.number_of_codes,
number_of_codes_processed: promotion_code_batch.promotion_codes.count
) %>
<% end %>
</td>
<td><%= promotion_code_batch.email %></td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<div class="no-objects-found">
<%= render 'spree/admin/shared/no_objects_found',
resource: Spree::PromotionCodeBatch,
new_resource_url: new_object_url %>
</div>
<% end %>
23 changes: 23 additions & 0 deletions backend/app/views/spree/admin/promotion_code_batches/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<% admin_breadcrumb(link_to plural_resource_name(Spree::Promotion), spree.admin_promotions_path) %>
<% admin_breadcrumb(link_to @promotion.name, spree.admin_promotion_path(@promotion.id)) %>
<% admin_breadcrumb(plural_resource_name(Spree::PromotionCodeBatch)) %>

<%= form_for :promotion_code_batch, url: collection_url do |f| %>
<%= f.hidden_field :promotion_id, value: params[:promotion_id] %>

<%= f.field_container :base_code do %>
<%= f.label :base_code %>
<%= f.text_field :base_code, class: "fullwidth" %>
<% end %>

<%= f.field_container :number_of_codes do %>
<%= f.label :number_of_codes %>
<%= f.text_field :number_of_codes, class: "fullwidth" %>
<% end %>

<%= f.field_container :email do %>
<%= f.label :email %>
<%= f.text_field :email, class: "fullwidth", value: spree_current_user.email %>
<% end %>
<%= button Spree.t('actions.create') %>
<% end %>
15 changes: 4 additions & 11 deletions backend/app/views/spree/admin/promotions/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,10 @@
<%= f.text_field :name, :class => 'fullwidth' %>
<% end %>

<%= fields_for :promotion_builder do |bf| %>
<%= bf.field_container :base_code do %>
<%= bf.label :base_code %>
<%= bf.text_field :base_code, :readonly => !@promotion.new_record?, :class => 'fullwidth' %>
<% end %>

<%= bf.field_container :number_of_codes do %>
<%= bf.label :number_of_codes %>
<%= bf.text_field :number_of_codes, :readonly => !@promotion.new_record?, class: 'fullwidth' %>
<% end %>
<% end %>
<div class="field" id="promotion_single_code_field">
<%= label_tag :single_code %>
<%= text_field_tag :single_code, @promotion.codes.first.try!(:value), :readonly => !@promotion.new_record?, :class => 'fullwidth' %>
</div>

<%= f.field_container :per_code_usage_limit do %>
<%= f.label :per_code_usage_limit %>
Expand Down
4 changes: 4 additions & 0 deletions backend/app/views/spree/admin/promotions/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
<% if can?(:display, Spree::PromotionCode) %>
<%= button_link_to Spree.t(:download_promotion_code_list), admin_promotion_promotion_codes_path(promotion_id: @promotion.id, format: :csv) %>
<% end %>

<% if can?(:display, Spree::PromotionCodeBatch) %>
<%= button_link_to plural_resource_name(Spree::PromotionCodeBatch), admin_promotion_promotion_code_batches_path(promotion_id: @promotion.id) %>
<% end %>
</li>
<% end %>

Expand Down
3 changes: 3 additions & 0 deletions backend/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
resources :promotion_rules
resources :promotion_actions
resources :promotion_codes, only: [:index]
resources :promotion_code_batches, only: [:index, :new, :create] do
get '/download', to: "promotion_code_batches#download", defaults: { format: "csv" }
end
end

resources :promotion_categories, except: [:show]
Expand Down
66 changes: 30 additions & 36 deletions backend/spec/controllers/spree/admin/promotions_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,52 +46,46 @@
let(:params) { { promotion: { name: 'some promo' } } }

context "it succeeds" do
it "creates a promotion" do
expect { subject }.to change { Spree::Promotion.count }.by(1)
end
context "with no single code param" do
it "creates a promotion" do
expect { subject }.to change { Spree::Promotion.count }.by(1)
end

it "sets the flash message" do
subject
expect(flash[:success]).to eq "Promotion has been successfully created!"
end
it "sets the flash message" do
subject
expect(flash[:success]).to eq "Promotion has been successfully created!"
end

it "redirects to promotion edit" do
subject
expect(response).to redirect_to "http://test.host/admin/promotions/#{assigns(:promotion).id}/edit"
end
it "redirects to promotion edit" do
subject
expect(response).to redirect_to "http://test.host/admin/promotions/#{assigns(:promotion).id}/edit"
end

context "with one promo codes" do
let(:params) do
super().merge(promotion_builder: { base_code: 'abc', number_of_codes: 1 })
it "doesn't create any promotion codes" do
expect { subject }.to_not change { Spree::PromotionCode.count }
end
end

it "succeeds and creates one code" do
expect {
expect {
subject
}.to change { Spree::Promotion.count }.by(1)
}.to change { Spree::PromotionCode.count }.by(1)
context "with a single code" do
let(:params) { { promotion: { name: 'some promo' }, single_code: "promo" } }

expect(assigns(:promotion).codes.first.value).to eq 'abc'
it "creates a promotion" do
expect { subject }.to change { Spree::Promotion.count }.by(1)
end
end

context "with multiple promo codes" do
let(:params) do
super().merge(promotion_builder: { base_code: 'abc', number_of_codes: 2 })
it "sets the flash message" do
subject
expect(flash[:success]).to eq "Promotion has been successfully created!"
end

it "redirects to promotion edit" do
subject
expect(response).to redirect_to "http://test.host/admin/promotions/#{assigns(:promotion).id}/edit"
end

it "succeeds and creates multiple codes" do
expect {
expect {
subject
}.to change { Spree::Promotion.count }.by(1)
}.to change { Spree::PromotionCode.count }.by(2)

codes = assigns(:promotion).codes.map(&:value).sort
expect(codes.length).to be 2
expect(codes[0]).to match(/abc_[a-z]{6}/)
expect(codes[1]).to match(/abc_[a-z]{6}/)
it "creates a promotion code" do
expect { subject }.to change { Spree::PromotionCode.count }.by(1)
expect(Spree::PromotionCode.last.value).to eq("promo")
end
end
end
Expand Down
8 changes: 4 additions & 4 deletions backend/spec/features/admin/promotion_adjustments_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@

it "should allow an admin to create a flat rate discount coupon promo" do
fill_in "Name", with: "Promotion"
fill_in "Base code", with: "order"
fill_in "Number of codes", with: "1"
fill_in "Single code", with: "order"

click_button "Create"
expect(page).to have_content("PromotionsPromotion")

Expand Down Expand Up @@ -48,8 +48,8 @@
it "should allow an admin to create a single user coupon promo with flat rate discount" do
fill_in "Name", with: "Promotion"
fill_in "promotion[usage_limit]", with: "1"
fill_in "Base code", with: "single_use"
fill_in "Number of codes", with: "1"
fill_in "Single code", with: "single_use"

click_button "Create"
expect(page).to have_content("PromotionsPromotion")

Expand Down
11 changes: 11 additions & 0 deletions core/app/jobs/spree/promotion_code_batch_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Spree
class PromotionCodeBatchJob < ActiveJob::Base
queue_as :default

def perform(promotion_batch)
PromotionCode::BatchBuilder.new(
promotion_batch
).build_promotion_codes
end
end
end
31 changes: 31 additions & 0 deletions core/app/mailers/spree/promotion_code_batch_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module Spree
class PromotionCodeBatchMailer < ApplicationMailer
def promotion_code_batch_finished(promotion_code_batch)
mail(
to: promotion_code_batch.email,
body: Spree.t(
"promotion_code_batches.finished",
number_of_codes: promotion_code_batch.number_of_codes
),
subject: Spree.t(
"promotion_code_batches.email_subject.batch_finished",
promotion_code_batch_id: promotion_code_batch.id
),
)
end

def promotion_code_batch_errored(promotion_code_batch)
mail(
to: promotion_code_batch.email,
body: Spree.t(
"promotion_code_batches.errored",
error: promotion_code_batch.error
),
subject: Spree.t(
"promotion_code_batches.email_subject.batch_errored",
promotion_code_batch_id: promotion_code_batch.id
),
)
end
end
end
2 changes: 2 additions & 0 deletions core/app/models/spree/promotion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class Promotion < Spree::Base
has_many :codes, class_name: "Spree::PromotionCode", inverse_of: :promotion, dependent: :destroy
alias_method :promotion_codes, :codes

has_many :promotion_code_batches, class_name: "Spree::PromotionCodeBatch", dependent: :destroy

accepts_nested_attributes_for :promotion_actions, :promotion_rules

validates_associated :rules
Expand Down
Loading

0 comments on commit a3babeb

Please sign in to comment.