subledger 0.7.7

Sign up to get free protection for your applications and to get access to all the features.
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