jamm 1.0.8 → 1.0.10

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +9 -1
  4. data/Rakefile +5 -0
  5. data/lib/jamm/api/api/customer_api.rb +68 -10
  6. data/lib/jamm/api/api/healthcheck_api.rb +2 -2
  7. data/lib/jamm/api/api/payment_api.rb +145 -20
  8. data/lib/jamm/api/api/webhook_service_api.rb +82 -0
  9. data/lib/jamm/api/api_client.rb +2 -2
  10. data/lib/jamm/api/api_error.rb +2 -2
  11. data/lib/jamm/api/configuration.rb +2 -2
  12. data/lib/jamm/api/models/customer_service_update_customer_body.rb +9 -4
  13. data/lib/jamm/api/models/{rpc_status.rb → googlerpc_status.rb} +5 -5
  14. data/lib/jamm/api/models/protobuf_any.rb +2 -2
  15. data/lib/jamm/api/models/v1_add_charge_request.rb +2 -2
  16. data/lib/jamm/api/models/v1_add_charge_response.rb +2 -2
  17. data/lib/jamm/api/models/v1_buyer.rb +11 -3
  18. data/lib/jamm/api/models/v1_charge.rb +2 -2
  19. data/lib/jamm/api/models/v1_charge_message.rb +297 -0
  20. data/lib/jamm/api/models/v1_charge_message_status.rb +44 -0
  21. data/lib/jamm/api/models/v1_charge_result.rb +285 -0
  22. data/lib/jamm/api/models/v1_contract.rb +2 -2
  23. data/lib/jamm/api/models/v1_contract_message.rb +222 -0
  24. data/lib/jamm/api/models/v1_contract_status.rb +2 -2
  25. data/lib/jamm/api/models/v1_create_contract_with_charge_request.rb +2 -2
  26. data/lib/jamm/api/models/v1_create_contract_with_charge_response.rb +2 -2
  27. data/lib/jamm/api/models/v1_create_contract_without_charge_request.rb +2 -2
  28. data/lib/jamm/api/models/v1_create_contract_without_charge_response.rb +2 -2
  29. data/lib/jamm/api/models/v1_create_customer_request.rb +2 -2
  30. data/lib/jamm/api/models/v1_create_customer_response.rb +2 -2
  31. data/lib/jamm/api/models/v1_customer.rb +9 -4
  32. data/lib/jamm/api/models/v1_delete_customer_response.rb +2 -2
  33. data/lib/jamm/api/models/v1_error.rb +217 -0
  34. data/lib/jamm/api/models/v1_event_type.rb +46 -0
  35. data/lib/jamm/api/models/v1_get_charge_response.rb +212 -0
  36. data/lib/jamm/api/models/v1_get_charges_response.rb +214 -0
  37. data/lib/jamm/api/models/v1_get_contract_response.rb +13 -13
  38. data/lib/jamm/api/models/v1_get_customer_response.rb +2 -2
  39. data/lib/jamm/api/models/v1_initial_charge.rb +2 -2
  40. data/lib/jamm/api/models/v1_merchant.rb +2 -2
  41. data/lib/jamm/api/models/v1_merchant_customer.rb +2 -2
  42. data/lib/jamm/api/models/v1_merchant_webhook_message.rb +259 -0
  43. data/lib/jamm/api/models/v1_message_response.rb +217 -0
  44. data/lib/jamm/api/models/v1_pagination.rb +212 -0
  45. data/lib/jamm/api/models/v1_payment_link.rb +2 -2
  46. data/lib/jamm/api/models/v1_ping_response.rb +2 -2
  47. data/lib/jamm/api/models/v1_update_customer_response.rb +2 -2
  48. data/lib/jamm/api/models/v1_url.rb +2 -2
  49. data/lib/jamm/api/models/v1_withdraw_request.rb +212 -0
  50. data/lib/jamm/api/models/v1_withdraw_response.rb +212 -0
  51. data/lib/jamm/api/version.rb +2 -2
  52. data/lib/jamm/api.rb +17 -3
  53. data/lib/jamm/api_patches.rb +14 -0
  54. data/lib/jamm/charge.rb +43 -0
  55. data/lib/jamm/client.rb +1 -1
  56. data/lib/jamm/contract.rb +35 -0
  57. data/lib/jamm/customer.rb +24 -9
  58. data/lib/jamm/healthcheck.rb +14 -0
  59. data/lib/jamm/openapi.rb +10 -0
  60. data/lib/jamm/version.rb +1 -1
  61. data/lib/jamm/webhook.rb +46 -0
  62. data/lib/jamm.rb +16 -14
  63. metadata +23 -4
  64. data/lib/jamm/payment.rb +0 -27
