ability to settle cashpositions
[smr.git] / gui / app / helpers / application_helper.rb
blob02364b48875a1ccfb82f2c48e6555267d8f9c68e
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 require 'percentage'
20 # Collection of helper methods for use in all views.
21 module ApplicationHelper
23     ##
24     # Date the user is currently browsing, as Time, positioned at
25     # end of day (23:59:59)
26     #
27     # use :keep_current_time=>true to take the time part of Time.now and apply
28     # it to the browse date
29     def smr_browse_date(options={:keep_current_time=>false})
30         bd = if session[:smr_browse_date].nil? then Time.new
31              else Time.at(session[:smr_browse_date]) end
33         if options[:keep_current_time]
34             bd.beginning_of_day + (Time.now - Time.now.beginning_of_day)
35         else bd end
36     end
38     ##
39     # Place the users us browsing as +String+.
40     def smr_browse_position
41         controller.class.to_s.sub('Controller', '')
42     end
44     ##
45     # Returns change from +val1+ to +val2+ in percent, as smr_humanize()d String.
46     def percentage_change(val1, val2)
47         return nil if val1.zero? or val2.blank?
48         smr_humanize(Percentage.change(val1, val2))
49     end
51     ##
52     # Returns percentage of +val+ from +base+, as smr_humanize()d String.
53     def percentage_of(base, val)
54         if base.zero? then return nil end
55         smr_humanize(BigDecimal(val.to_s).as_percentage_of(base))
56     end
58     ##
59     # humanize a number in ways useful in SMR
60     #
61     # Options:
62     # - :scientific notation, ie 1000 => 1.0e3
63     # - :shortword as spoken but short form, ie 1000 = 1 Kilo => 1k
64     # - :precision to force it to N digits, no matter what
65     # - :date_with_time adds time information, default for showing a Time
66     #   is YYYY-MM-DD
67     # - :date_time_only shows only the time information from given Time
68     def smr_humanize(n, options={
69                             :scientific=>false, :shortword=>false, :precision=>false,
70                             :date_with_time=>false, :date_time_only=>false })
71         unit = String.new
72         format = '%s'
73         skip_rounding=false
75         # handle 'inappropriate' data quickly
76         return '-' if n == 0.0 or n == false
77         return '' if n == ''
78         return n if n.is_a?(String)
80         # decide whether to round
81         skip_rounding = true if n.is_a?(Fixnum) and n.abs < 1000
82         skip_rounding = true if (n.nil? or n == false)
84         if n.is_a?(Percentage)
85             unit = '%'
86             if options[:precision]
87                 format = "%.#{options[:precision]}f"
88             else
89                 format = if n.to_f < 10 then '%.1f' else '%i' end
90             end
91             skip_rounding = true           
92         end
94         if n.is_a?(Time)
95             return '-' if n.to_i == 0
96             dateformat = if options[:date_with_time] then '%Y-%m-%d %H:%M'
97                 elsif options[:date_time_only] then '%H:%M:%S'
98                 else '%Y-%m-%d'
99             end
100             format = '%s' + n.strftime(dateformat)
101             n = nil 
102             skip_rounding = true
103         end
105         if options[:shortword]
106             skip_rounding = true
107             n = number_to_human(
108                 n,
109                 :units=>{
110                     :unit=>'', :thousand=>'k', :million=>'m', :billion=>'b',
111                     :trillion=>'t', :quadrillion=>'q'
112                 }
113             )
114         end
116         # do generic rounding if necessary
117         if not skip_rounding and not options[:precision]
118             case n.abs
119                 when 0..1 then format = '%.4f'
120                 when 1..9 then format = '%.3f'
121                 when 10..99 then format = '%.2f'
122                 when 100..1000 then format = '%.1f'
123             else
124                 format = if options[:scientific] then '%.3e' else '%i' end
125             end
126         elsif options[:precision]
127             format = "%.#{options[:precision]}f"
128         end
130         # return a String
131         (format + '%s') % [n, unit]
132     end
134     ##
135     # Turns Time into human speakable String
136     def smr_human_date(time)
137         time.strftime("%A, %B %d %Y")
138     end
140     ##
141     # Returns menu to browse SMR functionality in HTML format, see
142     # @smr_menu_items and smr_menu_addsubitem().
143     # TODO: supports one sublevel only, do we ever need more?
144     def smr_menu
145         content_tag(:ul, nil, :id=>'smr_menu') {
146           @smr_menu_items.reduce('') { |ctag, top|
147             if top.second.is_a?(Hash) then
148                 # sub level
149                 ctag << content_tag(:li) do
150                     link_to(top.first, top.second.delete('_toplink')) + 
151                     content_tag(:ul, nil) do
152                         top.second.reduce('') { |c, sub|
153                             c << content_tag(:li, link_to(sub.first, sub.second))
154                         }.html_safe
155                     end
156                 end
157             else
158                 # top level
159                 ctag << content_tag(:li, link_to(top.first, top.second))
160             end
161           }.html_safe
162         }
163     end
165     ##
166     # Provide link back to original object from Smr::BlogItem. Returns nil if
167     # there is no reference on that item.
168     #
169     # NOTE:
170     # - works only for +type=Comment+ right now and if the Comment is not
171     #   older than 7 days (the later is intentional as we want to store THE
172     #   TRUTH and not alternate it afterwards)
173     def smr_link_back(smr_blogitem, name)
174         raise 'smr_blogitem must be Smr::BlogItem' unless smr_blogitem.is_a?(Smr::BlogItem)
176         if smr_blogitem.type == 'Comment' and smr_blogitem.refid and smr_blogitem.date>7.days.ago then
177             link_to name, :controller=>:blog, :action=>:new, :id=>smr_blogitem.refid
178         else
179             nil
180         end
181     end
183     ##
184     # Create HTML container with page links.
185     #
186     # It will be positioned at +current_page+ with a maximum of +num_pages+
187     # and each link will direct to +basepath/?page=N+.
188     def smr_paginate(current_page, num_pages, basepath)
189             JustPaginate.page_navigation(current_page, num_pages) do |p|
190             '%s/?page=%i' % [basepath, p]
191         end.html_safe
192     end
194     ##
195     # Profit/Loss status number :n as text for humans to read or CSS class
196     # name.
197     def smr_profitloss_status(n, css=false)
198         if n.is_a?(FalseClass) or n == 0
199             s='Unvalued'
200         elsif n.between?(-150, 200)
201             s='Even'
202         elsif n > 0.0
203             s='Profit'
204         elsif n < 0.0
205             s='Loss'
206         end
208         if css then s.downcase else s end
209     end