solidus-returnly 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b0f4def9162a15735d56d0e508c00f16b208d490
4
- data.tar.gz: 4a4871b9e78dbbabaf7749a4e3367011567c46d9
3
+ metadata.gz: c766335abec60d67ec8b8cdd47f0f625298ccfc9
4
+ data.tar.gz: f10c5c2093ca06bba6968c36f95631805207fded
5
5
  SHA512:
6
- metadata.gz: 5c8a78e67e2dbcd2ec8c42f451f0105c81f2b83d71b2b44935f995722c81dfc450a7876d9aaac786f23b9fabdd26c38525c98341adde5c3b8c6c250d54505d46
7
- data.tar.gz: 31e5fcbcb4fa977710be28e31dea281c1554248390a142f8b52e0a47354d8fb117b2eb7dcd43c183d8fb4b111caef1c2f75c837f57d10f4ff1b9118234ff29ab
6
+ metadata.gz: 716c5b3aa3d8e4021f7df14f7bd8405b8fcee690324ce7b2c91f04a20b3d43e9620f0ed79761f870fd6f50f49a374d6bffdc8b01ab2aa284076437e587d5d7f9
7
+ data.tar.gz: 0dea426fb3dc4a023113a43506d9524326678234c807c6da8e3e9b5719194afe01019843d1f92a35d288617825f88a862df7577e2a66673f3d33f359f72f4d6b
@@ -2,18 +2,20 @@ module Spree
2
2
  module Api
3
3
  module Returnly
4
4
  class RefundsController < ApiController
5
+ include Solidus::Returnly::RefundsConfiguration
6
+
5
7
  def estimate
6
8
  authorize! :create, Order
7
- render json: Solidus::Returnly::Calculator.process(order, line_items_params)
9
+ render json: refund_calculator_class.process(order, line_items_params)
8
10
  end
9
11
 
10
12
  def create
11
13
  authorize! :create, Order
12
14
 
13
- refunds = Solidus::Returnly::Refunds.new order: order,
14
- line_items: line_items_params,
15
- restock: refund_restock_param,
16
- transactions: transactions_params
15
+ refunds = refunder_class.new order: order,
16
+ line_items: line_items_params,
17
+ restock: refund_restock_param,
18
+ transactions: transactions_params
17
19
  render json: refunds.proceed!
18
20
  end
19
21
 
@@ -1,5 +1,16 @@
1
1
  module Solidus
2
2
  module Returnly
3
+ class << self
4
+ mattr_accessor :return_item_amount_calculator,
5
+ :return_item_restock_policy,
6
+ :refunder,
7
+ :refund_calculator
8
+ end
9
+
10
+ def self.configure(&block)
11
+ yield self if block
12
+ end
13
+
3
14
  class Engine < Rails::Engine
4
15
  require 'spree/core'
5
16
 
@@ -0,0 +1,17 @@
1
+ module Solidus
2
+ module Returnly
3
+ module Refund
4
+ class AmountCalculator
5
+ attr_accessor :refund
6
+
7
+ def initialize(refund)
8
+ self.refund = refund
9
+ end
10
+
11
+ def return_item_refund_amount(return_item)
12
+ refund.refund_amount_per_item - Money.from_amount(return_item.total - return_item.pre_tax_amount)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ module Solidus
2
+ module Returnly
3
+ module Refund
4
+ class ReturnItemRestockPolicy
5
+ attr_accessor :refund
6
+
7
+ def initialize(refund)
8
+ self.refund = refund
9
+ end
10
+
11
+ #
12
+ def should_return_item?(_)
13
+ refund.restock
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,10 +1,10 @@
1
1
  module Solidus
2
2
  module Returnly
3
- class Calculator
3
+ class RefundCalculator
4
4
  attr_accessor :line_items, :order
5
5
 
6
6
  def self.process(order, line_items)
7
- new(order, line_items).calculated_estimate
7
+ RefundPresenter.present_estimate new(order, line_items)
8
8
  end
9
9
 
10
10
  def initialize(order, line_items)
@@ -12,46 +12,6 @@ module Solidus
12
12
  self.order = order
13
13
  end
14
14
 