data/lib/jamm/api.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # #api/v1/common.proto
3
+ # #Jamm API
4
4
  #
5
5
  # No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
6
6
  #
7
- # The version of the OpenAPI document: version not set
7
+ # The version of the OpenAPI document: 1.0
8
8
  #
9
9
  # Generated by: https://openapi-generator.tech
10
10
  # Generator version: 7.9.0
@@ -18,13 +18,17 @@ require 'jamm/api/configuration'
18
18
 
19
19
  # Models
20
20
  require 'jamm/api/models/customer_service_update_customer_body'
21
+ require 'jamm/api/models/googlerpc_status'
21
22
  require 'jamm/api/models/protobuf_any'
22
- require 'jamm/api/models/rpc_status'
23
23
  require 'jamm/api/models/v1_add_charge_request'
24
24
  require 'jamm/api/models/v1_add_charge_response'
25
25
  require 'jamm/api/models/v1_buyer'
26
26
  require 'jamm/api/models/v1_charge'
27
+ require 'jamm/api/models/v1_charge_message'
28
+ require 'jamm/api/models/v1_charge_message_status'
29
+ require 'jamm/api/models/v1_charge_result'
27
30
  require 'jamm/api/models/v1_contract'
31
+ require 'jamm/api/models/v1_contract_message'
28
32
  require 'jamm/api/models/v1_contract_status'
29
33
  require 'jamm/api/models/v1_create_contract_with_charge_request'
30
34
  require 'jamm/api/models/v1_create_contract_with_charge_response'
@@ -34,20 +38,30 @@ require 'jamm/api/models/v1_create_customer_request'
34
38
  require 'jamm/api/models/v1_create_customer_response'
35
39
  require 'jamm/api/models/v1_customer'
36
40
  require 'jamm/api/models/v1_delete_customer_response'
41
+ require 'jamm/api/models/v1_error'
42
+ require 'jamm/api/models/v1_event_type'
43
+ require 'jamm/api/models/v1_get_charge_response'
44
+ require 'jamm/api/models/v1_get_charges_response'
37
45
  require 'jamm/api/models/v1_get_contract_response'
38
46
  require 'jamm/api/models/v1_get_customer_response'
39
47
  require 'jamm/api/models/v1_initial_charge'
40
48
  require 'jamm/api/models/v1_merchant'
41
49
  require 'jamm/api/models/v1_merchant_customer'
50
+ require 'jamm/api/models/v1_merchant_webhook_message'
51
+ require 'jamm/api/models/v1_message_response'
52
+ require 'jamm/api/models/v1_pagination'
42
53
  require 'jamm/api/models/v1_payment_link'
43
54
  require 'jamm/api/models/v1_ping_response'
44
55
  require 'jamm/api/models/v1_url'
45
56
  require 'jamm/api/models/v1_update_customer_response'
57
+ require 'jamm/api/models/v1_withdraw_request'
58
+ require 'jamm/api/models/v1_withdraw_response'
46
59
 
47
60
  # APIs
48
61
  require 'jamm/api/api/customer_api'
49
62
  require 'jamm/api/api/healthcheck_api'
50
63
  require 'jamm/api/api/payment_api'
