tickethub 0.0.1

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 (73) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/lib/tickethub/address.rb +5 -0
  5. data/lib/tickethub/app/package.rb +9 -0
  6. data/lib/tickethub/app/subscription.rb +11 -0
  7. data/lib/tickethub/app.rb +36 -0
  8. data/lib/tickethub/category.rb +7 -0
  9. data/lib/tickethub/collection.rb +150 -0
  10. data/lib/tickethub/connection.rb +140 -0
  11. data/lib/tickethub/contact.rb +5 -0
  12. data/lib/tickethub/endpoint.rb +36 -0
  13. data/lib/tickethub/errors.rb +34 -0
  14. data/lib/tickethub/exceptions.rb +73 -0
  15. data/lib/tickethub/formats/form_format.rb +17 -0
  16. data/lib/tickethub/formats/json_format.rb +25 -0
  17. data/lib/tickethub/formats.rb +35 -0
  18. data/lib/tickethub/helpers.rb +108 -0
  19. data/lib/tickethub/request.rb +130 -0
  20. data/lib/tickethub/resource.rb +279 -0
  21. data/lib/tickethub/response/headers.rb +31 -0
  22. data/lib/tickethub/response.rb +49 -0
  23. data/lib/tickethub/supplier/answer.rb +11 -0
  24. data/lib/tickethub/supplier/app.rb +9 -0
  25. data/lib/tickethub/supplier/bill.rb +11 -0
  26. data/lib/tickethub/supplier/booking.rb +39 -0
  27. data/lib/tickethub/supplier/card.rb +11 -0
  28. data/lib/tickethub/supplier/coupon.rb +14 -0
  29. data/lib/tickethub/supplier/customer.rb +15 -0
  30. data/lib/tickethub/supplier/element.rb +11 -0
  31. data/lib/tickethub/supplier/fee.rb +15 -0
  32. data/lib/tickethub/supplier/gateway/handpoint.rb +8 -0
  33. data/lib/tickethub/supplier/gateway/ideal.rb +8 -0
  34. data/lib/tickethub/supplier/gateway/paypal.rb +8 -0
  35. data/lib/tickethub/supplier/gateway/stripe.rb +8 -0
  36. data/lib/tickethub/supplier/gateway.rb +16 -0
  37. data/lib/tickethub/supplier/invoice.rb +7 -0
  38. data/lib/tickethub/supplier/message/email.rb +8 -0
  39. data/lib/tickethub/supplier/message/sms.rb +8 -0
  40. data/lib/tickethub/supplier/message.rb +20 -0
  41. data/lib/tickethub/supplier/option.rb +18 -0
  42. data/lib/tickethub/supplier/order.rb +51 -0
  43. data/lib/tickethub/supplier/package.rb +9 -0
  44. data/lib/tickethub/supplier/payment/card.rb +18 -0
  45. data/lib/tickethub/supplier/payment/cash.rb +8 -0
  46. data/lib/tickethub/supplier/payment/credit.rb +8 -0
  47. data/lib/tickethub/supplier/payment/direct.rb +8 -0
  48. data/lib/tickethub/supplier/payment/gratuity.rb +8 -0
  49. data/lib/tickethub/supplier/payment.rb +34 -0
  50. data/lib/tickethub/supplier/product.rb +54 -0
  51. data/lib/tickethub/supplier/question.rb +11 -0
  52. data/lib/tickethub/supplier/rate.rb +16 -0
  53. data/lib/tickethub/supplier/receipt.rb +11 -0
  54. data/lib/tickethub/supplier/reseller.rb +36 -0
  55. data/lib/tickethub/supplier/scan.rb +17 -0
  56. data/lib/tickethub/supplier/season.rb +16 -0
  57. data/lib/tickethub/supplier/subscription.rb +11 -0
  58. data/lib/tickethub/supplier/tax.rb +16 -0
  59. data/lib/tickethub/supplier/template.rb +11 -0
  60. data/lib/tickethub/supplier/ticket.rb +25 -0
  61. data/lib/tickethub/supplier/tier.rb +20 -0
  62. data/lib/tickethub/supplier/user.rb +9 -0
  63. data/lib/tickethub/supplier/variant.rb +10 -0
  64. data/lib/tickethub/supplier/voucher.rb +23 -0
  65. data/lib/tickethub/supplier.rb +86 -0
  66. data/lib/tickethub/token.rb +9 -0
  67. data/lib/tickethub/user/app.rb +5 -0
  68. data/lib/tickethub/user/supplier.rb +5 -0
  69. data/lib/tickethub/user.rb +38 -0
  70. data/lib/tickethub/version.rb +3 -0
  71. data/lib/tickethub.rb +26 -0
  72. data/tickethub.gemspec +25 -0
  73. metadata +209 -0
