rexpense 1.0.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 (114) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +22 -0
  3. data/.coveralls.yml +1 -0
  4. data/.gitignore +24 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +54 -0
  7. data/.travis.yml +9 -0
  8. data/CHANGELOG.md +1 -0
  9. data/Gemfile +4 -0
  10. data/Gemfile.lock +97 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +195 -0
  13. data/Rakefile +6 -0
  14. data/bin/console +14 -0
  15. data/bin/rspec +21 -0
  16. data/bin/setup +7 -0
  17. data/lib/rexpense/client.rb +39 -0
  18. data/lib/rexpense/configuration.rb +13 -0
  19. data/lib/rexpense/entities/activity.rb +11 -0
  20. data/lib/rexpense/entities/activity_collection.rb +14 -0
  21. data/lib/rexpense/entities/advancement.rb +14 -0
  22. data/lib/rexpense/entities/advancement_collection.rb +14 -0
  23. data/lib/rexpense/entities/advancement_devolution.rb +13 -0
  24. data/lib/rexpense/entities/attachment.rb +13 -0
  25. data/lib/rexpense/entities/attachment_collection.rb +14 -0
  26. data/lib/rexpense/entities/base.rb +9 -0
  27. data/lib/rexpense/entities/collection.rb +65 -0
  28. data/lib/rexpense/entities/comment.rb +13 -0
  29. data/lib/rexpense/entities/comment_collection.rb +14 -0
  30. data/lib/rexpense/entities/expense.rb +22 -0
  31. data/lib/rexpense/entities/expense_collection.rb +14 -0
  32. data/lib/rexpense/entities/membership.rb +10 -0
  33. data/lib/rexpense/entities/membership_collection.rb +14 -0
  34. data/lib/rexpense/entities/organization.rb +14 -0
  35. data/lib/rexpense/entities/organization_collection.rb +14 -0
  36. data/lib/rexpense/entities/pre_expense.rb +17 -0
  37. data/lib/rexpense/entities/pre_expense_collection.rb +14 -0
  38. data/lib/rexpense/entities/reimbursement.rb +14 -0
  39. data/lib/rexpense/entities/reimbursement_collection.rb +14 -0
  40. data/lib/rexpense/entities/tag.rb +8 -0
  41. data/lib/rexpense/entities/tag_collection.rb +14 -0
  42. data/lib/rexpense/entities/user.rb +14 -0
  43. data/lib/rexpense/entities/user_collection.rb +14 -0
  44. data/lib/rexpense/entities/webhook.rb +10 -0
  45. data/lib/rexpense/entities/webhook_collection.rb +14 -0
  46. data/lib/rexpense/exception.rb +11 -0
  47. data/lib/rexpense/http.rb +41 -0
  48. data/lib/rexpense/request.rb +56 -0
  49. data/lib/rexpense/resources/activity.rb +24 -0
  50. data/lib/rexpense/resources/advancement.rb +20 -0
  51. data/lib/rexpense/resources/advancement_devolution.rb +36 -0
  52. data/lib/rexpense/resources/base.rb +52 -0
  53. data/lib/rexpense/resources/expense.rb +39 -0
  54. data/lib/rexpense/resources/nested_endpoints/attachment.rb +48 -0
  55. data/lib/rexpense/resources/nested_endpoints/comment.rb +84 -0
  56. data/lib/rexpense/resources/nested_endpoints/membership.rb +74 -0
  57. data/lib/rexpense/resources/nested_endpoints/participant.rb +43 -0
  58. data/lib/rexpense/resources/organization.rb +31 -0
  59. data/lib/rexpense/resources/pre_expense.rb +56 -0
  60. data/lib/rexpense/resources/reimbursement.rb +20 -0
  61. data/lib/rexpense/resources/resource_base.rb +105 -0
  62. data/lib/rexpense/resources/tag.rb +82 -0
  63. data/lib/rexpense/resources/webhook.rb +82 -0
  64. data/lib/rexpense/response.rb +43 -0
  65. data/lib/rexpense/version.rb +3 -0
  66. data/lib/rexpense.rb +19 -0
  67. data/rexpense.gemspec +48 -0
  68. data/spec/lib/rexpense/client_spec.rb +47 -0
  69. data/spec/lib/rexpense/configuration_spec.rb +26 -0
  70. data/spec/lib/rexpense/entities/activity_collection_spec.rb +5 -0
  71. data/spec/lib/rexpense/entities/activity_spec.rb +9 -0
  72. data/spec/lib/rexpense/entities/advancement_collection_spec.rb +5 -0
  73. data/spec/lib/rexpense/entities/advancement_devolution_spec.rb +9 -0
  74. data/spec/lib/rexpense/entities/advancement_spec.rb +10 -0
  75. data/spec/lib/rexpense/entities/base_spec.rb +28 -0
  76. data/spec/lib/rexpense/entities/collection_spec.rb +70 -0
  77. data/spec/lib/rexpense/entities/comment_collection_spec.rb +5 -0
  78. data/spec/lib/rexpense/entities/comment_spec.rb +10 -0
  79. data/spec/lib/rexpense/entities/expense_collection_spec.rb +5 -0
  80. data/spec/lib/rexpense/entities/expense_spec.rb +14 -0
  81. data/spec/lib/rexpense/entities/membership_collection_spec.rb +5 -0
  82. data/spec/lib/rexpense/entities/membership_spec.rb +7 -0
  83. data/spec/lib/rexpense/entities/organization_collection_spec.rb +5 -0
  84. data/spec/lib/rexpense/entities/organization_spec.rb +8 -0
  85. data/spec/lib/rexpense/entities/pre_expense_collection_spec.rb +5 -0
  86. data/spec/lib/rexpense/entities/pre_expense_spec.rb +10 -0
  87. data/spec/lib/rexpense/entities/reimbursement_collection_spec.rb +5 -0
  88. data/spec/lib/rexpense/entities/reimbursement_spec.rb +10 -0
  89. data/spec/lib/rexpense/entities/user_collection_spec.rb +5 -0
  90. data/spec/lib/rexpense/entities/user_spec.rb +10 -0
  91. data/spec/lib/rexpense/entities/webhook_collection_spec.rb +5 -0
  92. data/spec/lib/rexpense/entities/webhook_spec.rb +7 -0
  93. data/spec/lib/rexpense/http_spec.rb +37 -0
  94. data/spec/lib/rexpense/request_spec.rb +29 -0
  95. data/spec/lib/rexpense/resources/activity_spec.rb +16 -0
  96. data/spec/lib/rexpense/resources/advancement_devolution_spec.rb +29 -0
  97. data/spec/lib/rexpense/resources/advancement_spec.rb +207 -0
  98. data/spec/lib/rexpense/resources/expense_spec.rb +227 -0
  99. data/spec/lib/rexpense/resources/organization_spec.rb +162 -0
  100. data/spec/lib/rexpense/resources/pre_expense_spec.rb +83 -0
  101. data/spec/lib/rexpense/resources/reimbursement_spec.rb +207 -0
  102. data/spec/lib/rexpense/resources/tag_specs.rb +77 -0
  103. data/spec/lib/rexpense/resources/webhook_spec.rb +51 -0
  104. data/spec/lib/rexpense/response_spec.rb +91 -0
  105. data/spec/lib/rexpense_spec.rb +34 -0
  106. data/spec/spec_helper.rb +39 -0
  107. data/spec/support/attachments/logo.png +0 -0
  108. data/spec/support/client.rb +3 -0
  109. data/spec/support/matchers/have_attr_accessor.rb +18 -0
  110. data/spec/support/shared_examples/entity_attributes.rb +9 -0
  111. data/spec/support/shared_examples/entity_collection.rb +19 -0
  112. data/spec/support/shared_examples/http_request_methods.rb +35 -0
  113. data/spec/support/vcr.rb +7 -0
  114. metadata +390 -0
