mudrat_projector 0.9.3 → 0.9.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 99cf860a7f16e297d956e8b018652994a216552c
4
- data.tar.gz: 51de6ef4a9280d86339c5e045cd3514f6475259c
3
+ metadata.gz: d2181d2b58ff6ff66fc876cb0a69b95c40a73cb8
4
+ data.tar.gz: 506905ae2d682c9c3dd13712ad381fc2ba71b418
5
5
  SHA512:
6
- metadata.gz: 25820eacfe06c533db174462a6cc9ae66a826751ddbeda829250ae2970fb92ed8a15ffdc3366d92b9a76b478a3996206ec074ea7f965609d24b1904435b00834
7
- data.tar.gz: 89671345c7a2ebd2ef4513a20312d676bd1d0a023df1a066def36a6fa3c855eb6ec3400745431f375800ac7cc35240d795b84b0dff917d3f9b4d56c0c20ca0e4
6
+ metadata.gz: efafce27f94ec1a5c2a96535cd09fe6a3db785fe5581804cf0e7bd040b1d7adbf39e723d3c0bd55bec33325d4371aa59ac1dc6c19e73b8db7666cf037ab6ae1d
7
+ data.tar.gz: e3cd5fc24943b3ba408d68fb4ae2c5cefc484f4f1d425b39ed58fb8530791bb1323928daf3a3f6813d4e53d97a9a9805b6eb22c57a91d454403443eaf7dfbc88
@@ -28,9 +28,17 @@ module MudratProjector
28
28
  end
29
29
 
30
30
  def days_between
31
- (to - from).to_f + 1
31
+ to_big_decimal(to - from) + 1
32
32
  end
33
33
  private :days_between
34
+
35
+ def to_big_decimal(number)
36
+ if number.is_a? Rational
37
+ number.to_d(20)
38
+ else
39
+ number.to_d
40
+ end
41
+ end
34
42
  end
35
43
 
36
44
  class DayCalculator < Calculator
@@ -88,7 +96,7 @@ module MudratProjector
88
96
  end
89
97
 
90
98
  def days_in_unit unit
91
- ((unit.end + 1) - unit.begin).to_f
99
+ to_big_decimal((unit.end + 1) - unit.begin)
92
100
  end
93
101
 
94
102
  def units_between
@@ -18,7 +18,7 @@ module MudratProjector
18
18
  @validator = Validator.new projector: self, chart: @chart
19
19
  end
20
20
 
21
- def_delegators :@chart, *%i(accounts account_balance apply_transaction balance fetch net_worth split_account)
21
+ def_delegators :@chart, *%i(accounts account_balance apply_transaction balance fetch split_account)
22
22
  def_delegators :@validator, *%i(must_be_balanced! validate_account! validate_transaction!)
23
23
 
24
24
  def accounts= accounts
@@ -51,6 +51,10 @@ module MudratProjector
51
51
  balance.zero?
52
52
  end
53
53
 
54
+ def net_worth
55
+ @chart.net_worth.round(2).to_f
56
+ end
57
+
54
58
  def project to: end_of_projection, build_next: false, &block
55
59
  must_be_balanced!
56
60
  projection = Projection.new range: (from..to), chart: @chart
@@ -12,7 +12,9 @@ module MudratProjector
12
12
  split_count_over(range).reduce range.begin do |date, factor|
13
13
  @count -= factor if @count
14
14
  yield [date, factor]
15
- DateDiff.advance intervals: factor, unit: unit, from: date
15
+ scalar.times.reduce date do |date, _|
16
+ DateDiff.advance intervals: factor, unit: unit, from: date
17
+ end
16
18
  end
17
19
  end
18
20
 
@@ -22,7 +24,8 @@ module MudratProjector
22
24
 
23
25
  def split_count_over range
24
26
  diff = DateDiff.date_diff unit: unit, from: range.begin, to: range.end
25
- full_units, final_prorate = [@count, diff].compact.min.divmod 1
27
+ full_units, final_prorate = [@count, diff].compact.min.divmod scalar
28
+ final_prorate /= scalar
26
29
  ([1] * full_units).tap do |list|
27
30
  list.push final_prorate unless final_prorate.zero?
28
31
  end
@@ -99,7 +99,7 @@ module MudratProjector
99
99
  private
100
100
 
101
101
  def fmt number
102
- number.respond_to?(:round) ? number.round(2).to_f : number
102
+ number.respond_to?(:round) ? number.round(2).to_d : number
103
103
  end
104
104
  end
105
105
 
@@ -1,3 +1,3 @@
1
1
  module MudratProjector
2
- VERSION = "0.9.3"
2
+ VERSION = "0.9.4"
3
3
  end
@@ -16,47 +16,46 @@ class DateDiffTest < Minitest::Test
16
16
  end
17
17
 
18
18
  def test_years_between_a_few_days
