From a01fd7ed233406adfae7c1469e865a2f75ee4792 Mon Sep 17 00:00:00 2001 From: Himanshu Date: Mon, 6 Aug 2018 19:01:21 +0530 Subject: [PATCH] bulk upload store credit button added --- .../spree/backend/csv_input_button.js | 28 ++++++++ .../spree/backend/spree_bulk_store_credits.js | 3 +- .../backend/spree_bulk_store_credits.css | 7 ++ .../spree/admin/users_controller_decorator.rb | 22 +++++++ .../spree/store_credit_updater_mailer.rb | 11 ++++ app/models/spree/bulk_store_credit_updater.rb | 6 ++ .../add_import_button_on_user_index_page.rb | 6 ++ app/services/notify_store_credit_service.rb | 66 +++++++++++++++++++ .../spree/admin/users/_import_button.html.erb | 7 ++ .../spree/shared/_base_mailer_header.html.erb | 33 ++++++++++ .../update_admin.html.erb | 8 +++ .../spree_bulk_store_credits_constants.rb | 3 + config/locales/en.yml | 6 +- config/routes.rb | 6 ++ ..._create_spree_bulk_store_credit_updater.rb | 8 +++ lib/sample_csv/bulk_store_credits_example.csv | 2 + 16 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 app/assets/javascripts/spree/backend/csv_input_button.js create mode 100644 app/controllers/spree/admin/users_controller_decorator.rb create mode 100644 app/mailers/spree/store_credit_updater_mailer.rb create mode 100644 app/models/spree/bulk_store_credit_updater.rb create mode 100644 app/overrides/add_import_button_on_user_index_page.rb create mode 100644 app/services/notify_store_credit_service.rb create mode 100644 app/views/spree/admin/users/_import_button.html.erb create mode 100644 app/views/spree/shared/_base_mailer_header.html.erb create mode 100644 app/views/spree/store_credit_updater_mailer/update_admin.html.erb create mode 100644 config/initializers/spree_bulk_store_credits_constants.rb create mode 100644 db/migrate/20180806080802_create_spree_bulk_store_credit_updater.rb create mode 100644 lib/sample_csv/bulk_store_credits_example.csv diff --git a/app/assets/javascripts/spree/backend/csv_input_button.js b/app/assets/javascripts/spree/backend/csv_input_button.js new file mode 100644 index 0000000..247fa12 --- /dev/null +++ b/app/assets/javascripts/spree/backend/csv_input_button.js @@ -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(); +}); diff --git a/app/assets/javascripts/spree/backend/spree_bulk_store_credits.js b/app/assets/javascripts/spree/backend/spree_bulk_store_credits.js index 8aa3b01..f246b20 100644 --- a/app/assets/javascripts/spree/backend/spree_bulk_store_credits.js +++ b/app/assets/javascripts/spree/backend/spree_bulk_store_credits.js @@ -1,2 +1,3 @@ // Placeholder manifest file. -// the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/backend/all.js' \ No newline at end of file +// 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 diff --git a/app/assets/stylesheets/spree/backend/spree_bulk_store_credits.css b/app/assets/stylesheets/spree/backend/spree_bulk_store_credits.css index e3c2366..987bc6f 100644 --- a/app/assets/stylesheets/spree/backend/spree_bulk_store_credits.css +++ b/app/assets/stylesheets/spree/backend/spree_bulk_store_credits.css @@ -2,3 +2,10 @@ 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: 13px; +} diff --git a/app/controllers/spree/admin/users_controller_decorator.rb b/app/controllers/spree/admin/users_controller_decorator.rb new file mode 100644 index 0000000..e1c32f8 --- /dev/null +++ b/app/controllers/spree/admin/users_controller_decorator.rb @@ -0,0 +1,22 @@ +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 + redirect_to admin_users_path, notice: Spree.t(:email_sent, filename: @store_credit_updater.data_file_file_name) + rescue + redirect_to admin_users_path, notice: "Invalid CSV file format." + end + end + + private + + def create_store_credit_updater + @store_credit_updater = Spree::BulkStoreCreditUpdater.create(data_file: params[:file]) + NotifyStoreCreditService.delay(run_at: 1.minutes.from_now).new(@store_credit_updater.id, try_spree_current_user.email) + end + +end diff --git a/app/mailers/spree/store_credit_updater_mailer.rb b/app/mailers/spree/store_credit_updater_mailer.rb new file mode 100644 index 0000000..5dee1f8 --- /dev/null +++ b/app/mailers/spree/store_credit_updater_mailer.rb @@ -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 diff --git a/app/models/spree/bulk_store_credit_updater.rb b/app/models/spree/bulk_store_credit_updater.rb new file mode 100644 index 0000000..bb83aed --- /dev/null +++ b/app/models/spree/bulk_store_credit_updater.rb @@ -0,0 +1,6 @@ +module Spree + class BulkStoreCreditUpdater < Spree::Base + has_attached_file :data_file + validates_attachment :data_file, content_type: { content_type: ["text/csv", "text/plain"] } + end +end diff --git a/app/overrides/add_import_button_on_user_index_page.rb b/app/overrides/add_import_button_on_user_index_page.rb new file mode 100644 index 0000000..7b6d38d --- /dev/null +++ b/app/overrides/add_import_button_on_user_index_page.rb @@ -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' +) diff --git a/app/services/notify_store_credit_service.rb b/app/services/notify_store_credit_service.rb new file mode 100644 index 0000000..a8f57c5 --- /dev/null +++ b/app/services/notify_store_credit_service.rb @@ -0,0 +1,66 @@ +require 'csv' + class NotifyStoreCreditService + CSV_HEADERS = { 'Email': :Email, 'Store_Credit': :Store_Credit, 'Memo': :Memo, 'Category_ID': :Category_ID, 'Status': :Status } + + def initialize(store_credit_updater_id, admin_email) + @store_credit_updater = Spree::BulkStoreCreditUpdater.find_by(id: store_credit_updater_id) + update_store_credits + @store_credit_updater.update_column(:job_executed, true) + Spree::StoreCreditUpdaterMailer.update_admin(@csv_export, admin_email, @store_credit_updater.data_file_file_name, @total_records, @successfull_records).deliver_now + @store_credit_updater.destroy if @store_credit_updater.job_executed? + end + + private + def update_store_credits + @total_records = 0 + @successfull_records = 0 + @csv_export = CSV.generate do |csv| + unless csv_empty? + csv << CSV_HEADERS.keys + CSV.foreach(@store_credit_updater.data_file.path, headers: true) do |row| + @error = nil + @total_records += 1 + @row = row + @user = find_user + if @user + update_stocks_with_csv_values + else + @error = Spree.t(:user_not_found) + end + csv << set_row + end + end + end + end + + def csv_empty? + CSV.readlines(@store_credit_updater.data_file.path) == [[]] + end + + def set_row + row = [] + CSV_HEADERS.each do |key, value| + row << create_csv_row(key, value) + end + row + end + + def create_csv_row(key, value) + ( key == :Status ) ? error_message : @row[value.to_s] + end + + def error_message + @error ? @error : 'Successfully Updated' + end + + def update_stocks_with_csv_values + admin = Spree::User.admin.first + store_credit = Spree::StoreCredit.new(amount: @row['Store_Credit'].to_f, created_by_id: admin.id, currency: "USD", category_id: @row['Category_ID'], memo: @row['Memo']) + @user.store_credits << store_credit + @successfull_records += 1 + end + + def find_user + Spree::User.find_by_email(@row['Email']) + end +end diff --git a/app/views/spree/admin/users/_import_button.html.erb b/app/views/spree/admin/users/_import_button.html.erb new file mode 100644 index 0000000..0ead1a0 --- /dev/null +++ b/app/views/spree/admin/users/_import_button.html.erb @@ -0,0 +1,7 @@ +<% if request.path == admin_users_path %> + <%= form_tag import_store_credits_admin_users_path, multipart: true, class: 'form-inline', data: { hook: "csv_form" } do %> + <%= file_field_tag :file, class: 'file-browse' %> + <%= submit_tag Spree.t(:import), class: 'btn-success btn' %> + <%= link_to Spree.t(:example) , sample_store_credit_csv_admin_users_path, class: 'sample-download' %> + <% end %> +<% end %> diff --git a/app/views/spree/shared/_base_mailer_header.html.erb b/app/views/spree/shared/_base_mailer_header.html.erb new file mode 100644 index 0000000..b2dbe49 --- /dev/null +++ b/app/views/spree/shared/_base_mailer_header.html.erb @@ -0,0 +1,33 @@ + + + + + +
+
+ + + + + +
+ + + + + + +
+ <% if frontend_available? %> + <%= link_to root_url, class: 'template-label' do %> + <%= image_tag Spree::Config.logo, class: 'logo', alt: Spree::Store.current.name, title: Spree::Store.current.name %> + <% end %> + <% else %> + <%= image_tag Spree::Config.logo, class: 'logo', alt: Spree::Store.current.name, title: Spree::Store.current.name %> + <% end %> +
+ +
+ +
+
diff --git a/app/views/spree/store_credit_updater_mailer/update_admin.html.erb b/app/views/spree/store_credit_updater_mailer/update_admin.html.erb new file mode 100644 index 0000000..adc3287 --- /dev/null +++ b/app/views/spree/store_credit_updater_mailer/update_admin.html.erb @@ -0,0 +1,8 @@ +
+
<%= Spree.t(:update_status) %>
+ + Attached is a csv file of failed records for your information. +
diff --git a/config/initializers/spree_bulk_store_credits_constants.rb b/config/initializers/spree_bulk_store_credits_constants.rb new file mode 100644 index 0000000..4caab20 --- /dev/null +++ b/config/initializers/spree_bulk_store_credits_constants.rb @@ -0,0 +1,3 @@ +STORE_CREDIT_CSV_FILE = { + sample_store_credit_file: SpreeBulkStoreCredits::Engine.root.join('lib', 'sample_csv', 'bulk_store_credits_example.csv') +} diff --git a/config/locales/en.yml b/config/locales/en.yml index 179c14c..4cd47bb 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2,4 +2,8 @@ # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. en: - hello: "Hello world" + spree: + import: Import Store Credit CSV + example: Download Sample File + email_sent: "%{filename} has been successfully imported. Details will be sent shortly to you over an email." + user_not_found: User with this email Not found diff --git a/config/routes.rb b/config/routes.rb index 0339717..aafaaa2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,9 @@ Spree::Core::Engine.add_routes do # Add your extension routes here + namespace :admin, path: Spree.admin_path do + resources :users do + collection { post :import_store_credits } + collection { get :sample_store_credit_csv } + end + end end diff --git a/db/migrate/20180806080802_create_spree_bulk_store_credit_updater.rb b/db/migrate/20180806080802_create_spree_bulk_store_credit_updater.rb new file mode 100644 index 0000000..dfd6f37 --- /dev/null +++ b/db/migrate/20180806080802_create_spree_bulk_store_credit_updater.rb @@ -0,0 +1,8 @@ +class CreateSpreeBulkStoreCreditUpdater < ActiveRecord::Migration[4.2] + def change + create_table :spree_bulk_store_credit_updaters do |t| + t.boolean :job_executed, default: false + t.attachment :data_file + end + end +end diff --git a/lib/sample_csv/bulk_store_credits_example.csv b/lib/sample_csv/bulk_store_credits_example.csv new file mode 100644 index 0000000..afec6b7 --- /dev/null +++ b/lib/sample_csv/bulk_store_credits_example.csv @@ -0,0 +1,2 @@ +Email,Store Credit,Memo,Category ID +spree@example.com,10,Order benefit,1