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,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
|