64
+ require 'jamm/api/api/webhook_service_api'
51
65
 
52
66
  module Api
53
67
  class << self
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Api
4
+ class Customer
5
+ # Allow to drill down to list charges.
6
+ # e.g. cus.charges --> []
7
+ def charges(pagination: nil)
8
+ Jamm::Charge.list(
9
+ customer: self.id,
10
+ pagination: pagination
11
+ )
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rest-client'
4
+ require 'json'
5
+ require 'base64'
6
+ require 'jamm/errors'
7
+
8
+ module Jamm
9
+ module Charge
10
+ def self.create_with_redirect(customer:, charge:, redirect:)
11
+ request = Jamm::OpenAPI::AddChargeRequest.new(
12
+ customer: customer,
13
+ charge: charge,
14
+ redirect: redirect
15
+ )
16
+
17
+ Jamm::OpenAPI::PaymentApi.new(Jamm::Client.handler).add_charge(request)
18
+ end
19
+
20
+ def self.create_without_redirect(customer:, charge:)
21
+ request = Jamm::OpenAPI::WithdrawRequest.new(
22
+ customer: customer,
23
+ charge: charge
24
+ )
25
+
26
+ Jamm::OpenAPI::PaymentApi.new(Jamm::Client.handler).withdraw(request)
27
+ end
28
+
29
+ def self.get(charge_id)
30
+ Jamm::OpenAPI::PaymentApi.new(Jamm::Client.handler).get_charge(charge_id)
31
+ rescue Jamm::OpenAPI::ApiError => e
32
+ [404].include?(e.code) ? nil : raise
33
+ end
34
+
35
+ def self.list(customer:, pagination: nil)
36
+ got = Jamm::OpenAPI::PaymentApi.new(Jamm::Client.handler).get_charges(customer, pagination.nil? ? {} : pagination)
37
+
38
+ got.charges
39
+ rescue Jamm::OpenAPI::ApiError => e
40
+ [404].include?(e.code) ? nil : []
41
+ end
42
+ end
43
+ end
data/lib/jamm/client.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Jamm
2
2
  module Client
3
3
  def self.handler
4
- base = Jamm::ApiClient.new
4
+ base = Jamm::OpenAPI::ApiClient.new
5
5
 
6
6
  # Configure
7
7
  base.config.host = Jamm.openapi.config.host
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rest-client'
4
+ require 'json'
5
+ require 'base64'
6
+ require 'jamm/errors'
7
+
8
+ module Jamm
9
+ module Contract
10
+ def self.create_with_charge(buyer:, charge:, redirect:)
11
+ request = Jamm::OpenAPI::CreateContractWithChargeRequest.new(
12
+ buyer: buyer,
13
+ charge: charge,
14
+ redirect: redirect
15
+ )
16
+
17
+ Jamm::OpenAPI::PaymentApi.new(Jamm::Client.handler).create_contract_with_charge(request)
18
+ end
19
+
20
+ def self.create_without_charge(buyer:, redirect:)
21
+ request = Jamm::OpenAPI::CreateContractWithoutChargeRequest.new(
22
+ buyer: buyer,
23
+ redirect: redirect
24
+ )
25
+
26
+ Jamm::OpenAPI::PaymentApi.new(Jamm::Client.handler).create_contract_without_charge(request)
27
+ end
28
+
29
+ def self.get(customer_id)
30
+ Jamm::OpenAPI::CustomerApi.new(Jamm::Client.handler).get_contract(customer_id)
31
+ rescue Jamm::OpenAPI::ApiError => e
32
+ [404].include?(e.code) ? nil : raise
33
+ end
34
+ end
35
+ end
data/lib/jamm/customer.rb CHANGED
@@ -4,23 +4,38 @@ require 'rest-client'
4
4
  require 'json'
5
5
  require 'base64'
6
6
  require 'jamm/errors'
7
+ require 'jamm/api/models/v1_create_customer_request'
7
8
 
8
9
  module Jamm
9
10
  module Customer