15
- def calculated_estimate
16
- total = 0.0
17
- sub_total = 0.0
18
-
19
- line_items_return_items.values.flatten.each do |return_item|
20
- total += return_item.total
21
- sub_total += return_item.pre_tax_amount
22
- end
23
-
24
- {
25
- total_amount: total,
26
- subtotal_amount: sub_total,
27
- tax_amount: total - sub_total,
28
- discount_amount: order.promo_total,
29
- shipping_amount: order.shipment_total,
30
- line_items: present_line_items
31
- }
32
- end
33
-
34
- def present_line_items
35
- line_items_return_items.values.map do |return_items|
36
- line_item = return_items.first.inventory_unit.line_item
37
-
38
- total_amount = 0.0
39
- sub_total = 0.0
40
-
41
- return_items.each do |return_item|
42
- total_amount += return_item.total
43
- sub_total += return_item.pre_tax_amount
44
- end
45
-
46
- {
47
- order_line_item_id: line_item.id,
48
- quantity: return_items.size,
49
- total_amount: total_amount,
50
- tax_amount: total_amount - sub_total
51
- }
52
- end
53
- end
54
-
55
15
  def set_tax(return_item)
56
16
  percent_of_tax = (return_item.amount <= 0) ? 0 : return_item.amount /
57
17
  Spree::ReturnItem.refund_amount_calculator.new.compute(return_item)
@@ -69,20 +29,11 @@ module Solidus
69
29
  found_return_items = {}
70
30
 
71
31
  line_items.each do |line_item|
72
- quantity = line_item[:quantity].to_i
32
+ with_available_inventory_units line_item do |inventory_unit, quantity|
33
+ next unless quantity > 0
73
34
 
74
- next unless quantity > 0
75
- available_inventory_units = line_item_inventory_unit(line_item).slice(0, quantity)
76
-
77
- available_inventory_units.each do |inventory_unit|
78
35
  found_return_items[line_item[:order_line_item_id]] ||= []
79
-
80
- return_item = Spree::ReturnItem.new({ amount: inventory_unit.line_item.price,
81
- acceptance_status: 'accepted',
82
- inventory_unit_id: inventory_unit.id,
83
- reception_status_event: 'receive'
84
- })
85
-
36
+ return_item = create_return_item(inventory_unit)
86
37
  found_return_items[line_item[:order_line_item_id]] << set_tax(return_item)
87
38
  end
88
39
  end
@@ -111,6 +62,26 @@ module Solidus
111
62
  def requested_line_items
112
63
  line_items.map { |item| item[:order_line_item_id] }
113
64
  end
65
+
66
+
67
+ protected
68
+
69
+ def create_return_item(inventory_unit)
70
+ Spree::ReturnItem.new({ amount: inventory_unit.line_item.price,
71
+ acceptance_status: 'accepted',
72
+ inventory_unit_id: inventory_unit.id,
73
+ reception_status_event: 'receive'
74
+ })
75
+ end
76
+
77
+ def with_available_inventory_units(line_item)
78
+ quantity = line_item[:quantity].to_i
79
+
80
+ available_inventory_units = line_item_inventory_unit(line_item).slice(0, quantity)
81
+ available_inventory_units.each do |inventory_unit|
82
+ yield inventory_unit, quantity
83
+ end
84
+ end
114
85
  end
115
86
  end
116
87
  end
