blackbaud-client 0.1.4 → 0.2.0

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 (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