10
- def self.get(customer:)
11
- Jamm::CustomerApi.new(Jamm::Client.handler).get customer
12
- rescue Jamm::ApiError => e
13
- return nil if e.code == 404
11
+ def self.create(buyer:)
12
+ r = Jamm::OpenAPI::CustomerApi.new(Jamm::Client.handler).create(
13
+ buyer: buyer
14
+ )
14
15
 
15
- raise
16
+ r.customer
16
17
  end
17
18
 
18
- def self.update(**params)
19
- Jamm::CustomerApi.new(Jamm::Client.handler).update(params[:id], params)
19
+ def self.get(id_or_email)
20
+ Jamm::OpenAPI::CustomerApi.new(Jamm::Client.handler).get(id_or_email)
21
+ rescue Jamm::OpenAPI::ApiError => e
22
+ [404].include?(e.code) ? nil : raise
20
23
  end
21
24
 
22
- def self.delete(customer:)
23
- Jamm::CustomerApi.new(Jamm::Client.handler).delete customer
25
+ def self.get_contract(id)
26
+ Jamm::OpenAPI::CustomerApi.new(Jamm::Client.handler).get_contract(id)
27
+ rescue Jamm::OpenAPI::ApiError => e
28
+ [404].include?(e.code) ? nil : raise
29
+ end
30
+
31
+ def self.update(id, params)
32
+ r = Jamm::OpenAPI::CustomerApi.new(Jamm::Client.handler).update(id, params)
33
+
34
+ r.customer
35
+ end
36
+
37
+ def self.delete(id)
38
+ Jamm::OpenAPI::CustomerApi.new(Jamm::Client.handler).delete(id)
24
39
  end
25
40
  end
26
41
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rest-client'
4
+ require 'json'
5
+ require 'base64'
6
+ require 'jamm/errors'
7
+
8
+ module Jamm
9
+ module Healthcheck
10
+ def self.ping
11
+ Jamm::OpenAPI::HealthcheckApi.new(Jamm::Client.handler).ping
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jamm/api'
4
+
5
+ module Jamm
6
+ # Customer wrapper for OpenAPI definitions.
7
+ module OpenAPI
8
+ include Api
9
+ end
10
+ end
data/lib/jamm/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Jamm
4
- VERSION = '1.0.8'
4
+ VERSION = '1.0.10'
5
5
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rest-client'
4
+ require 'json'
5
+ require 'base64'
6
+ require 'jamm/errors'
7
+
8
+ module Jamm
9
+ module Webhook
10
+ # Parse command is for parsing the received webhook message.
11
+ # It does not call anything remotely, instead returns the suitable object.
12
+ def self.parse(json)
13
+ out = {
14
+ id: json[:id],
15
+ signature: json[:signature],
16
+ event_type: json[:event_type],
17
+ content: nil,
18
+ created_at: json[:created_at]
19
+ }
20
+
21
+ case json[:event_type]
22
+ when Jamm::OpenAPI::EventType::CHARGE_CREATED
23
+ out[:content] = Jamm::OpenAPI::ChargeMessage.new(json[:content])
24
+ return out
25
+
26
+ when Jamm::OpenAPI::EventType::CHARGE_UPDATED
27
+ out[:content] = Jamm::OpenAPI::ChargeMessage.new(json[:content])
28
+ return out
29
+
30
+ when Jamm::OpenAPI::EventType::CHARGE_SUCCESS
31
+ out[:content] = Jamm::OpenAPI::ChargeMessage.new(json[:content])
32
+ return out
33
+
34
+ when Jamm::OpenAPI::EventType::CHARGE_FAIL
35
+ out[:content] = Jamm::OpenAPI::ChargeMessage.new(json[:content])
36
+ return out
37
+
38
+ when Jamm::OpenAPI::EventType::CONTRACT_ACTIVATED
39
+ out[:content] = Jamm::OpenAPI::ContractMessage.new(json[:content])
40
+ return out
41
+ end
42
+
43
+ raise 'Unknown event type'
44
+ end
45
+ end
46
+ end
data/lib/jamm.rb CHANGED
@@ -4,15 +4,21 @@ require 'rest-client'
4
4
  require 'openssl'