@@ -0,0 +1,73 @@
1
+ module Solidus
2
+ module Returnly
3
+ class RefundPresenter
4
+
5
+ def self.present_estimate(calculator)
6
+ total = Money.new 0
7
+ sub_total = Money.new 0
8
+
9
+ calculator.line_items_return_items.values.flatten.each do |return_item|
10
+ total += Money.from_amount return_item.total
11
+ sub_total += Money.from_amount return_item.pre_tax_amount
12
+ end
13
+
14
+ {
15
+ total_amount: total.to_f,
16
+ subtotal_amount: sub_total.to_f,
17
+ tax_amount: (total - sub_total).to_f,
18
+ discount_amount: calculator.order.promo_total.to_f,
19
+ shipping_amount: calculator.order.shipment_total.to_f,
20
+ line_items: present_line_items(calculator)
21
+ }
22
+ end
23
+
24
+
25
+ def self.present_line_items(calculator)
26
+ calculator.line_items_return_items.values.map do |return_items|
27
+ line_item = return_items.first.inventory_unit.line_item
28
+
29
+ total_amount = 0.0
30
+ sub_total = 0.0
31
+
32
+ return_items.each do |return_item|
33
+ total_amount += return_item.total
34
+ sub_total += return_item.pre_tax_amount
35
+ end
36
+
37
+ {
38
+ order_line_item_id: line_item.id,
39
+ quantity: return_items.size,
40
+ total_amount: total_amount.to_f,
41
+ tax_amount: (total_amount - sub_total).to_f
42
+ }
43
+ end
44
+ end
45
+
46
+
47
+ def self.present_refund(refunder)
48
+ customer_return = refunder.customer_return
49
+
50
+ {
51
+ refund_id: customer_return.number,
52
+ created_at: customer_return.created_at,
53
+ updated_at: customer_return.updated_at,
54
+ line_items: customer_return.return_items.group_by{ |ri| ri.inventory_unit.line_item.id }.map do |_, return_items|
55
+ first_return_item = return_items.first
56
+ {
57
+ refund_line_item_id: first_return_item.id,
58
+ order_line_item_id: first_return_item.inventory_unit.line_item.id,
59
+ refunded_amount_per_item: first_return_item.amount.to_f,
60
+ total_refunded_per_line_item: return_items.sum(&:amount).to_f,
61
+ quantity: return_items.size
62
+ }
63
+ end,
64
+ transactions: [
65
+ id: refunder.reimbursement.id,
66
+ amount: refunder.reimbursement.total
67
+ ],
68
+ restock: refunder.restock
69
+ }
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,84 @@
1
+ module Solidus
2
+ module Returnly
3
+ class Refunder
4
+ include Solidus::Returnly::RefundsConfiguration
5
+
6
+ attr_accessor :order,
7
+ :line_items,
8
+ :restock,
9
+ :transactions,
10
+ :customer_return,
11
+ :return_item_amount_calculator,
12
+ :return_item_restock_policy,
13
+ :refund_calculator
14
+
15
+ def initialize(order:, line_items:, restock:, transactions:)
16
+ self.order = order
17
+ self.line_items = line_items
18
+ self.customer_return = Spree::CustomerReturn.new customer_return_params
19
+ self.transactions = transactions
20
+ self.restock = restock
21
+
22
+ configure
23
+ end
24
+
25
+ def process_return_items
26
+ each_return_item do |return_item|
27
+ return_item.amount = return_item_amount_calculator.return_item_refund_amount return_item
28
+ return_item.resellable = return_item_restock_policy.should_return_item? return_item
29
+ end
30
+ end
31
+
32
+ def proceed!
33
+ process_return_items
34
+
35
+ if customer_return.save!
36
+ perform_reimbursement
37
+ RefundPresenter.present_refund(self)
38
+ end
39
+ end
40
+
41
+ def refund_available_amount
42
+ @available_amount ||= transactions.sum { |t| Money.from_amount(t[:amount].to_f) }
43
+ end
44
+
45
+ def refund_amount_per_item
46
+ refund_available_amount / line_items.size
47
+ end
48
+
49
+ def reimbursement
50
+ @_reimbursement ||= Spree::Reimbursement.build_from_customer_return(customer_return)
51
+ end
52
+
53
+ private
54
+
55
+ def configure
56
+ self.return_item_amount_calculator = return_item_amount_calculator_class.new(self)
57
+ self.return_item_restock_policy = return_item_restock_policy_class.new(self)
58
+ self.refund_calculator = refund_calculator_class.new(order, line_items)
59
+ end
60
+
61
+ def perform_reimbursement
62
+ reimbursement.save!
63
+ reimbursement.perform!
64
+ end
65
+
66
+ def each_return_item
67
+ customer_return.return_items = refund_calculator.line_items_return_items.values.flatten
68
+ customer_return.return_items.each do |return_item|
69
+ yield return_item
70
+ end
71
+ end
72
+
73
+ def customer_return_params
74
+ {
75
+ stock_location_id: stock_location_id
76
+ }
77
+ end
78
+
79
+ def stock_location_id
80
+ order.shipments.last.stock_location.id
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,22 @@
1
+ module Solidus
2
+ module Returnly
3
+ module RefundsConfiguration
4
+ def return_item_amount_calculator_class
5
+ Solidus::Returnly.return_item_amount_calculator || Solidus::Returnly::Refund::AmountCalculator
6
+ end
7
+
8
+ # return item qualifies to be restocked (after refund)
9
+ def return_item_restock_policy_class
10
+ Solidus::Returnly.return_item_restock_policy || Solidus::Returnly::Refund::ReturnItemRestockPolicy
11
+ end
12
+
13
+ def refunder_class
14
+ Solidus::Returnly.refunder || Solidus::Returnly::Refunder
15
+ end
16
+
17
+ def refund_calculator_class
18
+ Solidus::Returnly.refund_calculator || Solidus::Returnly::RefundCalculator
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,5 +1,5 @@
1
1
  module Solidus
2
2
  module Returnly
3
- VERSION = '0.3.0'
3
+ VERSION = '0.4.0'
4
4
  end
5
5
  end
@@ -1,5 +1,7 @@
1
1
  require 'solidus_core'
2
2
 
3
3
  require 'solidus/returnly/engine'
