bright 1.3 → 2.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.
@@ -1,277 +0,0 @@
1
- module Bright
2
- module SisApi
3
- class Skyward < Base
4
-
5
- @@description = "Connects to the Skyward API for accessing student information"
6
- @@doc_url = "https://esdemo1.skyward.com/api/swagger/ui/index"
7
- @@api_version = "v1"
8
-
9
- attr_accessor :connection_options, :schools_cache
10
-
11
- DEMOGRAPHICS_CONVERSION = {
12
- "I"=>"American Indian Or Alaska Native",
13
- "A"=>"Asian",
14
- "B"=>"Black Or African American",
15
- "P"=>"Native Hawaiian Or Other Pacific Islander",
16
- "W"=>"White"
17
- }
18
-
19
- PHONE_TYPE_CONVERSION = {
20
- "Cellular" => "Cell",
21
- "Work" => "Work",
22
- "Home" => "Home",
23
- "Other" => "Other"
24
- }
25
-
26
- def initialize(options = {})
27
- self.connection_options = options[:connection] || {}
28
- # {
29
- # :client_id => "",
30
- # :client_secret => "",
31
- # :uri => "https://skywardinstall.com/API"
32
- # }
33
- end
34
-
35
- def get_student_by_api_id(api_id, params = {})
36
- st_hsh = self.request(:get, "v1/students/#{api_id}", params)[:parsed_body]
37
- Student.new(convert_to_user_data(st_hsh, {:type => "Student"})) unless st_hsh.blank?
38
- end
39
-
40
- def get_students(params = {}, options = {})
41
- params["paging.limit"] = params[:limit] || options[:limit] || 1000
42
- students_response = self.request(:get, 'v1/students', params)
43
- if !students_response[:parsed_body].blank?
44
- students = students_response[:parsed_body].compact.collect {|st_hsh|
45
- Student.new(convert_to_user_data(st_hsh, {:type => "Student"}))
46
- }
47
- end
48
-
49
- next_cursor = nil
50
- if students_response[:headers]["Link"]
51
- students_response[:headers]["Link"].split(",").each do |part, index|
52
- section = part.split(';')
53
- url = section[0][/<(.*)>/,1]
54
- name = section[1][/rel="(.*)"/,1].to_s
55
- if name == "next"
56
- next_cursor = CGI.parse(URI.parse(url).query)["cursor"].first
57
- end
58
- end
59
- end
60
- if options[:wrap_in_collection] != false
61
- api = self
62
- load_more_call = proc {|cursor|
63
- params["paging.cursor"] = cursor
64
- options = {:wrap_in_collection => false, :include_cursor => true}
65
- api.get_students(params, options)
66
- }
67
- CursorResponseCollection.new({
68
- :seed_page => students,
69
- :load_more_call => load_more_call,
70
- :next_cursor => next_cursor
71
- })
72
- elsif options[:include_cursor] == true
73
- return {:objects => students, :next_cursor => next_cursor}
74
- else
75
- return students
76
- end
77
- end
78
-
79
- def get_school_by_api_id(api_id, params = {})
80
- sc_hsh = self.request(:get, "v1/schools/#{api_id}", params)[:parsed_body]
81
- School.new(convert_to_school_data(sc_hsh)) unless sc_hsh.blank?
82
- end
83
-
84
- def get_schools(params = {}, options = {})
85
- params["paging.limit"] = params[:limit] || options[:limit] || 10000
86
- schools_hshs = self.request(:get, "v1/schools", params)[:parsed_body]
87
- if !schools_hshs.blank?
88
- schools = schools_hshs.compact.collect {|sc_hsh|
89
- School.new(convert_to_school_data(sc_hsh))
90
- }
91
- end
92
- return schools
93
- end
94
-
95
- def get_contact_by_api_id(api_id, params = {})
96
- contact_hsh = self.request(:get, "v1/names/#{api_id}", params)[:parsed_body]
97
- Contact.new(convert_to_user_data(contact_hsh, {:type => "Contact"})) unless contact_hsh.blank?
98
- end
99
-
100
- def get_guardians_by_api_id(api_id, params = {})
101
- guardians = []
102
- guardians_array = self.request(:get, "v1/guardians", params.merge({"studentNameId" => api_id}))[:parsed_body]
103
- if !guardians_array.blank?
104
- guardians_array.each do |guardian_hsh|
105
- relationship_type = guardian_hsh.delete("Students").detect{|s_hsh| s_hsh["StudentNameId"].to_s == api_id.to_s}["RelationshipDesc"]
106
- guardian_hsh["RelationshipType"] = relationship_type
107
- guardian_hsh["NameId"] = guardian_hsh.delete("GuardianNameId")
108
- guardians << Contact.new(convert_to_user_data(guardian_hsh, {:type => "Contact"}))
109
- end
110
- end
111
- return guardians
112
- end
113
-
114
- def retrieve_access_token
115
- connection = Bright::Connection.new("#{self.connection_options[:uri]}/token")
116
- response = connection.request(:post,
117
- {"grant_type" => "password",
118
- "username" => self.connection_options[:client_id],
119
- "password" => self.connection_options[:client_secret]
120
- },
121
- self.headers_for_access_token)
122
- if !response.error?
123
- response_hash = JSON.parse(response.body)
124
- end
125
- if response_hash["access_token"]
126
- self.connection_options[:access_token] = response_hash["access_token"]
127
- self.connection_options[:access_token_expires] = (Time.now - 10) + response_hash["expires_in"]
128
- end
129
- response_hash
130
- end
131
-
132
- def request(method, path, params = {})
133
- uri = "#{self.connection_options[:uri]}/#{path}"
134
- body = nil
135
- if method == :get
136
- query = URI.encode_www_form(params)
137
- uri += "?#{query}"
138
- else
139
- body = JSON.dump(params)
140
- end
141
-
142
- response = connection_retry_wrapper {
143
- connection = Bright::Connection.new(uri)
144
- headers = self.headers_for_auth
145
- connection.request(method, body, headers)
146
- }
147
-
148
- if !response.error?
149
- response_hash = JSON.parse(response.body)
150
- else
151
- puts "#{response.inspect}"
152
- puts "#{response.body}"
153
- end
154
- return {:parsed_body => response_hash, :headers => response.headers}
155
- end
156
-
157
- protected
158
-
159
- def convert_to_user_data(user_params, options = {})
160
- # :type => "Contact" || "Student"
161
- return {} if user_params.blank?
162
-
163
- user_data_hsh = {
164
- :api_id => user_params["NameId"],
165
- :first_name => user_params["FirstName"],
166
- :middle_name => user_params["MiddleName"],
167
- :last_name => user_params["LastName"],
168
- :sis_student_id => user_params["DisplayId"],
169
- :state_student_id => user_params["StateId"],
170
- :projected_graduation_year => user_params["GradYr"],
171
- # To avoid a mismatch of attributes, we'll ignore for now
172
- # :gender => user_params["Gender"],
173
- :hispanic_ethnicity => user_params["HispanicLatinoEthnicity"],
174
- :relationship_type => user_params["RelationshipType"]
175
- }.reject{|k,v| v.blank?}
176
- unless user_params["DateOfBirth"].blank?
177
- user_data_hsh[:birth_date] = Date.parse(user_params["DateOfBirth"]).to_s
178
- end
179
-
180
- DEMOGRAPHICS_CONVERSION.each do |demographics_key, demographics_value|
181
- if user_params["FederalRace"].to_s.upcase.include?(demographics_key)
182
- user_data_hsh[:race] ||= []
183
- user_data_hsh[:race] << demographics_value
184
- end
185
- end
186
-
187
- unless user_params["SchoolEmail"].blank?
188
- user_data_hsh[:email_address] = {
189
- :email_address => user_params["SchoolEmail"]
190
- }
191
- end
192
-
193
- unless user_params["Email"].blank?
194
- user_data_hsh[:email_address] = {
195
- :email_address => user_params["Email"]
196
- }
197
- end
198
-
199
- unless user_params["DefaultSchoolId"].blank?
200
- self.schools_cache ||= {}
201
- if (attending_school = self.schools_cache[user_params["DefaultSchoolId"]]).nil?
202
- attending_school = self.get_school_by_api_id(user_params["DefaultSchoolId"])
203
- self.schools_cache[attending_school.api_id] = attending_school
204
- end
205
- user_data_hsh[:school] = attending_school
206
- end
207
-
208
- unless user_params["StreetAddress"].blank?
209
- user_data_hsh[:addresses] = [{
210
- :street => user_params["StreetAddress"],
211
- :city => user_params["City"],
212
- :state => user_params["State"],
213
- :postal_code => user_params["ZipCode"]
214
- }]
215
- end
216
-
217
- ["PhoneNumber", "PhoneNumber2", "PhoneNumber3"].each do |phone_param|
218
- if user_params[phone_param].present? && user_params["#{phone_param}Type"].present?
219
- user_data_hsh[:phone_numbers] ||= []
220
- user_data_hsh[:phone_numbers] << {
221
- :phone_number => user_params[phone_param],
222
- :type => PHONE_TYPE_CONVERSION[user_params["#{phone_param}Type"]]
223
- }
224
- end
225
- end
226
-
227
- if options[:type] == "Student"
228
- #generate the contacts for a student
229
- user_data_hsh[:contacts] = self.get_guardians_by_api_id(user_data_hsh[:api_id])
230
- end
231
-
232
- return user_data_hsh
233
- end
234
-
235
- def convert_to_school_data(school_params)
236
- return {} if school_params.nil?
237
-
238
- school_data_hsh = {
239
- :api_id => school_params["SchoolId"],
240
- :name => school_params["SchoolName"],
241
- :low_grade => school_params["GradeLow"],
242
- :high_grade => school_params["GradeHigh"],
243
- }
244
-
245
- unless school_params["StreetAddress"].blank?
246
- school_data_hsh[:address] = {
247
- :street => school_params["StreetAddress"],
248
- :city => school_params["City"],
249
- :state => school_params["State"],
250
- :postal_code => school_params["ZipCode"]
251
- }
252
- end
253
-
254
- return school_data_hsh
255
- end
256
-
257
- def headers_for_access_token
258
- {
259
- "Authorization" => "Basic #{Base64.strict_encode64("#{self.connection_options[:client_id]}:#{self.connection_options[:client_secret]}")}",
260
- "Content-Type" => "application/x-www-form-urlencoded;charset=UTF-8"
261
- }
262
- end
263
-
264
- def headers_for_auth
265
- if self.connection_options[:access_token].nil? or self.connection_options[:access_token_expires] < Time.now
266
- self.retrieve_access_token
267
- end
268
- {
269
- "Authorization" => "Bearer #{self.connection_options[:access_token]}",
270
- "Accept" => "application/json;charset=UTF-8",
271
- "Content-Type" =>"application/json;charset=UTF-8"
272
- }
273
- end
274
-
275
- end
276
- end
277
- end