5
5
  require 'json'
6
6
 
7
- require 'jamm/api'
8
7
  require 'jamm/client'
9
8
  require 'jamm/errors'
10
9
  require 'jamm/oauth'
10
+ require 'jamm/openapi'
11
11
  require 'jamm/version'
12
12
 
13
13
  # OpenAPI wrappers
14
+ require 'jamm/charge'
14
15
  require 'jamm/customer'
15
- require 'jamm/payment'
16
+ require 'jamm/contract'
17
+ require 'jamm/healthcheck'
18
+ require 'jamm/webhook'
19
+
20
+ # Patches
21
+ require 'jamm/api_patches'
16
22
 
17
23
  # Jamm Ruby SDK
18
24
  module Jamm
@@ -23,10 +29,6 @@ module Jamm
23
29
  @read_timeout = 90
24
30
  @max_retry = 0
25
31
 
26
- # Include OpenAPI generated module into root Jamm namespace.
27
- # The OpenAPI sub-modules and methods can be accessed via Jamm::{foo}
28
- include Api
29
-
30
32
  class << self
31
33
  attr_accessor :api, :client_id, :client_secret, :api_base, :env, :oauth_base, :api_version, :connect_base,
32
34
  :openapi, :open_timeout, :read_timeout, :max_retry, :retry_initial_delay, :retry_max_delay
@@ -40,20 +42,20 @@ module Jamm
40
42
  when 'prod'
41
43
  self.oauth_base = 'https://merchant-identity.jamm-pay.jp'
42
44
 
43
- self.openapi = Jamm::ApiClient.new
45
+ self.openapi = Jamm::OpenAPI::ApiClient.new
44
46
  openapi.config.host = 'api.jamm-pay.jp'
45
47
 
46
- # Debugger mode, uncomment when needed
47
- # when 'local'
48
- # self.oauth_base = "https://merchant-identity.#{env}.jamm-pay.jp"
49
-
50
- # self.openapi = Jamm::ApiClient.new
51
- # openapi.config.host = 'api.jamm.test'
48
+ when 'local'
49
+ self.oauth_base = 'https://merchant-identity.develop.jamm-pay.jp'
52
50
 
51
+ self.openapi = Jamm::OpenAPI::ApiClient.new
52
+ openapi.config.host = 'api.jamm.test'
53
+ openapi.config.verify_ssl = false
54
+ openapi.config.verify_ssl_host = false
53
55
  else
54
56
  self.oauth_base = "https://merchant-identity.#{env}.jamm-pay.jp"
55
57
 
56
- self.openapi = Jamm::ApiClient.new
58
+ self.openapi = Jamm::OpenAPI::ApiClient.new
57
59
  openapi.config.host = "api.#{env}.jamm-pay.jp"
58
60
  end
59
61
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jamm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.8
4
+ version: 1.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-05 00:00:00.000000000 Z
11
+ date: 2024-11-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -63,17 +63,22 @@ files:
63
63
  - lib/jamm/api/api/customer_api.rb
64
64
  - lib/jamm/api/api/healthcheck_api.rb
65
65
  - lib/jamm/api/api/payment_api.rb
66
+ - lib/jamm/api/api/webhook_service_api.rb
66
67
  - lib/jamm/api/api_client.rb
67
68
  - lib/jamm/api/api_error.rb
68
69
  - lib/jamm/api/configuration.rb
69
70
  - lib/jamm/api/models/customer_service_update_customer_body.rb
71
+ - lib/jamm/api/models/googlerpc_status.rb
70
72
  - lib/jamm/api/models/protobuf_any.rb
71
- - lib/jamm/api/models/rpc_status.rb
72
73
  - lib/jamm/api/models/v1_add_charge_request.rb