19
- assert_equal (1.0 / 366.0), date_diff(:year, jan_1_2000, jan_1_2000)
20
- assert_equal (31.0 / 366.0), date_diff(:year, jan_1_2000, jan_31_2000)
21
- assert_equal (32.0 / 366.0), date_diff(:year, jan_1_2000, feb_1_2000)
22
- assert_equal (2/366.0 + 2/365.0), date_diff(:year, dec_30_2000, jan_2_2001)
19
+ assert_equal (1 / 366.to_d), date_diff(:year, jan_1_2000, jan_1_2000)
20
+ assert_equal (31 / 366.to_d), date_diff(:year, jan_1_2000, jan_31_2000)
21
+ assert_equal (32 / 366.to_d), date_diff(:year, jan_1_2000, feb_1_2000)
22
+ assert_equal (2/366.to_d + 2/365.to_d), date_diff(:year, dec_30_2000, jan_2_2001)
23
23
  end
24
24
 
25
25
  def test_quarters_between_a_few_days
26
- q1_2000 = (31 + 29 + 31).to_f
27
- q4_2000 = (31 + 30 + 31).to_f
28
- q1_2001 = (31 + 28 + 31).to_f
29
- assert_equal (1.0 / q1_2000), date_diff(:quarter, jan_1_2000, jan_1_2000)
30
- assert_equal (31.0 / q1_2000), date_diff(:quarter, jan_1_2000, jan_31_2000)
31
- assert_equal (32.0 / q1_2000), date_diff(:quarter, jan_1_2000, feb_1_2000)
26
+ q1_2000 = (31 + 29 + 31).to_d
27
+ q4_2000 = (31 + 30 + 31).to_d
28
+ q1_2001 = (31 + 28 + 31).to_d
29
+ assert_equal (1 / q1_2000), date_diff(:quarter, jan_1_2000, jan_1_2000)
30
+ assert_equal (31 / q1_2000), date_diff(:quarter, jan_1_2000, jan_31_2000)
31
+ assert_equal (32 / q1_2000), date_diff(:quarter, jan_1_2000, feb_1_2000)
32
32
  assert_equal (2/q4_2000 + 2/q1_2001), date_diff(:quarter, dec_30_2000, jan_2_2001)
33
33
  end
34
34
 
35
35
  def test_months_between_a_few_days
36
- assert_equal (1.0 / 31.0), date_diff(:month, jan_1_2000, jan_1_2000)
37
- assert_equal (31.0 / 31.0), date_diff(:month, jan_1_2000, jan_31_2000)
38
- assert_equal (1.0 + 1/29.0), date_diff(:month, jan_1_2000, feb_1_2000)
39
- assert_equal (2.0/31.0 + 2.0/31.0), date_diff(:month, dec_30_2000, jan_2_2001)
36
+ assert_equal (1 / 31.to_d), date_diff(:month, jan_1_2000, jan_1_2000)
37
+ assert_equal (31 / 31.to_d), date_diff(:month, jan_1_2000, jan_31_2000)
38
+ assert_equal (1 + 1/29.to_d), date_diff(:month, jan_1_2000, feb_1_2000)
39
+ assert_equal (2/31.to_d + 2/31.to_d), date_diff(:month, dec_30_2000, jan_2_2001)
40
40
  end
41
41
 
42
42
  def test_weeks_between_a_few_days
43
- assert_equal (1.0 / 7.0), date_diff(:week, jan_1_2000, jan_1_2000)
44
- assert_equal (31.0 / 7.0), date_diff(:week, jan_1_2000, jan_31_2000)
45
- assert_equal (32.0 / 7.0), date_diff(:week, jan_1_2000, feb_1_2000)
46
- assert_equal (2/7.0 + 2/7.0), date_diff(:week, dec_30_2000, jan_2_2001)
43
+ assert_equal (1 / 7.to_d), date_diff(:week, jan_1_2000, jan_1_2000)
44
+ assert_equal (31 / 7.to_d), date_diff(:week, jan_1_2000, jan_31_2000)
45
+ assert_equal (Rational(32, 7).to_d(19)), date_diff(:week, jan_1_2000, feb_1_2000)
47
46
  end
48
47
 
49
48
  def test_days_between_a_few_days
50
- assert_equal 1.0, date_diff(:day, jan_1_2000, jan_1_2000)
51
- assert_equal 31.0, date_diff(:day, jan_1_2000, jan_31_2000)
52
- assert_equal 32.0, date_diff(:day, jan_1_2000, feb_1_2000)
53
- assert_equal 4.0, date_diff(:day, dec_30_2000, jan_2_2001)
49
+ assert_equal 1, date_diff(:day, jan_1_2000, jan_1_2000)
50
+ assert_equal 31, date_diff(:day, jan_1_2000, jan_31_2000)
51
+ assert_equal 32, date_diff(:day, jan_1_2000, feb_1_2000)
52
+ assert_equal 4, date_diff(:day, dec_30_2000, jan_2_2001)
54
53
  end
55
54
 
56
55
  def test_six_months
