market_town-checkout 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/market_town/checkout.rb +2 -0
- data/lib/market_town/checkout/steps/address_step.rb +25 -0
- data/lib/market_town/checkout/steps/cart_step.rb +20 -0
- data/lib/market_town/checkout/steps/complete_step.rb +18 -0
- data/lib/market_town/checkout/steps/delivery_step.rb +17 -0
- data/lib/market_town/checkout/steps/step.rb +93 -1
- data/lib/market_town/checkout/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d56e8ab33f9b246e43a09187bafe27f4f1726337
|
4
|
+
data.tar.gz: f4365e815a8df693f3d0e0a146445b20310e2377
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b812c35b5a8e7942859866e7635f6eaefbf2d08107830352d2a2e63a434534ffde09a75c15bccf841b96a3cf317f8acc514dc51bbfdcbd173a7f34df157875b
|
7
|
+
data.tar.gz: 0103ea588a6c72642cd4ad491de1c7d09be48027b56b857cc93d12a7bf320b31d6879faf45caf897e24f45fae7d23e20f46f4d51ad2020cd25c9b87c8e53567f
|
data/lib/market_town/checkout.rb
CHANGED
@@ -32,6 +32,7 @@ module MarketTown
|
|
32
32
|
#
|
33
33
|
# ## Available steps
|
34
34
|
#
|
35
|
+
# - {CartStep} – Handles the initialisation of the checkout process
|
35
36
|
# - {AddressStep} – Handles the taking of billing and delivery addresses
|
36
37
|
# - {DeliveryStep} – Handles the choosing of delivery method
|
37
38
|
# - {CompleteStep} – Handles completion of order
|
@@ -56,6 +57,7 @@ require_relative './checkout/missing_dependency'
|
|
56
57
|
require_relative './checkout/dependencies'
|
57
58
|
require_relative './checkout/error'
|
58
59
|
require_relative './checkout/steps/step'
|
60
|
+
require_relative './checkout/steps/cart_step'
|
59
61
|
require_relative './checkout/steps/address_step'
|
60
62
|
require_relative './checkout/steps/delivery_step'
|
61
63
|
require_relative './checkout/steps/complete_step'
|
@@ -1,5 +1,13 @@
|
|
1
1
|
module MarketTown
|
2
2
|
module Checkout
|
3
|
+
# Handles addresses by validating them and optionally storing them.
|
4
|
+
#
|
5
|
+
# Dependencies:
|
6
|
+
# - fulfilments#can_fulfil_address?
|
7
|
+
# - address_storage#store
|
8
|
+
# - fulfilments#propose_shipments
|
9
|
+
# - finish#address_step
|
10
|
+
#
|
3
11
|
class AddressStep < Step
|
4
12
|
class InvalidAddressError < Error; end
|
5
13
|
class CannotFulfilAddressError < Error; end
|
@@ -14,20 +22,30 @@ module MarketTown
|
|
14
22
|
|
15
23
|
protected
|
16
24
|
|
25
|
+
# @raise [InvalidAddressError]
|
26
|
+
#
|
17
27
|
def validate_billing_address(state)
|
18
28
|
validate_address(:billing, state[:billing_address])
|
19
29
|
end
|
20
30
|
|
31
|
+
# Copies billing address into delivery address if requested
|
32
|
+
#
|
21
33
|
def use_billing_address_as_delivery_address(state)
|
22
34
|
if state[:use_billing_address] == true
|
23
35
|
state.merge(delivery_address: state[:billing_address])
|
24
36
|
end
|
25
37
|
end
|
26
38
|
|
39
|
+
# @raise [InvalidAddressError]
|
40
|
+
#
|
27
41
|
def validate_delivery_address(state)
|
28
42
|
validate_address(:delivery, state[:delivery_address])
|
29
43
|
end
|
30
44
|
|
45
|
+
# Tries to ensure delivery can be made to address
|
46
|
+
#
|
47
|
+
# @raise [CannotFulfilAddressError]
|
48
|
+
#
|
31
49
|
def ensure_delivery(state)
|
32
50
|
unless deps.fulfilments.can_fulfil_address?(state)
|
33
51
|
raise CannotFulfilAddressError.new(state[:delivery_address])
|
@@ -36,18 +54,25 @@ module MarketTown
|
|
36
54
|
add_dependency_missing_warning(state, :cannot_ensure_delivery)
|
37
55
|
end
|
38
56
|
|
57
|
+
# Tries to store addresses
|
58
|
+
#
|
39
59
|
def store_addresses(state)
|
40
60
|
deps.address_storage.store(state)
|
41
61
|
rescue MissingDependency
|
42
62
|
add_dependency_missing_warning(state, :cannot_store_address)
|
43
63
|
end
|
44
64
|
|
65
|
+
# Tries to proposes shipments to delivery address ready to be confirmed at
|
66
|
+
# delivery step.
|
67
|
+
#
|
45
68
|
def propose_shipments(state)
|
46
69
|
deps.fulfilments.propose_shipments(state)
|
47
70
|
rescue MissingDependency
|
48
71
|
add_dependency_missing_warning(state, :cannot_propose_shipments)
|
49
72
|
end
|
50
73
|
|
74
|
+
# Finishes address step
|
75
|
+
#
|
51
76
|
def finish_address_step(state)
|
52
77
|
deps.finish.address_step(state)
|
53
78
|
end
|
@@ -1,5 +1,14 @@
|
|
1
1
|
module MarketTown
|
2
2
|
module Checkout
|
3
|
+
# The place where a checkout process begins. This step represents the
|
4
|
+
# finalisation of a cart before the checkout process.
|
5
|
+
#
|
6
|
+
# Dependencies:
|
7
|
+
# - order#has_line_items?
|
8
|
+
# - address_storage#load_default
|
9
|
+
# - promotions#apply_cart_promotions
|
10
|
+
# - finish#cart_step
|
11
|
+
#
|
3
12
|
class CartStep < Step
|
4
13
|
class NoLineItemsError < Error; end
|
5
14
|
|
@@ -9,18 +18,29 @@ module MarketTown
|
|
9
18
|
|
10
19
|
protected
|
11
20
|
|
21
|
+
# @raise [NoLineItemsError] when no line items on order
|
22
|
+
#
|
12
23
|
def ensure_line_items(state)
|
13
24
|
unless deps.order.has_line_items?(state)
|
14
25
|
raise NoLineItemsError.new(state)
|
15
26
|
end
|
16
27
|
end
|
17
28
|
|
29
|
+
# Tries to load default addresses
|
30
|
+
#
|
18
31
|
def load_default_addresses(state)
|
19
32
|
deps.address_storage.load_default(state)
|
20
33
|
rescue MissingDependency
|
21
34
|
add_dependency_missing_warning(state, :cannot_load_default_addresses)
|
22
35
|
end
|
23
36
|
|
37
|
+
# Tries to apply cart promotions
|
38
|
+
#
|
39
|
+
def apply_cart_promotions(state)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Finishes cart step
|
43
|
+
#
|
24
44
|
def finish_cart_step(state)
|
25
45
|
deps.finish.cart_step(state)
|
26
46
|
end
|
@@ -1,5 +1,15 @@
|
|
1
1
|
module MarketTown
|
2
2
|
module Checkout
|
3
|
+
# Handles completion of checkout. All payments and options should have
|
4
|
+
# already been completed by this point. The purpose of this step is to
|
5
|
+
# request the fulfilment of the order and notify the customer.
|
6
|
+
#
|
7
|
+
# Dependencies:
|
8
|
+
# - finish#complete_step_finished?
|
9
|
+
# - fulfilments#fulfil
|
10
|
+
# - notifications#notify
|
11
|
+
# - finish#complete_step
|
12
|
+
#
|
3
13
|
class CompleteStep < Step
|
4
14
|
class AlreadyCompleteError < Error; end
|
5
15
|
|
@@ -10,24 +20,32 @@ module MarketTown
|
|
10
20
|
|
11
21
|
protected
|
12
22
|
|
23
|
+
# @raise [AlreadyCompleteError]
|
24
|
+
#
|
13
25
|
def ensure_incomplete(state)
|
14
26
|
if deps.finish.complete_step_finished?(state)
|
15
27
|
raise AlreadyCompleteError.new(state)
|
16
28
|
end
|
17
29
|
end
|
18
30
|
|
31
|
+
# Tries to fulfil order
|
32
|
+
#
|
19
33
|
def fulfil_order(state)
|
20
34
|
deps.fulfilments.fulfil(state)
|
21
35
|
rescue MissingDependency
|
22
36
|
add_dependency_missing_warning(state, :cannot_fulfil_order)
|
23
37
|
end
|
24
38
|
|
39
|
+
# Tries to send notifications about order complete
|
40
|
+
#
|
25
41
|
def send_order_complete_notice(state)
|
26
42
|
deps.notifications.notify(:order_complete, state)
|
27
43
|
rescue MissingDependency
|
28
44
|
add_dependency_missing_warning(state, :cannot_send_order_complete_notice)
|
29
45
|
end
|
30
46
|
|
47
|
+
# Finishes complete step
|
48
|
+
#
|
31
49
|
def finish_complete_step(state)
|
32
50
|
deps.finish.complete_step(state)
|
33
51
|
end
|
@@ -1,5 +1,12 @@
|
|
1
1
|
module MarketTown
|
2
2
|
module Checkout
|
3
|
+
# Handles delivery method and application of delivery promotions.
|
4
|
+
#
|
5
|
+
# Dependencies:
|
6
|
+
# - fulfilments#can_fulfil_shipments?
|
7
|
+
# - promotions#apply_delivery_promotions
|
8
|
+
# - finish#delivery_step
|
9
|
+
#
|
3
10
|
class DeliveryStep < Step
|
4
11
|
class InvalidDeliveryAddressError < Error; end
|
5
12
|
class CannotFulfilShipmentsError < Error; end
|
@@ -11,12 +18,18 @@ module MarketTown
|
|
11
18
|
|
12
19
|
protected
|
13
20
|
|
21
|
+
# @raise [InvalidDeliveryAddressError]
|
22
|
+
#
|
14
23
|
def validate_delivery_address(state)
|
15
24
|
Address.validate!(state[:delivery_address])
|
16
25
|
rescue Address::InvalidError => e
|
17
26
|
raise InvalidDeliveryAddressError.new(e.data)
|
18
27
|
end
|
19
28
|
|
29
|
+
# Tries to validate shipments
|
30
|
+
#
|
31
|
+
# @raise [CannotFulfilShipmentsError]
|
32
|
+
#
|
20
33
|
def validate_shipments(state)
|
21
34
|
unless deps.fulfilments.can_fulfil_shipments?(state)
|
22
35
|
raise CannotFulfilShipmentsError.new(state[:shipments])
|
@@ -25,12 +38,16 @@ module MarketTown
|
|
25
38
|
add_dependency_missing_warning(state, :cannot_validate_shipments)
|
26
39
|
end
|
27
40
|
|
41
|
+
# Tries to apply delivery promotions
|
42
|
+
#
|
28
43
|
def apply_delivery_promotions(state)
|
29
44
|
deps.promotions.apply_delivery_promotions(state)
|
30
45
|
rescue MissingDependency
|
31
46
|
add_dependency_missing_warning(state, :cannot_apply_delivery_promotions)
|
32
47
|
end
|
33
48
|
|
49
|
+
# Finish delivery step
|
50
|
+
#
|
34
51
|
def finish_delivery_step(state)
|
35
52
|
deps.finish.delivery_step(state)
|
36
53
|
end
|
@@ -1,6 +1,92 @@
|
|
1
1
|
module MarketTown
|
2
2
|
module Checkout
|
3
|
+
# Extended by all steps provided by {MarketTown::Checkout}.
|
4
|
+
#
|
5
|
+
# ## Creating your own {Step}
|
6
|
+
#
|
7
|
+
# If you wish to create your own step then you can extend {Step} or you can
|
8
|
+
# create a class that looks like step.
|
9
|
+
#
|
10
|
+
# ### Extending {Step}
|
11
|
+
#
|
12
|
+
# ``` ruby
|
13
|
+
# class MyStep < MarketTown::Checkout::Step
|
14
|
+
# steps :a_step,
|
15
|
+
# :a_second_step
|
16
|
+
#
|
17
|
+
# protected
|
18
|
+
#
|
19
|
+
# def a_step(state)
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# def a_second_step(state)
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# ```
|
26
|
+
#
|
27
|
+
# ### Duck typing {Step}
|
28
|
+
#
|
29
|
+
# ``` ruby
|
30
|
+
# class MyCustomStep
|
31
|
+
# def initialize(dependencies)
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# def process(state)
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
# ```
|
38
|
+
#
|
39
|
+
# ## Extending an existing step
|
40
|
+
#
|
41
|
+
# You may want to alter the behaviour of a {Step}. You can do this quite
|
42
|
+
# easily by extending the class.
|
43
|
+
#
|
44
|
+
# In the example below we'll replace the behaviour of {AddressStep} to
|
45
|
+
# allow the use of delivery address as billing address instead of the
|
46
|
+
# default behaviour that does the opposite.
|
47
|
+
#
|
48
|
+
# ``` ruby
|
49
|
+
# class MyAddressStep < MarketTown::Checkout::AddressStep
|
50
|
+
# # Here we override the step order as defined in AddressStep. We
|
51
|
+
# # also replace #use_billing_address_as_delivery_address with
|
52
|
+
# # #use_delivery_address_as_billing_address.
|
53
|
+
# #
|
54
|
+
# steps :validate_delivery_address,
|
55
|
+
# :use_delivery_address_as_billing_address,
|
56
|
+
# :validate_billing_address,
|
57
|
+
# :ensure_delivery,
|
58
|
+
# :store_addresses,
|
59
|
+
# :propose_shipments,
|
60
|
+
# :finish_address_step
|
61
|
+
#
|
62
|
+
# protected
|
63
|
+
#
|
64
|
+
# def use_delivery_address_as_billing_address(state)
|
65
|
+
# if state[:use_delivery_address] == true
|
66
|
+
# state.merge(billing_address: state[:delivery_address])
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
# end
|
70
|
+
# ```
|
71
|
+
#
|
72
|
+
#
|
3
73
|
class Step
|
74
|
+
# Set steps for a subclass of {Step}.
|
75
|
+
#
|
76
|
+
# @example
|
77
|
+
# class MyStep < MarketTown::Checkout::Step
|
78
|
+
# steps :a_step,
|
79
|
+
# :a_second_step
|
80
|
+
#
|
81
|
+
# protected
|
82
|
+
#
|
83
|
+
# def a_step(state)
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# def a_second_step(state)
|
87
|
+
# end
|
88
|
+
# end
|
89
|
+
#
|
4
90
|
def self.steps(*steps)
|
5
91
|
if steps.empty?
|
6
92
|
@steps
|
@@ -11,11 +97,17 @@ module MarketTown
|
|
11
97
|
|
12
98
|
attr_reader :meta, :deps
|
13
99
|
|
100
|
+
# Setup step meta object.
|
101
|
+
#
|
102
|
+
# @param [Dependencies]
|
103
|
+
#
|
14
104
|
def initialize(dependencies = Dependencies.new)
|
15
105
|
@meta = { name: name_from_class }
|
16
106
|
@deps = dependencies
|
17
107
|
end
|
18
108
|
|
109
|
+
# Process each sub-step that makes up step.
|
110
|
+
#
|
19
111
|
def process(state)
|
20
112
|
self.class.steps.reduce(state) do |state, step|
|
21
113
|
send(step, state) || state
|
@@ -33,7 +125,7 @@ module MarketTown
|
|
33
125
|
end
|
34
126
|
|
35
127
|
def add_dependency_missing_warning(state, warning)
|
36
|
-
deps.logger.warn("MissingDependency so #{warning.to_s.
|
128
|
+
deps.logger.warn("MissingDependency so #{warning.to_s.gsub('_', ' ')}")
|
37
129
|
state.merge(warnings: state.fetch(:warnings, []).push(warning))
|
38
130
|
end
|
39
131
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: market_town-checkout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luke Morton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-04-
|
11
|
+
date: 2016-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|