intacct_ruby_team 1.7.1

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 (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +179 -0
  10. data/Rakefile +6 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/intacct_ruby.gemspec +36 -0
  14. data/lib/intacct_ruby.rb +27 -0
  15. data/lib/intacct_ruby/api.rb +31 -0
  16. data/lib/intacct_ruby/exceptions/empty_request_exception.rb +5 -0
  17. data/lib/intacct_ruby/exceptions/function_failure_exception.rb +5 -0
  18. data/lib/intacct_ruby/exceptions/insufficient_credentials_exception.rb +5 -0
  19. data/lib/intacct_ruby/exceptions/unknown_function_type.rb +5 -0
  20. data/lib/intacct_ruby/function.rb +92 -0
  21. data/lib/intacct_ruby/functions/base_function.rb +48 -0
  22. data/lib/intacct_ruby/functions/create_aradjustment.rb +48 -0
  23. data/lib/intacct_ruby/functions/create_customer.rb +23 -0
  24. data/lib/intacct_ruby/functions/create_employee.rb +21 -0
  25. data/lib/intacct_ruby/functions/create_gltransaction.rb +28 -0
  26. data/lib/intacct_ruby/functions/create_item.rb +21 -0
  27. data/lib/intacct_ruby/functions/create_location.rb +21 -0
  28. data/lib/intacct_ruby/functions/create_project.rb +20 -0
  29. data/lib/intacct_ruby/functions/create_statgltransaction.rb +28 -0
  30. data/lib/intacct_ruby/functions/customer_base_function.rb +27 -0
  31. data/lib/intacct_ruby/functions/employee_base_function.rb +36 -0
  32. data/lib/intacct_ruby/functions/gltransaction_base_function.rb +64 -0
  33. data/lib/intacct_ruby/functions/item_base_function.rb +29 -0
  34. data/lib/intacct_ruby/functions/location_base_function.rb +24 -0
  35. data/lib/intacct_ruby/functions/project_base_function.rb +22 -0
  36. data/lib/intacct_ruby/functions/update_customer.rb +22 -0
  37. data/lib/intacct_ruby/functions/update_employee.rb +20 -0
  38. data/lib/intacct_ruby/functions/update_item.rb +20 -0
  39. data/lib/intacct_ruby/functions/update_location.rb +20 -0
  40. data/lib/intacct_ruby/functions/update_project.rb +20 -0
  41. data/lib/intacct_ruby/helpers/contacts_helper.rb +32 -0
  42. data/lib/intacct_ruby/helpers/date_helper.rb +22 -0
  43. data/lib/intacct_ruby/request.rb +138 -0
  44. data/lib/intacct_ruby/response.rb +43 -0
  45. data/lib/intacct_ruby/version.rb +3 -0
  46. metadata +205 -0
@@ -0,0 +1,64 @@
1
+ require 'intacct_ruby/functions/base_function'
2
+ require 'intacct_ruby/helpers/date_helper'
3
+
4
+ module IntacctRuby
5
+ module Functions
6
+ # creates gltransaction instance in Intacct
7
+ class GLTransactionBaseFunction < BaseFunction
8
+ include DateHelper
9
+
10
+ private
11
+
12
+ def gltransaction_header_params(attributes)
13
+ xml = Builder::XmlMarkup.new
14
+
15
+ xml << extract_from_attrs(attributes, :journalid)
16
+ xml << date_params(:datecreated, attributes[:datecreated])
17
+ xml << extract_from_attrs(attributes, :description)
18
+
19
+ xml.target!
20
+ end
21
+
22
+ def gltransactionentry_params(transaction_entries)
23
+ xml = Builder::XmlMarkup.new
24
+
25
+ transaction_entries.each do |entry_attrs|
26
+ xml << glentry_params(entry_attrs)
27
+ end
28
+
29
+ xml.target!
30
+ end
31
+
32
+ def glentry_params(attrs)
33
+ xml = Builder::XmlMarkup.new
34
+
35
+ xml.glentry do
36
+ xml << extract_from_attrs(attrs, :trtype, :amount, :glaccountno)
37
+ xml << date_params(:datecreated, attrs[:datecreated])
38
+ xml << extract_from_attrs(
39
+ attrs,
40
+ :memo,
41
+ :locationid,
42
+ :customerid,
43
+ :employeeid,
44
+ :projectid,
45
+ :itemid
46
+ )
47
+ end
48
+
49
+ xml.target!
50
+ end
51
+
52
+ def extract_from_attrs(attributes_hash, *keys)
53
+ xml = Builder::XmlMarkup.new
54
+
55
+ keys.each do |key|
56
+ value = attributes_hash[key]
57
+ xml.tag!(key) { xml << value.to_s } if value
58
+ end
59
+
60
+ xml.target!
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,29 @@
1
+ require 'intacct_ruby/functions/base_function'
2
+
3
+ module IntacctRuby
4
+ module Functions
5
+ # function that all item functions are built off of, to decreate dupe code
6
+ class ItemBaseFunction < BaseFunction
7
+ ALL_PARAMS = [
8
+ :name,
9
+ :itemtype,
10
+ :extended_description,
11
+ :productlineid,
12
+ :standard_cost,
13
+ :glgroup,
14
+ :uomgrp
15
+ ].freeze
16
+
17
+ def item_params
18
+ xml = Builder::XmlMarkup.new
19
+
20
+ ALL_PARAMS.each do |param_name|
21
+ param_value = @attrs[param_name]
22
+ xml.tag!(param_name) { xml << param_value } if param_value
23
+ end
24
+
25
+ xml.target!
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ require 'intacct_ruby/functions/base_function'
2
+ require 'intacct_ruby/helpers/date_helper'
3
+
4
+ module IntacctRuby
5
+ module Functions
6
+ # base for all location-related functions, to cut down on duplicate code
7
+ class LocationBaseFunction < BaseFunction
8
+ include IntacctRuby::DateHelper
9
+
10
+ private
11
+
12
+ def location_params
13
+ xml = Builder::XmlMarkup.new
14
+
15
+ xml.name @attrs[:name]
16
+ xml.parentid @attrs[:parentid]
17
+
18
+ xml << start_date_params
19
+
20
+ xml.target!
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ require 'intacct_ruby/functions/base_function'
2
+
3
+ module IntacctRuby
4
+ module Functions
5
+ # contains shared code for creating and updating projects
6
+ class ProjectBaseFunction < BaseFunction
7
+ private
8
+
9
+ def project_params
10
+ xml = Builder::XmlMarkup.new
11
+
12
+ [:projectid, :name, :projectcategory, :customerid].each do |key|
13
+ xml.tag!(key.to_s) { xml << @attrs[key].to_s }
14
+ end
15
+
16
+ xml << custom_field_params(@attrs[:customfields])
17
+
18
+ xml.target!
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require 'intacct_ruby/functions/customer_base_function'
2
+
3
+ module IntacctRuby
4
+ module Functions
5
+ # update customer instance
6
+ class UpdateCustomer < CustomerBaseFunction
7
+ include ContactsHelper
8
+
9
+ def initialize(attrs = {})
10
+ super "update_customer_#{attrs[:customerid]} (#{timestamp})", attrs
11
+ end
12
+
13
+ def to_xml
14
+ super do |xml|
15
+ xml.update_customer customerid: @attrs[:customerid] do
16
+ xml << customer_params
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ require 'intacct_ruby/functions/employee_base_function'
2
+
3
+ module IntacctRuby
4
+ module Functions
5
+ # function used to update employee instances
6
+ class UpdateEmployee < EmployeeBaseFunction
7
+ def initialize(attrs = {})
8
+ super("update_employee_#{attrs[:employeeid]} (#{timestamp})", attrs)
9
+ end
10
+
11
+ def to_xml
12
+ super do |xml|
13
+ xml.update_employee employeeid: @attrs[:employeeid] do
14
+ xml << employee_params
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'intacct_ruby/functions/item_base_function'
2
+
3
+ module IntacctRuby
4
+ module Functions
5
+ # updates item instance in Intacct
6
+ class UpdateItem < ItemBaseFunction
7
+ def initialize(attrs = {})
8
+ super "update_item_#{attrs[:itemid]} (#{timestamp})", attrs
9
+ end
10
+
11
+ def to_xml
12
+ super do |xml|
13
+ xml.update_item itemid: @attrs[:itemid] do
14
+ xml << item_params
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'intacct_ruby/functions/location_base_function'
2
+
3
+ module IntacctRuby
4
+ module Functions
5
+ # used to update location instances in Intacct
6
+ class UpdateLocation < LocationBaseFunction
7
+ def initialize(attrs = {})
8
+ super("update_location_#{attrs[:locationid]} (#{timestamp})", attrs)
9
+ end
10
+
11
+ def to_xml
12
+ super do |xml|
13
+ xml.update_location locationid: @attrs[:locationid] do
14
+ xml << location_params
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'intacct_ruby/functions/project_base_function'
2
+
3
+ module IntacctRuby
4
+ module Functions
5
+ # creates a project instance in Intacct
6
+ class UpdateProject < ProjectBaseFunction
7
+ def initialize(attrs = {})
8
+ super("update_project_#{attrs[:projectid]} (#{timestamp})", attrs)
9
+ end
10
+
11
+ def to_xml
12
+ super do |xml|
13
+ xml.update_project key: @attrs[:projectid] do
14
+ xml << project_params
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,32 @@
1
+ module IntacctRuby
2
+ # methods to avoid duplication when creating and updating contact records
3
+ module ContactsHelper
4
+ def contact_params(attributes, id, person_type)
5
+ xml = Builder::XmlMarkup.new
6
+
7
+ name = full_name(attributes)
8
+
9
+ xml.contact do
10
+ xml.contactname contactname(name, id, person_type)
11
+ xml.printas full_name(attributes)
12
+ xml.firstname attributes[:first_name]
13
+ xml.lastname attributes[:last_name]
14
+ xml.email1 attributes[:email1]
15
+ end
16
+
17
+ xml.target!
18
+ end
19
+
20
+ def contactname(name, id, person_type)
21
+ # a unique identifier for a contact, to be used for Intacct's
22
+ # contactname field. Person Type required to ensure that there aren't
23
+ # duplicates (e.g. a customer and employee w/ ID 1 both named
24
+ # 'John Smith')
25
+ "#{name} (#{person_type} \##{id})"
26
+ end
27
+
28
+ def full_name(attrs = {})
29
+ "#{attrs[:first_name]} #{attrs[:last_name]}"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ require 'builder'
2
+
3
+ module IntacctRuby
4
+ # methods to help generate date XML for calls
5
+ module DateHelper
6
+ def date_params(block_name, attrs = {})
7
+ xml = Builder::XmlMarkup.new
8
+
9
+ xml.tag!(block_name) do
10
+ xml.year attrs[:year]
11
+ xml.month attrs[:month]
12
+ xml.day attrs[:day]
13
+ end
14
+ end
15
+
16
+ # Note: @attrs[:startdate] MUST be defined in the invoking context for this
17
+ # bad boy to work
18
+ def start_date_params
19
+ date_params :startdate, @attrs[:startdate]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,138 @@
1
+ require 'builder'
2
+
3
+ require 'intacct_ruby/api'
4
+ require 'intacct_ruby/response'
5
+ require 'intacct_ruby/function'
6
+
7
+ require 'intacct_ruby/exceptions/insufficient_credentials_exception'
8
+ require 'intacct_ruby/exceptions/empty_request_exception'
9
+
10
+ module IntacctRuby
11
+ # An outgoing request to the Intacct API. Can have multiple functions.
12
+ # Complete with send method that gets (and wraps) response from Intacct.
13
+ class Request
14
+ attr_reader :functions
15
+
16
+ DEFAULTS = {
17
+ uniqueid: false,
18
+ dtdversion: 3.0,
19
+ includewhitespace: false,
20
+ transaction: true
21
+ }.freeze
22
+
23
+ REQUIRED_AUTHENTICATION_KEYS = [
24
+ :senderid,
25
+ :sender_password,
26
+ :userid,
27
+ :companyid,
28
+ :user_password
29
+ ].freeze
30
+
31
+ def initialize(*functions, request_params)
32
+ # request_params should contain all req'd authentication information. If
33
+ # not, an error will be thrown on #send
34
+ @opts = DEFAULTS.dup.merge request_params
35
+
36
+ # If a hash is provided + popped, the remaining attrs are functions
37
+ @functions = functions
38
+ end
39
+
40
+ def to_xml
41
+ @to_xml ||= begin
42
+ @request = Builder::XmlMarkup.new
43
+
44
+ @request.instruct!
45
+ @request.request do
46
+ control_block
47
+ operation_block
48
+ end
49
+ end
50
+ end
51
+
52
+ def send(opts = {})
53
+ if opts.is_a? Hash
54
+ api = opts[:api] || Api.new
55
+
56
+ validate_keys!
57
+ validate_functions!
58
+
59
+ Response.new api.send_request(self)
60
+ else
61
+ # so that Request#send can play nice alongside Object#send
62
+ super
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def method_missing(method_name, *arguments, &block)
69
+ super unless Function::ALLOWED_TYPES.include? method_name.to_s
70
+
71
+ # object_type must be the first argument in arguments
72
+ @functions << Function.new(method_name, arguments.shift, *arguments)
73
+ end
74
+
75
+ def respond_to_missing?(method_name, include_private = false)
76
+ Function::ALLOWED_TYPES.include?(method_name) || super
77
+ end
78
+
79
+ def validate_functions!
80
+ unless functions.any?
81
+ raise Exceptions::EmptyRequestException,
82
+ 'a successful request must contain at least one function'
83
+ end
84
+ end
85
+
86
+ def validate_keys!
87
+ missing_keys = REQUIRED_AUTHENTICATION_KEYS - @opts.keys
88
+
89
+ unless missing_keys.empty?
90
+ missing_keys.map! { |s| ":#{s}" } # so they appear as symbols in output
91
+
92
+ raise Exceptions::InsufficientCredentialsException,
93
+ "[#{missing_keys.join(', ')}] required for a valid request. "
94
+ 'All authentication-related keys should be provided on ' \
95
+ 'instantiation in IntacctRuby::Request#new'
96
+ end
97
+ end
98
+
99
+ def timestamp
100
+ @timestamp ||= Time.now.utc.to_s
101
+ end
102
+
103
+ def control_block
104
+ @request.control do
105
+ @request.senderid @opts[:senderid]
106
+ @request.password @opts[:sender_password]
107
+
108
+ # As recommended by Intacct API reference. This ID should be unique
109
+ # to the call: it's used to associate a response with a request.
110
+ @request.controlid timestamp
111
+ @request.uniqueid @opts[:uniqueid]
112
+ @request.dtdversion @opts[:dtdversion]
113
+ @request.includewhitespace @opts[:includewhitespace]
114
+ end
115
+ end
116
+
117
+ def authentication_block
118
+ @request.authentication do
119
+ @request.login do
120
+ @request.userid @opts[:userid]
121
+ @request.companyid @opts[:companyid]
122
+ @request.password @opts[:user_password]
123
+ end
124
+ end
125
+ end
126
+
127
+ def operation_block
128
+ @request.operation transaction: @opts[:transaction] do
129
+ authentication_block
130
+ @request.content do
131
+ functions.each do |function|
132
+ @request << function.to_xml
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end