4
- require 'solidus/returnly/refunds'
5
- require 'solidus/returnly/calculator'
4
+ require 'solidus/returnly/refunds_configuration'
5
+
6
+ require 'solidus/returnly/refunder'
7
+ require 'solidus/returnly/refund_calculator'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solidus-returnly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Returnly Technologies, Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-25 00:00:00.000000000 Z
11
+ date: 2017-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: solidus
@@ -248,6 +248,20 @@ dependencies:
248
248
  - - ">="
249
249
  - !ruby/object:Gem::Version
250
250
  version: '0'
251
+ - !ruby/object:Gem::Dependency
252
+ name: yard
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - ">="
256
+ - !ruby/object:Gem::Version
257
+ version: '0'
258
+ type: :development
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - ">="
263
+ - !ruby/object:Gem::Version
264
+ version: '0'
251
265
  description: Solidus API extensions for returnly
252
266
  email: support@returnly.com
253
267
  executables: []
@@ -264,10 +278,14 @@ files:
264
278
  - config/routes.rb
265
279
  - lib/generators/solidus_returnly/install/install_generator.rb
266
280
  - lib/solidus-returnly.rb
267
- - lib/solidus/returnly/calculator.rb
268
281
  - lib/solidus/returnly/engine.rb
269
282
  - lib/solidus/returnly/factories.rb
270
- - lib/solidus/returnly/refunds.rb
283
+ - lib/solidus/returnly/refund/amount_calculator.rb
284
+ - lib/solidus/returnly/refund/return_item_restock_policy.rb
285
+ - lib/solidus/returnly/refund_calculator.rb
286
+ - lib/solidus/returnly/refund_presenter.rb
287
+ - lib/solidus/returnly/refunder.rb
288
+ - lib/solidus/returnly/refunds_configuration.rb
271
289
  - lib/solidus/returnly/version.rb
272
290
  homepage: https://github.com/returnly/solidus-returnly
273
291
  licenses:
@@ -1,79 +0,0 @@
1
- module Solidus
2
- module Returnly
3
- class Refunds
4
- attr_accessor :calculator, :order, :line_items, :restock, :transactions, :customer_return
5
-
6
- def initialize(order:, line_items:, restock: true, transactions:)
7
- self.order = order
8
- self.line_items = line_items
9
- self.calculator = Calculator.new order, line_items
10
- self.restock = restock
11
- self.transactions = transactions
12
- self.customer_return = Spree::CustomerReturn.new customer_return_params
13
- end
14
-
15
- def proceed!
16
- customer_return.return_items = calculator.line_items_return_items.values.flatten
17
-
18
- customer_return.return_items.each do |return_item|
19
- return_item.amount = refund_amount_per_item - Money.from_amount(return_item.total - return_item.pre_tax_amount)
20
- return_item.resellable = restock
21
- end
22
-
23
- if customer_return.save!
24
- perform_reimbursement
25
- processed_customer_return(customer_return, reimbursement)
26
- end
27
- end
28
-
29
- def processed_customer_return(customer_return, reimbursement)
30
- {
31
- refund_id: customer_return.number,
32
- created_at: customer_return.created_at,
33
- updated_at: customer_return.updated_at,
34
- line_items: customer_return.return_items.group_by{ |ri| ri.inventory_unit.line_item.id }.map {|_, return_items|
35
- {
36
- refund_line_item_id: return_items.first.id,
37
- order_line_item_id: return_items.first.inventory_unit.line_item.id,
38
- refunded_amount_per_item: return_items.first.amount.to_f,
39
- total_refunded_per_line_item: return_items.sum(&:amount).to_f,
40
- quantity: return_items.size
41
- }
42
- },
43
- transactions: [
44
- id: reimbursement.id,
45
- amount: reimbursement.total
46
- ],
47
- restock: restock
48
- }
49
- end
50
-
51
- def perform_reimbursement
52
- reimbursement.save!
53
- reimbursement.perform!
54
- end
55
-
56
- def reimbursement
57
- @_reimbursement ||= Spree::Reimbursement.build_from_customer_return(customer_return)
58
- end
59
-
60
- def customer_return_params
61
- {
62
- stock_location_id: stock_location_id
63
- }
64
- end
65
-
66
- def stock_location_id
67
- order.shipments.last.stock_location.id
68
- end
69
-
70
- def refund_available_amount
71
- @available_amount ||= transactions.sum { |t| Money.from_amount(t[:amount].to_f) }
72
- end
73
-
74
- def refund_amount_per_item
75
- refund_available_amount / line_items.size
76
- end
77
- end
78
- end
79
- end