minor features, layout improvements, many fixes
[smr.git] / gui / lib / smr / cashflowitem.rb
blob507be6f1ceac75a5bdacf801a90fe38fcd8b2d54
2 # This file is part of SMR.
4 # SMR is free software: you can redistribute it and/or modify it under the
5 # terms of the GNU General Public License as published by the Free Software
6 # Foundation, either version 3 of the License, or (at your option) any later
7 # version.
9 # SMR is distributed in the hope that it will be useful, but WITHOUT ANY
10 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License along with
14 # SMR.  If not, see <http://www.gnu.org/licenses/>.
17 module Smr  #:nodoc:
18   ##
19   # Represents a single item of cashflow. Useful for viewing.
20   class CashflowItem
21       include Comparable
23       ##
24       # Reader for given attribute, see #new
25       attr_reader :date
26       attr_reader :what
27       attr_reader :amount_per_share
28       attr_reader :poolfactor
29       attr_reader :comment
30       attr_reader :type
32       # number of shares (or face value) that produced this cashflow item
33       attr_writer :shares
35       # Smr::Link to whatever has created this item, may be false
36       attr_accessor :link
38       ##
39       # A piece of cashflow at a specific time.
40       #
41       # By default its for a single share. But can be scaled by using
42       # #shares=X.Y or specifying options[:shares].
43       #
44       # Note options[:poolfactor]. This is also applied. Make sure to set it
45       # correctly if one existed at :date.
46       #
47       # Pass a Smr::Link in via :link option to make use of the #link method.
48       def initialize(date, what, amount_per_share, options={})
49         raise ':date must be Time' unless date.is_a? Time
50         raise ':amount_per_share must be Integer, Float or Percentage' unless [Integer, Float, Percentage].include? amount_per_share.class
52         options.reverse_update({
53             :comment=>nil, :type=>false, :poolfactor=>1.0, :shares=>1.0,
54             :link=>false,
55         })
57         @date=date
58         @what=what
59         @amount_per_share=amount_per_share
60         @options = options
61         @comment = options[:comment]
62         @shares = options[:shares]
63         @type = options[:type]
64         @link = options[:link]
66         @poolfactor = options[:poolfactor]
67         @lock_poolfactor = false
68       end
70       ##
71       # Human readable description of #type.
72       def describe_type
73         PositionRevision.describe_type(@options[:type]) if PositionRevision.types.include?(@options[:type])
74       end
76       ##
77       # Human readable representation of this item.
78       def to_s
79         '%s: %-25.24s %10.4f (pf=%4.2f)' % [date, describe_type, total, @poolfactor]
80       end
82       ##
83       # Absolute amount of cashflow.
84       #
85       # It is scaled to #shares and the :poolfactor is applied unless its a
86       # redemption payment which causes the poolfactor to shrink in most cases.
87       def total
88         @lock_poolfactor = true
89         if @type == :redemption_booking
90             @shares * @amount_per_share
91         else @shares * @amount_per_share * poolfactor end
92       end
94       ##
95       # Compares items by :date, then by :total amount
96       def <=>(other)
97         comp = (date <=> other.date)
98         if comp.zero? then (total <=> other.total) else comp end
99       end
101       ##
102       # Adjust :poolfactor to some other value.
103       # Works only once and not at all after #total has been called!
104       def adjust_poolfactor(value)
105         raise '#adjust_poolfactor should never be called twice, check algorithm.' if @lock_poolfactor
106         @lock_poolfactor = true
107         @poolfactor = value
108       end
109   end
110 end # module