@@ -0,0 +1,108 @@
1
+ require 'uri'
2
+
3
+ module Tickethub
4
+ module Helpers extend self
5
+ def to_path(*params)
6
+ params.map(&:to_s).reject(&:empty?) * '/'
7
+ end
8
+
9
+ def camelize(value)
10
+ value.to_s.split('_').map {|w| w.capitalize }.join
11
+ end
12
+
13
+ def deep_merge(hash, other_hash)
14
+ hash.merge(other_hash) do |key, oldval, newval|
15
+ oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
16
+ newval = newval.to_hash if newval.respond_to?(:to_hash)
17
+ oldval.class.to_s == 'Hash' && newval.class.to_s == 'Hash' ? deep_merge(oldval, newval) : newval
18
+ end
19
+ end
20
+
21
+ # Stolen from Rack:
22
+
23
+ DEFAULT_SEP = /[&;] */n
24
+
25
+ def to_param(value, prefix = nil)
26
+ case value
27
+ when Array
28
+ value.map { |v|
29
+ to_param(v, "#{prefix}[]")
30
+ }.join("&")
31
+ when Hash
32
+ value.map { |k, v|
33
+ to_param(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
34
+ }.join("&")
35
+ else
36
+ raise ArgumentError, "value must be a Hash" if prefix.nil?
37
+ "#{prefix}=#{escape(value)}"
38
+ end
39
+ end
40
+
41
+ def from_param(param)
42
+ Rack::Utils.parse_nested_query(param)
43
+ (value || '').split('&').each do |res|
44
+ key, value = res.split('=')
45
+ @params[key] = value
46
+ end
47
+ end
48
+
49
+ def from_param(qs, d = nil)
50
+ params = {}
51
+
52
+ (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p|
53
+ k, v = p.split('=', 2).map { |s| unescape(s) }
54
+
55
+ normalize_params(params, k, v)
56
+ end
57
+
58
+ params
59
+ end
60
+
61
+ def escape(s)
62
+ URI.encode_www_form_component(s)
63
+ end
64
+
65
+ if defined?(::Encoding)
66
+ def unescape(s, encoding = Encoding::UTF_8)
67
+ URI.decode_www_form_component(s, encoding)
68
+ end
69
+ else
70
+ def unescape(s, encoding = nil)
71
+ URI.decode_www_form_component(s, encoding)
72
+ end
73
+ end
74
+
75
+ protected
76
+
77
+ def normalize_params(params, name, v = nil)
78
+ name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
79
+ k = $1 || ''
80
+ after = $' || ''
81
+
82
+ return if k.empty?
83
+
84
+ if after == ""
85
+ params[k] = v
86
+ elsif after == "[]"
87
+ params[k] ||= []
88
+ raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
89
+ params[k] << v
90
+ elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
91
+ child_key = $1
92
+ params[k] ||= []
93
+ raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
94
+ if params[k].last.kind_of?(Hash) && !params[k].last.key?(child_key)
95
+ normalize_params(params[k].last, child_key, v)
96
+ else
97
+ params[k] << normalize_params(params.class.new, child_key, v)
98
+ end
99
+ else
100
+ params[k] ||= params.class.new
101
+ raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].kind_of?(Hash)
102
+ params[k] = normalize_params(params[k], after, v)
103
+ end
104
+
105
+ return params
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,130 @@
1
+ module Tickethub
2
+ class Request
3
+ attr_reader :options, :format, :url
4
+ attr_accessor :params, :body, :method, :headers
5
+
6
+ # Connection options
7
+ attr_accessor :proxy, :user, :password, :auth_type, :timeout, :ssl_options
8
+
9
+ def initialize(url, options = {})
10
+ @url = url.to_s
11
+
12
+ @options = options
13
+ @options.each do |key, val|
14
+ method = "#{key}="
15
+ send(method, val) if respond_to?(method)
16
+ end
17
+
18
+ self.method ||= :get
19
+ self.params ||= {}
20
+ self.headers ||= {}
21
+ self.format ||= :form
22
+ end
23
+
24
+ def format=(mime_or_format)
25
+ @format = mime_or_format.is_a?(Symbol) ?
26
+ Formats[mime_or_format].new : mime_or_format
27
+ end
28
+
29
+ def url=(value)
30
+ @url = value
31
+ @uri = nil
32
+ @url
33
+ end
34
+
35
+ def uri
36
+ return @uri if @uri
37
+
38
+ url = @url.match(/\Ahttps?:\/\//) ? @url : "http://#{@url}"
39
+
40
+ @uri = URI.parse(url)
41
+ @uri.path = '/' if @uri.path.empty?
42
+
43
+ if @uri.query
44
+ @params.merge!(Helpers.from_param(@uri.query))
45
+ @uri.query = nil
46
+ end
47
+
48
+ @uri
49
+ end
50
+
51
+ def path
52
+ uri.path
53
+ end
54
+
55
+ def execute
56
+ if encoded?
57
+ result = connection.send(method, path, encoded, build_headers)
58
+ else
59
+ result = connection.send(method, query_path, build_headers)
60
+ end
61
+
62
+ Response.new(result)
63
+
64
+ rescue Redirection => error
65
+ raise error unless error.response['Location']
66
+
67
+ location = URI.parse(error.response['Location'])
68
+
69
+ # Path is relative
70
+ unless location.host
71
+ location = URI.join(uri, location)
72
+ end
73
+
74
+ self.url = location.to_s
75
+ execute
76
+ end
77
+
78
+ protected
79
+
80
+ def connection
81
+ Connection.new(uri,
82
+ :proxy => proxy,
83
+ :timeout => timeout,
84
+ :ssl_options => ssl_options
85
+ )
86
+ end
87
+
88
+ def content_type_headers
89
+ if encoded?
90
+ {'Content-Type' => format.mime_type}
91
+ else
92
+ {}
93
+ end
94
+ end
95
+
96
+ def auth_headers
97
+ if auth_type == :bearer
98
+ { 'Authorization' => "Bearer #{@password}" }
99
+ elsif auth_type == :basic
100
+ { 'Authorization' => 'Basic ' + ["#{@user}:#{@password}"].pack('m').delete("\r\n") }
101
+ else
102
+ { }
103
+ end
104
+ end
105
+
106
+ def build_headers
107
+ auth_headers
108
+ .merge(content_type_headers)
109
+ .merge(headers)
110
+ end
111
+
112
+ def query_path
113
+ query_path = path
114
+
115
+ if params.any?
116
+ query_path += '?' + Helpers.to_param(params)
117
+ end
118
+
119
+ query_path
120
+ end
121
+
122
+ def encoded?
123
+ [:post, :patch].include?(method)
124
+ end
125
+
126
+ def encoded
127
+ params.any? ? format.encode(params) : body
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,279 @@
1
+ require 'money'
2
+ require 'iso8601'
3
+ require 'timezone'
4
+ require 'countries'
5
+
6
+ require_relative 'collection'
7
+
8
+ module Tickethub
9
+ class Resource
10
+
11
+ class << self
12
+ attr_reader :endpoint
13
+
14
+ def all(params = {})
15
+ Tickethub::Collection.new @endpoint, self, params
16
+ end
17
+
18
+ def polymorphic(type, options = {})
19
+ self.superclass.register_type type, **options
20
+ end
21
+
22
+ def register_type(type, klass: self, attribute: :type) # klass, attribute
23
+ registered_types[type] = { klass: klass, attribute: attribute }
24
+ end
25
+
26
+ def registered_types
27
+ @registered_types ||= {}
28
+ end
29
+
30
+ def scopes
31
+ @scopes ||= {}
32
+ end
33
+
34
+ def path(value, options = {})
35
+ @singleton = options.delete(:singleton) || false
36
+ @endpoint = Tickethub.endpoint[value, options]
37
+ end
38
+
39
+ def scope(key, proc = -> (params = {}) { self.scope key, params })
40
+ self.scopes[key] = proc
41
+ end
42
+
43
+ def singleton?
44
+ !! @singleton
45
+ end
46
+
47
+ def attribute(key, options = nil)
48
+ options.nil?? (self.attributes[key] ||= {}).dup
49
+ : self.attributes[key] = options
50
+ end
51
+
52
+ def attributes
53
+ @attributes ||= {}
54
+ end
55
+
56
+ def load_value(key, value, object)
57
+ return nil if value.nil? || (value.is_a?(String) && value.empty?)
58
+ case self.attribute(key)[:type]
59
+ when :date
60
+ case value
61
+ when String then ISO8601::Date.new(value)
62
+ else raise ArgumentError, 'invalid date value: ' + value
63
+ end
64
+ when :datetime
65
+ case value
66
+ when String then ISO8601::DateTime.new(value)
67
+ else raise ArgumentError, 'invalid datetime value: ' + value
68
+ end
69
+ when :time
70
+ case value
71
+ when String then ISO8601::Time.new(value)
72
+ else raise ArgumentError, 'invalid time value: ' + value
73
+ end
74
+ when :duration
75
+ case value
76
+ when String then ISO8601::Duration.new(value)
77
+ else raise ArgumentError, 'invalid time value: ' + value
78
+ end
79
+ when :money
80
+ currency = Money::Currency.new(object.currency)
81
+ raise ArgumentError, 'invalid money currency' if currency.blank?
82
+
83
+ case value
84
+ when Fixnum then Money.new(value, currency)
85
+ when Numeric, String
86
+ currency = Money::Currency.wrap(currency)
87
+ Money.new(value.to_d * currency.subunit_to_unit, currency)
88
+ else raise ArgumentError, 'invalid money value: ' + value
89
+ end
90
+ when :currency
91
+ case value
92
+ when String then Money::Currency.new(value)
93
+ else raise ArgumentError, 'invalid currency value: ' + value
94
+ end
95
+ when :timezone
96
+ case value
97
+ when String then Timezone::Zone.new(zone: value)
98
+ else raise ArgumentError, 'invalid timezone value: ' + value
99
+ end
100
+ when :country
101
+ case value
102
+ when String then Country.new(value)
103
+ else raise ArgumentError, 'invalid country value: ' + value
104
+ end
105
+ else value
106
+ end
107
+ end
108
+
109
+ def dump_value(key, value)
110
+ case self.attribute(key)[:type]
111
+ when :date then value.iso8601
112
+ when :datetime then value.iso8601
113
+ when :time then value.iso8601[10..-1]
114
+ when :duration then value.iso8601
115
+ when :money then value.fractional
116
+ when :timezone then value.zone
117
+ when :country then value.alpha2
118
+ when :currency then value.iso_code
119
+ else value
120
+ end
121
+ end
122
+
123
+ def serialize(attributes)
124
+ attributes.collect do |key, value|
125
+ [key, dump_value(key, value)]
126
+ end.to_h
127
+ end
128
+
129
+ def load(endpoint, attributes = nil)
130
+ attributes ||= endpoint.get
131
+
132
+ klass = registered_types.find do |type, options|
133
+ attributes[options[:attribute].to_s] == type
134
+ end
135
+
136
+ klass = klass ? klass[1][:klass] : self
137
+
138
+ if id = attributes['id']
139
+ endpoint = klass.endpoint[id, endpoint.options]
140
+ end
141
+
142
+ klass.new endpoint, attributes
143
+ end
144
+
145
+ def association(key, klass, path: key)
146
+ define_method key do
147
+ instance_variable_defined?("@#{key}") ? instance_variable_get("@#{key}") :
148
+ instance_variable_set("@#{key}", klass.load(@endpoint[path]))
149
+ end
150
+
151
+ define_method "#{key}=" do |value|
152
+ instance_variable_set "@#{key}", ((value.nil? || value.is_a?(klass)) ? value :
153
+ klass.load(@endpoint[path], value))
154
+ end
155
+ end
156
+
157
+ def collection(key, klass, path: key, &block)
158
+
159
+ define_method key do |params = {}|
160
+ (instance_variable_defined?("@#{key}") ? instance_variable_get("@#{key}") :
161
+ (sinleton? || id?) ? instance_variable_set("@#{key}",
162
+ Tickethub::Collection.new(@endpoint[path], klass, params)) : []).tap do |collection|
163
+ collection.instance_eval &block if block
164
+ end
165
+ end
166
+
167
+ define_method "#{key}=" do |values|
168
+ instance_variable_set "@#{key}", (singleton? || id?) ?
169
+ (Tickethub::Collection.new(@endpoint[path], klass).tap do |collection|
170
+ collection.cache = values
171
+ end) : values.collect { |value| klass.load @endpoint, value }
172
+ end
173
+ end
174
+ end
175
+
176
+ attr_accessor :endpoint
177
+
178
+ def initialize(endpoint, attributes = nil)
179
+ @endpoint = endpoint
180
+ attributes ||= endpoint.get
181
+
182
+ self.load attributes
183
+ end
184
+
185
+ def valid?
186
+ errors.nil? || errors.valid?
187
+ end
188
+
189
+ def update(attributes)
190
+ self.load @endpoint.patch(attributes).decoded
191
+ return true
192
+ rescue Tickethub::ResourceInvalid => err
193
+ self.load Tickethub::Response.new(err.response).decoded
194
+ return false
195
+ end
196
+
197
+ def destroy
198
+ self.load @endpoint.delete.decoded
199
+ end
200
+
201
+ def singleton?
202
+ !! @singleton
203
+ end
204
+
205
+ def respond_to?(method, include_priv = false)
206
+ @attributes.key?(method.to_s.remove(/[=\?]\Z/).to_sym) || super
207
+ end
208
+
209
+ def reload!
210
+ self.load @endpoint.get
211
+ end
212
+
213
+ def load(attributes)
214
+ @attributes = {}
215
+ attributes.each do |key, value|
216
+ send "#{key}=", value
217
+ end
218
+ return self
219
+ end
220
+
221
+ def [](key)
222
+ send key
223
+ end
224
+
225
+ def []=(key, value)
226
+ send "#{key}=", value
227
+ end
228
+
229
+ def ==(other)
230
+ self.hash == other.hash
231
+ end
232
+
233
+ def eql?(other)
234
+ self == other
235
+ end
236
+
237
+ def hash
238
+ id?? id.hash : super
239
+ end
240
+
241
+ def to_param
242
+ self.id
243
+ end
244
+
245
+ def errors
246
+ @errors ||= Tickethub::Errors.new @attributes[:errors]
247
+ end
248
+
249
+ def to_h
250
+ @attributes
251
+ end
252
+
253
+ def to_s
254
+ self.id?? id : super
255
+ end
256
+
257
+ def inspect
258
+ "#<#{self.class.name} #{to_h}>"
259
+ end
260
+
261
+ protected
262
+
263
+ def method_missing(method, *arguments)
264
+ if match = method.to_s.match(/^(.+)(=|\?)$/)
265
+ key = match[1].to_sym
266
+
267
+ case match[2]
268
+ when '='
269
+ @attributes[key] = self.class
270
+ .load_value(key, arguments.first, self)
271
+ when "?"
272
+ !! @attributes[key]
273
+ end
274
+ else
275
+ @attributes.key?(method) ? @attributes[method] : super
276
+ end
277
+ end
278
+ end
279
+ end
@@ -0,0 +1,31 @@
1
+ module Tickethub
2
+ class Response #:nodoc:
3
+ class Headers
4
+ include ::Net::HTTPHeader
5
+
6
+ def initialize(header = {})
7
+ @header = header
8
+ end
9
+
10
+ def ==(other)
11
+ @header == other
12
+ end
13
+
14
+ def inspect
15
+ @header.inspect
16
+ end
17
+
18
+ def method_missing(name, *args, &block)
19
+ if @header.respond_to?(name)
20
+ @header.send(name, *args, &block)
21
+ else
22
+ super
23
+ end
24
+ end
25
+
26
+ def respond_to?(method)
27
+ super || @header.respond_to?(method)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,49 @@
1
+ module Tickethub
2
+ class Response
3
+ attr_reader :response, :body, :headers, :parser
4
+
5
+ def initialize(response, parser = nil)
6
+ @response = response
7
+ @body = response.body
8
+ @headers = Headers.new(response.to_hash)
9
+ @format = Formats.for(headers.content_type)
10
+ @parser ||= @format && @format.new
11
+ end
12
+
13
+ def as_json
14
+ decoded
15
+ end
16
+
17
+ def to_json(*)
18
+ as_json.to_json
19
+ end
20
+
21
+ def code
22
+ response.code.to_i
23
+ end
24
+
25
+ alias_method :status, :code
26
+
27
+ def decoded
28
+ @decoded ||= parser ? parser.decode(body) : body
29
+ end
30
+
31
+ def respond_to?(name)
32
+ super || decoded.respond_to?(name) || response.respond_to?(name)
33
+ end
34
+
35
+ protected
36
+
37
+ def method_missing(name, *args, &block)
38
+ if decoded.respond_to?(name)
39
+ decoded.send(name, *args, &block)
40
+ elsif response.respond_to?(name)
41
+ response.send(name, *args, &block)
42
+ else
43
+ super
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ require_relative 'response/headers'
@@ -0,0 +1,11 @@
1
+ require_relative '../resource'
2
+
3
+ module Tickethub
4
+ class Supplier::Answer < Resource
5
+ path '/supplier/answers'
6
+
7
+ require_relative 'question'
8
+
9
+ association :question, Supplier::Question
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module Tickethub
2
+ class Supplier::App < Resource
3
+ path '/apps'
4
+
5
+ require_relative 'package'
6
+
7
+ collection :packages, Supplier::Package
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../resource'
2
+
3
+ module Tickethub
4
+ class Supplier::Bill < Resource
5
+ path '/supplier/bills'
6
+
7
+ require_relative 'receipt'
8
+
9
+ collection :receipts, Supplier::Receipt
10
+ end
11
+ end
@@ -0,0 +1,39 @@
1
+ require_relative '../resource'
2
+
3
+ module Tickethub
4
+ class Supplier::Booking < Resource
5
+ path '/supplier/bookings'
6
+
7
+ require_relative 'rate'
8
+ require_relative 'order'
9
+ require_relative 'ticket'
10
+ require_relative 'answer'
11
+ require_relative 'product'
12
+ require_relative 'variant'
13
+ require_relative 'message'
14
+ require_relative 'fee'
15
+
16
+ collection :tickets, Supplier::Ticket
17
+ collection :answers, Supplier::Answer
18
+ collection :messages, Supplier::Message
19
+ collection :fees, Supplier::Fee
20
+
21
+ association :order, Supplier::Order
22
+ association :rate, Supplier::Rate
23
+ association :coupon, Supplier::Coupon
24
+ association :product, Supplier::Product
25
+ association :variant, Supplier::Variant
26
+
27
+ attribute :amount, type: :money
28
+ attribute :tax, type: :money
29
+ attribute :total, type: :money
30
+
31
+ attribute :currency, type: :currency
32
+ attribute :valid_from, type: :datetime
33
+ attribute :expires_at, type: :datetime
34
+ attribute :timeout_at, type: :datetime
35
+ attribute :created_at, type: :datetime
36
+ attribute :updated_at, type: :datetime
37
+ attribute :cancelled_at, type: :datetime
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../resource'
2
+
3
+ module Tickethub
4
+ class Supplier::Card < Resource
5
+ path '/supplier/cards'
6
+
7
+ require_relative 'payment'
8
+
9
+ collection :payments, Supplier::Payment
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ require_relative '../resource'
2
+
3
+ module Tickethub
4
+ class Supplier::Coupon < Resource
5
+ path '/supplier/coupons'
6
+
7
+ require_relative 'booking'
8
+ require_relative 'product'
9
+
10
+ collection :bookings, Supplier::Booking
11
+
12
+ association :product, Supplier::Product
13
+ end
14
+ end