subledger 0.7.7

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 (85) hide show
  1. data/.gitignore +9 -0
  2. data/LICENSE.txt +12 -0
  3. data/README.md +136 -0
  4. data/Rakefile +5 -0
  5. data/bin/subledger +6 -0
  6. data/lib/subledger/actor.rb +32 -0
  7. data/lib/subledger/collection_name.rb +25 -0
  8. data/lib/subledger/domain/account.rb +168 -0
  9. data/lib/subledger/domain/balance.rb +102 -0
  10. data/lib/subledger/domain/book.rb +111 -0
  11. data/lib/subledger/domain/category.rb +157 -0
  12. data/lib/subledger/domain/control.rb +180 -0
  13. data/lib/subledger/domain/formatters.rb +31 -0
  14. data/lib/subledger/domain/identity.rb +159 -0
  15. data/lib/subledger/domain/journal_entry.rb +293 -0
  16. data/lib/subledger/domain/key.rb +113 -0
  17. data/lib/subledger/domain/line.rb +272 -0
  18. data/lib/subledger/domain/org.rb +110 -0
  19. data/lib/subledger/domain/report.rb +247 -0
  20. data/lib/subledger/domain/report_rendering.rb +233 -0
  21. data/lib/subledger/domain/roles/activatable.rb +11 -0
  22. data/lib/subledger/domain/roles/archivable.rb +11 -0
  23. data/lib/subledger/domain/roles/attributable.rb +14 -0
  24. data/lib/subledger/domain/roles/collectable.rb +175 -0
  25. data/lib/subledger/domain/roles/creatable.rb +58 -0
  26. data/lib/subledger/domain/roles/describable.rb +33 -0
  27. data/lib/subledger/domain/roles/describable_report_rendering.rb +50 -0
  28. data/lib/subledger/domain/roles/identifiable.rb +15 -0
  29. data/lib/subledger/domain/roles/postable.rb +54 -0
  30. data/lib/subledger/domain/roles/progressable.rb +11 -0
  31. data/lib/subledger/domain/roles/readable.rb +34 -0
  32. data/lib/subledger/domain/roles/restable.rb +69 -0
  33. data/lib/subledger/domain/roles/storable.rb +30 -0
  34. data/lib/subledger/domain/roles/timeable.rb +18 -0
  35. data/lib/subledger/domain/roles/updatable.rb +35 -0
  36. data/lib/subledger/domain/roles/versionable.rb +35 -0
  37. data/lib/subledger/domain/roles.rb +16 -0
  38. data/lib/subledger/domain/value/credit.rb +16 -0
  39. data/lib/subledger/domain/value/debit.rb +16 -0
  40. data/lib/subledger/domain/value/zero.rb +24 -0
  41. data/lib/subledger/domain/value.rb +111 -0
  42. data/lib/subledger/domain.rb +95 -0
  43. data/lib/subledger/exception_handler.rb +65 -0
  44. data/lib/subledger/interface/client.rb +295 -0
  45. data/lib/subledger/interface/dispatcher.rb +20 -0
  46. data/lib/subledger/interface.rb +2 -0
  47. data/lib/subledger/path.rb +106 -0
  48. data/lib/subledger/rest.rb +128 -0
  49. data/lib/subledger/server.rb +3 -0
  50. data/lib/subledger/store/api/errors.rb +95 -0
  51. data/lib/subledger/store/api/roles/activate.rb +21 -0
  52. data/lib/subledger/store/api/roles/archive.rb +21 -0
  53. data/lib/subledger/store/api/roles/balance.rb +39 -0
  54. data/lib/subledger/store/api/roles/categories.rb +51 -0
  55. data/lib/subledger/store/api/roles/collect.rb +58 -0
  56. data/lib/subledger/store/api/roles/create.rb +26 -0
  57. data/lib/subledger/store/api/roles/create_and_post.rb +35 -0
  58. data/lib/subledger/store/api/roles/create_identity.rb +39 -0
  59. data/lib/subledger/store/api/roles/create_line.rb +24 -0
  60. data/lib/subledger/store/api/roles/first_and_last_line.rb +31 -0
  61. data/lib/subledger/store/api/roles/post.rb +25 -0
  62. data/lib/subledger/store/api/roles/progress.rb +21 -0
  63. data/lib/subledger/store/api/roles/read.rb +19 -0
  64. data/lib/subledger/store/api/roles/reports.rb +77 -0
  65. data/lib/subledger/store/api/roles/update.rb +24 -0
  66. data/lib/subledger/store/api/store.rb +103 -0
  67. data/lib/subledger/store/api.rb +20 -0
  68. data/lib/subledger/store.rb +236 -0
  69. data/lib/subledger/supervisor.rb +21 -0
  70. data/lib/subledger/uuid.rb +52 -0
  71. data/lib/subledger/version.rb +4 -0
  72. data/lib/subledger.rb +234 -0
  73. data/spec/spec_helper.rb +77 -0
  74. data/spec/subledger_account_spec.rb +354 -0
  75. data/spec/subledger_book_spec.rb +130 -0
  76. data/spec/subledger_category_spec.rb +203 -0
  77. data/spec/subledger_control_spec.rb +43 -0
  78. data/spec/subledger_identity_spec.rb +47 -0
  79. data/spec/subledger_journal_entry_spec.rb +417 -0
  80. data/spec/subledger_key_spec.rb +43 -0
  81. data/spec/subledger_org_spec.rb +68 -0
  82. data/spec/subledger_report_spec.rb +295 -0
  83. data/spec/subledger_spec.rb +101 -0
  84. data/subledger.gemspec +52 -0
  85. metadata +205 -0
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+
3
+ Test 'Subledger' do
4
+
5
+ let(:factory) { Subledger::Factory.create }
6
+
7
+ Instance do
8
+ subject { factory.client }
9
+
10
+ Test 'Book' do
11
+ # POST /books
12
+ RespondsTo 'book.create' do
13
+ ByReturning 'an instance of Subledger::Domain::ActiveBook' do
14
+ subject.book.create( factory.book_args ).
15
+ must_be_instance_of Subledger::Domain::ActiveBook
16
+ end
17
+ end
18
+
19
+ # GET /books/:id
20
+ RespondsTo 'books.read' do
21
+ let(:book) { factory.create_book :active }
22
+
23
+ ByReturning 'a kind of Subledger::Domain::Book' do
24
+ subject.books.read( :id => book.id ).
25
+ must_be_instance_of Subledger::Domain::ActiveBook
26
+ end
27
+ end
28
+
29
+ # PATCH /books/:id
30
+ RespondsTo 'books.update' do
31
+ let(:book ) { factory.create_book :active }
32
+ let(:description) { 'updated description' }
33
+ let(:args ) { book.attributes }
34
+ let(:update_args) { args.merge :description => description,
35
+ :version => 2 }
36
+
37
+ ByReturning 'an updated kind of Subledger::Domain::Book' do
38
+ patched = subject.books.update update_args
39
+
40
+ patched.must_be_instance_of Subledger::Domain::ActiveBook
41
+ patched.description.must_equal description
42
+ end
43
+ end
44
+
45
+ # GET /books ? before = :description & limit = :limit & state = :state
46
+ # ending
47
+ # starting
48
+ # after
49
+ # preceding = :book_id & limit = :limit & state = :state
50
+ # following
51
+ [ :archived, :active ].each do |state|
52
+ Subledger.scenarios.each do |scenario|
53
+ action = scenario.keys.first
54
+ expectations = scenario[action]
55
+
56
+ value_key = if action == :preceding or action == :following
57
+ 'id'
58
+ else
59
+ 'description'
60
+ end
61
+
62
+ RespondsTo "books.collect :state => #{state}, :action => #{action.inspect}" do
63
+ let(:books) { factory.create_book_collection state }
64
+ let(:book ) { books[2] }
65
+ let(:limit) { 2 }
66
+
67
+ if action == :preceding or action == :following
68
+ let(:value) { book.id }
69
+ else
70
+ let(:value) { URI.escape book.description }
71
+ end
72
+
73
+ let(:args) { { :action => action,
74
+ value_key.to_sym => value,
75
+ :state => state,
76
+ :limit => limit } }
77
+
78
+ When 'not given a block' do
79
+ let(:collection) { subject.books.collect args }
80
+
81
+ ByReturning "a list of #{state} books" do
82
+ collection.length.must_equal limit
83
+ end
84
+ end
85
+
86
+ When 'given a block' do
87
+ ByYielding "a list of #{state} books" do
88
+ count = 0
89
+
90
+ subject.books.collect( args ).each do |item|
91
+ expectation = expectations[count]
92
+
93
+ item.description.must_equal expectation
94
+
95
+ item.must_be_instance_of book.class
96
+
97
+ count += 1
98
+ end
99
+
100
+ count.must_equal limit
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ # POST /books/:id/archive
108
+ [ :archived, :active ].each do |state|
109
+ RespondsTo "#{state}_book_instance.archive" do
110
+ let(:book) { factory.create_book state }
111
+
112
+ ByReturning 'an instance of Subledger::Domain::ArchivedBook' do
113
+ book.archive.must_be_instance_of Subledger::Domain::ArchivedBook
114
+ end
115
+ end
116
+ end
117
+
118
+ # POST /books/:id/activate
119
+ [ :archived, :active ].each do |state|
120
+ RespondsTo "#{state}_book_instance.activate" do
121
+ let(:book) { factory.create_book state }
122
+
123
+ ByReturning 'an instance of Subledger::Domain::ActiveBook' do
124
+ book.activate.must_be_instance_of Subledger::Domain::ActiveBook
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,203 @@
1
+ require 'spec_helper'
2
+
3
+ Test 'Subledger' do
4
+
5
+ let(:factory) { Subledger::Factory.create }
6
+ let(:amount ) { '1' }
7
+
8
+ Instance do
9
+ subject { factory.client }
10
+
11
+ Test 'Category' do
12
+
13
+ # POST /books/:book_id/categories
14
+ RespondsTo 'category.create' do
15
+ ByReturning 'an instance of Subledger::Domain::ActiveCategory' do
16
+ subject.category.create( factory.category_args ).
17
+ must_be_instance_of Subledger::Domain::ActiveCategory
18
+ end
19
+ end
20
+
21
+ # GET /books/:book_id/categories/:id
22
+ [ :archived, :active ].each do |state|
23
+ RespondsTo 'category.read' do
24
+ let(:category) { factory.create_category state }
25
+
26
+ ByReturning "an instance of #{state} category" do
27
+ subject.category.read( :id => category.id ).
28
+ must_be_instance_of category.class
29
+ end
30
+ end
31
+ end
32
+
33
+ # PATCH /books/:book_id/categories/:id
34
+ [ :archived, :active ].each do |state|
35
+ RespondsTo 'categories.update' do
36
+ let(:category ) { factory.create_category state }
37
+ let(:args ) { category.attributes }
38
+ let(:description) { 'updated description' }
39
+ let(:update_args) { args.merge :description => description,
40
+ :version => 2 }
41
+
42
+ ByReturning "an instance of #{state} category" do
43
+ patched = subject.categories.update update_args
44
+
45
+ patched.must_be_instance_of category.class
46
+ patched.description.must_equal description
47
+ end
48
+ end
49
+ end
50
+
51
+ # GET /books/:book_id/categories ? before = :description & limit = :limit & state = :state
52
+ # ending
53
+ # starting
54
+ # after
55
+ [ :active, :archived ].each do |state|
56
+ Subledger.scenarios_order.each do |scenario|
57
+ action = scenario.keys.first
58
+ expectations = scenario[action]
59
+
60
+ RespondsTo "categories.collect :action => #{action}, :state => #{state}" do
61
+ let(:categories) { factory.create_category_collection state }
62
+ let(:item ) { categories[2] }
63
+ let(:limit ) { 2 }
64
+ let(:collection) { subject.categories.collect args }
65
+ let(:klass ) { item.class }
66
+
67
+ let(:args) { { :action => action,
68
+ :description => item.description,
69
+ :state => state,
70
+ :limit => limit } }
71
+
72
+ When 'not given a block' do
73
+ ByReturning "a list of #{state} categories" do
74
+ collection.length.must_equal limit
75
+ end
76
+ end
77
+
78
+ When 'given a block' do
79
+ ByYielding "a list of #{state} categories" do
80
+ count = 0
81
+
82
+ collection.each do |category|
83
+ expectation = expectations[count]
84
+
85
+ category.description.must_equal expectation
86
+
87
+ category.must_be_instance_of klass
88
+
89
+ count += 1
90
+ end
91
+
92
+ count.must_equal limit
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ # GET /categories ? preceding = :book_id & limit = :limit & state = :state
100
+ # following = :book_id & limit = :limit & state = :state
101
+ [ :active, :archived ].each do |state|
102
+ Subledger.scenarios_id.each do |scenario|
103
+ action = scenario.keys.first
104
+ expectations = scenario[action]
105
+
106
+ RespondsTo "categories.collect :action => #{action}" do
107
+ let(:categories) { factory.create_category_collection state }
108
+ let(:item ) { categories[2] }
109
+ let(:limit ) { 2 }
110
+ let(:collection) { subject.categories.collect args }
111
+ let(:klass ) { item.class }
112
+
113
+ let(:args) { { :action => action,
114
+ :id => item.id,
115
+ :state => state,
116
+ :limit => limit } }
117
+
118
+ When 'not given a block' do
119
+ ByReturning "a list of #{state} categories" do
120
+ collection.length.must_equal limit
121
+ end
122
+ end
123
+
124
+ When 'given a block' do
125
+ ByYielding "a list of #{state} categories" do
126
+ count = 0
127
+
128
+ collection.each do |category|
129
+ expectation = expectations[count]
130
+
131
+ category.description.must_equal expectation
132
+
133
+ category.must_be_instance_of klass
134
+
135
+ count += 1
136
+ end
137
+
138
+ count.must_equal limit
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ # GET /books/:book_id/categories/:id/accounts
146
+ if Subledger::STORE == :api
147
+ RespondsTo 'category_instance.accounts' do
148
+ ByRaising 'a Store::ReportError' do
149
+ lambda do
150
+ factory.create_category(:active).accounts
151
+ end.must_raise Subledger::Store::CategoryError
152
+ end
153
+ end
154
+ else
155
+ RespondsTo "category_instance.accounts" do
156
+ let(:category) { factory.create_category :active }
157
+
158
+ let(:category_accounts) { }
159
+
160
+ When 'not given a block' do
161
+ ByReturning 'a list of accounts' #do
162
+ # category.accounts.length.must_equal category_accounts.length
163
+ # end
164
+ end
165
+
166
+ When 'given a block' do
167
+ ByYielding 'a list of accounts' #do
168
+ # count = 0
169
+ #
170
+ # category.accounts do |account|
171
+ # expectation = category_accounts[count]
172
+ #
173
+ # account.description.must_equal expectation.description
174
+ #
175
+ # account.must_be_instance_of Subledger::Domain::ActiveAccount
176
+ #
177
+ # count += 1
178
+ # end
179
+ #
180
+ # count.must_equal category_accounts.length
181
+ # end
182
+ end
183
+ end
184
+ end
185
+
186
+ # POST /books/:book_id/categories/:id/archive
187
+ RespondsTo 'category_instance.archive' do
188
+ ByReturning 'an instance of Subledger::Domain::ArchivedCategory' do
189
+ factory.create_category(:active).archive.
190
+ must_be_instance_of Subledger::Domain::ArchivedCategory
191
+ end
192
+ end
193
+
194
+ # POST /books/:book_id/archived_categories/:id/activate
195
+ RespondsTo 'archived_category_instance.activate' do
196
+ ByReturning 'an instance of Subledger::Domain::ActiveCategory' do
197
+ factory.create_category(:archived).activate.
198
+ must_be_instance_of Subledger::Domain::ActiveCategory
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,43 @@
1
+ # require 'spec_helper'
2
+ #
3
+ # Test 'Subledger' do
4
+ #
5
+ # let(:factory) { Subledger::Factory.create }
6
+ # let(:identity) { factory.identity }
7
+ #
8
+ # Instance do
9
+ # subject { factory.client }
10
+ #
11
+ # Test 'Control' do
12
+ # # POST /v2/orgs/:org_id/controls
13
+ # RespondsTo 'controls.create' do
14
+ # ByReturning 'an instance of Subledger::Domain::ActiveControl' do
15
+ # subject.controls.create( factory.control_args ).
16
+ # must_be_instance_of Subledger::Domain::ActiveControl
17
+ # end
18
+ # end
19
+ #
20
+ # # POST /v2/orgs/:org_id/controls/:control_id/archive
21
+ # [ :archived, :active ].each do |state|
22
+ # RespondsTo "#{state}_control_instance.archive" do
23
+ # let(:control) { factory.create_control state, identity }
24
+ #
25
+ # ByReturning 'an instance of Subledger::Domain::ArchivedControl' do
26
+ # control.archive.must_be_instance_of Subledger::Domain::ArchivedControl
27
+ # end
28
+ # end
29
+ # end
30
+ #
31
+ # # POST /v2/orgs/:org_id/controls/:control_id/activate
32
+ # [ :archived, :active ].each do |state|
33
+ # RespondsTo "#{state}_control_instance.activate" do
34
+ # let(:control) { factory.create_control state, identity }
35
+ #
36
+ # ByReturning 'an instance of Subledger::Domain::ActiveControl' do
37
+ # control.activate.must_be_instance_of Subledger::Domain::ActiveControl
38
+ # end
39
+ # end
40
+ # end
41
+ # end
42
+ # end
43
+ # end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ Test 'Subledger' do
4
+
5
+ let(:factory) { Subledger::Factory.create }
6
+
7
+ Instance do
8
+ subject { factory.client }
9
+
10
+ Test 'Identities' do
11
+ # POST /identities
12
+ RespondsTo 'identities.create' do
13
+ ByReturning 'an instance of ActiveIdentity and ActiveKey' do
14
+ identity, key = subject.identities.create factory.identity_args
15
+ identity.must_be_instance_of Subledger::Domain::ActiveIdentity
16
+ key.must_be_instance_of Subledger::Domain::ActiveKey
17
+ end
18
+ end
19
+
20
+ # GET /identities/:id
21
+ RespondsTo 'identities.read' do
22
+ let(:identity) { factory.identity }
23
+
24
+ ByReturning 'a kind of Subledger::Domain::ActiveIdentity' do
25
+ subject.identities.read( :id => identity.id ).
26
+ must_be_instance_of Subledger::Domain::ActiveIdentity
27
+ end
28
+ end
29
+
30
+ # PATCH /identities/:id
31
+ RespondsTo 'identities.update' do
32
+ let(:identity ) { factory.identity }
33
+ let(:description) { 'updated description' }
34
+ let(:args ) { identity.attributes }
35
+ let(:update_args) { args.merge :description => description,
36
+ :version => 2 }
37
+
38
+ ByReturning 'an updated kind of Subledger::Domain::ActiveIdentity' do
39
+ patched = subject.identities.update update_args
40
+
41
+ patched.must_be_instance_of Subledger::Domain::ActiveIdentity
42
+ patched.description.must_equal description
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end