57
- assert_equal ((1 + 29 + 31 + 30 + 31 + 2) / 366.0), date_diff(:year, jan_31_2000, jun_2_2000)
58
- assert_equal (1.0/31.0 + 4.0 + 2.0/30.0), date_diff(:month, jan_31_2000, jun_2_2000)
59
- assert_equal ((1 + 29 + 31 + 30 + 31 + 2) / 7.0), date_diff(:week, jan_31_2000, jun_2_2000)
56
+ assert_equal ((1 + 29 + 31 + 30 + 31 + 2) / 366.to_d), date_diff(:year, jan_31_2000, jun_2_2000)
57
+ assert_equal (1/31.to_d + 4 + 2/30.to_d), date_diff(:month, jan_31_2000, jun_2_2000)
58
+ assert_equal ((1 + 29 + 31 + 30 + 31 + 2) / 7.to_d), date_diff(:week, jan_31_2000, jun_2_2000)
60
59
  assert_equal (1 + 29 + 31 + 30 + 31 + 2), date_diff(:day, jan_31_2000, jun_2_2000)
61
60
  end
62
61
 
@@ -74,8 +73,8 @@ class DateDiffTest < Minitest::Test
74
73
  end
75
74
 
76
75
  def test_a_year_and_four_days_across_a_leap_year
77
- assert_equal (2/366.0 + 1.0 + 2/365.0), date_diff(:year, dec_30_2000, Date.new(2002, 1, 2))
78
- assert_equal (2/31.0 + 12.0 + 2/31.0), date_diff(:month, dec_30_2000, Date.new(2002, 1, 2))
76
+ assert_equal (2/366.to_d + 1 + 2/365.to_d), date_diff(:year, dec_30_2000, Date.new(2002, 1, 2))
77
+ assert_equal (2/31.to_d + 12 + 2/31.to_d), date_diff(:month, dec_30_2000, Date.new(2002, 1, 2))
79
78
  end
80
79
 
81
80
  def test_advancing_days
@@ -147,6 +147,32 @@ class ProjectorTransactionTest < Minitest::Test
147
147
  assert_equal 0, @projector.net_worth
148
148
  end
149
149
 
150
+ def test_annual_transactions_by_12_months
151
+ @projector.add_transaction(
152
+ date: apr_1_2012,
153
+ credit: { amount: 50000, account_id: :nustartup_inc },
154
+ debit: { amount: 50000, account_id: :checking },
155
+ schedule: { scalar: 12, unit: :month },
156
+ )
157
+
158
+ @projector.project to: mar_31_2042
159
+
160
+ assert_equal 1500000, @projector.net_worth
161
+ end
162
+
163
+ def test_annual_transactions
164
+ @projector.add_transaction(
165
+ date: apr_1_2012,
166
+ credit: { amount: 50000, account_id: :nustartup_inc },
167
+ debit: { amount: 50000, account_id: :checking },
168
+ schedule: { scalar: 12, unit: :month },
169
+ )
170
+
171
+ @projector.project to: mar_31_2042
172
+
173
+ assert_equal 1500000, @projector.net_worth
174
+ end
175
+
150
176
  private
151
177
 
152
178
  def add_scheduled_transaction date = jan_1_2000
@@ -43,6 +43,28 @@ class ScheduledTransactionTest < Minitest::Test
43
43
  assert_equal expected_prorates, actual_prorates
44
44
  end
45
45
 
46
+ def test_slice_handles_scalar_greater_than_1
47
+ @schedule = Schedule.new scalar: 2, unit: :month
48
+
49
+ expected_dates = [jan_1_2000, mar_1_2000]
50
+ actual_dates, _ = @schedule.slice(jan_1_2000..mar_31_2000)
51
+ actual_dates.map! &:first
52
+
53
+ assert_equal expected_dates, actual_dates
54
+
55
+ expected_prorates = [1.0, 0.5]
56
+ actual_prorates, _ = @schedule.slice(jan_1_2000..mar_31_2000)
57
+ actual_prorates.map! &:last
58
+
59
+ assert_equal expected_prorates, actual_prorates
60
+
61
+ expected_prorates = [1.0, 0.75]
62
+ actual_prorates, _ = @schedule.slice(jan_1_2000..apr_15_2000)
63
+ actual_prorates.map! &:last
64
+
65
+ assert_equal expected_prorates, actual_prorates
66
+ end
67
+
46
68
  def test_handles_start_after_projection
47
69
  @schedule = Schedule.new every_month(from: apr_1_2000, until: jun_15_2000)
48
70
 
data/test/test_helper.rb CHANGED
@@ -31,7 +31,7 @@ end
31
31
  # BigDecimal needs friendlier output
32
32
  class BigDecimal < Numeric
33
33
  def inspect
34
- "#<BigDecmial:#{round(10).to_f.inspect}>"
34
+ "#<BigDecmial:#{round(20).to_f.inspect}>"
35
35
  end
36
36
  end
37
37
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mudrat_projector
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - ntl