bright 1.3 → 2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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