spree_batch_capture 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ # Add your extension routes here
3
+ end
@@ -0,0 +1,10 @@
1
+ class AddLastProcessingErrorToPayments < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :payments, :last_processing_error, :string
4
+ end
5
+
6
+ def self.down
7
+ remove_column :payments, :last_processing_error
8
+
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ module SpreeBatchCapture
2
+ module Error
3
+ class InvalidWorker < StandardError; end
4
+ class UnexpectedWorkerError < StandardError; end
5
+ end
6
+ end
@@ -0,0 +1,98 @@
1
+ require 'resque'
2
+ #require 'resque/plugins/lock'
3
+
4
+ module SpreeBatchCapture
5
+ class Worker::Base
6
+ #extend Resque::Plugins::Lock
7
+
8
+ # Actual method called by Resque.
9
+ # This method cleans up any options and allows a consistent interface
10
+ # for the worker's run method.
11
+ def self.perform(options={})
12
+ begin
13
+ options.symbolize_keys!
14
+ if before_run(options)
15
+ result = run(options)
16
+ return after_run(result, options)
17
+ else
18
+ return false
19
+ end
20
+ rescue => e
21
+ handle_error(e)
22
+ end
23
+ end
24
+
25
+ # Override to do any modifications or validation
26
+ # before running the job. Job will fail if before_run
27
+ # returns false.
28
+ def self.before_run(options)
29
+ return true
30
+ end
31
+
32
+ # Override to do any post run checking. Receives the
33
+ # result (true/false) of the run and the options
34
+ # which may have been altered by the run. Job will fail if
35
+ # after_run returns false
36
+ def self.after_run(result, options)
37
+ return true
38
+ end
39
+
40
+ # Override to handle any exceptions that come up during the execution of
41
+ # the job. Returning false will fail the job, while returning true
42
+ # will indicate that the job was successful.
43
+ def self.handle_error(exception)
44
+ return false
45
+ end
46
+
47
+ # Implemented by subclasses and performs the actual work of the worker.
48
+ def self.run(options)
49
+ return true
50
+ end
51
+
52
+ # Use enqueue to add a job to the queue to be captured.
53
+ # Returns the result of the enqueue and the queue name as an array.
54
+ def self.enqueue(options, custom_queue_name=nil)
55
+ queue_name = custom_queue_name || default_queue_name || worker_klass_name
56
+
57
+ # Resque.enqueue_to is currently supported only in the master branch
58
+ # of the gem and not included in any gem. When it is, the following line
59
+ # should work.
60
+ #added = ::Resque.enqueue_to(queue_name, worker_class, options)
61
+
62
+ #Until then, we have to do this work-around:
63
+ @queue = queue_name
64
+
65
+ added = ::Resque.enqueue(worker_class, options)
66
+ [ added, queue_name ]
67
+ end
68
+
69
+ # Override this in the subclass to provide the name of the queue
70
+ def self.worker_klass_name
71
+ return "Base"
72
+ end
73
+
74
+ # Provides a default queue name. Returning nil will default to the class name.
75
+ def self.default_queue_name
76
+ return nil
77
+ end
78
+
79
+ private
80
+
81
+ def self.worker_class
82
+ begin
83
+ @worker_class = "SpreeBatchCapture::Worker::#{worker_klass_name.camelize}".constantize
84
+ rescue
85
+ raise Error::InvalidWorker.new "Worker class name (#{worker_klass_name.camelize}) doesn't match a valid worker."
86
+ end
87
+ end
88
+
89
+
90
+ # Override the default lock for resque-lock. The out-of-the-box
91
+ # lock doesn't work for this case.
92
+ def self.lock(options)
93
+ "lock:#{default_queue_name || worker_klass_name}::#{options}"
94
+ end
95
+
96
+
97
+ end
98
+ end
@@ -0,0 +1,14 @@
1
+ class SpreeBatchCapture::Worker::Bogus < SpreeBatchCapture::Worker::Base
2
+
3
+ def self.run(options)
4
+ return true
5
+ end
6
+
7
+ def self.worker_klass_name
8
+ return "Bogus"
9
+ end
10
+
11
+ def self.default_queue_name
12
+ return "bogus"
13
+ end
14
+ end
@@ -0,0 +1,53 @@
1
+ module SpreeBatchCapture
2
+ class Worker::Capture < Worker::Base
3
+
4
+ def self.run(options)
5
+ order = options[:order]
6
+
7
+ return true unless order.payment_state == "balance_due"
8
+
9
+ if order.payments.nil? || ( order.payments && order.payments.empty? )
10
+ raise UnexpectedWorkerError.new "Attempted to capture an order without any payments."
11
+ else
12
+
13
+ order.payments.each do |payment|
14
+ payment_source = payment.source
15
+ if payment_source.can_capture? payment
16
+ begin
17
+ payment_source.capture(payment)
18
+ rescue => e
19
+ payment.fail
20
+ log_payment_error payment, "Error capturing payment for order #{order.number}. #{e.class} :: #{e.message}"
21
+ end
22
+
23
+ else
24
+ log_payment_error payment, "Order #{order.number} is not eligible for capture with payment #{payment.source_type} for #{payment.amount}."
25
+ end
26
+ end
27
+ end
28
+
29
+ return true
30
+
31
+ end
32
+
33
+ def self.before_run(options)
34
+ options[:order] = Order.find(options[:order_id])
35
+ end
36
+
37
+ def self.worker_klass_name
38
+ return "Capture"
39
+ end
40
+
41
+ def self.default_queue_name
42
+ return "capture"
43
+ end
44
+
45
+ private
46
+
47
+ def self.log_payment_error(payment, error)
48
+ payment.last_processing_error = error
49
+ payment.save!
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,18 @@
1
+ require 'spree_core'
2
+ require 'spree_batch_capture_hooks'
3
+
4
+ module SpreeBatchCapture
5
+ class Engine < Rails::Engine
6
+
7
+ config.autoload_paths += %W(#{config.root}/lib)
8
+
9
+ def self.activate
10
+ Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
11
+ Rails.env.production? ? require(c) : load(c)
12
+ end
13
+
14
+ end
15
+
16
+ config.to_prepare &method(:activate).to_proc
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ class BatchProcessHooks < Spree::ThemeSupport::HookListener
2
+ # custom hooks go here
3
+ end
@@ -0,0 +1,25 @@
1
+ namespace :spree_batch_capture do
2
+ desc "Copies all migrations and assets (NOTE: This will be obsolete with Rails 3.1)"
3
+ task :install do
4
+ Rake::Task['spree_batch_capture:install:migrations'].invoke
5
+ Rake::Task['spree_batch_capture:install:assets'].invoke
6
+ end
7
+
8
+ namespace :install do
9
+ desc "Copies all migrations (NOTE: This will be obsolete with Rails 3.1)"
10
+ task :migrations do
11
+ source = File.join(File.dirname(__FILE__), '..', '..', 'db')
12
+ destination = File.join(Rails.root, 'db')
13
+ Spree::FileUtilz.mirror_files(source, destination)
14
+ end
15
+
16
+ desc "Copies all assets (NOTE: This will be obsolete with Rails 3.1)"
17
+ task :assets do
18
+ source = File.join(File.dirname(__FILE__), '..', '..', 'public')
19
+ destination = File.join(Rails.root, 'public')
20
+ puts "INFO: Mirroring assets from #{source} to #{destination}"
21
+ Spree::FileUtilz.mirror_files(source, destination)
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1 @@
1
+ # add custom rake tasks here
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_batch_capture
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mike Farmer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-12-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: spree_core
16
+ requirement: &16020680 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.60.4
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *16020680
25
+ - !ruby/object:Gem::Dependency
26
+ name: resque
27
+ requirement: &16020220 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 1.19.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *16020220
36
+ - !ruby/object:Gem::Dependency
37
+ name: resque-lock
38
+ requirement: &16019760 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.0
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *16019760
47
+ description: Adds batch processing to Spree. Includes batch capture and batch export
48
+ of orders.
49
+ email: ''
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - config/routes.rb
55
+ - lib/spree_batch_capture_hooks.rb
56
+ - lib/tasks/install.rake
57
+ - lib/tasks/spree_batch_capture.rake
58
+ - lib/spree_batch_capture/worker/bogus.rb
59
+ - lib/spree_batch_capture/worker/capture.rb
60
+ - lib/spree_batch_capture/worker/base.rb
61
+ - lib/spree_batch_capture/error.rb
62
+ - lib/spree_batch_capture.rb
63
+ - db/migrate/20111129223646_add_last_processing_error_to_payments.rb
64
+ homepage: http://vitrue.com
65
+ licenses: []
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: 1.8.7
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements:
83
+ - none
84
+ rubyforge_project: ''
85
+ rubygems_version: 1.8.10
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: Adds batch capture and export to Spree
89
+ test_files: []