blackbaud-client 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +13 -5
  2. data/.gitignore +1 -1
  3. data/.travis.yml +8 -0
  4. data/CHANGELOG.md +6 -0
  5. data/README.md +8 -5
  6. data/blackbaud-client.gemspec +5 -2
  7. data/lib/blackbaud-client/api/academic_year.rb +6 -5
  8. data/lib/blackbaud-client/api/attendance_by_class_record.rb +5 -0
  9. data/lib/blackbaud-client/api/attendance_by_day_record.rb +5 -0
  10. data/lib/blackbaud-client/api/attendance_code.rb +5 -0
  11. data/lib/blackbaud-client/api/attendance_record.rb +13 -0
  12. data/lib/blackbaud-client/api/blackbaud_class.rb +26 -0
  13. data/lib/blackbaud-client/api/blackbaud_object.rb +25 -3
  14. data/lib/blackbaud-client/api/code_table.rb +5 -0
  15. data/lib/blackbaud-client/api/grade.rb +13 -0
  16. data/lib/blackbaud-client/api/marking_column.rb +10 -0
  17. data/lib/blackbaud-client/api/person.rb +13 -15
  18. data/lib/blackbaud-client/api/relation.rb +3 -3
  19. data/lib/blackbaud-client/api/session.rb +7 -5
  20. data/lib/blackbaud-client/api/translation_table.rb +12 -0
  21. data/lib/blackbaud-client/api/translation_table_entry.rb +5 -0
  22. data/lib/blackbaud-client/connector.rb +42 -0
  23. data/lib/blackbaud-client/version.rb +2 -2
  24. data/lib/blackbaud-client.rb +144 -57
  25. data/spec/client_spec.rb +84 -0
  26. data/spec/response_data/get/grade/classes/marking_columns/grades.json +29 -0
  27. data/spec/response_data/get/grade/classes/marking_columns.json +52 -0
  28. data/spec/response_data/post/grade/class.json +15 -0
  29. data/spec/response_data/post/security/access_token.json +7 -0
  30. data/spec/spec_helper.rb +11 -0
  31. metadata +68 -11
  32. data/lib/blackbaud-client/api/class.rb +0 -12
  33. data/lib/blackbaud-client/api/table_entry.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 631c752d0154a233be0dced206e8a25f4d339f59
4
- data.tar.gz: cf6b78ac100ad91fd7e79a998389172540f0b737
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MjI4YjQ0ZjBlZmM2MDJiMmQ5YTc1YTA0Y2EzYjY2YWI3ZjhkOGMxYQ==
5
+ data.tar.gz: !binary |-
6
+ YmQ2YTFkOTJhYTkxMWFiMjZhODgwNjNmMTIwYTFlNDM3OTcwMmY2ZQ==
5
7
  SHA512:
6
- metadata.gz: 19e17a3ab89fe833b422dc2f36e284b430875f5b34f703bb849c6f17342d467b935537b81867e5993be7114854cb45faaa92462df984a4e4294edb62f4e2a4a2
7
- data.tar.gz: 1a9793df98ce432240f2e491ec953447479e7793182891f9c1863d7612de39544e28def1749676019a0a883e0a86c22e3269070ff865ab6abdd0f0dd66b65c38
8
+ metadata.gz: !binary |-
9
+ YjY4MDdkZDJkYzQ5NDljN2E5MzEzYjc5ZWUxN2IyOGU4MmRmMjZiYTQxOTZi
10
+ ZWNiNmVkMjUwMmNiYWRlMjQyYTA0NDQ4YjkxYjQ4YjgxOTNhZWE4Njk0NTM3
11
+ ZDJkNGVkM2Y5YTc1Y2YxYzFlZDJiNGUwMTRhNmY5MmMwYzc2Mzc=
12
+ data.tar.gz: !binary |-
13
+ ZWQwMDc1NDdlY2IzZWEwZmRlMjM5NWYwNzk2NDZiMDNiODAxYWI1NWRlODEz
14
+ YzRjMzIyZGNhMWM3YWMyMmM5NzdiNGNiNWUyZWM2N2FmMjJhMTIyZjZhZDkx
15
+ NThhNjI4MDMyOWZkOTllNzRiOTgzODhjZDc3MGJiOGI0MmQ3ODk=
data/.gitignore CHANGED
@@ -5,4 +5,4 @@ test/
5
5
  log/
6
6
  .ruby-version
7
7
  .ruby-gemset
8
- Gemfile.lock
8
+ Gemfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.1.7
5
+ - 2.2.3
6
+
7
+ script: bundle exec rspec spec
8
+ sudo: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.1.5 - 2015-09-30
4
+ ### Changed
5
+ - Major refactor to support Post reuqests
6
+ - Rename client methods to reflect their request type
7
+ - Add get objects and methods for TransalationTable, TranslationTableEntry, Grades, and MarkingColumn
8
+
3
9
  ## 0.1.4 - 2015-07-14
4
10
  ### Changed
