qbfc 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +11 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +85 -0
- data/Rakefile +84 -0
- data/VERSION +1 -0
- data/lib/qbfc.rb +41 -0
- data/lib/qbfc/base.rb +82 -0
- data/lib/qbfc/element.rb +243 -0
- data/lib/qbfc/entities/generated.rb +8 -0
- data/lib/qbfc/entity.rb +11 -0
- data/lib/qbfc/info.rb +42 -0
- data/lib/qbfc/infos/generated.rb +9 -0
- data/lib/qbfc/item.rb +29 -0
- data/lib/qbfc/items/generated.rb +11 -0
- data/lib/qbfc/list.rb +84 -0
- data/lib/qbfc/lists/account.rb +24 -0
- data/lib/qbfc/lists/generated.rb +15 -0
- data/lib/qbfc/lists/qb_class.rb +25 -0
- data/lib/qbfc/modifiable.rb +31 -0
- data/lib/qbfc/ole_wrapper.rb +201 -0
- data/lib/qbfc/qb_collection.rb +26 -0
- data/lib/qbfc/qb_types.rb +18 -0
- data/lib/qbfc/qbfc_const.rb +14 -0
- data/lib/qbfc/report.rb +95 -0
- data/lib/qbfc/reports/aging.rb +13 -0
- data/lib/qbfc/reports/budget_summary.rb +13 -0
- data/lib/qbfc/reports/custom_detail.rb +9 -0
- data/lib/qbfc/reports/custom_summary.rb +9 -0
- data/lib/qbfc/reports/general_detail.rb +44 -0
- data/lib/qbfc/reports/general_summary.rb +33 -0
- data/lib/qbfc/reports/job.rb +14 -0
- data/lib/qbfc/reports/payroll_detail.rb +13 -0
- data/lib/qbfc/reports/payroll_summary.rb +13 -0
- data/lib/qbfc/reports/rows.rb +51 -0
- data/lib/qbfc/reports/time.rb +12 -0
- data/lib/qbfc/request.rb +295 -0
- data/lib/qbfc/session.rb +147 -0
- data/lib/qbfc/terms.rb +10 -0
- data/lib/qbfc/terms/generated.rb +10 -0
- data/lib/qbfc/transaction.rb +110 -0
- data/lib/qbfc/transactions/generated.rb +25 -0
- data/lib/qbfc/voidable.rb +11 -0
- data/qbfc.gemspec +166 -0
- data/spec/fixtures/test.lgb +0 -0
- data/spec/fixtures/test.qbw +0 -0
- data/spec/fixtures/test.qbw.TLG +0 -0
- data/spec/integration/add_spec.rb +31 -0
- data/spec/integration/base_spec.rb +18 -0
- data/spec/integration/belongs_to_spec.rb +64 -0
- data/spec/integration/company_spec.rb +30 -0
- data/spec/integration/conditions_spec.rb +59 -0
- data/spec/integration/customer_spec.rb +46 -0
- data/spec/integration/element_finders_spec.rb +20 -0
- data/spec/integration/quick_test.rb +31 -0
- data/spec/integration/request_options_spec.rb +68 -0
- data/spec/rcov.opts +1 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +62 -0
- data/spec/unit/base_spec.rb +138 -0
- data/spec/unit/element_finder_spec.rb +185 -0
- data/spec/unit/element_spec.rb +108 -0
- data/spec/unit/entities/generated_spec.rb +18 -0
- data/spec/unit/entity_spec.rb +18 -0
- data/spec/unit/info/generated_spec.rb +12 -0
- data/spec/unit/info_spec.rb +48 -0
- data/spec/unit/item_spec.rb +33 -0
- data/spec/unit/items/generated_spec.rb +16 -0
- data/spec/unit/list_finders_spec.rb +129 -0
- data/spec/unit/list_spec.rb +86 -0
- data/spec/unit/lists/account_spec.rb +20 -0
- data/spec/unit/lists/generated_spec.rb +15 -0
- data/spec/unit/lists/qb_class_spec.rb +9 -0
- data/spec/unit/modifiable_spec.rb +84 -0
- data/spec/unit/ole_wrapper_spec.rb +337 -0
- data/spec/unit/qb_collection_spec.rb +13 -0
- data/spec/unit/qbfc_const_spec.rb +10 -0
- data/spec/unit/qbfc_spec.rb +10 -0
- data/spec/unit/report_spec.rb +12 -0
- data/spec/unit/request_query_survey.txt +48 -0
- data/spec/unit/request_spec.rb +486 -0
- data/spec/unit/session_spec.rb +144 -0
- data/spec/unit/terms/generated_spec.rb +14 -0
- data/spec/unit/terms_spec.rb +18 -0
- data/spec/unit/transaction_finders_spec.rb +125 -0
- data/spec/unit/transaction_spec.rb +94 -0
- data/spec/unit/transactions/generated_spec.rb +20 -0
- data/spec/unit/voidable_spec.rb +32 -0
- data/tasks/qbfc_tasks.rake +4 -0
- metadata +182 -0
data/lib/qbfc/entity.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
module QBFC
|
2
|
+
# Entity objects are Customers, Employees, Vendors and OtherNames
|
3
|
+
class Entity < List
|
4
|
+
is_base_class
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
# Require subclass files
|
9
|
+
Dir.new(File.dirname(__FILE__) + '/entities').each do |file|
|
10
|
+
require('qbfc/entities/' + File.basename(file)) if File.extname(file) == ".rb"
|
11
|
+
end
|
data/lib/qbfc/info.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module QBFC
|
2
|
+
# Info objects are those which have only one instance within Quickbooks,
|
3
|
+
# which are: Company, CompanyActivity, Host and Preferences.
|
4
|
+
#
|
5
|
+
# Access through QBFC for these objects is read-only.
|
6
|
+
#
|
7
|
+
# QBFC::Info can be accessed via session::company, for example, or
|
8
|
+
# through QBFC::Company::get(session).
|
9
|
+
class Info < Base
|
10
|
+
class << self
|
11
|
+
|
12
|
+
# Get the Info object for the given session.
|
13
|
+
# session.[qb_name] aliases this functionality.
|
14
|
+
# For example QBFC::Company.get(session) and
|
15
|
+
# session.company are equivalent.
|
16
|
+
#
|
17
|
+
# It accepts the follow options as a hash:
|
18
|
+
# - <tt>:owner_id</tt>: One or more OwnerIDs, used in accessing
|
19
|
+
# custom fields (aka private data extensions).
|
20
|
+
def get(sess, *args)
|
21
|
+
# Setup q, options and base_options arguments
|
22
|
+
q, options, base_options = parse_find_args(*args)
|
23
|
+
q ||= create_query(sess)
|
24
|
+
q.apply_options(options)
|
25
|
+
|
26
|
+
new(sess, q.response)
|
27
|
+
end
|
28
|
+
|
29
|
+
# This is a convenience alias for +get+.
|
30
|
+
# It exists solely so that I don't have to modify
|
31
|
+
# Session#method_missing.
|
32
|
+
def find(sess, what, *args) #:nodoc:
|
33
|
+
get(sess, *args)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Require subclass files
|
40
|
+
Dir.new(File.dirname(__FILE__) + '/infos').each do |file|
|
41
|
+
require('qbfc/infos/' + File.basename(file)) if File.extname(file) == ".rb"
|
42
|
+
end
|
data/lib/qbfc/item.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module QBFC
|
2
|
+
class Item < List
|
3
|
+
is_base_class
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# Adds a SpecialItem.
|
8
|
+
#
|
9
|
+
# +item_type+ should be a constent, for example:
|
10
|
+
#
|
11
|
+
# Account.add_special(sess, QBFC_CONST::SitFinanceCharge)
|
12
|
+
#
|
13
|
+
# See SDK docs for SpecialItemAdd for more details.
|
14
|
+
def add_special(sess, item_type)
|
15
|
+
rq = QBFC::Request.new(sess, "SpecialItemAdd")
|
16
|
+
rq.special_item_type = item_type
|
17
|
+
|
18
|
+
# Insofar as I never actually plan to use this method, just return
|
19
|
+
# response.
|
20
|
+
return rq.response
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Require subclass files
|
27
|
+
Dir.new(File.dirname(__FILE__) + '/items').each do |file|
|
28
|
+
require('qbfc/items/' + File.basename(file)) if File.extname(file) == ".rb"
|
29
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module QBFC
|
2
|
+
|
3
|
+
# Generated Item Types (Inherit from List)
|
4
|
+
ITEM_TYPES = %w{ItemService ItemNonInventory ItemOtherCharge ItemInventory ItemInventoryAssembly ItemFixedAsset
|
5
|
+
ItemSubtotal ItemDiscount ItemPayment ItemSalesTax ItemSalesTaxGroup ItemGroup}
|
6
|
+
|
7
|
+
# Generate Item subclasses
|
8
|
+
# NB: All Items are Modifiable
|
9
|
+
generate(ITEM_TYPES, Item, {Modifiable => ITEM_TYPES})
|
10
|
+
|
11
|
+
end
|
data/lib/qbfc/list.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
module QBFC
|
2
|
+
# List objects are those with names, such as Accounts, Entities, and Items.
|
3
|
+
#
|
4
|
+
# Note on the name: it doesn't make sense since a List is actually a single object,
|
5
|
+
# but it fits with the SDK's naming scheme, and I couldn't think of a better one.
|
6
|
+
class List < Element
|
7
|
+
is_base_class
|
8
|
+
ID_NAME = "ListID"
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
# Find by name (actually, FullName) of List record.
|
13
|
+
# +options+ are the same as those for in +find+.
|
14
|
+
def find_by_name(sess, full_name, options = {})
|
15
|
+
q = create_query(sess)
|
16
|
+
q.query.FullNameList.Add(full_name)
|
17
|
+
find(sess, :first, q, options)
|
18
|
+
end
|
19
|
+
|
20
|
+
alias_method :find_by_full_name, :find_by_name
|
21
|
+
|
22
|
+
# Find by ListID of List record.
|
23
|
+
# +options+ are the same as those for in +find+.
|
24
|
+
def find_by_id(sess, id, options = {})
|
25
|
+
q = create_query(sess)
|
26
|
+
q.query.ListIDList.Add(id)
|
27
|
+
find(sess, :first, q, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Find by either name or id. Tries id first, then name.
|
31
|
+
def find_by_name_or_id(*args)
|
32
|
+
find_by_id(*args) || find_by_name(*args)
|
33
|
+
end
|
34
|
+
|
35
|
+
alias_method :find_by_unique_id, :find_by_name_or_id
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# Alias of ListID for this record. This is a unique within each type of List.
|
40
|
+
def id
|
41
|
+
@ole.list_id
|
42
|
+
end
|
43
|
+
|
44
|
+
# If an entity has a Name field but not a FullName field,
|
45
|
+
# use Name (which, by implication, is the FullName)
|
46
|
+
def full_name
|
47
|
+
respond_to_ole?("FullName") ?
|
48
|
+
@ole.full_name :
|
49
|
+
@ole.name
|
50
|
+
end
|
51
|
+
|
52
|
+
# Delete this List record.
|
53
|
+
def delete
|
54
|
+
req = QBFC::Request.new(@sess, "ListDel")
|
55
|
+
req.list_del_type = QBFC_CONST::const_get("Ldt#{qb_name}")
|
56
|
+
req.list_id = id
|
57
|
+
req.submit
|
58
|
+
return true
|
59
|
+
end
|
60
|
+
|
61
|
+
# Display the Transaction add (for new records) or edit dialog box
|
62
|
+
def display
|
63
|
+
if new_record?
|
64
|
+
req = QBFC::Request.new(@sess, "ListDisplayAdd")
|
65
|
+
req.list_display_add_type = QBFC_CONST::const_get("Ldat#{qb_name}")
|
66
|
+
else
|
67
|
+
req = QBFC::Request.new(@sess, "ListDisplayMod")
|
68
|
+
req.list_display_mod_type = QBFC_CONST::const_get("Ldmt#{qb_name}")
|
69
|
+
req.list_id = id
|
70
|
+
end
|
71
|
+
req.submit
|
72
|
+
return true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Require subclass files
|
78
|
+
%w{ entity item terms }.each do |file|
|
79
|
+
require 'qbfc/' + file
|
80
|
+
end
|
81
|
+
|
82
|
+
Dir.new(File.dirname(__FILE__) + '/lists').each do |file|
|
83
|
+
require('qbfc/lists/' + File.basename(file)) if File.extname(file) == ".rb"
|
84
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module QBFC
|
2
|
+
class Account < List
|
3
|
+
include Modifiable
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# Adds a SpecialAccount, per SDK documentation:
|
8
|
+
# "An account normally created automatically as needed within the
|
9
|
+
# QuickBooks UI, or in the SDK via the SpecialAccountAdd request."
|
10
|
+
#
|
11
|
+
# +account_type+ should be a constent, for example:
|
12
|
+
#
|
13
|
+
# Account.add_special(sess, QBFC_CONST::SatAccountsPayable)
|
14
|
+
#
|
15
|
+
# See SDK docs for SpecialAccountAdd for more details.
|
16
|
+
def add_special(sess, account_type)
|
17
|
+
rq = QBFC::Request.new(sess, "SpecialAccountAdd")
|
18
|
+
rq.special_account_type = account_type
|
19
|
+
|
20
|
+
new(sess, rq.response)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module QBFC
|
2
|
+
|
3
|
+
# Generated List types that will inherit directly from QBFC::List
|
4
|
+
LIST_TYPES = %w{ BillingRate CustomerMsg CustomerType JobType PaymentMethod
|
5
|
+
PayrollItemNonWage PayrollItemWage PriceLevel SalesRep SalesTaxCode
|
6
|
+
ShipMethod ToDo Vehicle VendorType}
|
7
|
+
|
8
|
+
# Generated List types that do accept Mod Requests
|
9
|
+
# (most direct subclasses of List do not)
|
10
|
+
LIST_MOD_TYPES = %w{ PriceLevel SalesRep Vehicle }
|
11
|
+
|
12
|
+
# Generate List subclasses
|
13
|
+
generate(LIST_TYPES, List, {Modifiable => LIST_MOD_TYPES})
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module QBFC
|
2
|
+
# QBClass objects represent QuickBooks SDK's <tt>Class</tt> objects.
|
3
|
+
# As naming this Class <tt>Class</tt> would be impractical, it is
|
4
|
+
# instead called QBClass. It is otherwise similar to the other List
|
5
|
+
# classes.
|
6
|
+
#
|
7
|
+
# From QBFC6 SDK docs:
|
8
|
+
#
|
9
|
+
# Classes can be used to separate transactions into meaningful categories.
|
10
|
+
# (For example, transactions could be classified according to department,
|
11
|
+
# business location, or type of work.) In QuickBooks, class tracking is
|
12
|
+
# off by default.
|
13
|
+
class QBClass < List
|
14
|
+
class << self
|
15
|
+
|
16
|
+
# The QuickBooks SDK class is called 'Class'.
|
17
|
+
# Calling this class QBClass avoids making ruby
|
18
|
+
# very angry; the qb_name method ensures that calls
|
19
|
+
# to QBFC use the correct name.
|
20
|
+
def qb_name
|
21
|
+
"Class"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module QBFC
|
2
|
+
module Modifiable
|
3
|
+
|
4
|
+
# Extend initialize of including classes to set up a Mod Request
|
5
|
+
# if the record is existing.
|
6
|
+
def initialize(*args)
|
7
|
+
super
|
8
|
+
|
9
|
+
unless @new_record
|
10
|
+
setup_mod_request
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Setup a Mod Request for this object and attach it
|
15
|
+
# to the ole object.
|
16
|
+
def setup_mod_request
|
17
|
+
@setter = QBFC::Request.new(@sess, "#{self.qb_name}Mod")
|
18
|
+
|
19
|
+
if self.kind_of?(List)
|
20
|
+
@setter.list_id = id
|
21
|
+
else # Transaction
|
22
|
+
@setter.txn_id = id
|
23
|
+
end
|
24
|
+
|
25
|
+
@setter.edit_sequence = @ole.edit_sequence
|
26
|
+
@ole.setter = @setter.ole_object
|
27
|
+
end
|
28
|
+
|
29
|
+
private :setup_mod_request
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
module QBFC
|
2
|
+
|
3
|
+
# OLEWrapper is more or less the centerpiece of RubyQBFC. (Nearly) every
|
4
|
+
# WIN32OLE object accessed within the library is wrapped in this class, which
|
5
|
+
# is responsible for allowing Ruby-esque methods in place of the OLE methods.
|
6
|
+
#
|
7
|
+
# customer.full_name # => Customer.FullName.GetValue
|
8
|
+
# customer.full_name=(val) # => Customer.FullName.SetValue(val)
|
9
|
+
#
|
10
|
+
# It also creates referenced objects when accessed.
|
11
|
+
#
|
12
|
+
# check.payee # => Entity.find_by_list_id(check.PayeeEntityRef.ListID.GetValue)
|
13
|
+
# check.account # => Account.find_by_list_id(check.AccountRef.ListID.GetValue)
|
14
|
+
#
|
15
|
+
# When an OLE method called via OLEWrapper returns a WIN32OLE object, a new
|
16
|
+
# OLEWrapper object is created with the WIN32OLE object and returned.
|
17
|
+
#
|
18
|
+
# Now, the fun (and +really+ hackish) part. In many cases within the QBFC
|
19
|
+
# library, the wrapper is actually wrapping two WIN32OLE objects, the additional
|
20
|
+
# being a 'setter' object. This object is used when creating a ModRequest. In
|
21
|
+
# such cases, a method ending in '=' is always sent to both the primary and the
|
22
|
+
# setter objects. To facilitate this, traversing child ole_objects also
|
23
|
+
# traverses the child setter objects.
|
24
|
+
class OLEWrapper
|
25
|
+
attr_reader :ole_object
|
26
|
+
attr_accessor :setter
|
27
|
+
|
28
|
+
# Set up wrapped object, by passing a WIN32OLE object
|
29
|
+
# (or a String with the name of a WIN32OLE server)
|
30
|
+
# Optionally, pass a +setter+ WIN32OLE object.
|
31
|
+
def initialize(ole_object, setter = nil)
|
32
|
+
ole_object = WIN32OLE.new(ole_object) if ole_object.kind_of?(String)
|
33
|
+
@ole_object = ole_object
|
34
|
+
@setter = setter
|
35
|
+
end
|
36
|
+
|
37
|
+
# Return Array of ole_methods for request WIN32OLE object.
|
38
|
+
def ole_methods
|
39
|
+
@ole_object.ole_methods
|
40
|
+
end
|
41
|
+
|
42
|
+
# Does this OLE object respond to the given ole method?
|
43
|
+
def respond_to_ole?(symbol)
|
44
|
+
detect_ole_method?(@ole_object, symbol)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Use [idx] syntax for objects that respond to <tt>GetAt(idx)</tt>
|
48
|
+
def [](idx)
|
49
|
+
if idx.kind_of? Integer
|
50
|
+
self.class.new(@ole_object.GetAt(idx))
|
51
|
+
else
|
52
|
+
@ole_object[idx]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Called by #method_missing of other classes. Initiates the OLEWrapper#method_missing
|
57
|
+
# method which is responsible for the various method conversions.
|
58
|
+
# +sess+ argument is a QBFC::Session.
|
59
|
+
def qbfc_method_missing(sess, symbol, *params)
|
60
|
+
@sess = sess
|
61
|
+
method_missing(symbol, *params)
|
62
|
+
end
|
63
|
+
|
64
|
+
# If the method name is capitalized, send directly to ole_object; if
|
65
|
+
# a WIN32OLE is returned, wrap it.
|
66
|
+
# If the method name starts with a lower-case letter, send to +lower_method_missing+
|
67
|
+
# for conversion.
|
68
|
+
def method_missing(symbol, *params) #:nodoc:
|
69
|
+
if (('a'..'z') === symbol.to_s[0].chr)
|
70
|
+
lower_case_method_missing(symbol, *params)
|
71
|
+
else
|
72
|
+
resp = @ole_object.send(symbol, *params)
|
73
|
+
return( resp.kind_of?(WIN32OLE) ?
|
74
|
+
self.class.new(resp) :
|
75
|
+
resp )
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# Decide which conversion method needs to handle this method and send.
|
82
|
+
def lower_case_method_missing(symbol, *params)
|
83
|
+
if '=' == symbol.to_s[-1].chr
|
84
|
+
set_value(symbol.to_s[0..-2], *params)
|
85
|
+
elsif symbol.to_s =~ /\A(\w+)_(full_name|id)\Z/ && ref_name($1)
|
86
|
+
get_ref_name_or_id(ref_name($1), $2)
|
87
|
+
elsif detect_ole_method?(@ole_object, ole_sym(symbol))
|
88
|
+
get_value(symbol, *params)
|
89
|
+
elsif detect_ole_method?(@ole_object, (s = symbol.to_s.singularize.camelize + "RetList"))
|
90
|
+
setup_array(s)
|
91
|
+
elsif detect_ole_method?(@ole_object, (s = "OR" + symbol.to_s.singularize.camelize + "RetList"))
|
92
|
+
setup_array(s, true)
|
93
|
+
elsif detect_ole_method?(@ole_object, (s = symbol.to_s.singularize.camelize + "List"))
|
94
|
+
setup_array(s)
|
95
|
+
elsif detect_ole_method?(@ole_object, (s = "OR" + symbol.to_s.singularize.camelize + "List"))
|
96
|
+
setup_array(s, true)
|
97
|
+
elsif ref_name(symbol)
|
98
|
+
create_ref(ref_name(symbol), *params)
|
99
|
+
elsif detect_ole_method?(@ole_object, symbol)
|
100
|
+
# Occassionally, QBFC uses a lower case method
|
101
|
+
@ole_object.send(symbol, *params)
|
102
|
+
else
|
103
|
+
raise NoMethodError, symbol.to_s
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Sets a value by calling OLEMethodName.SetValue(*params)
|
108
|
+
def set_value(ole_method_name, *params)
|
109
|
+
ole_method_name = ole_sym(ole_method_name)
|
110
|
+
obj = @ole_object.send(ole_method_name)
|
111
|
+
|
112
|
+
if detect_ole_method?(obj, "SetValue")
|
113
|
+
params[0] = params[0].strftime("%Y-%m-%d") if params[0].kind_of?(Date)
|
114
|
+
obj.SetValue(*params)
|
115
|
+
if @setter && detect_ole_method?(@setter, ole_method_name)
|
116
|
+
@setter.send(ole_method_name).SetValue(*params)
|
117
|
+
end
|
118
|
+
else
|
119
|
+
raise SetValueMissing, "SetValue is expected, but missing, for #{ole_method_name}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Gets a value by calling OLEMethodName.GetValue
|
124
|
+
def get_value(ole_method_name, *params)
|
125
|
+
ole_method_name = ole_sym(ole_method_name)
|
126
|
+
obj = @ole_object.send(ole_method_name, *params)
|
127
|
+
if detect_ole_method?(obj, "GetValue")
|
128
|
+
if ole_method_name =~ /date/i || ole_method_name.to_s =~ /time/i
|
129
|
+
Time.parse(obj.GetValue)
|
130
|
+
else
|
131
|
+
obj.GetValue
|
132
|
+
end
|
133
|
+
else
|
134
|
+
if obj.kind_of?(WIN32OLE)
|
135
|
+
if @setter && detect_ole_method?(@setter, ole_method_name)
|
136
|
+
self.class.new(obj, @setter.send(ole_method_name, *params))
|
137
|
+
else
|
138
|
+
self.class.new(obj)
|
139
|
+
end
|
140
|
+
else
|
141
|
+
obj
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Sets up an array to return if the return of OLEMethodName appears
|
147
|
+
# to be a list structure.
|
148
|
+
# <tt>is_OR_list</tt> indicates the list is an OR*RetList which
|
149
|
+
# is structured differently.
|
150
|
+
def setup_array(ole_method_name, is_OR_list = false)
|
151
|
+
list = @ole_object.send(ole_method_name)
|
152
|
+
ary = []
|
153
|
+
0.upto(list.Count - 1) do |i|
|
154
|
+
if is_OR_list
|
155
|
+
ary << self.class.new(list.GetAt(i)).send(ole_method_name.match(/\AOR(.*)List\Z/)[1])
|
156
|
+
else
|
157
|
+
ary << self.class.new(list.GetAt(i))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
return ary
|
161
|
+
end
|
162
|
+
|
163
|
+
def ref_name(symbol)
|
164
|
+
if detect_ole_method?(@ole_object, symbol.to_s.camelize + "Ref")
|
165
|
+
symbol.to_s.camelize + "Ref"
|
166
|
+
elsif detect_ole_method?(@ole_object, symbol.to_s.camelize + "EntityRef")
|
167
|
+
symbol.to_s.camelize + "EntityRef"
|
168
|
+
else
|
169
|
+
nil
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Creates a QBFC::Base inherited object if the return of
|
174
|
+
# OLEMethodName appears to be a reference to such an object.
|
175
|
+
def create_ref(ref_ole_name, *options)
|
176
|
+
ref_ole_object = @ole_object.send(ref_ole_name)
|
177
|
+
if ref_ole_object
|
178
|
+
ref_ole_name =~ /EntityRef/ ?
|
179
|
+
QBFC::Entity.find_by_id(@sess, ref_ole_object.ListID.GetValue(), *options) :
|
180
|
+
QBFC::const_get(ref_ole_name.gsub(/Ref/,"")).find_by_id(@sess, ref_ole_object.ListID.GetValue(), *options)
|
181
|
+
else
|
182
|
+
return nil
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def get_ref_name_or_id(symbol, field)
|
187
|
+
field = (field == "id" ? "ListID" : "FullName")
|
188
|
+
@ole_object.send(symbol).send(field).GetValue()
|
189
|
+
end
|
190
|
+
|
191
|
+
# Check if the obj has an ole_method matching the symbol.
|
192
|
+
def detect_ole_method?(obj, symbol)
|
193
|
+
obj && obj.respond_to?(:ole_methods) && obj.ole_methods.detect{|m| m.to_s == symbol.to_s}
|
194
|
+
end
|
195
|
+
|
196
|
+
# Helper method to convert 'Ruby-ish' method name to WIN32OLE method name
|
197
|
+
def ole_sym(symbol)
|
198
|
+
symbol.to_s.camelize.gsub(/Id/, 'ID')
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|