financial 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.gitignore +4 -0
  2. data/.infinity_test +16 -0
  3. data/.rspec +3 -0
  4. data/.rvmrc +1 -0
  5. data/Gemfile +15 -0
  6. data/Gemfile.lock +74 -0
  7. data/README.markdown +157 -0
  8. data/Rakefile +1 -0
  9. data/duck_tales.gif +0 -0
  10. data/example.png +0 -0
  11. data/examples/two_accounts.rb +32 -0
  12. data/features/portuguese_dsl.feature +93 -0
  13. data/features/print_financial_table.feature +318 -0
  14. data/features/support/env.rb +1 -0
  15. data/financial.gemspec +22 -0
  16. data/lib/financial.rb +39 -0
  17. data/lib/financial/account.rb +129 -0
  18. data/lib/financial/account_manager.rb +26 -0
  19. data/lib/financial/balance.rb +11 -0
  20. data/lib/financial/balance_calculation.rb +35 -0
  21. data/lib/financial/cost.rb +34 -0
  22. data/lib/financial/costs.rb +30 -0
  23. data/lib/financial/deposit.rb +30 -0
  24. data/lib/financial/deposits.rb +15 -0
  25. data/lib/financial/dsl.rb +16 -0
  26. data/lib/financial/financial_date.rb +18 -0
  27. data/lib/financial/financial_table.rb +109 -0
  28. data/lib/financial/locale.rb +153 -0
  29. data/lib/financial/locales/en.yml +34 -0
  30. data/lib/financial/locales/pt.yml +67 -0
  31. data/lib/financial/parcels.rb +87 -0
  32. data/lib/financial/per_cent.rb +12 -0
  33. data/lib/financial/print_table.rb +34 -0
  34. data/lib/financial/revenue.rb +40 -0
  35. data/lib/financial/revenues.rb +16 -0
  36. data/lib/financial/rspec_matchers.rb +32 -0
  37. data/lib/financial/tax.rb +4 -0
  38. data/lib/financial/version.rb +3 -0
  39. data/spec/financial/account_manager_spec.rb +38 -0
  40. data/spec/financial/account_spec.rb +399 -0
  41. data/spec/financial/balance_spec.rb +44 -0
  42. data/spec/financial/cost_spec.rb +78 -0
  43. data/spec/financial/costs_spec.rb +18 -0
  44. data/spec/financial/deposit_spec.rb +78 -0
  45. data/spec/financial/deposits_spec.rb +23 -0
  46. data/spec/financial/english_spec.rb +76 -0
  47. data/spec/financial/financial_date_spec.rb +50 -0
  48. data/spec/financial/financial_spec.rb +14 -0
  49. data/spec/financial/financial_table_spec.rb +31 -0
  50. data/spec/financial/locale_spec.rb +37 -0
  51. data/spec/financial/parcels_spec.rb +179 -0
  52. data/spec/financial/per_cent_spec.rb +24 -0
  53. data/spec/financial/portuguese_spec.rb +117 -0
  54. data/spec/financial/print_table_spec.rb +76 -0
  55. data/spec/financial/revenue_spec.rb +89 -0
  56. data/spec/financial/revenues_spec.rb +18 -0
  57. data/spec/financial/tax_spec.rb +42 -0
  58. data/spec/spec_helper.rb +25 -0
  59. metadata +139 -0