5
11
  - Added deceased attribute to Person.
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/blackbaud-client.svg)](http://badge.fury.io/rb/blackbaud-client)
2
2
  [![Code Climate](https://codeclimate.com/github/haikulearning/blackbaud-client/badges/gpa.svg)](https://codeclimate.com/github/haikulearning/blackbaud-client)
3
+ [![Build Status](https://secure.travis-ci.org/haikulearning/blackbaud-client.svg)](http://travis-ci.org/haikulearning/blackbaud-client)
3
4
 
4
5
  # Blackbaud Client
5
6
  Ruby client for the Blackbaud API.
@@ -8,12 +9,14 @@ Ruby client for the Blackbaud API.
8
9
 
9
10
  Create a Blackbaud API Client
10
11
 
12
+ require 'blackbaud-client'
13
+
11
14
  options = {
12
- :password => "pass",
13
- :key => "abcde",
14
- :username => "user",
15
- :database => "1"
16
- :url => "https://blackbaud.api.url.example/key/"
15
+ :database_key => "db_key",
16
+ :database_number => 1,
17
+ :vendor_id => 'vendor_id',
18
+ :vendor_key => 'vendor_key',
19
+ :url => "https://blackbaud-api-url.com"
17
20
  }
18
21
 
19
22
  @client = Blackbaud::Client.new(options)
@@ -18,5 +18,8 @@ Gem::Specification.new do |gem|
18
18
  gem.add_runtime_dependency 'ruby-hmac', '~>0.4'
19
19
  gem.add_runtime_dependency 'rest-client', '~>1.6'
20
20
 
21
- gem.add_development_dependency 'rake'
22
- end
21
+ gem.add_development_dependency 'rspec', '~>3.3'
22
+ gem.add_development_dependency 'webmock', '~>1.21'
23
+ gem.add_development_dependency 'rake', '~>0.9'
24
+ gem.add_development_dependency 'pry', '~>0.10'
25
+ end
@@ -2,15 +2,16 @@ module Blackbaud
2
2
  class AcademicYear < BlackbaudObject
3
3
  attr_accessor(:description, :ea7_academic_year_id, :end_date, :school_id, :school_name, :sessions, :short_description, :start_date, :links)
4
4
 
5
- def initialize(values)
6
- values["sessions"].map! {|s| Blackbaud::Session.new(s)} if values["sessions"]
5
+ def initialize(options)
6
+
7
+ options.fetch(:values)["sessions"].map! {|s| Blackbaud::Session.new(values: s)} if options.fetch(:values)["sessions"]
7
8
 
8
9
  ["start_date", "end_date"].each do |date|
9
- send("#{date}=".intern, format_date(values["#{date}"]))
10
- values.delete("#{date}")
10
+ send("#{date}=".intern, format_date(options.fetch(:values)["#{date}"]))
11
+ options.fetch(:values).delete("#{date}")
11
12
  end
12
13
 
13
- super(values)
14
+ super
14
15
  end
15
16
 
16
17
  def connection_string
@@ -0,0 +1,5 @@
1
+ module Blackbaud
2
+ class AttendanceByClassRecord < AttendanceRecord
3
+ attr_accessor(:ea7_attendance_by_class_id, :ea7_class_meeting_id)
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Blackbaud
2
+ class AttendanceByDayRecord < AttendanceRecord
3
+ attr_accessor(:ea7_attendance_by_day_id)
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Blackbaud
2
+ class AttendanceCode < BlackbaudObject
3
+ attr_accessor(:ea7_attendance_code_id, :allow_daily_entry, :code_type, :code_type_desc, :description, :short_description)
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ module Blackbaud
2
+ class AttendanceRecord < BlackbaudObject
3
+ attr_accessor(:ea7_record_id, :code, :date, :name_for_display, :ea7_attendance_code_id)
4
+
5
+ def initialize(options)
6
+ options.fetch(:values)
7
+ self.date = format_date(options.fetch(:values)["date"])
8
+ options.fetch(:values).delete(:date)
9
+ super
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,26 @@
1
+ module Blackbaud
2
+ class BlackbaudClass < BlackbaudObject
3
+ attr_accessor(:ea7_class_id, :course_id, :course_name, :section, :ea7_term_id, :ea7_term_name, :faculty, :students)
4
+
5
+ def initialize(options)
6
+ {
7
+ 'faculty' => Blackbaud::Person::USER_TYPE[:faculty],
8
+ 'students' => Blackbaud::Person::USER_TYPE[:student],
9
+ }.each do |response_key, type_id|
10
+ if options.fetch(:values)[response_key].is_a?(Enumerable)
11
+ options.fetch(:values)[response_key].map! do |person|
12
+ person['type'] = type_id
13
+ Blackbaud::Person.new({values: person})
14
+ end
15
+ end
16
+ end
17
+
18
+ super
19
+ end
20
+
21
+ def marking_columns
22
+ @client.get_class_marking_columns(self.ea7_class_id)
23
+ end
24
+
25
+ end
26
+ end
@@ -1,15 +1,37 @@
1
1
  module Blackbaud
2
2
  class BlackbaudObject
3
3
 
4
- def initialize(values)
5
- values.each do |k,v|
4
+ attr_accessor :client
5
+
6
+ def initialize(options)
7
+ @client ||= options.delete(:client)
8
+
9
+ options.fetch(:values).each do |k,v|
6
10
  send("#{k}=".intern, v) if respond_to?("#{k}=".intern)
7
11
  end
12
+ rescue NoMethodError
13
+ puts "NoMethodError: There is no method for one of the keys in your options: #{options}"
14
+ return nil
8
15
  end
9
16
 
10
17
  def format_date(d)
11
18
  DateTime.parse(d)
12
19
  end
13
20
 
21
+ def to_hash(keys=nil)
22
+ ivs = (keys ? (instance_variables & keys) : instance_variables)
23
+ ivs -= [:@client]
24
+ Hash[*
25
+ ivs.map { |v|
26
+ [v.to_s[1..-1].to_sym, instance_variable_get(v)]
27
+ }.flatten]
28
+ end
29
+
30
+ def to_json(*args)
31
+ JSON.generate(to_hash)
32
+ end
33
+
34
+ alias_method :to_h, :to_hash
35
+
14
36
  end
15
- end
37
+ end
@@ -1,5 +1,10 @@
1
1
  module Blackbaud
2
2
  class CodeTable < BlackbaudObject
3
3
  attr_accessor(:_links, :id, :name, :links)
4
+
5
+ def entries
6
+ @client.get_code_table_entries(self)
7
+ end
8
+
4
9
  end
5
10
  end
@@ -0,0 +1,13 @@
1
+ module Blackbaud
2
+ class Grade < BlackbaudObject
3
+ attr_accessor(:ea7_marking_column_id,:ea7_record_id,:ea7_student_course_id,:ea7_student_grade_id,:ea7_student_gradebook_grade_id,:ea7_translation_table_entry_id,:grade,:grade_post_status,:grade_type,:message,:name_for_display)
4
+
5
+ def to_hash
6
+ super([:@ea7_marking_column_id, :@ea7_student_course_id, :@ea7_student_grade_id, :@ea7_translation_table_entry_id, :@message])
7
+ end
8
+
9
+ def post
10
+ @client.post_grades(self)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ module Blackbaud
2
+ class MarkingColumn < BlackbaudObject
3
+ attr_accessor(:ea7_course_grading_info_grade_id, :description, :ea7_marking_column_id, :ea7_translation_table_id, :short_description, :values_allowed, :ea7_class_id)
4
+
5
+ def grades
6
+ @client.get_grades(self.ea7_class_id, self.ea7_marking_column_id)
7
+ end
8
+
9
+ end
10
+ end
@@ -8,30 +8,28 @@ module Blackbaud
8
8
  :undefined => nil,
9
9
  }
10
10
 
11
- def initialize(values, type_id)
12
- values["type"] = type_id
13
-
14
- if values["bio"]
15
- values["bio"].each {|k, v| values[k] = v}
16
- values.delete("bio")
11
+ def initialize(options)
12
+ if options.fetch(:values)["bio"]
13
+ options.fetch(:values)["bio"].each {|k, v| options.fetch(:values)[k] = v}
14
+ options.fetch(:values).delete("bio")
17
15
  end
18
16
 
19
- if values["contact_info"]
20
- values["contacts"] = values["contact_info"].map {|c| Blackbaud::Contact.new(c)}
21
- values.delete("contact_info")
17
+ if options.fetch(:values)["contact_info"]
18
+ options.fetch(:values)["contacts"] = options.fetch(:values)["contact_info"].map {|c| Blackbaud::Contact.new({values: c})}
19
+ options.fetch(:values).delete("contact_info")
22
20
  else
23
- values["contacts"] = []
21
+ options.fetch(:values)["contacts"] = []
24
22
  end
25
23
 
26
- if values["relations"]
27
- values["relations"].map! {|r| Blackbaud::Relation.new(r)}
24
+ if options.fetch(:values)["relations"]
25
+ options.fetch(:values)["relations"].map! {|r| Blackbaud::Relation.new({values: r})}
28
26
  else
29
- values["relations"] = []
27
+ options.fetch(:values)["relations"] = []
30
28
  end
31
29
 
32
- values["birth_date"] = format_date(values["birth_date"]) if values["birth_date"]
30
+ options.fetch(:values)["birth_date"] = format_date(options.fetch(:values)["birth_date"]) if options.fetch(:values)["birth_date"]
33
31
 
34
- super(values)
32
+ super
35
33
  end
36
34
 
37
35
  def faculty?
@@ -2,9 +2,9 @@ module Blackbaud
2
2
  class Relation < BlackbaudObject
3
3
  attr_accessor(:relationship_code_id, :relationship_code_value, :reciprocal_code_id, :reciprocal_code_value, :person, :emergency_contact)
4
4
 
5
- def initialize(values)
6
- values["person"] = Blackbaud::Person.new(values["person"], Blackbaud::Person::USER_TYPE[:undefined]) if values["person"]
7
- super(values)
5
+ def initialize(options)
6
+ options.fetch(:values)["person"] = Blackbaud::Person.new(values: options.fetch(:values)["person"]) if options.fetch(:values)["person"]
7
+ super
8
8
  end
9
9
 
10
10
  end
@@ -1,11 +1,13 @@
1
1
  module Blackbaud
2
2
  class Session < BlackbaudObject
3
- attr_accessor(:name, :ea7_session_id, :terms, :links)
3
+ attr_accessor(:name, :ea7_session_id, :marking_columns, :terms, :track_schedule_changes, :beginning_track_date, :message, :links)
4
4
 
5
- def initialize(values)
6
- values["terms"].map! {|t| Blackbaud::Term.new(t)} if values["terms"]
7
- super(values)
5
+
6
+ def initialize(options)
7
+ options.fetch(:values)["terms"].map! {|t| Blackbaud::Term.new({values: t})} if options.fetch(:values)["terms"]
8
+ options.fetch(:values)["marking_columns"].map! {|t| Blackbaud::MarkingColumn.new({values: t})} if options.fetch(:values)["marking_columns"]
9
+ super
8
10
  end
9
11
 
10
12
  end
11
- end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Blackbaud
2
+ class TranslationTable < BlackbaudObject
3
+ attr_accessor(:ea7_translation_table_id, :highest_numeric_grade_allowed, :lowest_numeric_grade_allowed, :name, :translation_table_entries)
4
+ alias_method :entries, :translation_table_entries
5
+
6
+ def initialize(options)
7
+ options.fetch(:values)["translation_table_entries"].map! {|e| Blackbaud::TranslationTableEntry.new({values: e})} if options.fetch(:values)["translation_table_entries"]
8
+ super
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ module Blackbaud
2
+ class TranslationTableEntry < BlackbaudObject
3
+ attr_accessor(:ea7_translation_table_entry_id, :grade)
4
+ end
5
+ end
@@ -0,0 +1,42 @@
1
+ module Blackbaud
2
+ class Connector
3
+ attr_accessor(:token, :web_services_url, :save_request_data_to)
4
+ def initialize(url, save_request_data_to)
5
+ @web_services_url = url
6
+ @save_request_data_to = save_request_data_to
7
+ end
8
+
9
+ def get(endpoint, filters=nil)
10
+ url = construct_url(@web_services_url, endpoint, filters)
11
+ response = RestClient.get(url)
12
+ write_json_to_file(url, response) if @save_request_data_to
13
+ JSON.parse(response)
14
+ end
15
+
16
+ def post(endpoint, body)
17
+ url = construct_url(@web_services_url, endpoint)
18
+ response = RestClient.post(url, body, {:content_type=>'application/json'})
19
+ JSON.parse(response)
20
+ end
21
+
22
+ def construct_url(web_services_url, endpoint, filters=nil)
23
+ params = "?token=#{@token}" if @token
24
+ if filters
25
+ filters = Array(filters).map do |k,v|
26
+ v = Array(v)
27
+ "(#{k}%20eq%20#{v.join(',')})" if v && !v.join.empty?
28
+ end
29
+ params << "&filter=#{filters.join}"
30
+ end
31
+ url = "#{web_services_url}/#{endpoint}#{params}"
32
+ end
33
+
34
+ def write_json_to_file(url, data)
35
+ return unless data
36
+ file = url.gsub( /\/|\\/, ':' ).match(/.{,250}$/).to_s + '.json'
37
+ file = File.expand_path(File.join(@save_request_data_to, file))
38
+ FileUtils.mkdir_p @save_request_data_to
39
+ File.open(file, 'w') { |f| f.write(JSON.pretty_unparse(JSON.parse(data)))}
40
+ end
41
+ end
42
+ end
@@ -2,8 +2,8 @@ module Blackbaud
2
2
  class Client
3
3
  class Version
4
4
  MAJOR = 0
5
- MINOR = 1
6
- PATCH = 4
5
+ MINOR = 2
6
+ PATCH = 0
7
7
  STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
8
8
 
9
9
  class << self
@@ -1,16 +1,24 @@
1
+ require 'blackbaud-client/connector.rb'
1
2
  require 'blackbaud-client/version.rb'
2
3
  require 'blackbaud-client/api/blackbaud_object.rb'
3
4
  require 'blackbaud-client/api/academic_year.rb'
4
- require 'blackbaud-client/api/class.rb'
5
+ require 'blackbaud-client/api/blackbaud_class.rb'
5
6
  require 'blackbaud-client/api/code_table.rb'
6
7
  require 'blackbaud-client/api/person.rb'
7
8
  require 'blackbaud-client/api/contact.rb'
8
9
  require 'blackbaud-client/api/relation.rb'
9
10
  require 'blackbaud-client/api/session.rb'
10
11
  require 'blackbaud-client/api/static_code_table.rb'
11
- require 'blackbaud-client/api/table_entry.rb'
12
12
  require 'blackbaud-client/api/term.rb'
13
13
  require 'blackbaud-client/api/code_table_entry.rb'
14
+ require 'blackbaud-client/api/attendance_code.rb'
15
+ require 'blackbaud-client/api/attendance_record.rb'
16
+ require 'blackbaud-client/api/attendance_by_day_record.rb'
17
+ require 'blackbaud-client/api/attendance_by_class_record.rb'
18
+ require 'blackbaud-client/api/grade.rb'
19
+ require 'blackbaud-client/api/marking_column.rb'
20
+ require 'blackbaud-client/api/translation_table.rb'
21
+ require 'blackbaud-client/api/translation_table_entry.rb'
14
22
  require 'hmac-sha1'
15
23
  require 'cgi'
16
24
  require 'base64'
@@ -20,39 +28,44 @@ require 'date'
20
28
 
21
29
  module Blackbaud
22
30
  class Client
23
-
31
+ attr_accessor(:connector)
24
32
  def initialize(options)
33
+ @connector = Blackbaud::Connector.new(options[:url], options[:save_request_data_to])
25
34
  auth_params = {
26
35
  :database_key => options[:database_key],
27
36
  :database_number => options[:database_number],
28
37
  :vendor_id => options[:vendor_id],
29
38
  :vendor_key => options[:vendor_key]
30
39
  }.to_json
31
- @web_services_url = options[:url]
32
- @token = JSON.parse(RestClient.post (@web_services_url+'/security/access_token'), auth_params, {:content_type=>'application/json'})["token"]
33
- @save_request_data_to = options[:save_request_data_to]
40
+ @connector.token = get_token(auth_params)
34
41
  end
35
42
 
36
- def connect(endpoint, filters=nil)
37
- url = construct_url(@web_services_url, endpoint, filters)
38
- json = RestClient::Request.execute(:method=>'get', :url=>url)
39
- write_json_to_file(url, json) if @save_request_data_to
40
- JSON.parse(json)
43
+ def get_token(auth_params)
44
+ results = @connector.post('/security/access_token', auth_params)
45
+ results["token"]
41
46
  end
42
47
 
43
- def academic_years(id)
44
- results = connect("schedule/#{id}/academic_years")
45
- results["academic_years"].collect {|year| Blackbaud::AcademicYear.new(year)}
48
+ def get_academic_years(id)
49
+ results = @connector.get("schedule/#{id}/academic_years")
50
+ create_blackbaud_objects(Blackbaud::AcademicYear, results["academic_years"])
46
51
  end
47
52
 
48
- def contact_types
49
- results = connect("global/code_tables/phone%20type")
50
- results["table_entries"].collect {|entry| Blackbaud::CodeTableEntry.new(entry)}
53
+ def get_contact_types
54
+ results = @connector.get("global/code_tables/phone%20type")
55
+ create_blackbaud_objects(Blackbaud::CodeTableEntry, results["table_entries"])
51
56
  end
52
57
 
53
- def relationships
54
- results = connect("global/code_tables/relationship")
55
- results["table_entries"].collect {|entry| Blackbaud::CodeTableEntry.new(entry)}
58
+ def get_relationships
59
+ results = @connector.get("global/code_tables/relationship")
60
+ create_blackbaud_objects(Blackbaud::CodeTableEntry, results["table_entries"])
61
+ end
62
+
63
+ def get_person(id, filter_opts={})
64
+ filters = {}
65
+ filters["contact.type_id"] = filter_opts[:contact_types]
66
+ filters["relation.relationship_code_id"] = filter_opts[:relationships]
67
+ results = @connector.get("person/people/#{id}", filters)
68
+ create_blackbaud_object(Blackbaud::Person, results["people"].first)
56
69
  end
57
70
 
58
71
  # Return an Array of Person records
@@ -60,71 +73,145 @@ module Blackbaud
60
73
  # Available filter_opts:
61
74
  # * :contact_types: An Array of id values that correspond to code_table table_entry records from the "phone type" code_table
62
75
  # * :relationships: An Array of id values that correspond to code_table table_entry records from the "relationship" code_table
63
- def people(scope, filter_opts={})
76
+ def get_people(scope, filter_opts={})
64
77
  filters = {}
65
-
66
78
  filters["contact.type_id"] = filter_opts[:contact_types]
67
79
  filters["relation.relationship_code_id"] = filter_opts[:relationships]
68
80
 
69
- results = connect("person/#{scope.connection_string}/people", filters )
70
- r = []
81
+ results = @connector.get("person/#{scope.connection_string}/people", filters)["people"].first
71
82
 
72
83
  {
73
84
  'faculty' => Blackbaud::Person::USER_TYPE[:faculty],
74
85
  'students' => Blackbaud::Person::USER_TYPE[:student],
75
86
  }.each do |response_key, type_id|
76
- ppl = results["people"].first[response_key]
77
- ppl = [] unless ppl.is_a?(Enumerable)
78
- ppl.each do |person|
79
- r << Blackbaud::Person.new(person, type_id)
87
+ if results[response_key].is_a?(Enumerable)
88
+ results[response_key].each{|person| person['type'] = type_id}
80
89
  end
81
90
  end
91
+ create_blackbaud_objects(Blackbaud::Person, results['faculty'] + results['students'])
92
+ end
82
93
 
83
- r
94
+ def get_classes(scope)
95
+ results = @connector.get("schedule/#{scope.connection_string}/classes")
96
+ create_blackbaud_objects(Blackbaud::BlackbaudClass, results["classes"])
84
97
  end
85
98
 
86
- def classes(scope)
87
- results = connect("schedule/#{scope.connection_string}/classes")
88
- results["classes"].collect {|c| Blackbaud::Class.new(c)}
99
+ def get_class(id)
100
+ results = @connector.get("schedule/classes/#{id}")
101
+ create_blackbaud_object(Blackbaud::BlackbaudClass, results["classes"].first)
89
102
  end
90
103
 
91
- def code_tables
92
- results = connect("global/code_tables")
93
- results["code_tables"].collect {|table| Blackbaud::CodeTable.new(table)}
104
+ def get_code_tables
105
+ results = @connector.get("global/code_tables")
106
+ create_blackbaud_objects(Blackbaud::CodeTable, results["code_tables"])
94
107
  end
95
108
 
96
- def code_table_entries(code_table)
97
- results = connect("global/code_tables/#{code_table.id}")
98
- results["table_entries"].collect {|entry| Blackbaud::TableEntry.new(entry)}
109
+ def get_code_table_entries(code_table)
110
+ results = @connector.get("global/code_tables/#{code_table.id}")
111
+ create_blackbaud_objects(Blackbaud::CodeTableEntry, results["table_entries"])
99
112
  end
100
113
 
101
- def static_code_tables(id)
102
- results = connect("global/static_code_tables/#{id}")
103
- results["table_entries"].collect {|c| Blackbaud::TableEntry.new(c)}
114
+ def get_static_code_tables(id)
115
+ results = @connector.get("global/static_code_tables/#{id}")
116
+ create_blackbaud_objects(Blackbaud::CodeTableEntry, results["table_entries"])
104
117
  end
105
118
 
106
- private
119
+ def get_attendance_codes
120
+ results = @connector.get("attendance/codes")
121
+ create_blackbaud_objects(Blackbaud::AttendanceCode, results["attendance_codes"])
122
+ end
123
+
124
+ def get_attendance_by_class(ea7_class_id, start_date, end_date = nil)
125
+ results = @connector.get("attendance/class/#{ea7_class_id}/#{format_date(start_date)}/#{format_date(end_date)}")
126
+ create_blackbaud_objects(Blackbaud::AttendanceByClassRecord, results["attendance_by_class_records"])
127
+ end
128
+
129
+ def get_attendance_by_day(ea7_class_id, start_date, end_date = nil)
130
+ results = @connector.get("attendance/day/#{ea7_class_id}/#{start_date}/#{end_date}")
131
+ create_blackbaud_objects(Blackbaud::AttendanceByDayRecord, results["attendance_by_day_records"])
132
+ end
133
+
134
+ def get_academic_year_marking_columns(year_id)
135
+ results = @connector.get("configuration/academic_years/#{year_id}/marking_columns")
136
+ create_blackbaud_objects(Blackbaud::Session, results["sessions"])
137
+ end
107
138
 
108
- def write_json_to_file(url, data)
109
- return unless data
110
- file = url.gsub( /\/|\\/, ':' ).match(/.{,250}$/).to_s + '.json'
111
- # file = /[^\/]*$/.match(url).to_s + '.json'
112
- file = File.expand_path(File.join(@save_request_data_to, file))
113
- FileUtils.mkdir_p @save_request_data_to
114
- File.open(file, 'w') { |f| f.write(JSON.pretty_unparse(JSON.parse(data)))}
139
+ def get_session_marking_columns(session_id)
140
+ results = @connector.get("configuration/sessions/#{session_id}/marking_columns")
141
+ create_blackbaud_objects(Blackbaud::MarkingColumn, results["marking_columns"])
115
142
  end
116
143
 
117
- def construct_url(web_services_url, endpoint, filters=nil)
118
- url = "#{web_services_url}/#{endpoint}?token=#{@token}"
119
- filters = Array(filters).map do |k,v|
120
- v = Array(v)
121
- "(#{k}%20eq%20#{v.join(',')})" if v && !v.join.empty?
144
+ def get_class_marking_columns(class_id)
145
+ results = @connector.get("grade/classes/#{class_id}/marking_columns")
146
+ results["class_marking_columns"].each{|column| column["ea7_class_id"] = class_id}
147
+ create_blackbaud_objects(Blackbaud::MarkingColumn, results["class_marking_columns"])
148
+ end
149
+
150
+ def get_grades(class_id, marking_column_id)
151
+ results = @connector.get("grade/classes/#{class_id}/marking_columns/#{marking_column_id}/grades")
152
+ create_blackbaud_objects(Blackbaud::Grade, results["grades"])
153
+ end
154
+
155
+ def get_faweb_grades(class_id, marking_column_id)
156
+ results = @connector.get("faweb_grade/classes/#{class_id}/marking_columns/#{marking_column_id}/grades")
157
+ create_blackbaud_objects(Blackbaud::Grade, results["faweb_grades"])
158
+ end
159
+
160
+ def get_translation_tables(id=nil)
161
+ results = @connector.get("grade/translation_tables/#{id}")
162
+ create_blackbaud_objects(Blackbaud::TranslationTable, results["translation_tables"])
163
+ end
164
+
165
+ def post_grades(grades)
166
+ results = @connector.post('/grade/class', format_grades(grades))
167
+ create_blackbaud_objects(Blackbaud::Grade, results["grades"])
168
+ end
169
+
170
+ # These are for backwards compatibilty with version <=0.1.4. Remove them before v 1.0.
171
+ alias_method :academic_years, :get_academic_years
172
+ alias_method :contact_types, :get_contact_types
173
+ alias_method :relationships, :get_relationships
174
+ alias_method :person, :get_person
175
+ alias_method :people, :get_people
176
+ alias_method :classes, :get_classes
177
+ alias_method :class, :get_class
178
+ alias_method :code_tables, :get_code_tables
179
+ alias_method :code_table_entries, :get_code_table_entries
180
+ alias_method :static_code_tables, :get_static_code_tables
181
+ alias_method :attendance_codes, :get_attendance_codes
182
+ alias_method :attendance_by_class, :get_attendance_by_class
183
+ alias_method :attendance_by_day, :get_attendance_by_day
184
+ alias_method :class_marking_columns, :get_class_marking_columns
185
+ alias_method :grades, :get_grades
186
+ alias_method :faweb_grades, :get_faweb_grades
187
+ alias_method :translation_tables, :get_translation_tables
188
+
189
+ private
190
+
191
+ def create_blackbaud_objects(klass, results)
192
+ results = [results] if results.class == Hash
193
+ ret = results.collect do |result|
194
+ klass.new({values: result, client: self})
122
195
  end
196
+ ret || []
197
+ end
198
+
199
+ def create_blackbaud_object(klass, result)
200
+ klass.new({values: result, client: self})
201
+ end
123
202
 
124
- url << "&filter=#{filters.join}"
203
+ def format_grades(grades)
204
+ grades = [grades] unless grades.is_a?(Array)
205
+ JSON.generate({
206
+ grades: grades
207
+ })
208
+ end
125
209
 
126
- url
210
+ def format_date(date)
211
+ return unless date
212
+ date = DateTime.parse(date) if date.is_a?(String)
213
+ date.strftime("%F")
127
214
  end
128
215
 
129
216
  end
130
- end
217
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ def stub_requests
4
+ stub_request(:any, /www.example.com/).
5
+ to_return(lambda do |request|
6
+ response_path = request.uri.path.split('/').select{|p| p[/[a-zA-Z_]+/]}.join("/")
7
+ body = File.read("spec/response_data/#{request.method}/#{response_path}.json")
8
+ response = {
9
+ :status => 200,
10
+ :body => body,
11
+ :headers => {
12
+ "Content-Length" => body.size,
13
+ "Content-Type" => "application/json; charset=utf-8",
14
+ "Date" => DateTime.now.rfc2822,
15
+ "Server" => "Microsoft-HTTPAPI/2.0"
16
+ }
17
+ }
18
+ end
19
+ )
20
+ end
21
+
22
+ describe Blackbaud::Client do
23
+
24
+ before :all do
25
+ stub_requests
26
+
27
+ options = {
28
+ :database_key => "database_key",
29
+ :database_number => 1,
30
+ :vendor_id => 'vendor_id',
31
+ :vendor_key => 'vendor_key',
32
+ :url => "https://www.example.com"
33
+ }
34
+ @client = Blackbaud::Client.new(options)
35
+ end
36
+
37
+ before :each do
38
+ stub_requests
39
+ end
40
+
41
+ describe "#initalize" do
42
+ context "given auth params" do
43
+ it "gets an auth token" do
44
+ expect(@client.connector.token).to eq 'abcdefgh-1234-zyxw-9876-ijklmnopqrst_1'
45
+ end
46
+ end
47
+ end
48
+
49
+ describe "#get_class_marking_columns" do
50
+ context "initialized and given an ea7_class_id" do
51
+ it "gets marking_column data" do
52
+ r = @client.get_class_marking_columns(7)
53
+ expect(r.size).to eq 6
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "#post_grades" do
59
+ context "given an ea7_class_id" do
60
+ it "posts an updated grade" do
61
+ marking_column = @client.get_class_marking_columns(7).first
62
+ grade = marking_column.grades.first
63
+ grade.grade = '100'
64
+ grade.ea7_translation_table_entry_id = nil
65
+ r = grade.post
66
+ expect(r.size).to eq 1
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "#format_grades" do
72
+ context "given a set of grades" do
73
+ it "formats a json object to match the blackbaud spec" do
74
+ marking_column = @client.get_class_marking_columns(7).first
75
+ grades = marking_column.grades
76
+ result = @client.send(:format_grades, grades)
77
+ expect(JSON.parse(result)['grades'].size).to eq 3
78
+ expect(JSON.parse(result)['grades'].first.keys.size).to eq 5
79
+ end
80
+ end
81
+ end
82
+
83
+
84
+ end
@@ -0,0 +1,29 @@
1
+ {
2
+ "grades": [
3
+ {
4
+ "ea7_student_grade_id": 1654,
5
+ "ea7_marking_column_id": 55,
6
+ "ea7_student_course_id": 143325,
7
+ "ea7_translation_table_entry_id": 22,
8
+ "grade": "A",
9
+ "grade_type": 1,
10
+ "ea7_record_id": 75,
11
+ "name_for_display": "Samantha Rae Andrews",
12
+ "message": "(explanation of fields: a grade exists so all fields filled in)"
13
+ },
14
+ {
15
+ "ea7_student_course_id": 143329,
16
+ "ea7_record_id": 403,
17
+ "name_for_display": "Lisa Green",
18
+ "message": "(explanation of fields: no grade exists so minimum fields filled in)"
19
+ },
20
+ {
21
+ "ea7_student_grade_id": 1659,
22
+ "ea7_marking_column_id": 55,
23
+ "ea7_student_course_id": 143330,
24
+ "ea7_record_id": 204,
25
+ "name_for_display": "Colvin Bryant",
26
+ "message": "(explanation of fields: no grade exists but a comment does (not available thru api) so some fields filled in)"
27
+ }
28
+ ]
29
+ }
@@ -0,0 +1,52 @@
1
+ {
2
+ "class_marking_columns": [
3
+ {
4
+ "ea7_course_grading_info_grade_id": 43,
5
+ "description": "Quarter 1",
6
+ "ea7_marking_column_id": 51,
7
+ "ea7_translation_table_id": 2,
8
+ "short_description": "QT1",
9
+ "values_allowed": 2
10
+ },
11
+ {
12
+ "ea7_course_grading_info_grade_id": 44,
13
+ "description": "Quarter 2",
14
+ "ea7_marking_column_id": 52,
15
+ "ea7_translation_table_id": 2,
16
+ "short_description": "QT2",
17
+ "values_allowed": 2
18
+ },
19
+ {
20
+ "ea7_course_grading_info_grade_id": 45,
21
+ "description": "Quarter 3",
22
+ "ea7_marking_column_id": 53,
23
+ "ea7_translation_table_id": 2,
24
+ "short_description": "QT3",
25
+ "values_allowed": 2
26
+ },
27
+ {
28
+ "ea7_course_grading_info_grade_id": 46,
29
+ "description": "Quarter 4",
30
+ "ea7_marking_column_id": 54,
31
+ "ea7_translation_table_id": 2,
32
+ "short_description": "QT4",
33
+ "values_allowed": 2
34
+ },
35
+ {
36
+ "ea7_course_grading_info_grade_id": 47,
37
+ "description": "Semester 1",
38
+ "ea7_marking_column_id": 55,
39
+ "ea7_translation_table_id": 1,
40
+ "short_description": "Sem1",
41
+ "values_allowed": 1
42
+ },
43
+ {
44
+ "ea7_course_grading_info_grade_id": 48,
45
+ "description": "Semester 2",
46
+ "ea7_marking_column_id": 56,
47
+ "ea7_translation_table_id": 1,
48
+ "short_description": "Sem2",
49
+ "values_allowed": 1
50
+ }
51
+ ]
52
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "grades": [
3
+ {
4
+ "ea7_student_grade_id": 1654,
5
+ "ea7_marking_column_id": 55,
6
+ "ea7_student_course_id": 143325,
7
+ "ea7_translation_table_entry_id": 22,
8
+ "grade": "A",
9
+ "grade_type": 1,
10
+ "ea7_record_id": 75,
11
+ "name_for_display": "Samantha Rae Andrews",
12
+ "message": "(explanation of fields: a grade exists so all fields filled in)"
13
+ }
14
+ ]
15
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "database_key": "34E0B2B6FB91",
3
+ "database_number": 1572,
4
+ "token": "abcdefgh-1234-zyxw-9876-ijklmnopqrst_1",
5
+ "user_id": 46,
6
+ "vendor_id": "uFO69lS9TkyIOPqGyFVEVg"
7
+ }
@@ -0,0 +1,11 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'blackbaud-client'
5
+ require 'webmock/rspec'
6
+ require 'pry'
7
+
8
+ WebMock.disable_net_connect!(allow_localhost: true)
9
+
10
+ RSpec.configure do |config|
11
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blackbaud-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Dugger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-15 00:00:00.000000000 Z
11
+ date: 2015-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-hmac
@@ -38,20 +38,62 @@ dependencies:
38
38
  - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '3.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.21'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.21'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rake
43
71
  requirement: !ruby/object:Gem::Requirement
44
72
  requirements:
45
- - - '>='
73
+ - - ~>
46
74
  - !ruby/object:Gem::Version
47
- version: '0'
75
+ version: '0.9'
48
76
  type: :development
49
77
  prerelease: false
50
78
  version_requirements: !ruby/object:Gem::Requirement
51
79
  requirements:
52
- - - '>='
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '0.9'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '0.10'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
53
95
  - !ruby/object:Gem::Version
54
- version: '0'
96
+ version: '0.10'
55
97
  description: A client for the Blackbaud API.
56
98
  email: alexd@haikulearning.com
57
99
  executables: []
@@ -59,6 +101,7 @@ extensions: []
59
101
  extra_rdoc_files: []
60
102
  files:
61
103
  - .gitignore
104
+ - .travis.yml
62
105
  - CHANGELOG.md
63
106
  - Gemfile
64
107
  - LICENSE.txt
@@ -67,18 +110,32 @@ files:
67
110
  - blackbaud-client.gemspec
68
111
  - lib/blackbaud-client.rb
69
112
  - lib/blackbaud-client/api/academic_year.rb
113
+ - lib/blackbaud-client/api/attendance_by_class_record.rb
114
+ - lib/blackbaud-client/api/attendance_by_day_record.rb
115
+ - lib/blackbaud-client/api/attendance_code.rb
116
+ - lib/blackbaud-client/api/attendance_record.rb
117
+ - lib/blackbaud-client/api/blackbaud_class.rb
70
118
  - lib/blackbaud-client/api/blackbaud_object.rb
71
- - lib/blackbaud-client/api/class.rb
72
119
  - lib/blackbaud-client/api/code_table.rb
73
120
  - lib/blackbaud-client/api/code_table_entry.rb
74
121
  - lib/blackbaud-client/api/contact.rb
122
+ - lib/blackbaud-client/api/grade.rb
123
+ - lib/blackbaud-client/api/marking_column.rb
75
124
  - lib/blackbaud-client/api/person.rb
76
125
  - lib/blackbaud-client/api/relation.rb
77
126
  - lib/blackbaud-client/api/session.rb
78
127
  - lib/blackbaud-client/api/static_code_table.rb
79
- - lib/blackbaud-client/api/table_entry.rb
80
128
  - lib/blackbaud-client/api/term.rb
129
+ - lib/blackbaud-client/api/translation_table.rb
130
+ - lib/blackbaud-client/api/translation_table_entry.rb
131
+ - lib/blackbaud-client/connector.rb
81
132
  - lib/blackbaud-client/version.rb
133
+ - spec/client_spec.rb
134
+ - spec/response_data/get/grade/classes/marking_columns.json
135
+ - spec/response_data/get/grade/classes/marking_columns/grades.json
136
+ - spec/response_data/post/grade/class.json
137
+ - spec/response_data/post/security/access_token.json
138
+ - spec/spec_helper.rb
82
139
  homepage: https://github.com/haikulearning/blackbaud-api-client
83
140
  licenses: []
84
141
  metadata: {}
@@ -88,17 +145,17 @@ require_paths:
88
145
  - lib
89
146
  required_ruby_version: !ruby/object:Gem::Requirement
90
147
  requirements:
91
- - - '>='
148
+ - - ! '>='
92
149
  - !ruby/object:Gem::Version
93
150
  version: '0'
94
151
  required_rubygems_version: !ruby/object:Gem::Requirement
95
152
  requirements:
96
- - - '>='
153
+ - - ! '>='
97
154
  - !ruby/object:Gem::Version
98
155
  version: '0'
99
156
  requirements: []
100
157
  rubyforge_project:
101
- rubygems_version: 2.0.14
158
+ rubygems_version: 2.4.3
102
159
  signing_key:
103
160
  specification_version: 4
104
161
  summary: A client for the Blackbaud API.
@@ -1,12 +0,0 @@
1
- module Blackbaud
2
- class Class < BlackbaudObject
3
- attr_accessor(:ea7_class_id, :course_id, :course_name, :section, :ea7_term_id, :ea7_term_name, :faculty, :students)
4
-
5
- def initialize(values)
6
- values["faculty"].map! {|s| Blackbaud::Person.new(s, 1)} if values["faculty"]
7
- values["students"].map! {|s| Blackbaud::Person.new(s, 2)} if values["students"]
8
- super(values)
9
- end
10
-
11
- end
12
- end
@@ -1,5 +0,0 @@
1
- module Blackbaud
2
- class TableEntry < BlackbaudObject
3
- attr_accessor(:id, :name)
4
- end
5
- end