clearbooks 0.16.3
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/AUTHORS.md +31 -0
- data/CHANGELOG.md +0 -0
- data/COPYING.md +12 -0
- data/FAQ.md +8 -0
- data/Gemfile +105 -0
- data/LICENSE.md +14 -0
- data/MAINTAINERS.md +40 -0
- data/README.md +549 -0
- data/Rakefile +94 -0
- data/Thorfile +80 -0
- data/bin/clearbooks +28 -0
- data/clearbooks.gemspec +119 -0
- data/examples/demo.rb +8 -0
- data/lib/clearbooks.rb +92 -0
- data/lib/clearbooks/core_ext.rb +8 -0
- data/lib/clearbooks/core_ext/array.rb +51 -0
- data/lib/clearbooks/core_ext/hash.rb +47 -0
- data/lib/clearbooks/core_ext/io_binary_read.rb +20 -0
- data/lib/clearbooks/core_ext/string.rb +21 -0
- data/lib/clearbooks/error.rb +8 -0
- data/lib/clearbooks/error/errors.rb +228 -0
- data/lib/clearbooks/interface/rake/cucumber.rb +36 -0
- data/lib/clearbooks/interface/rake/default.rb +28 -0
- data/lib/clearbooks/interface/rake/documentation.rb +45 -0
- data/lib/clearbooks/interface/rake/guard.rb +13 -0
- data/lib/clearbooks/interface/rake/helpers.rb +27 -0
- data/lib/clearbooks/interface/rake/library.rb +126 -0
- data/lib/clearbooks/interface/rake/metric.rb +15 -0
- data/lib/clearbooks/interface/rake/rspec.rb +31 -0
- data/lib/clearbooks/interface/thor/info.thor +292 -0
- data/lib/clearbooks/interface/thor/mixin/config_choice.rb +27 -0
- data/lib/clearbooks/interface/thor/mixin/configuration.rb +28 -0
- data/lib/clearbooks/interface/thor/mixin/default.rb +30 -0
- data/lib/clearbooks/interface/thor/mixin/default_config.rb +31 -0
- data/lib/clearbooks/interface/thor/mixin/guess.rb +57 -0
- data/lib/clearbooks/interface/thor/mixin/shell.rb +225 -0
- data/lib/clearbooks/interface/thor/version.thor +34 -0
- data/lib/clearbooks/library/client.rb +257 -0
- data/lib/clearbooks/library/configuration.rb +34 -0
- data/lib/clearbooks/model/account_code.rb +65 -0
- data/lib/clearbooks/model/base.rb +67 -0
- data/lib/clearbooks/model/entity.rb +225 -0
- data/lib/clearbooks/model/invoice.rb +163 -0
- data/lib/clearbooks/model/item.rb +78 -0
- data/lib/clearbooks/model/journal.rb +74 -0
- data/lib/clearbooks/model/ledger.rb +52 -0
- data/lib/clearbooks/model/payment.rb +113 -0
- data/lib/clearbooks/model/project.rb +58 -0
- data/lib/clearbooks/version.rb +12 -0
- data/spec/clearbooks/clearbooks_spec.rb +27 -0
- data/spec/clearbooks/model/account_code_spec.rb +52 -0
- data/spec/clearbooks/model/entity_spec.rb +107 -0
- data/spec/clearbooks/model/invoice_spec.rb +109 -0
- data/spec/clearbooks/model/journal_spec.rb +77 -0
- data/spec/clearbooks/model/payment_spec.rb +103 -0
- data/spec/clearbooks/model/project_spec.rb +72 -0
- data/spec/fixtures/response/allocate_payment.xml +12 -0
- data/spec/fixtures/response/create_entity.xml +12 -0
- data/spec/fixtures/response/create_invoice.xml +11 -0
- data/spec/fixtures/response/create_journal.xml +12 -0
- data/spec/fixtures/response/create_payment.xml +12 -0
- data/spec/fixtures/response/create_project.xml +12 -0
- data/spec/fixtures/response/delete_entity.xml +12 -0
- data/spec/fixtures/response/delete_journal.xml +12 -0
- data/spec/fixtures/response/list_account_codes.xml +168 -0
- data/spec/fixtures/response/list_entities.xml +45 -0
- data/spec/fixtures/response/list_invoices.xml +56 -0
- data/spec/fixtures/response/list_projects.xml +16 -0
- data/spec/fixtures/response/no_api_key_fault.xml +8 -0
- data/spec/fixtures/response/well_formed_request.xml +10 -0
- data/spec/fixtures/response/wrong_api_key_fault.xml +8 -0
- data/spec/spec_helper.rb +26 -0
- metadata +212 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
# @class class Hash
|
5
|
+
# @brief Ruby Hash Object functions adding Savon and some other tweaks
|
6
|
+
class Hash
|
7
|
+
|
8
|
+
# @fn def except *keys {{{
|
9
|
+
# @brief Deletes specified keys from hash copy and returns it
|
10
|
+
# @credit https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/hash/except.rb
|
11
|
+
def except(*keys)
|
12
|
+
copy = self.dup
|
13
|
+
keys.each { |key| copy.delete(key) }
|
14
|
+
copy
|
15
|
+
end # }}}
|
16
|
+
|
17
|
+
# @fn def compact {{{
|
18
|
+
# @brief Deletes keys with +nil+ values from hash copy and returns it
|
19
|
+
def compact
|
20
|
+
delete_if { |k, v| v.nil? }
|
21
|
+
end # }}}
|
22
|
+
|
23
|
+
# @fn def savon key {{{
|
24
|
+
# @brief Savon shortcut to get attributes via :key or :@key
|
25
|
+
def savon(key)
|
26
|
+
v = self[key] || self["@#{(key.to_s)}".to_sym]
|
27
|
+
if (v.is_a? Hash)
|
28
|
+
v.from_savon
|
29
|
+
else
|
30
|
+
v
|
31
|
+
end
|
32
|
+
end # }}}
|
33
|
+
|
34
|
+
# @fn def from_savon {{{
|
35
|
+
# @brief Translates ":@key" savon attribute keys to ":key"
|
36
|
+
def from_savon
|
37
|
+
self.reduce({}) do |hash, (k, v)|
|
38
|
+
k = k.to_s
|
39
|
+
k = k[1..-1] if k.start_with? '@'
|
40
|
+
hash[k.to_sym] = v
|
41
|
+
hash
|
42
|
+
end
|
43
|
+
end # }}}
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
# @class class IO #:nodoc:
|
5
|
+
#
|
6
|
+
# @credit https://github.com/erikhuda/thor/blob/master/lib/thor/core_ext/io_binary_read.rb
|
7
|
+
class IO
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def binread(file, *args)
|
11
|
+
fail ArgumentError, "wrong number of arguments (#{1 + args.size} for 1..3)" unless args.size < 3
|
12
|
+
File.open(file, "rb") do |f|
|
13
|
+
f.read(*args)
|
14
|
+
end
|
15
|
+
end unless method_defined? :binread
|
16
|
+
end
|
17
|
+
|
18
|
+
end # of class IO
|
19
|
+
|
20
|
+
# vim:ts=2:tw=100:wm=100
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
# @class class String
|
5
|
+
# @brief Ruby core String handling
|
6
|
+
class String
|
7
|
+
|
8
|
+
TRUE_VALUES = %W{1 t true on y yes}.freeze
|
9
|
+
|
10
|
+
# @fn def to_b {{{
|
11
|
+
# @brief Converts String to Boolean value
|
12
|
+
#
|
13
|
+
# @credit https://github.com/prodis/wannabe_bool/blob/master/lib/wannabe_bool/object.rb
|
14
|
+
def to_b
|
15
|
+
TRUE_VALUES.include?(self.to_s.strip.downcase)
|
16
|
+
end # }}}
|
17
|
+
|
18
|
+
end # of class String
|
19
|
+
|
20
|
+
|
21
|
+
# vim:ts=2:tw=100:wm=100
|
@@ -0,0 +1,228 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
# @module module Clearbooks
|
5
|
+
# @brief Clearbooks module namespace
|
6
|
+
module Clearbooks
|
7
|
+
|
8
|
+
|
9
|
+
class ClearbooksError < StandardError
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# @param [Integer] code
|
13
|
+
def status_code(code)
|
14
|
+
define_method(:status_code) { code }
|
15
|
+
define_singleton_method(:status_code) { code }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
alias_method :message, :to_s
|
20
|
+
end # of class ClearbooksError
|
21
|
+
|
22
|
+
class DeprecatedError < ClearbooksError; status_code(10); end
|
23
|
+
class InternalError < ClearbooksError; status_code(99); end
|
24
|
+
class ArgumentError < InternalError; end
|
25
|
+
class AbstractFunction < InternalError; end
|
26
|
+
|
27
|
+
class ClearbooksfileNotFound < ClearbooksError
|
28
|
+
status_code(100)
|
29
|
+
|
30
|
+
# @param [#to_s] filepath
|
31
|
+
# the path where a Clearbooksfile was not found
|
32
|
+
def initialize(filepath)
|
33
|
+
@filepath = File.dirname(File.expand_path(filepath)) rescue filepath
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
"No Clearbooksfile or Clearbooksfile.lock found at '#{@filepath}'!"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class CookbookNotFound < ClearbooksError
|
42
|
+
status_code(103)
|
43
|
+
|
44
|
+
def initialize(name, version, location)
|
45
|
+
@name = name
|
46
|
+
@version = version
|
47
|
+
@location = location
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
if @version
|
52
|
+
"Cookbook '#{@name}' (#{@version}) not found #{@location}!"
|
53
|
+
else
|
54
|
+
"Cookbook '#{@name}' not found #{@location}!"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class DuplicateDependencyDefined < ClearbooksError
|
60
|
+
status_code(105)
|
61
|
+
|
62
|
+
def initialize(name)
|
63
|
+
@name = name
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_s
|
67
|
+
out = "Your Clearbooksfile contains multiple entries named "
|
68
|
+
out << "'#{@name}'. Please remove duplicate dependencies, or put them in "
|
69
|
+
out << "different groups."
|
70
|
+
out
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class NoSolutionError < ClearbooksError
|
75
|
+
status_code(106)
|
76
|
+
|
77
|
+
attr_reader :demands
|
78
|
+
|
79
|
+
# @param [Array<Dependency>] demands
|
80
|
+
def initialize(demands)
|
81
|
+
@demands = demands
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_s
|
85
|
+
"Unable to find a solution for demands: #{demands.join(', ')}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class ClearbooksfileReadError < ClearbooksError
|
90
|
+
status_code(113)
|
91
|
+
|
92
|
+
# @param [#status_code] original_error
|
93
|
+
def initialize(original_error)
|
94
|
+
@original_error = original_error
|
95
|
+
@error_message = original_error.to_s
|
96
|
+
@error_backtrace = original_error.backtrace
|
97
|
+
end
|
98
|
+
|
99
|
+
def status_code
|
100
|
+
@original_error.respond_to?(:status_code) ? @original_error.status_code : 113
|
101
|
+
end
|
102
|
+
|
103
|
+
alias_method :original_backtrace, :backtrace
|
104
|
+
def backtrace
|
105
|
+
Array(@error_backtrace) + Array(original_backtrace)
|
106
|
+
end
|
107
|
+
|
108
|
+
def to_s
|
109
|
+
[
|
110
|
+
"An error occurred while reading the Clearbooksfile:",
|
111
|
+
"",
|
112
|
+
" #{@error_message}",
|
113
|
+
].join("\n")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
class InvalidConfiguration < ClearbooksError
|
119
|
+
status_code(115)
|
120
|
+
|
121
|
+
def initialize(errors)
|
122
|
+
@errors = errors
|
123
|
+
end
|
124
|
+
|
125
|
+
def to_s
|
126
|
+
out = "Invalid configuration:\n"
|
127
|
+
@errors.each do |key, errors|
|
128
|
+
errors.each do |error|
|
129
|
+
out << " #{key} #{error}\n"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
out.strip
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class InsufficientPrivledges < ClearbooksError
|
138
|
+
status_code(119)
|
139
|
+
|
140
|
+
def initialize(path)
|
141
|
+
@path = path
|
142
|
+
end
|
143
|
+
|
144
|
+
def to_s
|
145
|
+
"You do not have permission to write to '#{@path}'! Please chown the " \
|
146
|
+
"path to the current user, chmod the permissions to include the " \
|
147
|
+
"user, or choose a different path."
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class DependencyNotFound < ClearbooksError
|
152
|
+
status_code(120)
|
153
|
+
|
154
|
+
# @param [String, Array<String>] names
|
155
|
+
# the list of cookbook names that were not defined
|
156
|
+
def initialize(names)
|
157
|
+
@names = Array(names)
|
158
|
+
end
|
159
|
+
|
160
|
+
def to_s
|
161
|
+
if @names.size == 1
|
162
|
+
"Dependency '#{@names.first}' was not found. Please make sure it is " \
|
163
|
+
"in your Clearbooksfile, and then run `berks install` to download and " \
|
164
|
+
"install the missing dependencies."
|
165
|
+
else
|
166
|
+
out = "The following dependencies were not found:\n"
|
167
|
+
@names.each do |name|
|
168
|
+
out << " * #{name}\n"
|
169
|
+
end
|
170
|
+
out << "\n"
|
171
|
+
out << "Please make sure they are in your Clearbooksfile, and then run "
|
172
|
+
out << "`berks install` to download and install the missing "
|
173
|
+
out << "dependencies."
|
174
|
+
out
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
class LockfileParserError < ClearbooksError
|
181
|
+
status_code(136)
|
182
|
+
|
183
|
+
# @param [String] lockfile
|
184
|
+
# the path to the Lockfile
|
185
|
+
# @param [~Exception] original
|
186
|
+
# the original exception class
|
187
|
+
def initialize(original)
|
188
|
+
@original = original
|
189
|
+
end
|
190
|
+
|
191
|
+
def to_s
|
192
|
+
"Error reading the Clearbooks lockfile:\n\n" \
|
193
|
+
" #{@original.class}: #{@original.message}"
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class LockfileNotFound < ClearbooksError
|
198
|
+
status_code(140)
|
199
|
+
|
200
|
+
def to_s
|
201
|
+
'Lockfile not found! Run `berks install` to create the lockfile.'
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
class LockfileOutOfSync < ClearbooksError
|
207
|
+
status_code(144)
|
208
|
+
|
209
|
+
def to_s
|
210
|
+
'The lockfile is out of sync! Run `berks install` to sync the lockfile.'
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
class NoAPISourcesDefined < ClearbooksError
|
216
|
+
status_code(146)
|
217
|
+
|
218
|
+
def to_s
|
219
|
+
"Your Clearbooksfile does not define any API sources! You must define " \
|
220
|
+
"at least one source in order to download cookbooks. To add the " \
|
221
|
+
"default Clearbooks API server, add the following code to the top of " \
|
222
|
+
"your Clearbooksfile:"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
# vim:ts=2:tw=100:wm=100:syntax=ruby
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
## Handle Cucumber # {{{
|
5
|
+
|
6
|
+
namespace :cucumber do
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'cucumber'
|
10
|
+
require 'cucumber/rake/task'
|
11
|
+
|
12
|
+
desc "Cucumber Core Tasks" # {{{
|
13
|
+
Cucumber::Rake::Task.new(:pretty) do |t|
|
14
|
+
t.cucumber_opts = "--format pretty -S"
|
15
|
+
end # }}}
|
16
|
+
|
17
|
+
desc "Cucumber Core Tasks" # {{{
|
18
|
+
Cucumber::Rake::Task.new(:progress) do |t|
|
19
|
+
t.cucumber_opts = "--format progress -S"
|
20
|
+
end # }}}
|
21
|
+
|
22
|
+
rescue LoadError
|
23
|
+
desc 'Cucumber rake task not available'
|
24
|
+
task :pretty do
|
25
|
+
abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
|
26
|
+
end
|
27
|
+
|
28
|
+
task :progress do
|
29
|
+
abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end # pf namespace }}}
|
34
|
+
|
35
|
+
|
36
|
+
# vim:ts=2:tw=100:wm=100:syntax=ruby
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
# System
|
5
|
+
require 'bundler'
|
6
|
+
require 'bundler/gem_tasks'
|
7
|
+
|
8
|
+
require 'shellwords'
|
9
|
+
require 'fileutils'
|
10
|
+
|
11
|
+
require 'date'
|
12
|
+
require 'ostruct'
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
### General
|
17
|
+
|
18
|
+
desc "Show the default task when executing rake without arguments" # {{{
|
19
|
+
task :default => :help # }}}
|
20
|
+
|
21
|
+
desc "Shows the usage help screen" # {{{
|
22
|
+
task :help do |t|
|
23
|
+
`rake -T`
|
24
|
+
end # }}}
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
# vim:ts=2:tw=100:wm=100:syntax=ruby
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
namespace :docs do
|
5
|
+
|
6
|
+
desc "Generate Yardoc documentation for this project" # {{{
|
7
|
+
task :generate do |t|
|
8
|
+
|
9
|
+
# Define new tags for yardoc to detect
|
10
|
+
tags = {}
|
11
|
+
tags[ "module" ] = "Module"
|
12
|
+
tags[ "class" ] = "Class"
|
13
|
+
tags[ "fn" ] = "Function"
|
14
|
+
tags[ "brief" ] = "Description"
|
15
|
+
|
16
|
+
# Hide tags we don't want in yardoc output
|
17
|
+
hidden = %w[module class fn]
|
18
|
+
|
19
|
+
# Construct tag string for CLI command
|
20
|
+
tags_line = ""
|
21
|
+
tags.each_pair { |n,v| tags_line += " --tag #{n.to_s}:\"#{v.to_s}\"" }
|
22
|
+
hidden.each { |h| tags_line += " --hide-tag #{h.to_s}" }
|
23
|
+
|
24
|
+
puts "(II) Generating multi-file yardoc output written to doc/yardoc"
|
25
|
+
system "yard --private --protected --markup-provider=redcarpet --markup=markdown #{tags_line.to_s} -o doc/yardoc lib/**/*.rb lib/**/**/*.rb - LICENSE MAINTAINERS API_DOCS.md"
|
26
|
+
|
27
|
+
puts "(II) Generating one-file yardoc output written to doc/yardoc_pdf"
|
28
|
+
system "yard --private --protected --markup-provider=redcarpet --markup=markdown --one-file #{tags_line.to_s} -o doc/yardoc_pdf lib/**/*.rb lib/**/**/*.rb - LICENSE MAINTAINERS API_DOCS.md"
|
29
|
+
|
30
|
+
# puts "(II) HTML to PDF written to doc/yardoc_pdf"
|
31
|
+
# pdf = WickedPdf.new.pdf_from_string( File.read( "doc/yardoc_pdf/index.html" ) )
|
32
|
+
# File.write( "doc/yardoc_pdf/index.pdf", pdf )
|
33
|
+
end # }}}
|
34
|
+
|
35
|
+
desc "Generate Yard Graphs for this project" # {{{
|
36
|
+
task :graph do |t|
|
37
|
+
basedir = "doc/yard-graph"
|
38
|
+
FileUtils.mkdir_p( basedir )
|
39
|
+
system "yard graph --dependencies --empty-mixins --full > #{basedir.to_s}/graph.dot"
|
40
|
+
system "dot -Tpng #{basedir.to_s}/graph.dot > #{basedir.to_s}/graph.png"
|
41
|
+
end # }}}
|
42
|
+
|
43
|
+
end # of namespace :docs
|
44
|
+
|
45
|
+
# vim:ts=2:tw=100:wm=100:syntax=ruby
|