73
74
  - lib/jamm/api/models/v1_add_charge_response.rb
74
75
  - lib/jamm/api/models/v1_buyer.rb
75
76
  - lib/jamm/api/models/v1_charge.rb
77
+ - lib/jamm/api/models/v1_charge_message.rb
78
+ - lib/jamm/api/models/v1_charge_message_status.rb
79
+ - lib/jamm/api/models/v1_charge_result.rb
76
80
  - lib/jamm/api/models/v1_contract.rb
81
+ - lib/jamm/api/models/v1_contract_message.rb
77
82
  - lib/jamm/api/models/v1_contract_status.rb
78
83
  - lib/jamm/api/models/v1_create_contract_with_charge_request.rb
79
84
  - lib/jamm/api/models/v1_create_contract_with_charge_response.rb
@@ -83,22 +88,36 @@ files:
83
88
  - lib/jamm/api/models/v1_create_customer_response.rb
84
89
  - lib/jamm/api/models/v1_customer.rb
85
90
  - lib/jamm/api/models/v1_delete_customer_response.rb
91
+ - lib/jamm/api/models/v1_error.rb
92
+ - lib/jamm/api/models/v1_event_type.rb
93
+ - lib/jamm/api/models/v1_get_charge_response.rb
94
+ - lib/jamm/api/models/v1_get_charges_response.rb
86
95
  - lib/jamm/api/models/v1_get_contract_response.rb
87
96
  - lib/jamm/api/models/v1_get_customer_response.rb
88
97
  - lib/jamm/api/models/v1_initial_charge.rb
89
98
  - lib/jamm/api/models/v1_merchant.rb
90
99
  - lib/jamm/api/models/v1_merchant_customer.rb
100
+ - lib/jamm/api/models/v1_merchant_webhook_message.rb
101
+ - lib/jamm/api/models/v1_message_response.rb
102
+ - lib/jamm/api/models/v1_pagination.rb
91
103
  - lib/jamm/api/models/v1_payment_link.rb
92
104
  - lib/jamm/api/models/v1_ping_response.rb
93
105
  - lib/jamm/api/models/v1_update_customer_response.rb
94
106
  - lib/jamm/api/models/v1_url.rb
107
+ - lib/jamm/api/models/v1_withdraw_request.rb
108
+ - lib/jamm/api/models/v1_withdraw_response.rb
95
109
  - lib/jamm/api/version.rb
110
+ - lib/jamm/api_patches.rb
111
+ - lib/jamm/charge.rb
96
112
  - lib/jamm/client.rb
113
+ - lib/jamm/contract.rb
97
114
  - lib/jamm/customer.rb
98
115
  - lib/jamm/errors.rb
116
+ - lib/jamm/healthcheck.rb
99
117
  - lib/jamm/oauth.rb
100
- - lib/jamm/payment.rb
118
+ - lib/jamm/openapi.rb
101
119
  - lib/jamm/version.rb
120
+ - lib/jamm/webhook.rb
102
121
  homepage: https://jamm-pay.jp
103
122
  licenses:
104
123
  - MIT
data/lib/jamm/payment.rb DELETED
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rest-client'
4
- require 'json'
5
- require 'base64'
6
- require 'jamm/errors'
7
-
8
- module Jamm
9
- module Payment
10
- def self.contract_with_charge(**params)
11
- request = Jamm::CreateContractWithChargeRequest.new(params)
12
-
13
- Jamm::PaymentApi.new(Jamm::Client.handler).create_contract_with_charge(request)
14
- end
15
-
16
- def self.get_contract(contract:)
17
- Jamm::PaymentApi.new(Jamm::Client.handler).get_contract(contract)
18
- end
19
-
20
- def self.add_charge(**params)
21
- request = Jamm::AddChargeRequest.new(params)
22
-
23
- p = Jamm::PaymentApi.new(Jamm::Client.handler)
24
- p.add_charge(request)
25
- end
26
- end
27
- end