@@ -0,0 +1,32 @@
1
+ module Financial
2
+ module RSpecMatchers
3
+ def self.included(base)
4
+ create_include_balance_matcher
5
+ end
6
+
7
+ def create_include_balance_matcher
8
+ RSpec::Matchers.define :include_balance do |expected|
9
+ chain :in_date do |date|
10
+ @date = Financial::FinancialDate.new(date).date
11
+ end
12
+
13
+ failure_message_for_should do |actual|
14
+ if @date
15
+ "expected #{actual} to have balance #{expected} in date #{@date}"
16
+ else
17
+ "expected #{actual} to have balance #{expected}"
18
+ end
19
+ end
20
+
21
+ match do |actual|
22
+ actual.should_not be_empty
23
+ if @date
24
+ actual.any? { |balance| balance.date == @date and balance.value == expected }
25
+ else
26
+ actual.any? { |balance| balance.value == expected }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,4 @@
1
+ module Financial
2
+ class Tax < Cost
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module Financial
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ module Financial
4
+ describe AccountManager do
5
+ let(:account_manager) { AccountManager.instance }
6
+
7
+ describe '.instance' do
8
+ it 'should have the singleton pattern' do
9
+ account_manager.should be_equal AccountManager.instance
10
+ end
11
+ end
12
+
13
+ describe '#accounts' do
14
+ it 'should initialize with an Array' do
15
+ account_manager.accounts.should be_instance_of(Array)
16
+ end
17
+ end
18
+
19
+ describe '#find_account' do
20
+ before do
21
+ @lucy_bank = account_manager.new_account(:lucy_bank)
22
+ @leo_bank = account_manager.new_account(:leo_bank)
23
+ end
24
+
25
+ it 'should find the account specified' do
26
+ account_manager.find_account(:lucy_bank).should == [@lucy_bank]
27
+ end
28
+
29
+ it 'should find all the accounts when pass :all option' do
30
+ account_manager.find_account(:all).should equal account_manager.accounts
31
+ end
32
+
33
+ it 'should find all the accounts when pass :all option' do
34
+ account_manager.find_account(:todas).should equal account_manager.accounts
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,399 @@
1
+ require 'spec_helper'
2
+
3
+ module Financial
4
+ describe Account do
5
+ let(:reserved_bank) { Financial.account_manager.new_account(:reserved_bank) }
6
+ let(:bank_account) { Account.new([:bank_account, {:as=>"Bank Account"}]) }
7
+ let(:super_bank_account) { Account.new(:super_bank_account) }
8
+
9
+ describe '#name' do
10
+ it 'should return the name of the account' do
11
+ reserved_bank.name.should equal :reserved_bank
12
+ end
13
+
14
+ it 'should assign the name when pass many args' do
15
+ bank_account.name.should equal :bank_account
16
+ end
17
+ end
18
+
19
+ describe '#banner' do
20
+ it 'should assign the name with spaces and capitalize if dont pass a name' do
21
+ reserved_bank.banner.should == "Reserved bank"
22
+ end
23
+
24
+ it 'should assign the banner as a option' do
25
+ bank_account.banner.should == 'Bank Account'
26
+ end
27
+ end
28
+
29
+ describe '#total' do
30
+ it 'should return zero if dont pass any value' do
31
+ bank_account.total.should be 0
32
+ end
33
+
34
+ it 'should return the value passed in argument' do
35
+ bank_account.total(400)
36
+ bank_account.total.should be 400
37
+ end
38
+ end
39
+
40
+ describe '#total_costs' do
41
+ it 'should calculate total costs' do
42
+ bank_account.costs do
43
+ credit_card 100
44
+ other_costs 1040
45
+ end
46
+ bank_account.total_costs.should be 1140
47
+ end
48
+
49
+ it 'should calculate total costs counting parcels' do
50
+ bank_account.costs do
51
+ credit_card 1000
52
+ parcels(10).of(300)
53
+ end
54
+ bank_account.total_costs.should be 4000
55
+ end
56
+
57
+ it 'should calculate floats too' do
58
+ bank_account.costs do
59
+ credit 500.55
60
+ other 100.10
61
+ end
62
+ bank_account.total_costs.should == 600.65
63
+ end
64
+
65
+ it 'should assign to instance variable' do
66
+ bank_account.costs { some_costs 300 }
67
+ bank_account.total_costs
68
+ bank_account.instance_variable_get(:@total_costs).should be 300
69
+ end
70
+
71
+ it 'should return zero when dont have costs' do
72
+ bank_account.total_costs.should be 0
73
+ end
74
+
75
+ it 'should assign a instance variable zero if dont have revenues' do
76
+ bank_account.total_costs
77
+ bank_account.instance_variable_get(:@total_costs).should be 0
78
+ end
79
+
80
+ it 'should count the deposits with costs' do
81
+ bank_account.costs { credit 1000 }
82
+ bank_account.deposits { deposit(2000) }
83
+ bank_account.total_costs.should be 3000
84
+ end
85
+
86
+ it 'should count the deposits' do
87
+ bank_account.deposits { deposit(100) }
88
+ bank_account.total_costs.should be 100
89
+ end
90
+ end
91
+
92
+ describe '#deposits' do
93
+ it 'should have some deposits' do
94
+ bank_account.deposits do
95
+ deposit(100)
96
+ end
97
+ bank_account.deposits.should have(1).item
98
+ end
99
+ end
100
+
101
+ describe '#taxes' do
102
+ it 'should have some taxes' do
103
+ bank_account.revenues do
104
+ billing(100).tax(1)
105
+ end
106
+ bank_account.taxes.should == [Tax.new(:billing, 100)]
107
+ end
108
+
109
+ it 'should ignore the revenues without taxes' do
110
+ bank_account.revenues { billing 100 }
111
+ bank_account.taxes.should == []
112
+ end
113
+ end
114
+
115
+ describe '#total_revenues' do
116
+ it 'should return the revenue value if have one revenue only' do
117
+ bank_account.revenues { billing_value 500 }
118
+ bank_account.total_revenues.should be 500
119
+ end
120
+
121
+ it 'should return calculate the revenue value' do
122
+ bank_account.revenues do
123
+ billing_value 499
124
+ other_value 1000
125
+ end
126
+ bank_account.total_revenues.should be 1499
127
+ end
128
+
129
+ it 'should return zero when dont have revenues' do
130
+ bank_account.total_revenues.should be 0
131
+ end
132
+
133
+ it 'should assign a instance variable' do
134
+ bank_account.revenues { a_revenue 100 }
135
+ bank_account.total_revenues
136
+ bank_account.instance_variable_get(:@total_revenues).should be 100
137
+ end
138
+
139
+ it 'should assign a instance variable zero if dont have revenues' do
140
+ bank_account.total_revenues
141
+ bank_account.instance_variable_get(:@total_revenues).should be 0
142
+ end
143
+ end
144
+
145
+ describe '#costs' do
146
+ it 'should return an empty costs when does not have any costs' do
147
+ reserved_bank.costs.should be_empty
148
+ end
149
+
150
+ it 'should return an Costs' do
151
+ reserved_bank.costs.should be_instance_of(Costs)
152
+ end
153
+
154
+ context 'with parcels' do
155
+ before { reserved_bank.costs { parcels(2).of(400) } }
156
+
157
+ it 'should split all the parcels in cost' do
158
+ reserved_bank.costs.all? { |cost| cost.class == Cost }.should be_true
159
+ end
160
+
161
+ it 'should keep the value of the parcel and setting in the cost' do
162
+ reserved_bank.costs.all? { |cost| cost.value.equal?(400) }.should be_true
163
+ end
164
+
165
+ it 'should keep the dates of the parcel and setting in the cost' do
166
+ reserved_bank.costs.all? { |cost| cost.date.is_a?(Date) }.should be_true
167
+ end
168
+ end
169
+
170
+ context 'with a block' do
171
+ let(:cost) { reserved_bank.costs.first }
172
+ before do
173
+ Financial.locale = :en
174
+ reserved_bank.costs do
175
+ a_cost(400).in_date('09/20/2011')
176
+ end
177
+ cost.should_not be_nil
178
+ end
179
+
180
+ it 'cost should be instance of Cost' do
181
+ cost.should be_instance_of(Financial::Cost)
182
+ end
183
+
184
+ it 'cost should set the cost_name' do
185
+ cost.name.should == 'A cost'
186
+ end
187
+
188
+ it 'cost should set the value' do
189
+ cost.value.should equal 400
190
+ end
191
+
192
+ it 'cost should set the date' do
193
+ cost.date.should == Date.new(2011, 9, 20)
194
+ end
195
+ end
196
+ end
197
+
198
+ describe '#revenues' do
199
+ it 'should return an empty revenues when does not have revenues' do
200
+ reserved_bank.revenues.should be_empty
201
+ end
202
+
203
+ it 'should return an Array' do
204
+ reserved_bank.revenues.should be_instance_of(Financial::Revenues)
205
+ end
206
+
207
+ context 'with a block should push a revenue that:' do
208
+ let(:revenue) { reserved_bank.revenues.first }
209
+ before do
210
+ reserved_bank.revenues do
211
+ a_revenue(100).in_date('7/17/2011')
212
+ end
213
+ revenue.should_not be_nil
214
+ end
215
+
216
+ it 'contain a instance of Financial::Revenue' do
217
+ revenue.should be_instance_of(Financial::Revenue)
218
+ end
219
+
220
+ it 'contain the name of the revenue' do
221
+ revenue.name.should == 'A revenue'
222
+ end
223
+
224
+ it 'contain the value of the revenue' do
225
+ revenue.value.should equal 100
226
+ end
227
+
228
+ it 'contain the date of the revenue' do
229
+ revenue.date.should == Date.civil(2011, 7, 17)
230
+ end
231
+ end
232
+ end
233
+
234
+ describe '#balances' do
235
+ before do
236
+ reserved_bank.total 300
237
+ end
238
+
239
+ it 'should include a balance that subtract costs' do
240
+ reserved_bank.costs { credit(100).in_date('1/1/2011')}
241
+ reserved_bank.calculate_balances.should include_balance(200).in_date('1/1/2011')
242
+ end
243
+
244
+ it 'should include a balance that subtract deposits' do
245
+ reserved_bank.deposits { deposit(900).in_date('1/2/2011')}
246
+ reserved_bank.calculate_balances.should include_balance(-600).in_date('1/2/2011')
247
+ end
248
+
249
+ it 'should include a balance that subtract the tax' do
250
+ reserved_bank.revenues { bill(100).in_date('1/2/2011').tax(0.1).in_date('1/3/2011') }
251
+ reserved_bank.calculate_balances.should include_balance(390).in_date('1/3/2011')
252
+ end
253
+
254
+ it 'should include a balance that add a revenue' do
255
+ reserved_bank.revenues { bill(1000).in_date('4/4/2011') }
256
+ reserved_bank.calculate_balances.should include_balance(1300).in_date('4/4/2011')
257
+ end
258
+
259
+ it 'should include a balance that add a revenue and subtract a cost in the same date' do
260
+ reserved_bank.revenues { bill(900).in_date('3/3/2011')}
261
+ reserved_bank.costs { credit(600).in_date('3/3/2011')}
262
+ reserved_bank.calculate_balances.should include_balance(600).in_date('3/3/2011')
263
+ reserved_bank.balances.should include_balance(600).in_date('3/3/2011')
264
+ end
265
+
266
+ it 'should include a balance that subtract costs, deposits and taxes in the same date' do
267
+ reserved_bank.revenues { bill(1000).in_date('5/5/2011').tax(0.1).in_date('5/5/2011')}
268
+ reserved_bank.costs { credit(400).in_date('5/5/2011') }
269
+ reserved_bank.deposits { deposit(600).in_date('5/5/2011') }
270
+ reserved_bank.calculate_balances.should have(1).item
271
+ reserved_bank.calculate_balances.should include_balance(200.0).in_date('5/5/2011')
272
+ end
273
+
274
+ it 'should include a balance for the reserved_bank that receives a deposit' do
275
+ bank_account.total 110.0
276
+ reserved_bank.deposits { deposit(150).in_account(:bank_account).in_date('9/20/2011') }
277
+ bank_account.balances.should include_balance(260.0).in_date('9/20/2011')
278
+ end
279
+
280
+ it 'should include a balance of all receiveds deposits in the same date' do
281
+ super_bank_account.total 4000
282
+ account :other_super_account do
283
+ deposits do
284
+ deposit(100).in_account(:super_bank_account).in_date('9/20/2011')
285
+ end
286
+ end
287
+ account :hiper do
288
+ deposits do
289
+ deposit(1000).in_account(:super_bank_account).in_date('9/20/2011')
290
+ end
291
+ end
292
+ super_bank_account.balances.should include_balance(5100).in_date('9/20/2011')
293
+ end
294
+ end
295
+
296
+ describe '#costs_in_date' do
297
+ let(:date) { Date.civil(2011, 7, 1) }
298
+
299
+ it 'should return all costs in date' do
300
+ bank_account.costs do
301
+ credit_card(400).in_date '7/1/2011'
302
+ other(300).in_date '3/4/2011'
303
+ end
304
+ bank_account.costs_in_date(date).should == [bank_account.costs.first]
305
+ end
306
+
307
+ it 'should return an empty array when dont have costs' do
308
+ bank_account.costs_in_date(date).should == []
309
+ end
310
+ end
311
+
312
+ describe '#revenues_in_date' do
313
+ let(:date) { Date.civil(2011, 7, 1) }
314
+
315
+ it 'should return all costs in date' do
316
+ bank_account.revenues do
317
+ bill(400).in_date '7/1/2011'
318
+ salary(300).in_date '3/4/2011'
319
+ end
320
+ bank_account.revenues_in_date(date).should == [bank_account.revenues.first]
321
+ end
322
+
323
+ it 'should return the receiveds deposits for bank_account' do
324
+ bank_account.deposits { deposit(100).in_account(:super_bank_account).in_date('7/1/2011') }
325
+ super_account = Financial.account_manager.new_account(:super_bank_account)
326
+ Financial.account_manager.should_receive(:accounts).and_return([super_account, bank_account])
327
+ super_account.revenues_in_date(date).should == [bank_account.deposits.first]
328
+ end
329
+
330
+ it 'should return an empty array when dont have costs' do
331
+ bank_account.revenues_in_date(date).should == []
332
+ end
333
+ end
334
+
335
+ describe '#events_in_date' do
336
+ let(:date) { Date.civil(2011, 7, 1) }
337
+
338
+ it 'should return all costs in date' do
339
+ bank_account.costs do
340
+ credit_card(400).in_date '7/1/2011'
341
+ end
342
+ bank_account.events_in_date(date).should == [bank_account.costs.first]
343
+ end
344
+
345
+ it 'should return all revenues in date' do
346
+ bank_account.revenues do
347
+ service(500).in_date '7/1/2011'
348
+ end
349
+ bank_account.events_in_date(date).should == [bank_account.revenues.first]
350
+ end
351
+
352
+ it 'should return all deposits in date' do
353
+ bank_account.deposits do
354
+ deposit(500).in_date('7/1/2011')
355
+ deposit(1000).in_date('7/1/2011')
356
+ end
357
+ bank_account.events_in_date(date).should == bank_account.deposits
358
+ end
359
+ end
360
+
361
+ describe '#last_balance_in_date' do
362
+ let(:date) { Date.civil(2011, 6, 14)}
363
+
364
+ it 'should return the toal when not have balances' do
365
+ bank_account.last_balance_in_date(date).should be(0)
366
+ end
367
+
368
+ it 'should return the last balance for the exactly date' do
369
+ bank_account.costs { a_cost(400).in_date '6/14/2011' }
370
+ bank_account.last_balance_in_date(date).should be -400
371
+ end
372
+
373
+ it 'should return the last balance that is less than date' do
374
+ bank_account.costs { other_cost(980).in_date '6/01/2011'}
375
+ bank_account.last_balance_in_date(date).should be -980
376
+ end
377
+
378
+ it 'should not return a old balance that is not the last balance for date' do
379
+ bank_account.costs do
380
+ a_cost(700).in_date '6/01/2011'
381
+ credit(300).in_date '6/12/2011'
382
+ end
383
+ bank_account.last_balance_in_date(date).should be -1000
384
+ end
385
+ end
386
+
387
+ describe '.find' do
388
+ it 'should find the reserved_bank account' do
389
+ bank_account
390
+ Account.find(:name => :reserved_bank).should == reserved_bank
391
+ end
392
+
393
+ it 'should find the reserved_bank account pass a stirng value' do
394
+ bank_account
395
+ Account.find(:name => 'reserved_bank').should == reserved_bank
396
+ end
397
+ end
398
+ end
399
+ end