solidus-returnly 0.3.0 → 0.4.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.
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