alula-ruby 0.50.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 (102) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +14 -0
  3. data/.env.example +8 -0
  4. data/.github/workflows/gem-push.yml +45 -0
  5. data/.gitignore +23 -0
  6. data/.rspec +3 -0
  7. data/.travis.yml +7 -0
  8. data/Dockerfile +6 -0
  9. data/Gemfile +12 -0
  10. data/Guardfile +42 -0
  11. data/README.md +423 -0
  12. data/Rakefile +6 -0
  13. data/VERSION.md +84 -0
  14. data/alula-docker-compose.yml +80 -0
  15. data/alula.gemspec +38 -0
  16. data/bin/console +15 -0
  17. data/bin/docparse +36 -0
  18. data/bin/genresource +79 -0
  19. data/bin/setup +8 -0
  20. data/bin/testauth +24 -0
  21. data/bin/testprep +9 -0
  22. data/data/docs/Alula_API_Documentation_2021-04-06.html +16240 -0
  23. data/docker-compose.yml +11 -0
  24. data/lib/alula/alula_response.rb +20 -0
  25. data/lib/alula/api_operations/delete.rb +52 -0
  26. data/lib/alula/api_operations/list.rb +45 -0
  27. data/lib/alula/api_operations/request.rb +44 -0
  28. data/lib/alula/api_operations/save.rb +81 -0
  29. data/lib/alula/api_resource.rb +196 -0
  30. data/lib/alula/client.rb +142 -0
  31. data/lib/alula/errors.rb +169 -0
  32. data/lib/alula/filter_builder.rb +271 -0
  33. data/lib/alula/helpers/device_attribute_translations.rb +68 -0
  34. data/lib/alula/list_object.rb +64 -0
  35. data/lib/alula/meta.rb +16 -0
  36. data/lib/alula/monkey_patches.rb +24 -0
  37. data/lib/alula/oauth.rb +118 -0
  38. data/lib/alula/pagination.rb +25 -0
  39. data/lib/alula/procedures/dealer_device_stats_proc.rb +16 -0
  40. data/lib/alula/procedures/dealer_restore_proc.rb +25 -0
  41. data/lib/alula/procedures/dealer_suspend_proc.rb +25 -0
  42. data/lib/alula/procedures/device_assign_proc.rb +23 -0
  43. data/lib/alula/procedures/device_cellular_history_proc.rb +33 -0
  44. data/lib/alula/procedures/device_rateplan_get_proc.rb +21 -0
  45. data/lib/alula/procedures/device_register_proc.rb +31 -0
  46. data/lib/alula/procedures/device_signal_add_proc.rb +42 -0
  47. data/lib/alula/procedures/device_signal_delivered_proc.rb +31 -0
  48. data/lib/alula/procedures/device_signal_update_proc.rb +32 -0
  49. data/lib/alula/procedures/device_unassign_proc.rb +16 -0
  50. data/lib/alula/procedures/device_unregister_proc.rb +21 -0
  51. data/lib/alula/procedures/upload_touchpad_branding_proc.rb +24 -0
  52. data/lib/alula/procedures/user_plansvideo_price_get.rb +21 -0
  53. data/lib/alula/procedures/user_transfer_accept.rb +19 -0
  54. data/lib/alula/procedures/user_transfer_authorize.rb +18 -0
  55. data/lib/alula/procedures/user_transfer_cancel.rb +18 -0
  56. data/lib/alula/procedures/user_transfer_deny.rb +19 -0
  57. data/lib/alula/procedures/user_transfer_reject.rb +19 -0
  58. data/lib/alula/procedures/user_transfer_request.rb +19 -0
  59. data/lib/alula/query_interface.rb +142 -0
  60. data/lib/alula/rate_limit.rb +11 -0
  61. data/lib/alula/relationship_attributes.rb +107 -0
  62. data/lib/alula/resource_attributes.rb +206 -0
  63. data/lib/alula/resources/admin_user.rb +207 -0
  64. data/lib/alula/resources/billing_program.rb +41 -0
  65. data/lib/alula/resources/dealer.rb +218 -0
  66. data/lib/alula/resources/dealer_account_transfer.rb +172 -0
  67. data/lib/alula/resources/dealer_address.rb +89 -0
  68. data/lib/alula/resources/dealer_branding.rb +226 -0
  69. data/lib/alula/resources/dealer_program.rb +75 -0
  70. data/lib/alula/resources/dealer_suspension_log.rb +49 -0
  71. data/lib/alula/resources/device.rb +716 -0
  72. data/lib/alula/resources/device_cellular_status.rb +134 -0
  73. data/lib/alula/resources/device_charge.rb +70 -0
  74. data/lib/alula/resources/device_event_log.rb +167 -0
  75. data/lib/alula/resources/device_program.rb +54 -0
  76. data/lib/alula/resources/event_trigger.rb +75 -0
  77. data/lib/alula/resources/event_webhook.rb +47 -0
  78. data/lib/alula/resources/feature_bysubject.rb +74 -0
  79. data/lib/alula/resources/feature_plan.rb +57 -0
  80. data/lib/alula/resources/feature_planvideo.rb +54 -0
  81. data/lib/alula/resources/feature_price.rb +46 -0
  82. data/lib/alula/resources/receiver_connection.rb +95 -0
  83. data/lib/alula/resources/receiver_group.rb +74 -0
  84. data/lib/alula/resources/revision.rb +91 -0
  85. data/lib/alula/resources/self.rb +61 -0
  86. data/lib/alula/resources/station.rb +130 -0
  87. data/lib/alula/resources/token_exchange.rb +34 -0
  88. data/lib/alula/resources/user.rb +229 -0
  89. data/lib/alula/resources/user_address.rb +121 -0
  90. data/lib/alula/resources/user_phone.rb +116 -0
  91. data/lib/alula/resources/user_preferences.rb +57 -0
  92. data/lib/alula/resources/user_pushtoken.rb +75 -0
  93. data/lib/alula/resources/user_videoprofile.rb +38 -0
  94. data/lib/alula/rest_resource.rb +17 -0
  95. data/lib/alula/rpc_resource.rb +40 -0
  96. data/lib/alula/rpc_response.rb +14 -0
  97. data/lib/alula/singleton_rest_resource.rb +26 -0
  98. data/lib/alula/util.rb +107 -0
  99. data/lib/alula/version.rb +5 -0
  100. data/lib/alula.rb +135 -0
  101. data/lib/parser.rb +199 -0
  102. metadata +282 -0
