openpay_copemx 3.0.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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +10 -0
  5. data/LICENSE.txt +13 -0
  6. data/README.md +1984 -0
  7. data/Rakefile +16 -0
  8. data/lib/openpay/bankaccounts.rb +58 -0
  9. data/lib/openpay/cards.rb +73 -0
  10. data/lib/openpay/charges.rb +101 -0
  11. data/lib/openpay/colombia/cards_co.rb +73 -0
  12. data/lib/openpay/colombia/charges_co.rb +76 -0
  13. data/lib/openpay/colombia/customers_co.rb +166 -0
  14. data/lib/openpay/colombia/plans_co.rb +17 -0
  15. data/lib/openpay/colombia/pse_co.rb +17 -0
  16. data/lib/openpay/colombia/subscriptions_co.rb +50 -0
  17. data/lib/openpay/colombia/tokens_co.rb +5 -0
  18. data/lib/openpay/colombia/webhooks_co.rb +5 -0
  19. data/lib/openpay/customers.rb +200 -0
  20. data/lib/openpay/errors/openpay_connection_exception.rb +3 -0
  21. data/lib/openpay/errors/openpay_exception.rb +29 -0
  22. data/lib/openpay/errors/openpay_exception_factory.rb +56 -0
  23. data/lib/openpay/errors/openpay_transaction_exception.rb +5 -0
  24. data/lib/openpay/fees.rb +5 -0
  25. data/lib/openpay/open_pay_resource.rb +295 -0
  26. data/lib/openpay/open_pay_resource_factory.rb +17 -0
  27. data/lib/openpay/openpay_api.rb +72 -0
  28. data/lib/openpay/payouts.rb +55 -0
  29. data/lib/openpay/peru/cards_pe.rb +73 -0
  30. data/lib/openpay/peru/charges_pe.rb +76 -0
  31. data/lib/openpay/peru/checkouts_pe.rb +51 -0
  32. data/lib/openpay/peru/customers_pe.rb +79 -0
  33. data/lib/openpay/peru/tokens_pe.rb +5 -0
  34. data/lib/openpay/peru/webhooks_pe.rb +5 -0
  35. data/lib/openpay/plans.rb +17 -0
  36. data/lib/openpay/points.rb +10 -0
  37. data/lib/openpay/subscriptions.rb +50 -0
  38. data/lib/openpay/tokens.rb +7 -0
  39. data/lib/openpay/transfers.rb +39 -0
  40. data/lib/openpay/utils/country.rb +3 -0
  41. data/lib/openpay/utils/search_params.rb +24 -0
  42. data/lib/openpay/webhooks.rb +9 -0
  43. data/lib/openpay.rb +55 -0
  44. data/lib/version.rb +3 -0
  45. data/openpay.gemspec +30 -0
  46. data/test/Factories.rb +524 -0
  47. data/test/spec/bankaccounts_spec.rb +52 -0
  48. data/test/spec/cards_spec.rb +437 -0
  49. data/test/spec/charges_spec.rb +382 -0
  50. data/test/spec/colombia/cards_col_spec.rb +364 -0
  51. data/test/spec/colombia/charges_col_spec.rb +258 -0
  52. data/test/spec/colombia/customers_co_spec.rb +151 -0
  53. data/test/spec/colombia/plans_col_spec.rb +133 -0
  54. data/test/spec/colombia/pse_col_spec.rb +49 -0
  55. data/test/spec/colombia/subscriptions_col_spec.rb +230 -0
  56. data/test/spec/colombia/tokens_col_spec.rb +38 -0
  57. data/test/spec/customers_spec.rb +172 -0
  58. data/test/spec/exceptions_spec.rb +105 -0
  59. data/test/spec/fees_spec.rb +166 -0
  60. data/test/spec/openpayresource_spec.rb +54 -0
  61. data/test/spec/payouts_spec.rb +231 -0
  62. data/test/spec/peru/cards_pe_spec.rb +363 -0
  63. data/test/spec/peru/charges_pe_spec.rb +218 -0
  64. data/test/spec/peru/checkouts_pe_spec.rb +71 -0
  65. data/test/spec/peru/customers_pe_spec.rb +151 -0
  66. data/test/spec/peru/tokens_pe_spec.rb +38 -0
  67. data/test/spec/peru/webhook_pe_spec.rb +50 -0
  68. data/test/spec/plans_spec.rb +158 -0
  69. data/test/spec/points_spec.rb +26 -0
  70. data/test/spec/requesttimeout_spec.rb +22 -0
  71. data/test/spec/subscriptions_spec.rb +294 -0
  72. data/test/spec/transfers_spec.rb +219 -0
  73. data/test/spec/utils/search_params_spec.rb +36 -0
  74. data/test/spec_helper.rb +24 -0
  75. metadata +219 -0
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require 'rspec'
2
+ require 'rspec/core/rake_task'
3
+
4
+ task :default => [:spec]
5
+
6
+ desc 'run specifications'
7
+
8
+ RSpec::Core::RakeTask.new do |t|
9
+ t.pattern = Dir.glob('test/spec/**/*_spec.rb')
10
+ end
11
+
12
+
13
+ RSpec::Core::RakeTask.new('bankaccounts') do |t|
14
+ t.pattern = 'test/spec/bankaccounts*'
15
+ end
16
+
@@ -0,0 +1,58 @@
1
+ require 'open_pay_resource'
2
+
3
+ class Bankaccounts < OpenPayResource
4
+
5
+ def create(bank_account,customer_id)
6
+ customers=@api_hook.create(:customers)
7
+ customers.create_bank_account(customer_id,bank_account)
8
+ end
9
+
10
+ def get(customer_id='',bank_account=nil)
11
+ customers=@api_hook.create(:customers)
12
+
13
+ if bank_account
14
+ customers.get_bank_account(customer_id,bank_account)
15
+ else
16
+ customers.get_bank_account(customer_id)
17
+ end
18
+
19
+ end
20
+
21
+ def delete(customer_id,bank_account)
22
+ customers=@api_hook.create(:customers)
23
+ customers.delete_bank_account(customer_id,bank_account)
24
+ end
25
+
26
+ def each(customer_id)
27
+ customers=@api_hook.create(:customers)
28
+ customers.each_bank_account(customer_id) do |acc|
29
+ yield acc
30
+ end
31
+ end
32
+
33
+ def all(customer_id)
34
+ customers=@api_hook.create(:customers)
35
+ customers.all_bank_accounts(customer_id)
36
+ end
37
+
38
+ def list(search_params,customer_id=nil)
39
+ if customer_id
40
+ customers=@api_hook.create(:customers)
41
+ customers.list_bankaccounts(customer_id,search_params)
42
+ else
43
+ super search_params
44
+ end
45
+ end
46
+
47
+ def delete_all(customer_id)
48
+
49
+ if env == :production
50
+ raise OpenpayException.new('This method is not supported on PRODUCTION',false)
51
+ end
52
+
53
+ customers=@api_hook.create(:customers)
54
+ customers.delete_all_bank_accounts(customer_id)
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,73 @@
1
+ require 'open_pay_resource'
2
+
3
+ class Cards < OpenPayResource
4
+
5
+ def get(card='',customer_id=nil)
6
+ if customer_id
7
+ customers=@api_hook.create(:customers)
8
+ customers.get_card(customer_id,card)
9
+ else
10
+ super card
11
+ end
12
+ end
13
+
14
+ def create(card,customer_id=nil)
15
+ if customer_id
16
+ customers=@api_hook.create(:customers)
17
+ customers.create_card(customer_id,card)
18
+ else
19
+ super card
20
+ end
21
+ end
22
+
23
+ def delete(card_id,customer_id=nil)
24
+ if customer_id
25
+ customers=@api_hook.create(:customers)
26
+ customers.delete_card(customer_id,card_id)
27
+ else
28
+ super card_id
29
+ end
30
+ end
31
+
32
+ def delete_all(customer_id=nil)
33
+ if customer_id
34
+ customers=@api_hook.create(:customers)
35
+ customers.delete_all_cards(customer_id)
36
+ else
37
+ each do |card|
38
+ delete(card['id'])
39
+ end
40
+ end
41
+ end
42
+
43
+ def each(customer_id=nil)
44
+ if customer_id
45
+ all(customer_id).each do |card|
46
+ yield card
47
+ end
48
+ else
49
+ all.each do |card|
50
+ yield card
51
+ end
52
+ end
53
+ end
54
+
55
+ def all(customer_id=nil)
56
+ if customer_id
57
+ customers=@api_hook.create(:customers)
58
+ customers.all_cards(customer_id)
59
+ else
60
+ super ''
61
+ end
62
+ end
63
+
64
+ def list(search_params,customer_id=nil)
65
+ if customer_id
66
+ customers=@api_hook.create(:customers)
67
+ customers.list_cards(customer_id,search_params)
68
+ else
69
+ super search_params
70
+ end
71
+ end
72
+
73
+ end
@@ -0,0 +1,101 @@
1
+ require 'open_pay_resource'
2
+
3
+ class Charges < OpenPayResource
4
+
5
+ def all(customer_id=nil)
6
+ if customer_id
7
+ customers=@api_hook.create(:customers)
8
+ customers.all_charges(customer_id)
9
+ else
10
+ super ''
11
+ end
12
+ end
13
+
14
+ def cancel(transaction_id, customer_id=nil)
15
+ if customer_id
16
+ customers=@api_hook.create(:customers)
17
+ customers.cancel_charge(customer_id, transaction_id)
18
+ else
19
+ post('', transaction_id+'/cancel')
20
+ end
21
+ end
22
+
23
+ def refund(transaction_id, description, customer_id=nil)
24
+ if customer_id
25
+ customers=@api_hook.create(:customers)
26
+ customers.refund_charge(customer_id, transaction_id, description)
27
+ else
28
+ post(description, transaction_id+'/refund')
29
+ end
30
+ end
31
+
32
+ def capture(transaction_id, customer_id=nil)
33
+ if customer_id
34
+ customers=@api_hook.create(:customers)
35
+ customers.capture_charge(customer_id, transaction_id)
36
+ else
37
+ post('', transaction_id+'/capture')
38
+ end
39
+ end
40
+
41
+ def confirm_capture(options)
42
+
43
+ customer_id = options.fetch(:customer_id) { '' }
44
+ transaction_id = options.fetch(:transaction_id)
45
+ amount = options.fetch(:amount)
46
+
47
+ if amount.nil? or transaction_id.nil?
48
+ raise OpenpayException.new
49
+ end
50
+
51
+ amount_hash = { amount: amount }
52
+
53
+ unless customer_id.empty?
54
+ customers=@api_hook.create(:customers)
55
+ customers.confirm_customer_capture(customer_id, transaction_id, amount_hash)
56
+ else
57
+ post(amount_hash, transaction_id+'/capture')
58
+ end
59
+
60
+ end
61
+
62
+ def each(customer_id=nil)
63
+ if customer_id
64
+ all(customer_id).each do |card|
65
+ yield card
66
+ end
67
+ else
68
+ all.each do |card|
69
+ yield card
70
+ end
71
+ end
72
+ end
73
+
74
+ def get(charge='', customer_id=nil)
75
+ if customer_id
76
+ customers=@api_hook.create(:customers)
77
+ customers.get_charge(customer_id, charge)
78
+ else
79
+ super charge
80
+ end
81
+ end
82
+
83
+ def create(charge, customer_id=nil)
84
+ if customer_id
85
+ customers=@api_hook.create(:customers)
86
+ customers.create_charge(customer_id, charge)
87
+ else
88
+ super charge
89
+ end
90
+ end
91
+
92
+ def list(search_params, customer_id=nil)
93
+ if customer_id
94
+ customers=@api_hook.create(:customers)
95
+ customers.list_charges(customer_id, search_params)
96
+ else
97
+ super search_params
98
+ end
99
+ end
100
+
101
+ end
@@ -0,0 +1,73 @@
1
+ require 'open_pay_resource'
2
+
3
+ class CardsCo < OpenPayResource
4
+
5
+ def get(card='',customer_id=nil)
6
+ if customer_id
7
+ customers=@api_hook.create(:customers)
8
+ customers.get_card(customer_id,card)
9
+ else
10
+ super card
11
+ end
12
+ end
13
+
14
+ def create(card,customer_id=nil)
15
+ if customer_id
16
+ customers=@api_hook.create(:customers)
17
+ customers.create_card(customer_id,card)
18
+ else
19
+ super card
20
+ end
21
+ end
22
+
23
+ def delete(card_id,customer_id=nil)
24
+ if customer_id
25
+ customers=@api_hook.create(:customers)
26
+ customers.delete_card(customer_id,card_id)
27
+ else
28
+ super card_id
29
+ end
30
+ end
31
+
32
+ def delete_all(customer_id=nil)
33
+ if customer_id
34
+ customers=@api_hook.create(:customers)
35
+ customers.delete_all_cards(customer_id)
36
+ else
37
+ each do |card|
38
+ delete(card['id'])
39
+ end
40
+ end
41
+ end
42
+
43
+ def each(customer_id=nil)
44
+ if customer_id
45
+ all(customer_id).each do |card|
46
+ yield card
47
+ end
48
+ else
49
+ all.each do |card|
50
+ yield card
51
+ end
52
+ end
53
+ end
54
+
55
+ def all(customer_id=nil)
56
+ if customer_id
57
+ customers=@api_hook.create(:customers)
58
+ customers.all_cards(customer_id)
59
+ else
60
+ super ''
61
+ end
62
+ end
63
+
64
+ def list(search_params,customer_id=nil)
65
+ if customer_id
66
+ customers=@api_hook.create(:customers)
67
+ customers.list_cards(customer_id,search_params)
68
+ else
69
+ super search_params
70
+ end
71
+ end
72
+
73
+ end
@@ -0,0 +1,76 @@
1
+ require 'open_pay_resource'
2
+
3
+ class ChargesCo < OpenPayResource
4
+
5
+ def create(charge, customer_id = nil)
6
+ amount = charge[:amount].to_s.split('.')
7
+ if amount.length > 0
8
+ LOG.warn "The amount have decimals. Revoming.."
9
+ end
10
+ charge[:amount] = amount[0]
11
+ if customer_id
12
+ customers = @api_hook.create(:customers)
13
+ customers.create_charge(customer_id, charge)
14
+ else
15
+ super charge
16
+ end
17
+ end
18
+
19
+ def all(customer_id = nil)
20
+ if customer_id
21
+ customers = @api_hook.create(:customers)
22
+ customers.all_charges(customer_id)
23
+ else
24
+ super ''
25
+ end
26
+ end
27
+
28
+ def cancel(transaction_id, customer_id = nil)
29
+ if customer_id
30
+ customers = @api_hook.create(:customers)
31
+ customers.cancel_charge(customer_id, transaction_id)
32
+ else
33
+ post('', transaction_id + '/cancel')
34
+ end
35
+ end
36
+
37
+ def refund(transaction_id, description, customer_id = nil)
38
+ if customer_id
39
+ customers = @api_hook.create(:customers)
40
+ customers.refund_charge(customer_id, transaction_id, description)
41
+ else
42
+ post(description, transaction_id + '/refund')
43
+ end
44
+ end
45
+
46
+ def each(customer_id = nil)
47
+ if customer_id
48
+ all(customer_id).each do |card|
49
+ yield card
50
+ end
51
+ else
52
+ all.each do |card|
53
+ yield card
54
+ end
55
+ end
56
+ end
57
+
58
+ def get(charge = '', customer_id = nil)
59
+ if customer_id
60
+ customers = @api_hook.create(:customers)
61
+ customers.get_charge(customer_id, charge)
62
+ else
63
+ super charge
64
+ end
65
+ end
66
+
67
+ def list(search_params, customer_id = nil)
68
+ if customer_id
69
+ customers = @api_hook.create(:customers)
70
+ customers.list_charges(customer_id, search_params)
71
+ else
72
+ super search_params
73
+ end
74
+ end
75
+
76
+ end
@@ -0,0 +1,166 @@
1
+ require 'openpay/open_pay_resource'
2
+
3
+ class CustomersCo < OpenPayResource
4
+
5
+ #Charges
6
+ # customers.create_charge(customer_id,charge)
7
+ def create_charge(customer_id, charge)
8
+ create(charge, "#{customer_id}/charges")
9
+ end
10
+
11
+ #gets a charge_id for a given customer_id
12
+ def get_charge(customer_id, charge_id)
13
+ get("#{customer_id}/charges/#{charge_id}")
14
+ end
15
+
16
+ # def list_charges(customer, search_params)
17
+ # get("#{customer}/charges#{search_params.to_s}")
18
+ # end
19
+ #
20
+
21
+ #return all charges for the given customer_id
22
+ def all_charges(customer_id)
23
+ get("#{customer_id}/charges/")
24
+ end
25
+
26
+ # def cancel_charge(customer_id, charge_id)
27
+ # post(charge_id, "#{customer_id}/charges/#{charge_id}/cancel")
28
+ # end
29
+ #
30
+ def refund_charge(customer_id, charge_id, description)
31
+ post(description, "#{customer_id}/charges/#{charge_id}/refund")
32
+ end
33
+
34
+
35
+ # def capture_charge(customer_id, charge_id)
36
+ # post('', "#{customer_id}/charges/#{charge_id}/capture")
37
+ # end
38
+ #
39
+ # def confirm_customer_capture(customer_id, charge_id, amount)
40
+ # post(amount, "#{customer_id}/charges/#{charge_id}/capture")
41
+ # end
42
+ #
43
+ # #Payouts
44
+ # def create_payout(customer_id, payout)
45
+ # post(payout, "#{customer_id}/payouts")
46
+ # end
47
+ #
48
+ # def all_payouts(customer_id)
49
+ # get("#{customer_id}/payouts")
50
+ # end
51
+ #
52
+ # def get_payout(customer_id, payout_id)
53
+ # get("#{customer_id}/payouts/#{payout_id}")
54
+ # end
55
+ #
56
+ # def each_payout(customer_id)
57
+ # all_payouts(customer_id).each do |pay|
58
+ # yield pay
59
+ # end
60
+ # end
61
+ #
62
+ # def list_payouts(customer, search_params)
63
+ # get("#{customer}/payouts#{search_params.to_s}")
64
+ # end
65
+ #
66
+ # #Transfers
67
+ # def create_transfer(customer_id, transfer)
68
+ # post(transfer, "#{customer_id}/transfers")
69
+ # end
70
+ #
71
+ # def all_transfers(customer_id)
72
+ # get("#{customer_id}/transfers/")
73
+ # end
74
+ #
75
+ # def list_transfers(customer, search_params)
76
+ # get("#{customer}/transfers#{search_params.to_s}")
77
+ # end
78
+ #
79
+ # def get_transfer(customer_id, transfer_id)
80
+ # get("#{customer_id}/transfers/#{transfer_id}")
81
+ # end
82
+ #
83
+ # def each_transfer(customer_id)
84
+ # all_transfers(customer_id).each do |trans|
85
+ # yield trans
86
+ # end
87
+ # end
88
+ #
89
+ #Subscriptions
90
+ def create_subscription(subscription, customer_id)
91
+ #revisar la url
92
+ post(subscription, "#{customer_id}/subscriptions")
93
+ end
94
+
95
+ def delete_subscription(customer_id, subscription_id)
96
+ delete("#{customer_id}/subscriptions/#{subscription_id}")
97
+ end
98
+
99
+ def get_subscription(customer_id, subscription_id)
100
+ get("#{customer_id}/subscriptions/#{subscription_id}")
101
+ end
102
+
103
+ def all_subscriptions(customer_id)
104
+ get("#{customer_id}/subscriptions/")
105
+ end
106
+
107
+ def list_subscriptions(customer, search_params)
108
+ get("#{customer}/subscriptions#{search_params.to_s}")
109
+ end
110
+
111
+ def each_subscription(customer_id)
112
+ all_subscriptions(customer_id).each do |cust|
113
+ yield cust
114
+ end
115
+ end
116
+
117
+ def update_subscription(subscription, customer, params)
118
+ put(params, "#{customer}/subscriptions/#{subscription}")
119
+ end
120
+
121
+ def delete_all_subscriptions(customer_id)
122
+ if env == :production
123
+ raise OpenpayException.new('This method is not supported on PRODUCTION', false)
124
+ end
125
+ all_subscriptions(customer_id).each do |sub|
126
+ delete_subscription(customer_id, sub['id'])
127
+ end
128
+ end
129
+
130
+ #Card
131
+ def create_card(customer, card)
132
+ create(card, "#{customer}/cards")
133
+ end
134
+
135
+ def get_card(customer, card_id)
136
+ get("#{customer}/cards/#{card_id}")
137
+ end
138
+
139
+ def delete_card(customer, card_id)
140
+ delete("#{customer}/cards/#{card_id}")
141
+ end
142
+
143
+ def delete_all_cards(customer_id)
144
+ if env == :production
145
+ raise OpenpayException.new('This method is not supported on PRODUCTION', false)
146
+ end
147
+ each_card(customer_id) do |card|
148
+ delete_card(customer_id, card['id'])
149
+ end
150
+ end
151
+
152
+ def each_card(customer)
153
+ get("#{customer}/cards").each do |card|
154
+ yield card
155
+ end
156
+ end
157
+
158
+ def list_cards(customer, search_params)
159
+ get("#{customer}/cards#{search_params.to_s}")
160
+ end
161
+
162
+ def all_cards(customer)
163
+ get("#{customer}/cards")
164
+ end
165
+
166
+ end
@@ -0,0 +1,17 @@
1
+ require 'openpay/open_pay_resource'
2
+
3
+ class PlansCo < OpenPayResource
4
+
5
+ def update(plan,plan_id)
6
+ put(plan, "#{plan_id}")
7
+ end
8
+
9
+ def each_subscription(plan_id)
10
+ get("#{plan_id}/subscriptions")
11
+ end
12
+
13
+ def all_subscriptions(plan_id)
14
+ get("#{plan_id}/subscriptions")
15
+ end
16
+
17
+ end
@@ -0,0 +1,17 @@
1
+ class PseCo < OpenPayResource
2
+
3
+ def create(charge, customer_id = nil)
4
+ amount = charge[:amount].to_s.split('.')
5
+ if amount.length > 0
6
+ LOG.warn "The amount have decimals. Revoming.."
7
+ end
8
+ charge[:amount] = amount[0]
9
+ if customer_id
10
+ customers = @api_hook.create(:customers)
11
+ customers.create_charge(customer_id, charge)
12
+ else
13
+ super charge
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,50 @@
1
+ require 'openpay/open_pay_resource'
2
+
3
+ class SubscriptionsCo < OpenPayResource
4
+
5
+ def create(subscription, customer_id)
6
+ customers=@api_hook.create(:customers)
7
+ customers.create_subscription(subscription, customer_id)
8
+ end
9
+
10
+ def delete(subscription_id, customer_id)
11
+ customers=@api_hook.create(:customers)
12
+ customers.delete_subscription(customer_id, subscription_id)
13
+ end
14
+
15
+ def get(subscription_id, customer_id)
16
+ customers=@api_hook.create(:customers)
17
+ customers.get_subscription(customer_id, subscription_id)
18
+ end
19
+
20
+ def all(customer_id)
21
+ customers=@api_hook.create(:customers)
22
+ customers.all_subscriptions(customer_id)
23
+ end
24
+
25
+ def each(customer_id)
26
+ customers=@api_hook.create(:customers)
27
+ customers.each_subscription(customer_id) do |c|
28
+ yield c
29
+ end
30
+ end
31
+
32
+ def list(search_params,customer_id=nil)
33
+ if customer_id
34
+ customers=@api_hook.create(:customers)
35
+ customers.list_subscriptions(customer_id,search_params)
36
+ else
37
+ super search_params
38
+ end
39
+ end
40
+
41
+ def update(subscription_id,customer_id,params)
42
+ customers=@api_hook.create(:customers)
43
+ customers.update_subscription(subscription_id,customer_id,params)
44
+ end
45
+
46
+ def delete_all(customer_id)
47
+ customers=@api_hook.create(:customers)
48
+ customers.delete_all_subscriptions(customer_id)
49
+ end
50
+ end
@@ -0,0 +1,5 @@
1
+ require 'openpay/open_pay_resource'
2
+
3
+ class TokensCo < OpenPayResource
4
+
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'openpay/open_pay_resource'
2
+
3
+ class WebhooksCo < OpenPayResource
4
+
5
+ end