rexpense 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +22 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/.rubocop.yml +54 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +97 -0
- data/LICENSE.txt +21 -0
- data/README.md +195 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/rspec +21 -0
- data/bin/setup +7 -0
- data/lib/rexpense/client.rb +39 -0
- data/lib/rexpense/configuration.rb +13 -0
- data/lib/rexpense/entities/activity.rb +11 -0
- data/lib/rexpense/entities/activity_collection.rb +14 -0
- data/lib/rexpense/entities/advancement.rb +14 -0
- data/lib/rexpense/entities/advancement_collection.rb +14 -0
- data/lib/rexpense/entities/advancement_devolution.rb +13 -0
- data/lib/rexpense/entities/attachment.rb +13 -0
- data/lib/rexpense/entities/attachment_collection.rb +14 -0
- data/lib/rexpense/entities/base.rb +9 -0
- data/lib/rexpense/entities/collection.rb +65 -0
- data/lib/rexpense/entities/comment.rb +13 -0
- data/lib/rexpense/entities/comment_collection.rb +14 -0
- data/lib/rexpense/entities/expense.rb +22 -0
- data/lib/rexpense/entities/expense_collection.rb +14 -0
- data/lib/rexpense/entities/membership.rb +10 -0
- data/lib/rexpense/entities/membership_collection.rb +14 -0
- data/lib/rexpense/entities/organization.rb +14 -0
- data/lib/rexpense/entities/organization_collection.rb +14 -0
- data/lib/rexpense/entities/pre_expense.rb +17 -0
- data/lib/rexpense/entities/pre_expense_collection.rb +14 -0
- data/lib/rexpense/entities/reimbursement.rb +14 -0
- data/lib/rexpense/entities/reimbursement_collection.rb +14 -0
- data/lib/rexpense/entities/tag.rb +8 -0
- data/lib/rexpense/entities/tag_collection.rb +14 -0
- data/lib/rexpense/entities/user.rb +14 -0
- data/lib/rexpense/entities/user_collection.rb +14 -0
- data/lib/rexpense/entities/webhook.rb +10 -0
- data/lib/rexpense/entities/webhook_collection.rb +14 -0
- data/lib/rexpense/exception.rb +11 -0
- data/lib/rexpense/http.rb +41 -0
- data/lib/rexpense/request.rb +56 -0
- data/lib/rexpense/resources/activity.rb +24 -0
- data/lib/rexpense/resources/advancement.rb +20 -0
- data/lib/rexpense/resources/advancement_devolution.rb +36 -0
- data/lib/rexpense/resources/base.rb +52 -0
- data/lib/rexpense/resources/expense.rb +39 -0
- data/lib/rexpense/resources/nested_endpoints/attachment.rb +48 -0
- data/lib/rexpense/resources/nested_endpoints/comment.rb +84 -0
- data/lib/rexpense/resources/nested_endpoints/membership.rb +74 -0
- data/lib/rexpense/resources/nested_endpoints/participant.rb +43 -0
- data/lib/rexpense/resources/organization.rb +31 -0
- data/lib/rexpense/resources/pre_expense.rb +56 -0
- data/lib/rexpense/resources/reimbursement.rb +20 -0
- data/lib/rexpense/resources/resource_base.rb +105 -0
- data/lib/rexpense/resources/tag.rb +82 -0
- data/lib/rexpense/resources/webhook.rb +82 -0
- data/lib/rexpense/response.rb +43 -0
- data/lib/rexpense/version.rb +3 -0
- data/lib/rexpense.rb +19 -0
- data/rexpense.gemspec +48 -0
- data/spec/lib/rexpense/client_spec.rb +47 -0
- data/spec/lib/rexpense/configuration_spec.rb +26 -0
- data/spec/lib/rexpense/entities/activity_collection_spec.rb +5 -0
- data/spec/lib/rexpense/entities/activity_spec.rb +9 -0
- data/spec/lib/rexpense/entities/advancement_collection_spec.rb +5 -0
- data/spec/lib/rexpense/entities/advancement_devolution_spec.rb +9 -0
- data/spec/lib/rexpense/entities/advancement_spec.rb +10 -0
- data/spec/lib/rexpense/entities/base_spec.rb +28 -0
- data/spec/lib/rexpense/entities/collection_spec.rb +70 -0
- data/spec/lib/rexpense/entities/comment_collection_spec.rb +5 -0
- data/spec/lib/rexpense/entities/comment_spec.rb +10 -0
- data/spec/lib/rexpense/entities/expense_collection_spec.rb +5 -0
- data/spec/lib/rexpense/entities/expense_spec.rb +14 -0
- data/spec/lib/rexpense/entities/membership_collection_spec.rb +5 -0
- data/spec/lib/rexpense/entities/membership_spec.rb +7 -0
- data/spec/lib/rexpense/entities/organization_collection_spec.rb +5 -0
- data/spec/lib/rexpense/entities/organization_spec.rb +8 -0
- data/spec/lib/rexpense/entities/pre_expense_collection_spec.rb +5 -0
- data/spec/lib/rexpense/entities/pre_expense_spec.rb +10 -0
- data/spec/lib/rexpense/entities/reimbursement_collection_spec.rb +5 -0
- data/spec/lib/rexpense/entities/reimbursement_spec.rb +10 -0
- data/spec/lib/rexpense/entities/user_collection_spec.rb +5 -0
- data/spec/lib/rexpense/entities/user_spec.rb +10 -0
- data/spec/lib/rexpense/entities/webhook_collection_spec.rb +5 -0
- data/spec/lib/rexpense/entities/webhook_spec.rb +7 -0
- data/spec/lib/rexpense/http_spec.rb +37 -0
- data/spec/lib/rexpense/request_spec.rb +29 -0
- data/spec/lib/rexpense/resources/activity_spec.rb +16 -0
- data/spec/lib/rexpense/resources/advancement_devolution_spec.rb +29 -0
- data/spec/lib/rexpense/resources/advancement_spec.rb +207 -0
- data/spec/lib/rexpense/resources/expense_spec.rb +227 -0
- data/spec/lib/rexpense/resources/organization_spec.rb +162 -0
- data/spec/lib/rexpense/resources/pre_expense_spec.rb +83 -0
- data/spec/lib/rexpense/resources/reimbursement_spec.rb +207 -0
- data/spec/lib/rexpense/resources/tag_specs.rb +77 -0
- data/spec/lib/rexpense/resources/webhook_spec.rb +51 -0
- data/spec/lib/rexpense/response_spec.rb +91 -0
- data/spec/lib/rexpense_spec.rb +34 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/support/attachments/logo.png +0 -0
- data/spec/support/client.rb +3 -0
- data/spec/support/matchers/have_attr_accessor.rb +18 -0
- data/spec/support/shared_examples/entity_attributes.rb +9 -0
- data/spec/support/shared_examples/entity_collection.rb +19 -0
- data/spec/support/shared_examples/http_request_methods.rb +35 -0
- data/spec/support/vcr.rb +7 -0
- 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,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,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,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,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
|