qbwc 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in qbwc.gemspec
4
+ gemspec
@@ -0,0 +1,34 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ qbwc (0.0.3)
5
+ quickbooks_api (>= 0.1.6)
6
+ rubyjedi-soap4r (>= 1.5.8.20100619003610)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ activesupport (3.2.8)
12
+ i18n (~> 0.6)
13
+ multi_json (~> 1.0)
14
+ buffered_logger (0.1.3)
15
+ activesupport
16
+ i18n
17
+ term-ansicolor
18
+ httpclient (2.1.5.2)
19
+ i18n (0.6.0)
20
+ multi_json (1.3.6)
21
+ nokogiri (1.5.5)
22
+ quickbooks_api (0.1.6)
23
+ activesupport
24
+ buffered_logger (>= 0.1.3)
25
+ nokogiri
26
+ rubyjedi-soap4r (1.5.8.20100619003610)
27
+ httpclient (~> 2.1.5.2)
28
+ term-ansicolor (1.0.7)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ qbwc!
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,182 @@
1
+ # Quickbooks Web Connector (QBWC)
2
+
3
+ Be Warned, this code is still hot out of the oven.
4
+
5
+ ## Installation
6
+
7
+ Install the gem
8
+
9
+ `gem install qbwc`
10
+
11
+ Add it to your Gemfile
12
+
13
+ `gem "qbwc"`
14
+
15
+ Run the generator:
16
+
17
+ `rails generate qbwc:install`
18
+
19
+ ## Features
20
+
21
+ QBWC was designed to add quickbooks web connector integration to your Rails 3 application.
22
+
23
+ * Implementation of the Soap WDSL spec for Intuit Quickbooks and Point of Sale
24
+ * Integration with the [quickbooks_api](https://github.com/skryl/quickbooks_api) gem providing qbxml processing
25
+
26
+ ## Getting Started
27
+
28
+ ### Configuration
29
+
30
+ All configuration takes place in the gem initializer. See the initializer for more details regarding the configuration options.
31
+
32
+ ### Basics
33
+
34
+ The QBWC gem provides a persistent work queue for the Web Connector to talk to.
35
+
36
+ Every time the Web Connector initiates a new conversation with the application a
37
+ Session will be created. The Session is a collection of jobs and the requests
38
+ that comprise these jobs. A new Session will automatically queue up all the work
39
+ available across all currently enabled jobs for processing by the web connector.
40
+ The session instance will persist across all requests until the work it contains
41
+ has been exhausted. You never have to interact with the Session class directly
42
+ (unless you want to...) since creating a new job will automatically add it's
43
+ work to the next session instance.
44
+
45
+ A Job is just a named work queue. It consists of a name and a code block. The
46
+ block can contain:
47
+
48
+ * A single qbxml request
49
+ * An array of qbxml requests
50
+ * Code that genrates a qbxml request
51
+ * Code that generates an array of qbxml requests
52
+
53
+ *Note: All requests may be in ruby hash form, generated using quickbooks_api.
54
+ Raw requests are supported supported as of 0.0.3 (8/28/2012)*
55
+
56
+ The code block is re-evaluated every time a session instance with that job is
57
+ created. Only enabled jobs are added to a new session instance.
58
+
59
+ An optional response processor block can also be added to a job. Responses to
60
+ all requests are either processed immediately after being received or saved for
61
+ processing after the web connector closes its connection. The delayed processing
62
+ configuration option decides this.
63
+
64
+ Here is the rough order in which things happen:
65
+
66
+ 1. The Web Connector initiates a connection
67
+ 2. A new Session is created (with work from all enabled jobs)
68
+ 3. The web connector requests work
69
+ 4. The session responds with the next request in the work queue
70
+ 5. The web connector provides a response
71
+ 6. The session responds with the current progress of the work queue (0 - 100)
72
+ 6. The response is processed or saved for later processing
73
+ 7. If progress == 100 then the web connector closes the connection, otherwise goto 3
74
+ 8. Saved responses are processed if any exist
75
+
76
+ ### Adding Jobs
77
+
78
+ Create a new job
79
+
80
+ QBWC.add_job('my job') do
81
+ # work to do
82
+ end
83
+
84
+ Add a response proc
85
+
86
+ QBWC.jobs['my job'].set_response_proc do |r|
87
+ # response processing work here
88
+ end
89
+
90
+ Caveats
91
+ * Jobs are enabled by default
92
+ * Using a non unique job name will overwrite the existing job
93
+
94
+ ###Sample Jobs
95
+
96
+ Add a Customer (Wrapped)
97
+
98
+ { :qbxml_msgs_rq =>
99
+ [
100
+ {
101
+ :xml_attributes => { "onError" => "stopOnError"},
102
+ :customer_add_rq =>
103
+ [
104
+ {
105
+ :xml_attributes => {"requestID" => "1"}, ##Optional
106
+ :customer_add => { :name => "GermanGR" }
107
+ }
108
+ ]
109
+ }
110
+ ]
111
+ }
112
+
113
+ Add a Customer (Unwrapped)
114
+
115
+ {
116
+ :customer_add_rq =>
117
+ [
118
+ {
119
+ :xml_attributes => {"requestID" => "1"}, ##Optional
120
+ :customer_add => { :name => "GermanGR" }
121
+ }
122
+ ]
123
+ }
124
+
125
+ Get All Vendors (In Chunks of 5)
126
+
127
+ QBWC.add_job(:import_vendors) do
128
+ [
129
+ :vendor_query_rq =>
130
+ {
131
+ :xml_attributes => { "requestID" =>"1", 'iterator' => "Start" },
132
+
133
+ :max_returned => 5,
134
+ :owner_id => 0,
135
+ :from_modified_date=> "1984-01-29T22:03:19"
136
+
137
+ }
138
+ ]
139
+ end
140
+
141
+ Get All Vendors (Raw QBXML)
142
+
143
+ QBWC.add_job(:import_vendors) do
144
+ '<QBXML>
145
+ <QBXMLMsgsRq onError="continueOnError">
146
+ <VendorQueryRq requestID="6" iterator="Start">
147
+ <MaxReturned>5</MaxReturned>
148
+ <FromModifiedDate>1984-01-29T22:03:19-05:00</FromModifiedDate>
149
+ <OwnerID>0</OwnerID>
150
+ </VendorQueryRq>
151
+ </QBXMLMsgsRq>
152
+ </QBXML>
153
+ '
154
+ end
155
+
156
+ ### Managing Jobs
157
+
158
+ Jobs can be added, removed, enabled, and disabled. See the above section for
159
+ details on adding new jobs.
160
+
161
+ Removing jobs is as easy as deleting them from the jobs hash.
162
+
163
+ QBWC.jobs.delete('my job')
164
+
165
+ Disabling a job
166
+
167
+ QBWC.jobs['my job'].disable
168
+
169
+ Enabling a job
170
+
171
+ QBWC.jobs['my job'].enable
172
+
173
+
174
+ ## Contributing to qbwc
175
+
176
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
177
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
178
+ * Fork the project
179
+ * Start a feature/bugfix branch
180
+ * Commit and push until you are happy with your contribution
181
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
182
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
@@ -0,0 +1,3 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,24 @@
1
+ require 'rails/generators'
2
+
3
+ module QBWC
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ namespace "qbwc:install"
7
+ desc "Copy Quickbooks Web Connector default files"
8
+ source_root File.expand_path('../templates', __FILE__)
9
+
10
+ def copy_config
11
+ template('config/qbwc.rb', "config/initializers/qbwc.rb")
12
+ end
13
+
14
+ def copy_controller
15
+ template('controllers/qbwc_controller.rb', "app/controllers/qbwc_controller.rb")
16
+ end
17
+
18
+ def setup_routes
19
+ route("match 'apis/quickbooks/:action', :controller => 'qbwc', :as => 'quickbooks'")
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,35 @@
1
+ QBWC.configure do |c|
2
+
3
+ #Currently Only supported for single logins.
4
+ c.username = "foo"
5
+ c.password = "bar"
6
+
7
+ #Path to Company File (blank for open or named path or function etc..)
8
+ c.company_file_path = ""
9
+
10
+ #Minimum Quickbooks Version Required for use in QBXML Requests
11
+ c.min_version = 7.0
12
+
13
+ #Quickbooks Type (either :qb or :qbpos)
14
+ c.api = :qb
15
+
16
+ #Quickbooks Support URL provided in QWC File
17
+ c.support_site_url = "localhost:3000"
18
+
19
+ #Quickbooks Owner ID provided in QWC File
20
+ c.owner_id = '{57F3B9B1-86F1-4fcc-B1EE-566DE1813D20}'
21
+
22
+ # Perform response processing after session termination. Enabling this option
23
+ # will speed up qbwc session time (and potentially fix timeout issues) but
24
+ # will necessarily eat up more memory since every response must be stored
25
+ # until it is processed.
26
+ c.delayed_processing = false
27
+
28
+ # In the event of an error in the communcation process do you wish the sync to stop or blase through
29
+ #
30
+ # Options:
31
+ # :stop
32
+ # :continue
33
+ c.on_error = :stop
34
+
35
+ end
@@ -0,0 +1,39 @@
1
+ class QBWCController < ApplicationController
2
+ require "Quickbooks"
3
+
4
+ def qwc
5
+ qwc = <<-QWC
6
+ <QBWCXML>
7
+ <AppName>#{Rails.application.class.parent_name} #{Rails.env}</AppName>
8
+ <AppID></AppID>
9
+ <AppURL>#{quickbooks_url(:protocol => 'https://', :action => 'api')}</AppURL>
10
+ <AppDescription>I like to describe my awesome app</AppDescription>
11
+ <AppSupport>#{QBWC.support_site_url}</AppSupport>
12
+ <UserName>#{QBWC.username}</UserName>
13
+ <OwnerID>#{QBWC.owner_id}</OwnerID>
14
+ <FileID>{90A44FB5-33D9-4815-AC85-BC87A7E7D1EB}</FileID>
15
+ <QBType>QBFS</QBType>
16
+ <Style>Document</Style>
17
+ <Scheduler>
18
+ <RunEveryNMinutes>5</RunEveryNMinutes>
19
+ </Scheduler>
20
+ </QBWCXML>
21
+ QWC
22
+ send_data qwc, :filename => 'name_me.qwc'
23
+ end
24
+
25
+ def api
26
+ # respond successfully to a GET which some versions of the Web Connector send to verify the url
27
+
28
+ if request.get?
29
+ render :nothing => true
30
+ return
31
+ end
32
+
33
+ req = request
34
+ puts "========== #{ params["Envelope"]["Body"].keys.first} =========="
35
+ res = QBWC::SoapWrapper.route_request(req)
36
+ render :xml => res, :content_type => 'text/xml'
37
+ end
38
+
39
+ end
@@ -0,0 +1,3 @@
1
+ To copy a QBWC initializer to your Rails App, with some configuration values, just do:
2
+
3
+ rails generate qbwc:install
@@ -0,0 +1,83 @@
1
+ $:.unshift File.dirname(File.expand_path(__FILE__))
2
+ require 'qbwc/version'
3
+ require 'quickbooks'
4
+
5
+ module QBWC
6
+
7
+ # Web connector login credentials
8
+ mattr_accessor :username
9
+ @@username = 'foo'
10
+ mattr_accessor :password
11
+ @@password = 'bar'
12
+
13
+ # Full path to pompany file
14
+ mattr_accessor :company_file_path
15
+ @@company_file_path = ""
16
+
17
+ # Minimum quickbooks version required for use in qbxml requests
18
+ mattr_accessor :min_version
19
+ @@min_version = 3.0
20
+
21
+ # Quickbooks support url provided in qwc file
22
+ mattr_accessor :support_site_url
23
+ @@support_site_url = 'http://google.com'
24
+
25
+ # Quickbooks owner id provided in qwc file
26
+ mattr_accessor :owner_id
27
+ @@owner_id = '{57F3B9B1-86F1-4fcc-B1EE-566DE1813D20}'
28
+
29
+ # Job definitions
30
+ mattr_reader :jobs
31
+ @@jobs = {}
32
+
33
+ mattr_reader :on_error
34
+ @@on_error = 'stopOnError'
35
+ # Do processing after session termination
36
+ # Enabling this option will speed up qbwc session time but will necessarily eat
37
+ # up more memory since every response must be stored until it is processed.
38
+ mattr_accessor :delayed_processing
39
+ @@delayed_processing = false
40
+
41
+ # Quickbooks Type (either :qb or :qbpos)
42
+ mattr_reader :api, :parser
43
+ @@api= ::Quickbooks::API[:qb]
44
+
45
+ class << self
46
+
47
+ def add_job(name, &block)
48
+ @@jobs[name] = Job.new(name, &block)
49
+ end
50
+
51
+ def on_error=(reaction)
52
+ raise 'Quickbooks type must be :qb or :qbpos' unless [:stop, :continue].include?(reaction)
53
+ @@on_error = "stopOnError" if reaction == :stop
54
+ @@on_error = "continueOnError" if reaction == :continue
55
+ end
56
+
57
+ def api=(api)
58
+ raise 'Quickbooks type must be :qb or :qbpos' unless [:qb, :qbpos].include?(api)
59
+ @@api = api
60
+ @@parser = ::Quickbooks::API[api]
61
+ end
62
+
63
+ # Allow configuration overrides
64
+ def configure
65
+ yield self
66
+ end
67
+
68
+
69
+ end
70
+
71
+ end
72
+
73
+ require 'fiber'
74
+
75
+ #Todo Move this to Autolaod
76
+ require 'qbwc/soap_wrapper/default'
77
+ require 'qbwc/soap_wrapper/defaultMappingRegistry'
78
+ require 'qbwc/soap_wrapper/defaultServant'
79
+ require 'qbwc/soap_wrapper/QBWebConnectorSvc'
80
+ require 'qbwc/soap_wrapper'
81
+ require 'qbwc/session'
82
+ require 'qbwc/request'
83
+ require 'qbwc/job'
@@ -0,0 +1,47 @@
1
+ class QBWC::Job
2
+
3
+ attr_reader :name, :response_proc, :requests
4
+
5
+ def initialize(name, &block)
6
+ @name = name
7
+ @enabled = true
8
+ @requests = block
9
+
10
+ reset
11
+ end
12
+
13
+ def set_response_proc(&block)
14
+ @response_proc = block
15
+ end
16
+
17
+ def enable
18
+ @enabled = true
19
+ end
20
+
21
+ def disable
22
+ @enabled = false
23
+ end
24
+
25
+ def enabled?
26
+ @enabled
27
+ end
28
+
29
+ def next
30
+ @request_gen.alive? ? @request_gen.resume : nil
31
+ end
32
+
33
+ def reset
34
+ @request_gen = new_request_generator
35
+ end
36
+
37
+ private
38
+
39
+ def new_request_generator
40
+ Fiber.new { request_queue.each { |r| Fiber.yield r }; nil }
41
+ end
42
+
43
+ def request_queue
44
+ QBWC::Request.from_array(@requests.call, @response_proc )
45
+ end
46
+
47
+ end