@@ -0,0 +1,65 @@
1
+ module Rexpense
2
+ module Entities
3
+ #
4
+ # A wrapper to Rexpense collection returns from API.
5
+ # This wrapper represents a collection and it's responsible for
6
+ # processing pagination information as well.
7
+ #
8
+ class Collection < Base
9
+ PAGE_REGEX = /page=(\d+)/
10
+
11
+ attr_reader :response, :collection, :headers
12
+
13
+ def initialize(response)
14
+ @response = response
15
+ @collection = []
16
+ @headers = begin
17
+ response.headers["Link"].split(",")
18
+ rescue
19
+ []
20
+ end
21
+ end
22
+
23
+ def self.build(response)
24
+ new(response).build
25
+ end
26
+
27
+ def build
28
+ build_collection
29
+ self
30
+ end
31
+
32
+ def next_page
33
+ page_for(:next)
34
+ end
35
+
36
+ def last_page
37
+ page_for(:last)
38
+ end
39
+
40
+ def previous_page
41
+ page_for(:prev)
42
+ end
43
+
44
+ def first_page
45
+ page_for(:first)
46
+ end
47
+
48
+ private
49
+
50
+ def page_for(page_rel)
51
+ header_link_for(page_rel).match(PAGE_REGEX)[1].to_i
52
+ rescue
53
+ nil
54
+ end
55
+
56
+ def header_link_for(rel)
57
+ headers.select { |n| n =~ /rel=#{rel}/ }.first
58
+ end
59
+
60
+ def build_collection
61
+ raise NotImplementedError
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,13 @@
1
+ module Rexpense
2
+ module Entities
3
+ class Comment < Base
4
+ attribute :id, Integer
5
+ attribute :content, String
6
+ attribute :content_html, String
7
+ attribute :mentioned_users, Array[Rexpense::Entities::User]
8
+ attribute :user, Rexpense::Entities::User
9
+
10
+ [:created_at, :updated_at, :deleted_at].each { |n| attribute n, DateTime }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module Rexpense
2
+ module Entities
3
+ #
4
+ # A wrapper to Comment collection
5
+ #
6
+ class CommentCollection < Collection
7
+ def build_collection
8
+ response.parsed_body['comments'].each do |attributes|
9
+ collection.push(Rexpense::Entities::Comment.new(attributes))
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ module Rexpense
2
+ module Entities
3
+ class Expense < Base
4
+ [:id, :attachments_count, :comments_count, :activities_count,
5
+ :travel_time, :pre_expense_id].each { |n| attribute n, Integer }
6
+
7
+ [:description, :currency, :approved_amount_currency, :kind, :status,
8
+ :distance_kind, :destination, :origin].each { |n| attribute n, String }
9
+
10
+ [:amount, :approved_amount, :latitude, :longitude, :distance,
11
+ :destination_latitude, :destination_longitude, :origin_longitude,
12
+ :origin_latitude].each { |n| attribute n, Decimal }
13
+
14
+ attribute :tags, Array[String]
15
+ attribute :payer, Rexpense::Entities::Organization
16
+ attribute :receiver, Rexpense::Entities::User
17
+ attribute :liquidate_through_advancement, Boolean
18
+ attribute :created_at, DateTime
19
+ attribute :updated_at, DateTime
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module Rexpense
2
+ module Entities
3
+ #
4
+ # A wrapper to Expense collection
5
+ #
6
+ class ExpenseCollection < Collection
7
+ def build_collection
8
+ response.parsed_body['expenses'].each do |attributes|
9
+ collection.push(Rexpense::Entities::Expense.new(attributes))
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ module Rexpense
2
+ module Entities
3
+ class Membership < Base
4
+ attribute :id, Integer
5
+ attribute :role, String
6
+ attribute :organization, Rexpense::Entities::Organization
7
+ attribute :user, Rexpense::Entities::User
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ module Rexpense
2
+ module Entities
3
+ #
4
+ # A wrapper to Membership collection
5
+ #
6
+ class MembershipCollection < Collection
7
+ def build_collection
8
+ response.parsed_body['memberships'].each do |attributes|
9
+ collection.push(Rexpense::Entities::Membership.new(attributes))
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Rexpense
2
+ module Entities
3
+ class Organization < Base
4
+ attribute :id, Integer
5
+ attribute :name, String
6
+ attribute :restricted_tags, Boolean
7
+ attribute :expired, Boolean
8
+ attribute :members_count, Integer
9
+ attribute :logo, Array[Hash]
10
+
11
+ [:created_at, :updated_at].each { |n| attribute n, String }
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Rexpense
2
+ module Entities
3
+ #
4
+ # A wrapper to Organization collection
5
+ #
6
+ class OrganizationCollection < Collection
7
+ def build_collection
8
+ response.parsed_body['organizations'].each do |attributes|
9
+ collection.push(Rexpense::Entities::Organization.new(attributes))
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ module Rexpense
2
+ module Entities
3
+ class PreExpense < Base
4
+ attribute :id, Integer
5
+ attribute :amount, Decimal
6
+
7
+ [:description, :currency].each { |n| attribute n, String }
8
+
9
+ [:created_at, :converted_at, :updated_at,
10
+ :ignored_at, :occurred_at].each { |n| attribute n, String }
11
+
12
+ attribute :tags, Array[String]
13
+ attribute :payer, Rexpense::Entities::Organization
14
+ attribute :receiver, Rexpense::Entities::User
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module Rexpense
2
+ module Entities
3
+ #
4
+ # A wrapper to PreExpense collection
5
+ #
6
+ class PreExpenseCollection < Collection
7
+ def build_collection
8
+ response.parsed_body['pre_expenses'].each do |attributes|
9
+ collection.push(Rexpense::Entities::PreExpense.new(attributes))
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Rexpense
2
+ module Entities
3
+ class Reimbursement < Base
4
+ [:id, :comments_count, :activities_count].each { |n| attribute n, Integer }
5
+ [:description, :currency].each { |n| attribute n, String }
6
+ attribute :amount, Decimal
7
+ attribute :tags, Array[String]
8
+ attribute :created_at, DateTime
9
+ attribute :updated_at, DateTime
10
+ attribute :payer, Rexpense::Entities::Organization
11
+ attribute :receiver, Rexpense::Entities::User
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Rexpense
2
+ module Entities
3
+ #
4
+ # A wrapper to Reimbursement collection
5
+ #
6
+ class ReimbursementCollection < Collection
7
+ def build_collection
8
+ response.parsed_body['reimbursements'].each do |attributes|
9
+ collection.push(Rexpense::Entities::Reimbursement.new(attributes))
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,8 @@
1
+ module Rexpense
2
+ module Entities
3
+ class Tag < Base
4
+ attribute :id, Integer
5
+ attribute :name, String
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,14 @@
1
+ module Rexpense
2
+ module Entities
3
+ #
4
+ # A wrapper to Tag collection
5
+ #
6
+ class TagCollection < Collection
7
+ def build_collection
8
+ response.parsed_body['tags'].each do |attributes|
9
+ collection.push(Rexpense::Entities::Tag.new(attributes))
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Rexpense
2
+ module Entities
3
+ class User < Base
4
+ attribute :id, Integer
5
+ attribute :first_name, String
6
+ attribute :last_name, String
7
+ attribute :mention_name, String
8
+ attribute :default_currency, String
9
+ attribute :name, String
10
+ attribute :avatar, Array[Hash]
11
+ attribute :default_avatar, Boolean
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Rexpense
2
+ module Entities
3
+ #
4
+ # A wrapper to Tag collection
5
+ #
6
+ class UserCollection < Collection
7
+ def build_collection
8
+ response.parsed_body['participants'].each do |attributes|
9
+ collection.push(Rexpense::Entities::User.new(attributes))
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ module Rexpense
2
+ module Entities
3
+ class Webhook < Base
4
+ attribute :id, Integer
5
+ attribute :url, String
6
+ attribute :description, String
7
+ attribute :secret, String
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ module Rexpense
2
+ module Entities
3
+ #
4
+ # A wrapper to Webhooks collection
5
+ #
6
+ class WebhookCollection < Collection
7
+ def build_collection
8
+ response.parsed_body['webhooks'].each do |attributes|
9
+ collection.push(Rexpense::Entities::Webhook.new(attributes))
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ module Rexpense
2
+ class Exception < StandardError
3
+ attr_accessor :code, :body
4
+
5
+ def initialize(args = {})
6
+ super(args[:message])
7
+ @code = args[:code]
8
+ @body = args[:body]
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,41 @@
1
+ require "rexpense/request"
2
+ require "rexpense/response"
3
+
4
+ module Rexpense
5
+ class Http
6
+ attr_reader :token, :base_url
7
+
8
+ SANDBOX_URL = "https://sandbox.rexpense.com/api"
9
+ PRODUCTION_URL = "https://app.rexpense.com/api"
10
+
11
+ def initialize(token)
12
+ @token = token
13
+ @base_url = api_url + "/#{Rexpense.configuration.version}"
14
+ end
15
+
16
+ %w[get post delete put patch].each do |m|
17
+ define_method(m) do |path, options = {}, &block|
18
+ send_request(m.to_sym, path, options, &block)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def api_url
25
+ return PRODUCTION_URL if Rexpense.configuration.api_mode == 'production'
26
+ SANDBOX_URL
27
+ end
28
+
29
+ def send_request(method, path, options, &block)
30
+ request = Request.new(
31
+ options.merge!(
32
+ method: method,
33
+ token: token,
34
+ url: "#{base_url}#{path}",
35
+ user_agent: Rexpense.configuration.user_agent
36
+ )
37
+ )
38
+ Response.new(request.run).resolve!(&block)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,56 @@
1
+ module Rexpense
2
+ class Request
3
+ def initialize(args)
4
+ @args = args
5
+ end
6
+
7
+ def run
8
+ request.run
9
+ request.response
10
+ end
11
+
12
+ private
13
+
14
+ attr_reader :args
15
+
16
+ def request
17
+ @request ||= Typhoeus::Request.new(args[:url], options)
18
+ end
19
+
20
+ def options
21
+ {
22
+ method: args[:method],
23
+ params: args[:params],
24
+ body: body,
25
+ headers: headers,
26
+ accept_encoding: "gzip",
27
+ params_encoding: :rack
28
+ }.reject { |_k, v| v.nil? }
29
+ end
30
+
31
+ def headers
32
+ headers = args.fetch(:headers) { {} }
33
+
34
+ {
35
+ "Accept" => "application/json",
36
+ "Content-Type" => content_type,
37
+ "User-Agent" => args[:user_agent],
38
+ "Authorization" => "Basic #{authorization_hash}"
39
+ }.merge(headers).delete_if { |_, v| v.nil? || v.to_s.empty? }
40
+ end
41
+
42
+ def body
43
+ body = args[:body]
44
+ body = JSON.dump(body) if body.is_a?(Hash) && !args[:multipart]
45
+ body
46
+ end
47
+
48
+ def authorization_hash
49
+ ::Base64.strict_encode64("#{args[:token]}:X")
50
+ end
51
+
52
+ def content_type
53
+ args[:multipart] ? nil : "application/json"
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,24 @@
1
+ module Rexpense
2
+ module Resources
3
+ #
4
+ # A wrapper to Rexpense activity API
5
+ #
6
+ # [API]
7
+ # Documentation: http://developers.rexpense.com/api/v1/activities/
8
+ #
9
+ class Activity < Base
10
+ #
11
+ # Get user activities
12
+ #
13
+ # [API]
14
+ # Method: <tt>GET /api/v1/activities</tt>
15
+ #
16
+ # Documentation: http://developers.rexpense.com/api/activities#index
17
+ def find_all
18
+ http.get('/activities') do |response|
19
+ Rexpense::Entities::ActivityCollection.build response
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ module Rexpense
2
+ module Resources
3
+ #
4
+ # A wrapper to Rexpense advancements API
5
+ #
6
+ # [API]
7
+ # Documentation: http://developers.rexpense.com/api/v1/advancements/
8
+ #
9
+ class Advancement < ResourceBase
10
+ include Rexpense::Resources::Comment
11
+ include Rexpense::Resources::Participant
12
+
13
+ private
14
+
15
+ def endpoint_base
16
+ "/advancements"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,36 @@
1
+ module Rexpense
2
+ module Resources
3
+ #
4
+ # A wrapper to Rexpense advancement_devolutions API
5
+ #
6
+ # [API]
7
+ # Documentation: http://developers.rexpense.com/api/v1/advancement_devolutions/
8
+ #
9
+ class AdvancementDevolution < Base
10
+
11
+ #
12
+ # Create a resource
13
+ #
14
+ # [API]
15
+ # Method: <tt>POST /api/v1/expenses</tt>
16
+ # Method: <tt>POST /api/v1/advancements</tt>
17
+ # Method: <tt>POST /api/v1/reimbursements</tt>
18
+ #
19
+ # Documentation: http://developers.rexpense.com/api/v1/expenses/#create
20
+ # Documentation: http://developers.rexpense.com/api/v1/advancements/#create
21
+ # Documentation: http://developers.rexpense.com/api/v1/reimbursements/#create
22
+ #
23
+ def create(params)
24
+ http.post("#{endpoint_base}", body: params) do |response|
25
+ respond_with_object response
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def endpoint_base
32
+ "/advancement_devolutions"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,52 @@
1
+ module Rexpense
2
+ module Resources
3
+ class Base
4
+
5
+ attr_accessor :http
6
+
7
+ def initialize(http)
8
+ @http = http
9
+ end
10
+
11
+ private
12
+
13
+ def build_search_endpoint(params)
14
+ return URI.encode("#{endpoint_base}") if params.empty?
15
+ query_string = uri_query(params).join("&")
16
+ URI.encode("#{endpoint_base}?#{query_string}")
17
+ end
18
+
19
+ def uri_query(params)
20
+ page = params.delete(:page)
21
+ query = []
22
+ params.each { |k, v| query += query_value(k, v) }
23
+ query << "page=#{page}" if page
24
+ query
25
+ end
26
+
27
+ def query_value(key, value)
28
+ [].tap do |query|
29
+ if value.is_a?(Array)
30
+ value.each { |v| query << "q[#{key}][]=#{v}" }
31
+ else
32
+ query << "q[#{key}]=#{value}"
33
+ end
34
+ end
35
+ end
36
+
37
+ def respond_with_collection(response)
38
+ collection_klass = Rexpense::Entities.const_get("#{entity_klass_name}Collection")
39
+ collection_klass.build(response)
40
+ end
41
+
42
+ def respond_with_object(response, key=nil)
43
+ entity_klass = Rexpense::Entities.const_get(entity_klass_name)
44
+ entity_klass.new(response.parsed_body(key))
45
+ end
46
+
47
+ def entity_klass_name
48
+ self.class.to_s.gsub("Resources", "Entities")
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,39 @@
1
+ module Rexpense
2
+ module Resources
3
+ #
4
+ # A wrapper to Rexpense expenses API
5
+ #
6
+ # [API]
7
+ # Documentation: http://developers.rexpense.com/api/v1/expenses/
8
+ #
9
+ class Expense < ResourceBase
10
+ include Rexpense::Resources::Comment
11
+ include Rexpense::Resources::Participant
12
+ include Rexpense::Resources::Attachment
13
+
14
+ def status(id)
15
+ http.get("#{search_endpoint}/#{id}/status") do |response|
16
+ Rexpense::Entities::ExpenseStatus.new response.parsed_body
17
+ end
18
+ end
19
+
20
+ def update_status(id, params)
21
+ http.put("#{search_endpoint}/#{id}/status", body: params) do |response|
22
+ Rexpense::Entities::ExpenseStatus.new response.parsed_body
23
+ end
24
+ end
25
+
26
+ def mentionables(id)
27
+ http.get("#{endpoint_base}/#{id}/mentionables") do |response|
28
+ Rexpense::Entities::UserCollection.build response.parsed_body
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def endpoint_base
35
+ "/expenses"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,48 @@
1
+ module Rexpense::Resources
2
+ module Attachment
3
+ #
4
+ # Get resource attachments
5
+ #
6
+ # [API]
7
+ # Method: <tt>GET /api/v1/expenses/:id/attachments</tt>
8
+ #
9
+ # Documentation: http://developers.rexpense.com/api/attachments#index
10
+ def attachments(resource_id)
11
+ http.get(attachment_endpoint(resource_id)) do |response|
12
+ Rexpense::Entities::AttachmentCollection.build response
13
+ end
14
+ end
15
+
16
+ #
17
+ # Get resource attachment
18
+ #
19
+ # [API]
20
+ # Method: <tt>GET /api/v1/expenses/:id/attachments/:id</tt>
21
+ #
22
+ # Documentation: http://developers.rexpense.com/api/attachments#show
23
+ def find_attachment(resource_id, attachment_id)
24
+ http.get("#{attachment_endpoint(resource_id)}/#{attachment_id}") do |response|
25
+ Rexpense::Entities::Attachment.new response.parsed_body
26
+ end
27
+ end
28
+
29
+ #
30
+ # Destroy resource attachment
31
+ #
32
+ # [API]
33
+ # Method: <tt>DELETE /api/v1/expenses/:id/attachments/:id</tt>
34
+ #
35
+ # Documentation: http://developers.rexpense.com/api/attachments#show
36
+ def destroy_attachment(resource_id, attachment_id)
37
+ http.delete("#{attachment_endpoint(resource_id)}/#{attachment_id}") do |response|
38
+ true
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def attachment_endpoint(resource_id)
45
+ "#{endpoint_base}/#{resource_id}/attachments"
46
+ end
47
+ end
48
+ end