intacctrb 0.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.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +1 -0
- data/.rspec +3 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +113 -0
- data/LICENSE.txt +23 -0
- data/README.md +37 -0
- data/Rakefile +7 -0
- data/intacctrb.gemspec +31 -0
- data/lib/.DS_Store +0 -0
- data/lib/intacctrb.rb +35 -0
- data/lib/intacctrb/ap_payment.rb +168 -0
- data/lib/intacctrb/base.rb +119 -0
- data/lib/intacctrb/bill.rb +159 -0
- data/lib/intacctrb/customer.rb +116 -0
- data/lib/intacctrb/invoice.rb +133 -0
- data/lib/intacctrb/journal_entry.rb +166 -0
- data/lib/intacctrb/vendor.rb +130 -0
- data/lib/intacctrb/version.rb +3 -0
- data/spec/features/intacct_bill.feature +17 -0
- data/spec/features/intacct_customer.feature +18 -0
- data/spec/features/intacct_invoice.feature +17 -0
- data/spec/features/intacct_vendor.feature +17 -0
- data/spec/helpers.rb +115 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/steps/intacct_bill_steps.rb +178 -0
- data/spec/steps/intacct_customer_steps.rb +27 -0
- data/spec/steps/intacct_invoice_steps.rb +170 -0
- data/spec/steps/intacct_vendor_steps.rb +23 -0
- data/spec/turnip_helper.rb +7 -0
- metadata +224 -0
@@ -0,0 +1,119 @@
|
|
1
|
+
module IntacctRB
|
2
|
+
class Base < Struct.new(:object, :current_user)
|
3
|
+
include Hooks
|
4
|
+
include Hooks::InstanceHooks
|
5
|
+
|
6
|
+
define_hook :after_create, :after_update, :after_delete,
|
7
|
+
:after_get, :after_send_xml, :on_error, :before_create
|
8
|
+
|
9
|
+
after_create :set_intacct_system_id
|
10
|
+
after_delete :delete_intacct_system_id
|
11
|
+
after_delete :delete_intacct_key
|
12
|
+
after_send_xml :set_date_time
|
13
|
+
|
14
|
+
attr_accessor :response, :data, :sent_xml, :intacct_action
|
15
|
+
|
16
|
+
def initialize *params
|
17
|
+
params[0] = OpenStruct.new(params[0]) if params[0].is_a? Hash
|
18
|
+
super(*params)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def send_xml action
|
24
|
+
@intacct_action = action.to_s
|
25
|
+
run_hook :"before_#{intacct_action}" if action=="create"
|
26
|
+
|
27
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
28
|
+
xml.request {
|
29
|
+
xml.control {
|
30
|
+
xml.senderid IntacctRB.xml_sender_id
|
31
|
+
xml.password IntacctRB.xml_password
|
32
|
+
xml.controlid "INVOICE XML"
|
33
|
+
xml.uniqueid "false"
|
34
|
+
xml.dtdversion "2.1"
|
35
|
+
}
|
36
|
+
xml.operation(transaction: "false") {
|
37
|
+
xml.authentication {
|
38
|
+
xml.login {
|
39
|
+
xml.userid IntacctRB.app_user_id
|
40
|
+
xml.companyid IntacctRB.app_company_id
|
41
|
+
xml.password IntacctRB.app_password
|
42
|
+
}
|
43
|
+
}
|
44
|
+
xml.content {
|
45
|
+
yield xml
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
xml = builder.doc.root.to_xml
|
52
|
+
puts xml
|
53
|
+
@sent_xml = xml
|
54
|
+
|
55
|
+
url = "https://www.intacct.com/ia/xml/xmlgw.phtml"
|
56
|
+
uri = URI(url)
|
57
|
+
|
58
|
+
res = Net::HTTP.post_form(uri, 'xmlrequest' => xml)
|
59
|
+
@response = Nokogiri::XML(res.body)
|
60
|
+
puts res.body
|
61
|
+
if successful?
|
62
|
+
if key = response.at('//result//key')
|
63
|
+
set_intacct_key key.content
|
64
|
+
end
|
65
|
+
|
66
|
+
if intacct_action
|
67
|
+
run_hook :after_send_xml, intacct_action
|
68
|
+
#run_hook :"after_#{intacct_action}"
|
69
|
+
end
|
70
|
+
else
|
71
|
+
run_hook :on_error
|
72
|
+
end
|
73
|
+
|
74
|
+
@response
|
75
|
+
end
|
76
|
+
|
77
|
+
def successful?
|
78
|
+
if status = response.at('//result//status') and status.content == "success"
|
79
|
+
true
|
80
|
+
else
|
81
|
+
false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
%w(invoice bill vendor customer).each do |type|
|
86
|
+
define_method "intacct_#{type}_prefix" do
|
87
|
+
Intacct.send("#{type}_prefix")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def intacct_system_id
|
92
|
+
intacct_object_id
|
93
|
+
end
|
94
|
+
|
95
|
+
def set_intacct_system_id
|
96
|
+
object.intacct_system_id = intacct_object_id
|
97
|
+
end
|
98
|
+
|
99
|
+
def delete_intacct_system_id
|
100
|
+
object.intacct_system_id = nil
|
101
|
+
end
|
102
|
+
|
103
|
+
def set_intacct_key key
|
104
|
+
object.intacct_key = key if object.respond_to? :intacct_key
|
105
|
+
end
|
106
|
+
|
107
|
+
def delete_intacct_key
|
108
|
+
object.intacct_key = nil if object.respond_to? :intacct_key
|
109
|
+
end
|
110
|
+
|
111
|
+
def set_date_time type
|
112
|
+
if %w(create update delete).include? type
|
113
|
+
if object.respond_to? :"intacct_#{type}d_at"
|
114
|
+
object.send("intacct_#{type}d_at=", DateTime.now)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
module IntacctRB
|
2
|
+
class Bill < IntacctRB::Base
|
3
|
+
attr_accessor :customer_data
|
4
|
+
define_hook :custom_bill_fields, :bill_item_fields
|
5
|
+
|
6
|
+
def create
|
7
|
+
return false if object.payment.intacct_system_id.present?
|
8
|
+
|
9
|
+
# Need to create the customer if one doesn't exist
|
10
|
+
unless object.customer.intacct_system_id
|
11
|
+
intacct_customer = Intacct::Customer.new object.customer
|
12
|
+
unless intacct_customer.create
|
13
|
+
raise 'Could not grab Intacct customer data'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Create vendor if we have one and not in Intacct
|
18
|
+
if object.vendor and object.vendor.intacct_system_id.blank?
|
19
|
+
intacct_vendor = Intacct::Vendor.new object.vendor
|
20
|
+
if intacct_vendor.create
|
21
|
+
object.vendor = intacct_vendor.object
|
22
|
+
else
|
23
|
+
raise 'Could not create vendor'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
send_xml('create') do |xml|
|
28
|
+
xml.function(controlid: "f1") {
|
29
|
+
xml.send("create_bill") {
|
30
|
+
bill_xml xml
|
31
|
+
}
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
successful?
|
36
|
+
end
|
37
|
+
|
38
|
+
def delete
|
39
|
+
# return false unless object.payment.intacct_system_id.present?
|
40
|
+
|
41
|
+
send_xml('delete') do |xml|
|
42
|
+
xml.function(controlid: "1") {
|
43
|
+
xml.delete_bill(externalkey: "false", key: object.intacct_key)
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
successful?
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_list(options = {})
|
51
|
+
send_xml('get_list') do |xml|
|
52
|
+
xml.function(controlid: "f4") {
|
53
|
+
xml.get_list(object: "bill", maxitems: (options[:max_items] || 0),
|
54
|
+
start: (options[:start] || 0), showprivate:"true") {
|
55
|
+
if options[:filters]
|
56
|
+
xml.filter {
|
57
|
+
options[:filters].each do |filter|
|
58
|
+
xml.expression do
|
59
|
+
filter.each_pair do |k,v|
|
60
|
+
xml.send(k,v)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
}
|
65
|
+
end
|
66
|
+
if options[:fields]
|
67
|
+
xml.fields {
|
68
|
+
fields.each do |field|
|
69
|
+
xml.field field.to_s
|
70
|
+
end
|
71
|
+
}
|
72
|
+
end
|
73
|
+
}
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
if successful?
|
78
|
+
@data = []
|
79
|
+
@response.xpath('//bill').each do |invoice|
|
80
|
+
@data << OpenStruct.new({
|
81
|
+
id: invoice.at("key").content,
|
82
|
+
vendor_id: invoice.at("vendorid").content,
|
83
|
+
bill_number: invoice.at("billno").content,
|
84
|
+
po_number: invoice.at("ponumber").content,
|
85
|
+
state: invoice.at("state").content,
|
86
|
+
date_posted: get_date_at('dateposted', invoice),
|
87
|
+
date_due: get_date_at('datedue', invoice),
|
88
|
+
date_paid: get_date_at('datepaid', invoice),
|
89
|
+
total: invoice.at("totalamount").content,
|
90
|
+
total_paid: invoice.at("totalpaid").content,
|
91
|
+
total_due: invoice.at("totaldue").content,
|
92
|
+
termname: invoice.at("termname").content,
|
93
|
+
description: invoice.at("description").content,
|
94
|
+
modified_at: invoice.at("whenmodified").content
|
95
|
+
})
|
96
|
+
end
|
97
|
+
@data
|
98
|
+
else
|
99
|
+
false
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def get_date_at(xpath, object)
|
104
|
+
year = object.at("#{xpath}/year").content
|
105
|
+
month = object.at("#{xpath}/month").content
|
106
|
+
day = object.at("#{xpath}/day").content
|
107
|
+
if [year,month,day].any?(&:empty?)
|
108
|
+
nil
|
109
|
+
else
|
110
|
+
Date.new(year.to_i,month.to_i,day.to_i)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def intacct_object_id
|
115
|
+
"#{intacct_bill_prefix}#{object.payment.id}"
|
116
|
+
end
|
117
|
+
|
118
|
+
def bill_xml xml
|
119
|
+
xml.vendorid object.vendor.intacct_system_id
|
120
|
+
xml.datecreated {
|
121
|
+
xml.year object.payment.created_at.strftime("%Y")
|
122
|
+
xml.month object.payment.created_at.strftime("%m")
|
123
|
+
xml.day object.payment.created_at.strftime("%d")
|
124
|
+
}
|
125
|
+
xml.dateposted {
|
126
|
+
xml.year object.payment.created_at.strftime("%Y")
|
127
|
+
xml.month object.payment.created_at.strftime("%m")
|
128
|
+
xml.day object.payment.created_at.strftime("%d")
|
129
|
+
}
|
130
|
+
xml.datedue {
|
131
|
+
xml.year object.payment.paid_at.strftime("%Y")
|
132
|
+
xml.month object.payment.paid_at.strftime("%m")
|
133
|
+
xml.day object.payment.paid_at.strftime("%d")
|
134
|
+
}
|
135
|
+
run_hook :custom_bill_fields, xml
|
136
|
+
run_hook :bill_item_fields, xml
|
137
|
+
end
|
138
|
+
|
139
|
+
def set_intacct_system_id
|
140
|
+
object.payment.intacct_system_id = intacct_object_id
|
141
|
+
end
|
142
|
+
|
143
|
+
def delete_intacct_system_id
|
144
|
+
object.payment.intacct_system_id = nil
|
145
|
+
end
|
146
|
+
|
147
|
+
def delete_intacct_key
|
148
|
+
object.payment.intacct_key = nil
|
149
|
+
end
|
150
|
+
|
151
|
+
def set_date_time type
|
152
|
+
if %w(create update delete).include? type
|
153
|
+
if object.payment.respond_to? :"intacct_#{type}d_at"
|
154
|
+
object.payment.send("intacct_#{type}d_at=", DateTime.now)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module IntacctRB
|
2
|
+
class Customer < IntacctRB::Base
|
3
|
+
def create
|
4
|
+
send_xml('create') do |xml|
|
5
|
+
xml.function(controlid: "1") {
|
6
|
+
xml.send("create_customer") {
|
7
|
+
xml.customerid intacct_object_id
|
8
|
+
xml.name object.name
|
9
|
+
xml.comments
|
10
|
+
xml.status "active"
|
11
|
+
}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
successful?
|
16
|
+
end
|
17
|
+
|
18
|
+
def get *fields
|
19
|
+
#return false unless object.intacct_system_id.present?
|
20
|
+
|
21
|
+
fields = [
|
22
|
+
:customerid,
|
23
|
+
:name,
|
24
|
+
:termname
|
25
|
+
] if fields.empty?
|
26
|
+
|
27
|
+
send_xml('get') do |xml|
|
28
|
+
xml.function(controlid: "f4") {
|
29
|
+
xml.get(object: "customer", key: "intacct_system_id") {
|
30
|
+
xml.fields {
|
31
|
+
fields.each do |field|
|
32
|
+
xml.field field.to_s
|
33
|
+
end
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
if successful?
|
40
|
+
@data = OpenStruct.new({
|
41
|
+
id: response.at("//customer//customerid").content,
|
42
|
+
name: response.at("//customer//name").content,
|
43
|
+
termname: response.at("//customer//termname").content
|
44
|
+
})
|
45
|
+
end
|
46
|
+
|
47
|
+
successful?
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_list *fields
|
51
|
+
#return false unless object.intacct_system_id.present?
|
52
|
+
|
53
|
+
fields = [
|
54
|
+
:customerid,
|
55
|
+
:name,
|
56
|
+
:termname
|
57
|
+
] if fields.empty?
|
58
|
+
|
59
|
+
send_xml('get_list') do |xml|
|
60
|
+
xml.function(controlid: "f4") {
|
61
|
+
xml.get_list(object: "customer", maxitems: "10", showprivate:"false") {
|
62
|
+
# xml.fields {
|
63
|
+
# fields.each do |field|
|
64
|
+
# xml.field field.to_s
|
65
|
+
# end
|
66
|
+
# }
|
67
|
+
}
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
# if successful?
|
72
|
+
# @data = OpenStruct.new({
|
73
|
+
# id: response.at("//customer//customerid").content,
|
74
|
+
# name: response.at("//customer//name").content,
|
75
|
+
# termname: response.at("//customer//termname").content
|
76
|
+
# })
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# successful?
|
80
|
+
puts response
|
81
|
+
end
|
82
|
+
|
83
|
+
def update updated_customer = false
|
84
|
+
@object = updated_customer if updated_customer
|
85
|
+
return false unless object.intacct_system_id.present?
|
86
|
+
|
87
|
+
send_xml('update') do |xml|
|
88
|
+
xml.function(controlid: "1") {
|
89
|
+
xml.update_customer(customerid: intacct_system_id) {
|
90
|
+
xml.name object.name
|
91
|
+
xml.comments
|
92
|
+
xml.status "active"
|
93
|
+
}
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
successful?
|
98
|
+
end
|
99
|
+
|
100
|
+
def delete
|
101
|
+
return false unless object.intacct_system_id.present?
|
102
|
+
|
103
|
+
@response = send_xml('delete') do |xml|
|
104
|
+
xml.function(controlid: "1") {
|
105
|
+
xml.delete_customer(customerid: intacct_system_id)
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
successful?
|
110
|
+
end
|
111
|
+
|
112
|
+
def intacct_object_id
|
113
|
+
"#{intacct_customer_prefix}#{object.id}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module IntacctRB
|
2
|
+
class Invoice < IntacctRB::Base
|
3
|
+
attr_accessor :customer_data
|
4
|
+
define_hook :custom_invoice_fields
|
5
|
+
|
6
|
+
def get_list *fields
|
7
|
+
# return false unless object.intacct_system_id.present?
|
8
|
+
|
9
|
+
fields = [
|
10
|
+
:customerid,
|
11
|
+
:name,
|
12
|
+
:termname
|
13
|
+
] if fields.empty?
|
14
|
+
|
15
|
+
send_xml('get_list') do |xml|
|
16
|
+
xml.function(controlid: "f4") {
|
17
|
+
xml.get_list(object: "invoice", maxitems: "10", showprivate:"false") {
|
18
|
+
# xml.fields {
|
19
|
+
# fields.each do |field|
|
20
|
+
# xml.field field.to_s
|
21
|
+
# end
|
22
|
+
# }
|
23
|
+
}
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
if successful?
|
28
|
+
@data = []
|
29
|
+
@response.xpath('//invoice').each do |invoice|
|
30
|
+
@data << Invoice.new({
|
31
|
+
id: invoice.at("//customerid").content,
|
32
|
+
total: invoice.at("//totalamount").content,
|
33
|
+
total_paid: invoice.at("//totalpaid").content,
|
34
|
+
termname: invoice.at("//termname").content
|
35
|
+
})
|
36
|
+
end
|
37
|
+
@data
|
38
|
+
else
|
39
|
+
false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def create
|
44
|
+
return false if object.invoice.intacct_system_id.present?
|
45
|
+
|
46
|
+
# Need to create the customer if one doesn't exist
|
47
|
+
intacct_customer = Intacct::Customer.new object.customer
|
48
|
+
unless object.customer.intacct_system_id.present?
|
49
|
+
unless intacct_customer.create
|
50
|
+
raise 'Could not create customer'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if intacct_customer.get
|
55
|
+
object.customer = intacct_customer.object
|
56
|
+
@customer_data = intacct_customer.data
|
57
|
+
else
|
58
|
+
raise 'Could not grab Intacct customer data'
|
59
|
+
end
|
60
|
+
|
61
|
+
# Create vendor if we have one and not in Intacct
|
62
|
+
if object.vendor and object.vendor.intacct_system_id.blank?
|
63
|
+
intacct_vendor = Intacct::Vendor.new object.vendor
|
64
|
+
if intacct_vendor.create
|
65
|
+
object.vendor = intacct_vendor.object
|
66
|
+
else
|
67
|
+
raise 'Could not create vendor'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
send_xml('create') do |xml|
|
72
|
+
xml.function(controlid: "f1") {
|
73
|
+
xml.create_invoice {
|
74
|
+
invoice_xml xml
|
75
|
+
}
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
successful?
|
80
|
+
end
|
81
|
+
|
82
|
+
def delete
|
83
|
+
return false unless object.invoice.intacct_system_id.present?
|
84
|
+
|
85
|
+
send_xml('delete') do |xml|
|
86
|
+
xml.function(controlid: "1") {
|
87
|
+
xml.delete_invoice(externalkey: "false", key: object.invoice.intacct_key)
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
successful?
|
92
|
+
end
|
93
|
+
|
94
|
+
def intacct_object_id
|
95
|
+
"#{intacct_invoice_prefix}#{object.invoice.id}"
|
96
|
+
end
|
97
|
+
|
98
|
+
def invoice_xml xml
|
99
|
+
xml.customerid "#{object.customer.intacct_system_id}"
|
100
|
+
xml.datecreated {
|
101
|
+
xml.year object.invoice.created_at.strftime("%Y")
|
102
|
+
xml.month object.invoice.created_at.strftime("%m")
|
103
|
+
xml.day object.invoice.created_at.strftime("%d")
|
104
|
+
}
|
105
|
+
|
106
|
+
termname = customer_data.termname
|
107
|
+
xml.termname termname.present?? termname : "Net 30"
|
108
|
+
|
109
|
+
xml.invoiceno intacct_object_id
|
110
|
+
run_hook :custom_invoice_fields, xml
|
111
|
+
end
|
112
|
+
|
113
|
+
def set_intacct_system_id
|
114
|
+
object.invoice.intacct_system_id = intacct_object_id
|
115
|
+
end
|
116
|
+
|
117
|
+
def delete_intacct_system_id
|
118
|
+
object.invoice.intacct_system_id = nil
|
119
|
+
end
|
120
|
+
|
121
|
+
def delete_intacct_key
|
122
|
+
object.invoice.intacct_key = nil
|
123
|
+
end
|
124
|
+
|
125
|
+
def set_date_time type
|
126
|
+
if %w(create update delete).include? type
|
127
|
+
if object.invoice.respond_to? :"intacct_#{type}d_at"
|
128
|
+
object.invoice.send("intacct_#{type}d_at=", DateTime.now)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|