intacctrb 0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,166 @@
|
|
1
|
+
module IntacctRB
|
2
|
+
class JournalEntry < IntacctRB::Base
|
3
|
+
|
4
|
+
def create
|
5
|
+
return false if object.intacct_system_id.present?
|
6
|
+
send_xml('create') do |xml|
|
7
|
+
xml.function(controlid: "f1") {
|
8
|
+
xml.send("create_gltransaction") {
|
9
|
+
je_xml xml
|
10
|
+
}
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
successful?
|
15
|
+
end
|
16
|
+
|
17
|
+
def delete
|
18
|
+
# return false unless object.payment.intacct_system_id.present?
|
19
|
+
send_xml('delete') do |xml|
|
20
|
+
xml.function(controlid: "1") {
|
21
|
+
xml.delete_bill(externalkey: "false", key: object.intacct_key)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
successful?
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_list(options = {})
|
29
|
+
send_xml('get_list') do |xml|
|
30
|
+
xml.function(controlid: "f4") {
|
31
|
+
xml.get_list(object: "gltransaction", maxitems: (options[:max_items] || 0),
|
32
|
+
start: (options[:start] || 0), showprivate:"true") {
|
33
|
+
if options[:filters]
|
34
|
+
xml.filter {
|
35
|
+
options[:filters].each do |filter|
|
36
|
+
xml.expression do
|
37
|
+
filter.each_pair do |k,v|
|
38
|
+
xml.send(k,v)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
}
|
43
|
+
end
|
44
|
+
if options[:fields]
|
45
|
+
xml.fields {
|
46
|
+
fields.each do |field|
|
47
|
+
xml.field field.to_s
|
48
|
+
end
|
49
|
+
}
|
50
|
+
end
|
51
|
+
}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
if successful?
|
56
|
+
@data = []
|
57
|
+
@response.xpath('//bill').each do |invoice|
|
58
|
+
@data << OpenStruct.new({
|
59
|
+
id: invoice.at("key").content,
|
60
|
+
batch_number: invoice.at("batchno").content,
|
61
|
+
journal_id: invoice.at("journalid").content,
|
62
|
+
date_created: get_date_at('datecreated', invoice),
|
63
|
+
date_modified: get_date_at('datemodified', invoice),
|
64
|
+
description: invoice.at("description").content,
|
65
|
+
state: invoice.at("state").content
|
66
|
+
})
|
67
|
+
end
|
68
|
+
@data
|
69
|
+
else
|
70
|
+
false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def get_date_at(xpath, object)
|
75
|
+
year = object.at("#{xpath}/year").content
|
76
|
+
month = object.at("#{xpath}/month").content
|
77
|
+
day = object.at("#{xpath}/day").content
|
78
|
+
if [year,month,day].any?(&:empty?)
|
79
|
+
nil
|
80
|
+
else
|
81
|
+
Date.new(year.to_i,month.to_i,day.to_i)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def intacct_object_id
|
86
|
+
"#{intacct_bill_prefix}#{object.payment.id}"
|
87
|
+
end
|
88
|
+
|
89
|
+
def je_xml xml
|
90
|
+
xml.journalid object.journal_id
|
91
|
+
if object.date
|
92
|
+
xml.datecreated {
|
93
|
+
xml.year object.date.strftime("%Y")
|
94
|
+
xml.month object.date.strftime("%m")
|
95
|
+
xml.day object.date.strftime("%d")
|
96
|
+
}
|
97
|
+
end
|
98
|
+
if object.reverse_date
|
99
|
+
xml.reversedate {
|
100
|
+
xml.year object.reverse_date.strftime("%Y")
|
101
|
+
xml.month object.reverse_date.strftime("%m")
|
102
|
+
xml.day object.reverse_date.strftime("%d")
|
103
|
+
}
|
104
|
+
end
|
105
|
+
xml.description object.description
|
106
|
+
xml.referenceno object.reference_number
|
107
|
+
je_item_fields(xml)
|
108
|
+
end
|
109
|
+
|
110
|
+
def set_intacct_system_id
|
111
|
+
object.payment.intacct_system_id = intacct_object_id
|
112
|
+
end
|
113
|
+
|
114
|
+
def delete_intacct_system_id
|
115
|
+
object.payment.intacct_system_id = nil
|
116
|
+
end
|
117
|
+
|
118
|
+
def delete_intacct_key
|
119
|
+
object.payment.intacct_key = nil
|
120
|
+
end
|
121
|
+
|
122
|
+
def set_date_time type
|
123
|
+
if %w(create update delete).include? type
|
124
|
+
if object.payment.respond_to? :"intacct_#{type}d_at"
|
125
|
+
object.payment.send("intacct_#{type}d_at=", DateTime.now)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def je_item_fields xml
|
131
|
+
puts "object:: #{object}"
|
132
|
+
xml.gltransactionentries {
|
133
|
+
object.rows.each do |row|
|
134
|
+
xml.glentry {
|
135
|
+
xml.trtype row[:type]
|
136
|
+
xml.amount row[:amount]
|
137
|
+
xml.glaccountno row[:account_number]
|
138
|
+
if row[:date]
|
139
|
+
xml.datecreated {
|
140
|
+
xml.year row[:date].strftime("%Y")
|
141
|
+
xml.month row[:date].strftime("%m")
|
142
|
+
xml.day row[:date].strftime("%d")
|
143
|
+
}
|
144
|
+
end
|
145
|
+
xml.memo row[:memo]
|
146
|
+
xml.locationid row[:location_id] if row[:location_id]
|
147
|
+
xml.departmentid row[:department_id] if row[:department_id]
|
148
|
+
xml.customerid row[:customer_id] if row[:customer_id]
|
149
|
+
xml.employeeid row[:employee_id] if row[:employee_id]
|
150
|
+
xml.projectid row[:project_id] if row[:project_id]
|
151
|
+
xml.itemid row[:item_id] if row[:itemid]
|
152
|
+
xml.classid row[:class_id] if row[:class_id]
|
153
|
+
}
|
154
|
+
end
|
155
|
+
}
|
156
|
+
end
|
157
|
+
|
158
|
+
def to_date_xml xml, field_name, date
|
159
|
+
xml.send(field_name) {
|
160
|
+
xml.year date.strftime("%Y")
|
161
|
+
xml.month date.strftime("%m")
|
162
|
+
xml.day date.strftime("%d")
|
163
|
+
}
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module IntacctRB
|
2
|
+
class Vendor < IntacctRB::Base
|
3
|
+
def create
|
4
|
+
send_xml('create') do |xml|
|
5
|
+
xml.function(controlid: "1") {
|
6
|
+
xml.create_vendor {
|
7
|
+
xml.vendorid intacct_object_id
|
8
|
+
vendor_xml xml
|
9
|
+
}
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
successful?
|
14
|
+
end
|
15
|
+
|
16
|
+
def update updated_vendor = false
|
17
|
+
@object = updated_vendor if updated_vendor
|
18
|
+
return false if object.intacct_system_id.nil?
|
19
|
+
|
20
|
+
|
21
|
+
send_xml('update') do |xml|
|
22
|
+
xml.function(controlid: "1") {
|
23
|
+
xml.update_vendor(vendorid: intacct_system_id) {
|
24
|
+
vendor_xml xml
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
successful?
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete
|
33
|
+
return false if object.intacct_system_id.nil?
|
34
|
+
|
35
|
+
@response = send_xml('delete') do |xml|
|
36
|
+
xml.function(controlid: "1") {
|
37
|
+
xml.delete_vendor(vendorid: intacct_system_id)
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
successful?
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_list(options = {})
|
45
|
+
send_xml('get_list') do |xml|
|
46
|
+
xml.function(controlid: "f4") {
|
47
|
+
xml.get_list(object: "vendor", maxitems: (options[:max_items] || 0),
|
48
|
+
start: (options[:start] || 0), showprivate:"true") {
|
49
|
+
if options[:filters]
|
50
|
+
xml.filter {
|
51
|
+
options[:filters].each do |filter|
|
52
|
+
xml.expression do
|
53
|
+
filter.each_pair do |k,v|
|
54
|
+
xml.send(k,v)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
}
|
59
|
+
end
|
60
|
+
if options[:fields]
|
61
|
+
xml.fields {
|
62
|
+
fields.each do |field|
|
63
|
+
xml.field field.to_s
|
64
|
+
end
|
65
|
+
}
|
66
|
+
end
|
67
|
+
}
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
if successful?
|
72
|
+
@data = []
|
73
|
+
@response.xpath('//vendor').each do |invoice|
|
74
|
+
@data << OpenStruct.new({
|
75
|
+
id: invoice.at("vendorid").content,
|
76
|
+
name: invoice.at("name").content,
|
77
|
+
tax_id: invoice.at("taxid").content,
|
78
|
+
total_due: invoice.at("totaldue").content,
|
79
|
+
billing_type: invoice.at("billingtype").content,
|
80
|
+
vendor_account_number: invoice.at("vendoraccountno").content
|
81
|
+
})
|
82
|
+
end
|
83
|
+
@data
|
84
|
+
else
|
85
|
+
false
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def intacct_object_id
|
90
|
+
"#{intacct_vendor_prefix}#{object.id}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def vendor_xml xml
|
94
|
+
xml.name "#{object.company_name.present? ? object.company_name : object.full_name}"
|
95
|
+
#[todo] - Custom
|
96
|
+
xml.vendtype "Appraiser"
|
97
|
+
xml.taxid object.tax_id
|
98
|
+
xml.billingtype "balanceforward"
|
99
|
+
xml.status "active"
|
100
|
+
xml.contactinfo {
|
101
|
+
xml.contact {
|
102
|
+
xml.contactname "#{object.last_name}, #{object.first_name} (#{object.id})"
|
103
|
+
xml.printas object.full_name
|
104
|
+
xml.companyname object.company_name
|
105
|
+
xml.firstname object.first_name
|
106
|
+
xml.lastname object.last_name
|
107
|
+
xml.phone1 object.business_phone
|
108
|
+
xml.cellphone object.cell_phone
|
109
|
+
xml.email1 object.email
|
110
|
+
if object.billing_address.present?
|
111
|
+
xml.mailaddress {
|
112
|
+
xml.address1 object.billing_address.address1
|
113
|
+
xml.address2 object.billing_address.address2
|
114
|
+
xml.city object.billing_address.city
|
115
|
+
xml.state object.billing_address.state
|
116
|
+
xml.zip object.billing_address.zipcode
|
117
|
+
}
|
118
|
+
end
|
119
|
+
}
|
120
|
+
}
|
121
|
+
if object.ach_routing_number.present?
|
122
|
+
xml.achenabled "#{object.ach_routing_number.present? ? "true" : "false"}"
|
123
|
+
xml.achbankroutingnumber object.ach_routing_number
|
124
|
+
xml.achaccountnumber object.ach_account_number
|
125
|
+
xml.achaccounttype "#{object.ach_account_type.capitalize+" Account"}"
|
126
|
+
xml.achremittancetype "#{(object.ach_account_classification=="business" ? "CCD" : "PPD")}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Feature: Intacct Bill
|
2
|
+
I need to be able to send and receive Intacct Bills.
|
3
|
+
We need to also pass an invoice, customer and vendor when creating the object.
|
4
|
+
|
5
|
+
Background:
|
6
|
+
Given I have setup the correct settings
|
7
|
+
And I have an payment, customer and vendor
|
8
|
+
Then I create an Intacct Bill object
|
9
|
+
|
10
|
+
Scenario Outline: It should "CRUD" an invoice in Intacct
|
11
|
+
Given I use the #<method> method
|
12
|
+
Then I should recieve a sucessfull response
|
13
|
+
|
14
|
+
Examples:
|
15
|
+
| method |
|
16
|
+
| create |
|
17
|
+
| delete |
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Feature: Intacct Customer
|
2
|
+
I need to be able to send and receive Intacct customers (companies)
|
3
|
+
|
4
|
+
Background:
|
5
|
+
Given I have setup the correct settings
|
6
|
+
And I have a customer
|
7
|
+
Then I create an Intacct Customer object
|
8
|
+
|
9
|
+
Scenario Outline: It should "CRUD" a customer in Intacct
|
10
|
+
Given I use the #<method> method
|
11
|
+
Then I should recieve a sucessfull response
|
12
|
+
|
13
|
+
Examples:
|
14
|
+
| method |
|
15
|
+
| create |
|
16
|
+
| update |
|
17
|
+
| get |
|
18
|
+
| delete |
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Feature: Intacct Invoice
|
2
|
+
I need to be able to send and receive Intacct Invoices.
|
3
|
+
We need to also pass an invoice, customer and vendor when creating the object.
|
4
|
+
|
5
|
+
Background:
|
6
|
+
Given I have setup the correct settings
|
7
|
+
And I have an invoice, customer and vendor
|
8
|
+
Then I create an Intacct Invoice object
|
9
|
+
|
10
|
+
Scenario Outline: It should "CRUD" an invoice in Intacct
|
11
|
+
Given I use the #<method> method
|
12
|
+
Then I should recieve a sucessfull response
|
13
|
+
|
14
|
+
Examples:
|
15
|
+
| method |
|
16
|
+
| create |
|
17
|
+
| delete |
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Feature: Intacct Vendor
|
2
|
+
I need to be able to send and receive Intacct vendors
|
3
|
+
|
4
|
+
Background:
|
5
|
+
Given I have setup the correct settings
|
6
|
+
And I have a vendor
|
7
|
+
Then I create an Intacct Vendor object
|
8
|
+
|
9
|
+
Scenario Outline: It should "CRUD" a vendor in Intacct
|
10
|
+
Given I use the #<method> method
|
11
|
+
Then I should recieve a sucessfull response
|
12
|
+
|
13
|
+
Examples:
|
14
|
+
| method |
|
15
|
+
| create |
|
16
|
+
| update |
|
17
|
+
| delete |
|
data/spec/helpers.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
module Helpers
|
2
|
+
class << self
|
3
|
+
def random_id
|
4
|
+
return @random_id if @random_id
|
5
|
+
number = SecureRandom.random_number.to_s
|
6
|
+
@random_id = number[2..number.length]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def current_random_id
|
11
|
+
Helpers.random_id
|
12
|
+
end
|
13
|
+
|
14
|
+
def address
|
15
|
+
OpenStruct.new({
|
16
|
+
address1: Faker::Address.street_address,
|
17
|
+
address2: Faker::Address.secondary_address,
|
18
|
+
city: Faker::Address.city,
|
19
|
+
state: Faker::Address.state_abbr,
|
20
|
+
zipcode: Faker::Address.zip_code[0..4]
|
21
|
+
})
|
22
|
+
end
|
23
|
+
|
24
|
+
def person
|
25
|
+
fields = {
|
26
|
+
full_name: Faker::Name.name,
|
27
|
+
first_name: Faker::Name.first_name,
|
28
|
+
last_name: Faker::Name.last_name,
|
29
|
+
}
|
30
|
+
|
31
|
+
fields.merge! yield if block_given?
|
32
|
+
|
33
|
+
OpenStruct.new fields
|
34
|
+
end
|
35
|
+
|
36
|
+
def customer
|
37
|
+
@customer ||= OpenStruct.new({
|
38
|
+
id: current_random_id,
|
39
|
+
intacct_system_id: current_random_id,
|
40
|
+
name: 'RSpec Company'
|
41
|
+
})
|
42
|
+
end
|
43
|
+
|
44
|
+
def vendor
|
45
|
+
@vendor ||= OpenStruct.new({
|
46
|
+
id: current_random_id,
|
47
|
+
intacct_system_id: current_random_id,
|
48
|
+
first_name: "Rspec",
|
49
|
+
last_name: "Test",
|
50
|
+
full_name: "Rspec Test",
|
51
|
+
email: "test@example.com",
|
52
|
+
ach_account_number: "123456789",
|
53
|
+
ach_routing_number: "123456789",
|
54
|
+
ach_account_type: "savings",
|
55
|
+
ach_account_classification: "business",
|
56
|
+
ach_last_updated_at: Time.now,
|
57
|
+
billing_address: address
|
58
|
+
})
|
59
|
+
end
|
60
|
+
|
61
|
+
def payment
|
62
|
+
@payment ||= OpenStruct.new(invoice.to_h.merge({
|
63
|
+
type: 'some_type',
|
64
|
+
paid_at: DateTime.now,
|
65
|
+
base_amt: Faker::Number.number(2),
|
66
|
+
additional_amt: Faker::Number.number(2)
|
67
|
+
}))
|
68
|
+
end
|
69
|
+
|
70
|
+
def invoice
|
71
|
+
@invoice ||= OpenStruct.new({
|
72
|
+
id: current_random_id,
|
73
|
+
intacct_system_id: current_random_id,
|
74
|
+
created_at: DateTime.now,
|
75
|
+
mileage_miles: Faker::Number.number(3),
|
76
|
+
mileage_rate: Faker::Number.number(2),
|
77
|
+
mileage_fee: Faker::Number.number(2),
|
78
|
+
base_fee: Faker::Number.number(2),
|
79
|
+
additional_fee: Faker::Number.number(2),
|
80
|
+
note: Faker::Lorem.words,
|
81
|
+
creator: person,
|
82
|
+
claim: OpenStruct.new({
|
83
|
+
dlnumber: Faker::Number.number(6),
|
84
|
+
claimnumber: Faker::Number.number(6),
|
85
|
+
appraisal_type: 'auto',
|
86
|
+
insured_full_name: Faker::Name.name,
|
87
|
+
appraiser_driving_distance: Faker::Number.number(2),
|
88
|
+
dtcreated: DateTime.now,
|
89
|
+
vehicle: OpenStruct.new({
|
90
|
+
year: 2001,
|
91
|
+
make: Faker::Name.name,
|
92
|
+
model: 'A1',
|
93
|
+
address: address
|
94
|
+
}),
|
95
|
+
owner: person { {insuredorclaimant: 'INSURED' } },
|
96
|
+
adjuster: person
|
97
|
+
})
|
98
|
+
})
|
99
|
+
end
|
100
|
+
|
101
|
+
def default_setup
|
102
|
+
IntacctRB.setup do |config|
|
103
|
+
config.invoice_prefix = 'AUTO-'
|
104
|
+
config.bill_prefix = 'AUTO-'
|
105
|
+
config.customer_prefix = 'C'
|
106
|
+
config.vendor_prefix = 'A'
|
107
|
+
config.xml_sender_id = ENV['INTACCT_XML_SENDER_ID']
|
108
|
+
config.xml_password = ENV['INTACCT_XML_PASSWORD']
|
109
|
+
config.app_user_id = ENV['INTACCT_USER_ID']
|
110
|
+
config.app_company_id = ENV['INTACCT_COMPANY_ID']
|
111
|
+
config.app_password = ENV['INTACCT_PASSWORD']
|
112
|
+
yield if block_given?
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|