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.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS.md +31 -0
  3. data/CHANGELOG.md +0 -0
  4. data/COPYING.md +12 -0
  5. data/FAQ.md +8 -0
  6. data/Gemfile +105 -0
  7. data/LICENSE.md +14 -0
  8. data/MAINTAINERS.md +40 -0
  9. data/README.md +549 -0
  10. data/Rakefile +94 -0
  11. data/Thorfile +80 -0
  12. data/bin/clearbooks +28 -0
  13. data/clearbooks.gemspec +119 -0
  14. data/examples/demo.rb +8 -0
  15. data/lib/clearbooks.rb +92 -0
  16. data/lib/clearbooks/core_ext.rb +8 -0
  17. data/lib/clearbooks/core_ext/array.rb +51 -0
  18. data/lib/clearbooks/core_ext/hash.rb +47 -0
  19. data/lib/clearbooks/core_ext/io_binary_read.rb +20 -0
  20. data/lib/clearbooks/core_ext/string.rb +21 -0
  21. data/lib/clearbooks/error.rb +8 -0
  22. data/lib/clearbooks/error/errors.rb +228 -0
  23. data/lib/clearbooks/interface/rake/cucumber.rb +36 -0
  24. data/lib/clearbooks/interface/rake/default.rb +28 -0
  25. data/lib/clearbooks/interface/rake/documentation.rb +45 -0
  26. data/lib/clearbooks/interface/rake/guard.rb +13 -0
  27. data/lib/clearbooks/interface/rake/helpers.rb +27 -0
  28. data/lib/clearbooks/interface/rake/library.rb +126 -0
  29. data/lib/clearbooks/interface/rake/metric.rb +15 -0
  30. data/lib/clearbooks/interface/rake/rspec.rb +31 -0
  31. data/lib/clearbooks/interface/thor/info.thor +292 -0
  32. data/lib/clearbooks/interface/thor/mixin/config_choice.rb +27 -0
  33. data/lib/clearbooks/interface/thor/mixin/configuration.rb +28 -0
  34. data/lib/clearbooks/interface/thor/mixin/default.rb +30 -0
  35. data/lib/clearbooks/interface/thor/mixin/default_config.rb +31 -0
  36. data/lib/clearbooks/interface/thor/mixin/guess.rb +57 -0
  37. data/lib/clearbooks/interface/thor/mixin/shell.rb +225 -0
  38. data/lib/clearbooks/interface/thor/version.thor +34 -0
  39. data/lib/clearbooks/library/client.rb +257 -0
  40. data/lib/clearbooks/library/configuration.rb +34 -0
  41. data/lib/clearbooks/model/account_code.rb +65 -0
  42. data/lib/clearbooks/model/base.rb +67 -0
  43. data/lib/clearbooks/model/entity.rb +225 -0
  44. data/lib/clearbooks/model/invoice.rb +163 -0
  45. data/lib/clearbooks/model/item.rb +78 -0
  46. data/lib/clearbooks/model/journal.rb +74 -0
  47. data/lib/clearbooks/model/ledger.rb +52 -0
  48. data/lib/clearbooks/model/payment.rb +113 -0
  49. data/lib/clearbooks/model/project.rb +58 -0
  50. data/lib/clearbooks/version.rb +12 -0
  51. data/spec/clearbooks/clearbooks_spec.rb +27 -0
  52. data/spec/clearbooks/model/account_code_spec.rb +52 -0
  53. data/spec/clearbooks/model/entity_spec.rb +107 -0
  54. data/spec/clearbooks/model/invoice_spec.rb +109 -0
  55. data/spec/clearbooks/model/journal_spec.rb +77 -0
  56. data/spec/clearbooks/model/payment_spec.rb +103 -0
  57. data/spec/clearbooks/model/project_spec.rb +72 -0
  58. data/spec/fixtures/response/allocate_payment.xml +12 -0
  59. data/spec/fixtures/response/create_entity.xml +12 -0
  60. data/spec/fixtures/response/create_invoice.xml +11 -0
  61. data/spec/fixtures/response/create_journal.xml +12 -0
  62. data/spec/fixtures/response/create_payment.xml +12 -0
  63. data/spec/fixtures/response/create_project.xml +12 -0
  64. data/spec/fixtures/response/delete_entity.xml +12 -0
  65. data/spec/fixtures/response/delete_journal.xml +12 -0
  66. data/spec/fixtures/response/list_account_codes.xml +168 -0
  67. data/spec/fixtures/response/list_entities.xml +45 -0
  68. data/spec/fixtures/response/list_invoices.xml +56 -0
  69. data/spec/fixtures/response/list_projects.xml +16 -0
  70. data/spec/fixtures/response/no_api_key_fault.xml +8 -0
  71. data/spec/fixtures/response/well_formed_request.xml +10 -0
  72. data/spec/fixtures/response/wrong_api_key_fault.xml +8 -0
  73. data/spec/spec_helper.rb +26 -0
  74. 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,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ Dir[ "#{File.dirname(__FILE__)}/error/*.rb" ].sort.each do |path|
5
+ require_relative "error/#{File.basename( path, '.rb' )}"
6
+ end
7
+
8
+ # vim:ts=2:tw=100:wm=100:syntax=ruby
@@ -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
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ namespace :guard do
5
+
6
+ desc "Execute Ruby Guard" # {{{
7
+ task :default do |g|
8
+ sh "bundle exec guard start -G Guardfile"
9
+ end # }}}
10
+
11
+ end
12
+
13
+ # vim:ts=2:tw=100:wm=100:syntax=ruby