Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bulk upload store credit button added #1

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
SpreeBulkStoreCredits
=====================

Introduction goes here.
This extension allows the admin to provide store credits in bulk to users through csv import or multi-select user list from the users admin panel.

Try Spree Bulk Store Credit for Spree 3-4 with direct deployment on Heroku:

[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/himanshumishra31/teststorecredits)

## Installation

Expand Down Expand Up @@ -40,11 +44,13 @@ Simply add this require statement to your spec_helper:
require 'spree_bulk_store_credits/factories'
```

## See It In Action
<a href="http://www.youtube.com/watch?feature=player_embedded&v=iAMM7npK3vg
" target="_blank"><img src="http://img.youtube.com/vi/iAMM7npK3vg/0.jpg"
alt="Youtube Video Tutorial" /></a>

## Contributing
## Credits

If you'd like to contribute, please take a look at the
[instructions](CONTRIBUTING.md) for installing dependencies and crafting a good
pull request.
[![vinsol.com: Ruby on Rails, iOS and Android developers](http://vinsol.com/vin_logo.png "Ruby on Rails, iOS and Android developers")](http://vinsol.com)

Copyright (c) 2018 [name of extension creator], released under the New BSD License
Copyright (c) 2018 [vinsol.com](http://vinsol.com "Ruby on Rails, iOS and Android developers"), released under the New MIT License
28 changes: 28 additions & 0 deletions app/assets/javascripts/spree/backend/csv_input_button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
function CsvInputButton(input) {
this.fileInput = input.fileInput;
this.submitButton = input.submitButton;
this.form = input.form;
}
CsvInputButton.prototype.init = function() {
var _this = this;
this.submitButton.on('click', function() {
event.preventDefault();
_this.fileInput.click();
_this.submitForm();
});
};
CsvInputButton.prototype.submitForm = function() {
var _this = this;
this.fileInput.on('change', function() {
_this.form.submit();
});
};
$(function() {
var inputs = {
fileInput: $('input#file'),
submitButton: $('input[data-disable-with="Import Store Credit CSV"]'),
form: $("form[data-hook='csv_form']")
},
csvButtonsManager = new CsvInputButton(inputs);
csvButtonsManager.init();
});
54 changes: 54 additions & 0 deletions app/assets/javascripts/spree/backend/infinite_scroller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
function InfiniteScroller(options){
this.$infiniteScroll = options.$infiniteScroll
this.windowHeight = $(window).height();
this.documentHeight = $(document).height();
}

InfiniteScroller.prototype.init = function(){
var _this = this;
if(this.$infiniteScroll.length > 0){
this.enable();
}
};

InfiniteScroller.prototype.enable = function(){
this.timer = null,
_this = this;

//if no vertical scrollbar present
if(this.windowHeight >= this.documentHeight){
this.makeDelayedRequest();
}

//when scrolled
$(window).scroll(function() {
_this.makeDelayedRequest();
});

};

InfiniteScroller.prototype.makeDelayedRequest = function(){
var _this = this;

if(this.timer) {
window.clearTimeout(this.timer);
}

this.timer = window.setTimeout(function() {
_this.fetchMoreCollections();
}, 500);
};

InfiniteScroller.prototype.fetchMoreCollections = function(){
var more_collections_url = this.$infiniteScroll.find('[data-pagination="on"] .pagination .next a').attr('href');
if(more_collections_url && ($(window).scrollTop() >= (this.documentHeight - this.windowHeight))){
$.getScript(more_collections_url);
}
};

$(function(){
var infiniteScrollerArguments = { $infiniteScroll: $('#infinite-scroll') },
infiniteScroller = new InfiniteScroller(infiniteScrollerArguments);

infiniteScroller.init();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
function RestrictNumberField(input) {
this.numberField = input.numberField;
}

RestrictNumberField.prototype.init = function() {
this.numberField.keydown(function(e) {
if ([69, 187, 188, 189, 190].includes(e.keyCode)) {
e.preventDefault();
}
});
};

$(function() {
var input = {
numberField: $("input[name='credit_value']")
},
restrictNumberFieldManager = new RestrictNumberField(input);
restrictNumberFieldManager.init();
});
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
// Placeholder manifest file.
// the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/backend/all.js'
// the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/backend/all.js'
//= require spree/backend/csv_input_button
//= require spree/backend/restrict_alphabet_in_numeric_field
47 changes: 47 additions & 0 deletions app/assets/javascripts/spree/backend/user_selection_manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
function UserSelectionManager(options){
this.tableBodySelector = options.tableBodySelector;
this.checkboxSelector = options.checkboxSelector;
}

UserSelectionManager.prototype.init = function(){
$(this.tableBodySelector).on('change', this.checkboxSelector, this.hideRow());
};

UserSelectionManager.prototype.hideRow = function(){
var _this = this;

return function(){
var changedCheckbox = this,
$rowToMove = $($(this).parents('tr')[0]).fadeOut('slow', 'linear', _this.moveRow(changedCheckbox));
};
};

UserSelectionManager.prototype.moveRow = function(changedCheckbox){
var _this = this;

return function(){
$(this).remove();

if($(changedCheckbox).is(':checked')){
//moving row to the top of table
$(_this.tableBodySelector).prepend($(this));
}else{
//moving row to the top of unselected rows
var $latestSelectedCheckbox = $(_this.checkboxSelector + ':checked').last();
if($latestSelectedCheckbox.length == 0){
$(_this.tableBodySelector).prepend($(this));
}else{
$($latestSelectedCheckbox.parents('tr')[0]).after($(this));
}
}
$(this).fadeIn('slow', 'linear');
};
};

$(function(){
var userSelectionManagerArguments = { tableBodySelector: '#listing_users tbody',
checkboxSelector: '[data-checkbox="user_select"]' },
userSelectionManager = new UserSelectionManager(userSelectionManagerArguments);

userSelectionManager.init();
});
14 changes: 14 additions & 0 deletions app/assets/stylesheets/spree/backend/spree_bulk_store_credits.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,17 @@
Placeholder manifest file.
the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/backend/all.css'
*/
input.file-browse {
display: none;
}

a.sample-download {
padding-right: 30px;
}

input#credit_value {
padding-right: 30px;
width: 157px;
display: inline;
margin-left: 70%;
}
56 changes: 56 additions & 0 deletions app/controllers/spree/admin/users_controller_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
Spree::Admin::UsersController.class_eval do

def sample_store_credit_csv
send_file STORE_CREDIT_CSV_FILE[:sample_store_credit_file]
end

def import_store_credits
begin
create_store_credit_updater
flash[:success] = Spree.t(:email_sent, filename: @store_credit_updater.data_file_file_name)
redirect_to bulk_store_credits_admin_users_path
rescue
flash[:error] = Spree.t(:invalid_format)
redirect_to bulk_store_credits_admin_users_path
end
end

def bulk_store_credits
@search = Spree::User.ransack(params[:q])
@collection = @search.result.present? ? @search.result.page(params[:page]).per(Spree::BulkStoreCreditUpdater::USER_PER_PAGE) : Spree::User.page(params[:page]).per(Spree::BulkStoreCreditUpdater::USER_PER_PAGE)
respond_to do |format|
format.html
format.js
end
end

def update_bulk_credits
begin
list_store_credit_updater
flash[:success] = Spree.t(:email_sent_for_users_credit)
redirect_to bulk_store_credits_admin_users_path
rescue
flash[:error] = Spree.t(:integer_value_only)
redirect_to bulk_store_credits_admin_users_path
end
end

private

def create_store_credit_updater
@store_credit_updater = Spree::BulkStoreCreditUpdater.create(data_file: params[:file])
if @store_credit_updater.valid?
NotifyStoreCreditService.delay(run_at: 1.minutes.from_now).new(@store_credit_updater.id, try_spree_current_user.email)
else
raise 'Invalid Format Exception'
end
end

def list_store_credit_updater
if params[:credit_value].scan(/\D/).empty? && params[:credit_value].present?
ListStoreCreditUpdater.delay(run_at: 1.minutes.from_now).new(params[:users].reject(&:empty?), try_spree_current_user.email, params[:credit_value])
else
raise 'Please Enter Integer Value as Credit Value'
end
end
end
11 changes: 11 additions & 0 deletions app/mailers/spree/store_credit_updater_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Spree
class StoreCreditUpdaterMailer < BaseMailer
def update_admin(status_csv, admin_email, filename, total_records, successfull_records)
@total_records = total_records
@failed_records = total_records - successfull_records
attachments['stock_items.csv'] = status_csv
subject = "#{Spree::Store.current.name} import of #{ filename } has finished"
mail(to: admin_email, from: from_address, subject: subject)
end
end
end
9 changes: 9 additions & 0 deletions app/models/spree/bulk_store_credit_updater.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Spree
class BulkStoreCreditUpdater < Spree::Base

USER_PER_PAGE = 15

has_attached_file :data_file
validates_attachment :data_file, content_type: { content_type: ["text/csv", "text/plain"] }
end
end
6 changes: 6 additions & 0 deletions app/overrides/add_import_button_on_user_index_page.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Deface::Override.new(
virtual_path: 'spree/admin/shared/_content_header',
name: 'add_import_button_on_user_index_page',
insert_bottom: "div[data-hook='toolbar']",
partial: 'spree/admin/users/import_button'
)
69 changes: 69 additions & 0 deletions app/services/list_store_credit_updater.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
require 'csv'
class ListStoreCreditUpdater
CSV_HEADERS = { 'Email': :Email, 'Store_Credit': :Store_Credit, 'Status': :Status }

def initialize(users_ids, admin_email, credit_value)
@admin_email = admin_email
@users_ids = users_ids
@credit_value = credit_value
update_store_credits
Spree::StoreCreditUpdaterMailer.update_admin(@csv_export, @admin_email, 'Store Credit', @total_records, @successfull_records).deliver_now
end

private
def update_store_credits
@total_records = 0
@successfull_records = 0
@csv_export = CSV.generate do |csv|
csv << CSV_HEADERS.keys
@users_ids.each do |user_id|
@error = nil
@total_records += 1
@user = Spree::User.find_by_id(user_id.to_i)
if @user
update_store_credits_with_credit_value
else
@error = Spree.t(:user_not_found)
end
csv << set_row
end
end
end

def set_row
row = []
CSV_HEADERS.each do |key, value|
if key == :Store_Credit
row << @credit_value
else
row << create_csv_row(key, value)
end
end
row
end

def create_csv_row(key, value)
( key == :Status ) ? error_message : @user.try(:email)
end

def error_message
@error ? @error : Spree.t(:successfull_update)
end

def update_store_credits_with_credit_value
admin = Spree::User.find_by_email @admin_email
category = Spree::StoreCreditCategory.first
store_credit = Spree::StoreCredit.new(amount: @credit_value.to_f, created_by_id: admin.try(:id), currency: "USD", category_id: category.try(:id), memo: Spree.t(:admin_added_via_list))
@user.store_credits << store_credit
set_error_message(store_credit)
end

def set_error_message(store_credit)
if store_credit.valid?
@error = nil
@successfull_records += 1
else
@error = store_credit.errors.full_messages.join(',')
end
end
end
Loading