@@ -0,0 +1,142 @@
1
+ module Alula
2
+ class QueryInterface
3
+ extend Forwardable
4
+
5
+ def initialize(model_class)
6
+ @model_class = model_class
7
+ @filter_builder = Alula::FilterBuilder.new(model_class, self)
8
+ @filter = {}
9
+ @page = {}
10
+ @custom_options = {}
11
+ @includes = {}
12
+ @opts = {}
13
+ @sorts = {}
14
+ end
15
+
16
+ def filter(filter_hash)
17
+ @filter = Util.deep_merge @filter, filter_hash
18
+ self
19
+ end
20
+
21
+ def filter_builder(&block)
22
+ if block_given?
23
+ yield @filter_builder
24
+ @filter = Util.deep_merge(@filter, @filter_builder.as_json)
25
+ self
26
+ else
27
+ @filter_builder
28
+ end
29
+ end
30
+
31
+ def_delegators :filter_builder, :where, :and, :not, :ne, :or, :between, :not_between,
32
+ :builder, :gt, :gte, :lt, :lte, :like, :not_like, :in,
33
+ :not_in, :sort
34
+
35
+ def offset(offset)
36
+ @page = Util.deep_merge(@page, {
37
+ page: {
38
+ number: offset,
39
+ }
40
+ })
41
+ self
42
+ end
43
+
44
+ def limit(limit)
45
+ @page = Util.deep_merge(@page, {
46
+ page: {
47
+ size: limit
48
+ }
49
+ })
50
+ self
51
+ end
52
+
53
+ def custom_options(**options)
54
+ @custom_options = Util.deep_merge(@custom_options, {
55
+ customOptions: options
56
+ })
57
+ self
58
+ end
59
+
60
+ def include_relationships
61
+ custom_options(omitRelationships: false)
62
+ end
63
+
64
+ def includes(*relationships)
65
+ relationships = @model_class.get_relationships.keys if relationships == [:all]
66
+
67
+ validated_relationships = relationships.map do |relationship|
68
+ @model_class.check_relationship!(relationship)
69
+ end
70
+
71
+ @includes = Util.deep_merge(@includes, {
72
+ include: validated_relationships.compact.map { |r| Util.camelize(r) }.join(',')
73
+ })
74
+
75
+ self
76
+ end
77
+
78
+ def query_sort(options)
79
+ cleaned_sorts = options.each_pair.each_with_object([]) do |(key, value), collector|
80
+ collector << "#{value == :desc ? '-' : ''}#{key}"
81
+ end
82
+
83
+ @sorts = Util.deep_merge(@sorts, {
84
+ sort: cleaned_sorts.join(',')
85
+ })
86
+ self
87
+ end
88
+
89
+ def as_json
90
+ JSON.parse(to_json)
91
+ end
92
+
93
+ def to_json
94
+ JSON.generate(built_query_options)
95
+ end
96
+
97
+ def list(opts = {})
98
+ @model_class.list(built_query_options, @opts.merge(opts))
99
+ end
100
+
101
+ def list_all(opts = {})
102
+ # We have defaults we want to use, but if the caller wants to change, we support it
103
+ size = @page.to_h.dig(:page, :size) || 250
104
+ number = @page.to_h.dig(:page, :number) || 1
105
+
106
+ return to_enum(:list_all, opts) unless block_given?
107
+
108
+ page = self.page(number: number, size: size).list(opts)
109
+ return page unless page.is_a? Alula::ListObject
110
+
111
+ loop do
112
+ yield page
113
+ break unless page.meta.page.has_next?
114
+
115
+ page = self.page(number: number += 1, size: size).list(opts)
116
+ end
117
+ end
118
+
119
+ def retrieve(id)
120
+ @model_class.retrieve(id, built_query_options)
121
+ end
122
+
123
+ def page(number: 1, size: 10)
124
+ @page = Util.deep_merge(@page, {
125
+ page: {
126
+ number: number,
127
+ size: size
128
+ }
129
+ })
130
+ self
131
+ end
132
+
133
+ def built_query_options
134
+ built = Util.deep_merge({}, @page)
135
+ built = Util.deep_merge(built, @includes)
136
+ built = Util.deep_merge(built, @sorts)
137
+ built = Util.deep_merge(built, @custom_options)
138
+
139
+ Util.deep_merge(built, @filter)
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,11 @@
1
+ module Alula
2
+ class RateLimit
3
+ attr_accessor :request_limit, :requests_remaining, :reset_in
4
+
5
+ def initialize(headers)
6
+ self.request_limit = headers["x-rate-limit-limit"].to_i
7
+ self.requests_remaining = headers["x-rate-limit-remaining"].to_i
8
+ self.reset_in = headers["x-rate-limit-reset"].to_i
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,107 @@
1
+ module Alula
2
+ module RelationshipAttributes
3
+ def self.extended(base)
4
+ base.class_eval do
5
+ @relationships = {}
6
+ end
7
+ base.include(InstanceMethods)
8
+ end
9
+
10
+ # TODO: Walk the relationships and define methods to allow an instance to
11
+ # request a relationship with dot notation... Dealer.fetch(id).devices, etc
12
+ def relationship(name, **opts)
13
+ @relationships ||= {}
14
+ @relationships[name] = opts.merge(name: name)
15
+
16
+ # Define a getter for our relationship name
17
+ instance_eval do
18
+ define_method(name) do
19
+ @related_models[name]
20
+ end
21
+ end
22
+
23
+ if opts[:cardinality] == 'To-one'
24
+ instance_eval do
25
+ define_method("#{name}=") do |new_model|
26
+ @related_models[name] = new_model
27
+ end
28
+ end
29
+ elsif opts[:cardinality] == 'To-many'
30
+ instance_eval do
31
+ define_method("#{name}<<") do |new_model|
32
+ @related_models[name] ||= ListObject.new(self.class)
33
+ @related_models[name] << new_model
34
+ end
35
+ end
36
+ end
37
+
38
+ @relationships
39
+ end
40
+
41
+ def get_relationships
42
+ @relationships
43
+ end
44
+
45
+ def get_relationship(name)
46
+ identifier = name.is_a?(Symbol) ? :name : :type
47
+ relationship = get_relationships.find { |_key, opts| opts[identifier] == name }
48
+ raise "Unknown relationship #{identifier} #{name} for class #{self}" unless relationship
49
+ relationship.last
50
+ end
51
+
52
+ def relationship_exists?(possible_r)
53
+ get_relationships.keys.include?(possible_r.to_sym)
54
+ end
55
+
56
+ def check_relationship!(possible_r)
57
+ cleaned_relationship = Util.underscore(possible_r).to_sym
58
+
59
+ unless self.relationship_exists?(cleaned_relationship)
60
+ error = "Invalid relationship #{cleaned_relationship} for class #{self}. "\
61
+ "Please use one of #{get_relationships.keys.join(', ')}"
62
+ raise Alula::InvalidRelationshipError.new(error)
63
+ end
64
+
65
+ cleaned_relationship
66
+ end
67
+
68
+ module InstanceMethods
69
+ def get_relationships
70
+ self.class.get_relationships
71
+ end
72
+
73
+ def get_relationship(name)
74
+ self.class.get_relationship(name)
75
+ end
76
+
77
+ def add_model_to_relationship(model)
78
+ relation = get_relationship(model.get_type)
79
+ unless relation
80
+ raise "Unknown model relationship #{model.get_type} for model #{self.class}"
81
+ end
82
+
83
+ if relation[:cardinality] == 'To-one'
84
+ self.send("#{relation[:name]}=", model)
85
+
86
+ elsif relation[:cardinality] == 'To-many'
87
+ if self.send(relation[:name]).nil?
88
+ list = Alula::ListObject.new(model.class)
89
+ list << model
90
+ end
91
+
92
+ self.send("#{relation[:name]}<<", model)
93
+ else
94
+ raise "Unknown relationship cardinality for relationship #{relation.inspect}"
95
+ end
96
+ end
97
+
98
+ def relationship_exists?(relationship)
99
+ self.class.relationship_exists?(relationship)
100
+ end
101
+
102
+ def check_relationship!(relationship)
103
+ self.class.check_relationship!(relationship)
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,206 @@
1
+ # A mixin pulled into ImportedResources with which to define resource methods
2
+ module Alula
3
+ module ResourceAttributes
4
+ def self.extended(base)
5
+ base.class_eval do
6
+ @resource_path = nil
7
+ @type = nil
8
+ @http_methods = []
9
+ @fields = {}
10
+ end
11
+ base.include(InstanceMethods)
12
+ end
13
+
14
+
15
+ #
16
+ # Class methods for defining how fields and types work
17
+ # NOTE: We're not using real getters and setters here. I want the method signature
18
+ # to match how most other Ruby class configuration is done, and that is with
19
+ # simple methods that take params.
20
+
21
+
22
+ def resource_path(name)
23
+ @resource_path = name
24
+ end
25
+
26
+ def get_resource_path(id = nil)
27
+ return "#{@resource_path}/#{id}" if id
28
+ @resource_path
29
+ end
30
+
31
+ def type(type)
32
+ @type = type
33
+ end
34
+
35
+ def get_type
36
+ @type
37
+ end
38
+
39
+ def http_methods(methods)
40
+ @http_methods = methods
41
+ end
42
+
43
+ def get_http_methods
44
+ @http_methods
45
+ end
46
+
47
+ #
48
+ # Memoizes field names and options
49
+ def field(field_name, **opts)
50
+ @fields ||= {}
51
+ @fields[field_name] = opts
52
+
53
+ self.instance_eval do
54
+ jsonKey = Util.camelize(field_name)
55
+
56
+ # Reader method for attribute
57
+ define_method(field_name) do
58
+ value = @values[jsonKey]
59
+
60
+ if opts[:type] == :date && ![nil, ''].include?(value)
61
+ begin
62
+ DateTime.parse(value)
63
+ rescue ArgumentError
64
+ value
65
+ end
66
+ elsif opts[:type] == :boolean
67
+ [true, 'true', 1, '1'].include? value
68
+ elsif opts[:symbolize] == true
69
+ # API sends a camelCase string; provide symbol to Client
70
+ value ? Util.underscore(value).to_sym : nil
71
+ elsif opts[:hex_convert_required] == true
72
+ Util.convert_hex_crc?(self.program_id) ? value.to_s(16) : value
73
+ else
74
+ value
75
+ end
76
+ end
77
+
78
+ # Setter method
79
+ define_method("#{field_name}=") do |new_value|
80
+ #
81
+ # Coerce 'blank like' fields into a defined blank value
82
+ # This helps HTML form submissions. A blank text field comes through as an
83
+ # empty string, instead of a nil as the API validates for.
84
+ new_value = nil if new_value == ''
85
+
86
+ if opts[:symbolize] == true
87
+ # Client provides a symbol; send camelCase string to API
88
+ new_value = Util.camelize(new_value.to_s)
89
+ elsif opts[:type] == :boolean
90
+ new_value = [true, 'true', 1, '1'].include? new_value
91
+ end
92
+
93
+ #
94
+ # Mark the attribute as dirty if the new value is different
95
+ @dirty_attributes << field_name if @values[jsonKey] != new_value
96
+
97
+ #
98
+ # Assign the new value (always assigned even if a duplicate)
99
+ @values[jsonKey] = new_value
100
+ end
101
+
102
+
103
+ end
104
+ end
105
+
106
+ def get_fields
107
+ @fields
108
+ end
109
+
110
+ def read_only_attributes(record_persisted = false)
111
+ get_fields.each_pair.each_with_object([]) do |(field_name, opts), collector|
112
+ collector << field_name if !field_patchable?(opts, record_persisted)
113
+ end
114
+ end
115
+
116
+ def date_fields
117
+ get_fields.each_pair.each_with_object([]) do |(field_name, opts), collector|
118
+ collector << field_name if opts[:type].to_sym == :date
119
+ end
120
+ end
121
+
122
+ def filterable_fields
123
+ get_fields.each_pair.each_with_object([]) do |(field_name, opts), collector|
124
+ collector << field_name if opts[:filterable] == true
125
+ end
126
+ end
127
+
128
+ def sortable_fields
129
+ get_fields.each_pair.each_with_object([]) do |(field_name, opts), collector|
130
+ collector << field_name if opts[:sortable] == true
131
+ end
132
+ end
133
+
134
+ def field_names
135
+ get_fields.keys
136
+ end
137
+
138
+ def param_key
139
+ self.name.gsub('::', '_').downcase
140
+ end
141
+
142
+ private
143
+
144
+ def metaclass
145
+ class << self
146
+ self
147
+ end
148
+ end
149
+
150
+ def field_patchable?(opts, record_persisted)
151
+ user_role = Alula::Client.role
152
+
153
+ # different permission arrays are used for updates vs creates
154
+ perm_key = record_persisted == true ? :patchable_by : :creatable_by
155
+
156
+ return true if opts[perm_key].include? :all
157
+
158
+ opts[perm_key].include? user_role
159
+ end
160
+
161
+ #
162
+ # Extensions to allow instances to get at their class config, either raw or
163
+ # reduced to a useable format for a specific task.
164
+ module InstanceMethods
165
+ # Instance method extensions
166
+ def resource_path
167
+ self.class.resource_path
168
+ end
169
+
170
+ def type(arg)
171
+ self.class.type(arg)
172
+ end
173
+
174
+ def get_type
175
+ self.class.get_type
176
+ end
177
+
178
+ def fields
179
+ self.class.fields
180
+ end
181
+
182
+ def field_names
183
+ self.class.field_names
184
+ end
185
+
186
+ def persisted?
187
+ !self.id.nil?
188
+ end
189
+
190
+ def read_only_attributes
191
+ self.class.read_only_attributes(persisted?)
192
+ end
193
+
194
+ #
195
+ # Return the names of each field configured as a date type
196
+ def date_fields
197
+ self.class.date_fields
198
+ end
199
+
200
+ def to_key
201
+ key = respond_to?(:id) && id
202
+ key ? [key] : nil
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,207 @@
1
+ module Alula
2
+ class AdminUser < Alula::User
3
+ extend Alula::ResourceAttributes
4
+ extend Alula::RelationshipAttributes
5
+ extend Alula::ApiOperations::Request
6
+ extend Alula::ApiOperations::List
7
+ extend Alula::ApiOperations::Save
8
+
9
+ resource_path 'admins/users'
10
+ type 'admins-users'
11
+
12
+ relationship :devices, type: 'devices', cardinality: 'To-many'
13
+ relationship :dealer, type: 'dealers', cardinality: 'To-one'
14
+ relationship :phone, type: 'users-phones', cardinality: 'To-one'
15
+ relationship :address, type: 'users-addresses', cardinality: 'To-one'
16
+ relationship :pushtokens, type: 'users-pushtokens', cardinality: 'To-many'
17
+ relationship :preferences, type: 'users-preferences', cardinality: 'To-one'
18
+ relationship :videoprofiles, type: 'users-videoprofiles', cardinality: 'To-many'
19
+
20
+ # Resource Fields
21
+ # Not all params are used at the moment. See Alula::ResourceAttributes for details
22
+ # on how params are parsed,
23
+ field :id,
24
+ type: :string,
25
+ sortable: false,
26
+ filterable: false,
27
+ creatable_by: [],
28
+ patchable_by: []
29
+
30
+ field :username,
31
+ type: :string,
32
+ sortable: true,
33
+ filterable: true,
34
+ creatable_by: [:system, :station, :dealer, :technician, :user],
35
+ patchable_by: [:system, :station, :dealer, :technician, :user, :sub_user]
36
+
37
+ field :password,
38
+ type: :string,
39
+ sortable: false,
40
+ filterable: false,
41
+ creatable_by: [:system, :station, :dealer, :technician, :user],
42
+ patchable_by: []
43
+
44
+ field :u_type,
45
+ type: :string,
46
+ sortable: false,
47
+ filterable: true,
48
+ creatable_by: [:system, :station, :dealer, :technician, :user],
49
+ patchable_by: []
50
+
51
+ field :user_type,
52
+ type: :string,
53
+ sortable: false,
54
+ filterable: true,
55
+ creatable_by: [:system, :station, :dealer, :technician, :user],
56
+ patchable_by: [],
57
+ symbolize: true
58
+
59
+ field :u_level,
60
+ type: :string,
61
+ sortable: false,
62
+ filterable: false,
63
+ creatable_by: [],
64
+ patchable_by: []
65
+
66
+ field :parent_id,
67
+ type: :string,
68
+ sortable: false,
69
+ filterable: true,
70
+ creatable_by: [:system, :station, :dealer, :technician, :user],
71
+ patchable_by: []
72
+
73
+ field :dealer_id,
74
+ type: :string,
75
+ sortable: false,
76
+ filterable: true,
77
+ creatable_by: [:system, :station, :dealer, :technician, :user],
78
+ patchable_by: []
79
+
80
+ field :station_id,
81
+ type: :string,
82
+ sortable: false,
83
+ filterable: true,
84
+ creatable_by: [],
85
+ patchable_by: []
86
+
87
+ field :last_login,
88
+ type: :string,
89
+ sortable: false,
90
+ filterable: false,
91
+ creatable_by: [],
92
+ patchable_by: []
93
+
94
+ field :date_entered,
95
+ type: :date,
96
+ sortable: true,
97
+ filterable: true,
98
+ creatable_by: [],
99
+ patchable_by: []
100
+
101
+ field :date_modified,
102
+ type: :date,
103
+ sortable: true,
104
+ filterable: true,
105
+ creatable_by: [],
106
+ patchable_by: []
107
+
108
+ field :entered_by,
109
+ type: :string,
110
+ sortable: false,
111
+ filterable: false,
112
+ creatable_by: [],
113
+ patchable_by: []
114
+
115
+ field :modified_by,
116
+ type: :string,
117
+ sortable: false,
118
+ filterable: false,
119
+ creatable_by: [],
120
+ patchable_by: []
121
+
122
+ field :pwch,
123
+ type: :string,
124
+ sortable: false,
125
+ filterable: false,
126
+ creatable_by: [],
127
+ patchable_by: []
128
+
129
+ field :features_selected,
130
+ type: :object,
131
+ sortable: false,
132
+ filterable: false,
133
+ creatable_by: [:system, :station, :dealer, :technician],
134
+ patchable_by: [:system, :station, :dealer, :technician]
135
+
136
+ field :eula,
137
+ type: :string,
138
+ sortable: false,
139
+ filterable: false,
140
+ creatable_by: [],
141
+ patchable_by: [:system, :station, :dealer, :technician, :user, :sub_user]
142
+
143
+ field :def_mod,
144
+ type: :string,
145
+ sortable: false,
146
+ filterable: false,
147
+ creatable_by: [],
148
+ patchable_by: []
149
+
150
+ field :rg_activated,
151
+ type: :string,
152
+ sortable: false,
153
+ filterable: false,
154
+ creatable_by: [],
155
+ patchable_by: []
156
+
157
+ field :company_name,
158
+ type: :string,
159
+ sortable: false,
160
+ filterable: false,
161
+ creatable_by: [],
162
+ patchable_by: []
163
+
164
+ field :name_first,
165
+ type: :string,
166
+ sortable: true,
167
+ filterable: true,
168
+ creatable_by: [:system, :station, :dealer, :technician, :user],
169
+ patchable_by: [:system, :station, :dealer, :technician, :user, :sub_user]
170
+
171
+ field :name_last,
172
+ type: :string,
173
+ sortable: true,
174
+ filterable: true,
175
+ creatable_by: [:system, :station, :dealer, :technician, :user],
176
+ patchable_by: [:system, :station, :dealer, :technician, :user, :sub_user]
177
+
178
+ field :email,
179
+ type: :string,
180
+ sortable: true,
181
+ filterable: true,
182
+ creatable_by: [:system, :station, :dealer, :technician, :user],
183
+ patchable_by: [:system, :station, :dealer, :technician, :user, :sub_user]
184
+
185
+ field :time_offset,
186
+ type: :string,
187
+ sortable: false,
188
+ filterable: false,
189
+ creatable_by: [],
190
+ patchable_by: []
191
+
192
+ field :timezone,
193
+ type: :string,
194
+ sortable: false,
195
+ filterable: false,
196
+ creatable_by: [:system, :station, :dealer, :technician, :user],
197
+ patchable_by: [:system, :station, :dealer, :technician, :user, :sub_user]
198
+
199
+ field :hidden,
200
+ type: :boolean,
201
+ sortable: true,
202
+ filterable: true,
203
+ creatable_by: [:system],
204
+ patchable_by: [:system]
205
+
206
+ end
207
+ end
@@ -0,0 +1,41 @@
1
+ module Alula
2
+ class BillingProgram < Alula::RestResource
3
+ extend Alula::ResourceAttributes
4
+ extend Alula::ApiOperations::Request
5
+ extend Alula::ApiOperations::List
6
+
7
+ resource_path 'billing/programs'
8
+ type 'billing-program'
9
+
10
+ # Resource Fields
11
+ # Not all params are used at the moment. See Alula::ResourceAttributes for details
12
+ # on how params are parsed,
13
+ field :id,
14
+ type: :string,
15
+ sortable: false,
16
+ filterable: false,
17
+ creatable_by: [],
18
+ patchable_by: []
19
+
20
+ field :name,
21
+ type: :string,
22
+ sortable: false,
23
+ filterable: false,
24
+ creatable_by: [],
25
+ patchable_by: []
26
+
27
+ field :description,
28
+ type: :string,
29
+ sortable: false,
30
+ filterable: false,
31
+ creatable_by: [],
32
+ patchable_by: []
33
+
34
+ field :params_schema,
35
+ type: :object,
36
+ sortable: false,
37
+ filterable: false,
38
+ creatable_by: [],
39
+ patchable_by: []
40
+ end
41
+ end