manage bookmarks, bugfixes
[smr.git] / gui / app / controllers / objects / security_controller.rb
blob877b02d6a2b3df503706878e04907d4d25a0a7f3
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/>.
16 require 'csv'
19 # handles CRUD on Security records
20 class Objects::SecurityController < ObjectsController
22     ##
23     # List all Security records for editing.
24     def index
25         super
26         session[:objects_security_query] = params[:q] if params[:q]
28         @query = Security.ransack(session[:objects_security_query])
29         @securities, @total_pages = smr_paginate(
30             @page=smr_page,
31             @query.result.includes(:Organization).to_a
32         )
33         @select_securities = smr_securities_list
34     end
36     ##
37     # defines empty Security to #create a new one
38     def new
39         @organizations = Organization.all.order(:name).to_a
41         if params[:symbol]
42             @security = Security.new(:symbol=>params[:symbol])
43             @security.id_organization = session[:objects_security_organization] if session[:objects_security_organization]
45             begin @security.fetch_metadata
46             rescue ActiveRecord::RecordInvalid => errors
47                 flash[:alert] = errors.to_s
48                 @security = false
49             end
50         else @security = Security.new end
51     end
53     ##
54     # retrieve Security for editing
55     # - NOTE: disabled @quote_retrieval_status because it hinders fluent
56     # security editing
57     def edit
58         self.new
60         @security = Security.find(params[:id])
61         render :new
62     end
64     ##
65     # handles creates and updates
66     def create
67         n = Array.new
69         if params[:security][:id].to_i > 0 then
70             security = Security.find(params[:security][:id])
71             security.update(security_params)
72         else security = Security.create(security_params) end
74         if params[:security_use_type] then
75             security.create_type(params[:security_use_type])
76         end
78         if params[:security_stock]
79             if params[:security_stock][:id].to_i > 0 then
80                 st = SecurityStock.find(params[:security_stock][:id])
81                 st.update(security_stock_params)
82             else st = SecurityStock.create(security_stock_params) end
83             security.id_security_stock = st.id
84             n << st.errors.full_messages.uniq
85         end
87         if params[:security_bond]
88             if params[:security_bond][:id].to_i > 0 then
89                 st = SecurityBond.find(params[:security_bond][:id])
90                 st.update(security_bond_params)
91             else st = SecurityBond.create(security_bond_params) end
92             security.id_security_bond = st.id
93             n << st.errors.full_messages.uniq
94         end
96         if params[:security_fund]
97             if params[:security_fund][:id].to_i > 0 then
98                 st = SecurityFund.find(params[:security_fund][:id])
99                 st.update(security_fund_params)
100             else st = SecurityFund.create(security_fund_params) end
101             security.id_security_fund = st.id
102             n << st.errors.full_messages.uniq
103         end
105         if params[:security_metal]
106             if params[:security_metal][:id].to_i > 0 then
107                 st = SecurityMetal.find(params[:security_metal][:id])
108                 st.update(security_metal_params)
109             else st = SecurityMetal.create(security_metal_params) end
110             security.id_security_metal = st.id
111             n << st.errors.full_messages.uniq
112         end
114         if params[:security_derivative]
115             if params[:security_derivative][:id].to_i > 0 then
116                 st = SecurityDerivative.find(params[:security_derivative][:id])
117                 st.update(security_derivative_params)
118             else st = SecurityDerivative.create(security_derivative_params) end
119             security.id_security_derivative = st.id
120             n << st.errors.full_messages.uniq
121         end
123         if params[:security_index]
124             if params[:security_index][:id].to_i > 0 then
125                 st = SecurityIndex.find(params[:security_index][:id])
126                 st.update(security_index_params)
127             else st = SecurityIndex.create(security_index_params) end
128             security.id_security_index = st.id
129             n << st.errors.full_messages.uniq
130         end
132         security.save
133         n << security.errors.full_messages.uniq
135         redirect_to objects_security_index_path, :notice=>n.flatten.join(', ')
136     end
138     ##
139     # delete Security unless (!) important data is related to it
140     # - basically delete is not possible if a Position exist (of any user)
141     # - also "observations" block it, ie. a assigned Document or FigureData
142     # - see the model to know what else is important
143     # - unimportant records such as Quote will be removed along
144     def destroy
145         s = Security.find(params[:id])
146         begin s.destroy
147         rescue ActiveRecord::DeleteRestrictionError => errors
148             flash[:alert] = errors.to_s
149         end
151         redirect_to :action=>:index
152     end
154     ##
155     # export list of Securities as CSV data
156     def export
157         self.index
158         respond_to do |format|
159           format.html { redirect_to :action=>:index }
161           format.csv do
162             typemodel_join_str = Security.types.map{ |t|
163                 unless [:unknown, :cash].include?(t.to_sym) then
164                     'LEFT OUTER JOIN security_%s ON security_%s.id=security.id_security_%s' % [t, t, t]
165                 end
166             }.compact.join(' ')
168             lines = ActiveRecord::Base.connection.exec_query(
169                 'SELECT * FROM security %s' % typemodel_join_str
170             ).to_hash
172             csvdata = CSV.generate(:return_headers=>true, :force_quotes=>true){ |csv|
173                 csv.add_row(['name', 'type'] + lines.first.keys) # header with column names
174                 lines.each do |l|
175                     s = Security.find_by_symbol l['symbol']
176                     csv.add_row( [s.to_s, s.type] + l.values )
177                 end
178             }
180             send_data(
181                 csvdata,
182                 :type => 'text/csv; charset=utf-8; header=present',
183                 :disposition => 'attachment; filename=payments.csv'
184             )
185           end
186         end
187     end
189  protected
191     ##
192     # internal helper defining parameters acceptable for Security create/update
193     def security_params
194         params.require(:security).permit(
195           :symbol,
196           :preferred_reaper, :preferred_reaper_locked,
197           :id_organization, :brief, :description, :fetch_quote,
198           :collateral_coverage_ratio,
199           :time_trading_ceased, :trading_ceased_reason,
200           :Bookmark_attributes=> [ :id, :name, :url, :rank ]
201         )
202     end
204     ##
205     # internal helper defining parameters acceptable for Security Type model create/update
206     def security_stock_params
207         params.require(:security_stock).permit(
208           :dividend, :time_dividend_exdate, :dividend_interval, :type, :comment
209         )
210     end
212     def security_bond_params
213         params.require(:security_bond).permit(
214           :type, :currency, :denomination, :issue_size,
215           :is_subordinated, :is_callable, :is_stepup, :is_stepdown,
216           :coupon, :coupon_interval, :interest_method, :time_first_coupon, :time_last_coupon,
217           :time_maturity, :redemption_price, :redemption_installments, :redemption_interval,
218           :time_issue, :time_first_call, :call_price, :call_interval, :call_notify_deadline,
219           :comment
220         )
221     end
223     def security_fund_params
224         params.require(:security_fund).permit(
225           :type, :currency, :tranche, :time_inception, :time_fiscalyearend, :investment_minimum, :is_synthetic,
226           :distribution, :time_distribution, :distribution_interval, :is_retaining_profits,
227           :issue_surcharge, :management_fee, :redemption_fee, :redemption_period,
228           :comment
229         )
230     end
232     def security_metal_params
233         params.require(:security_metal).permit(
234           :type, :unit, :comment
235         )
236     end
238     def security_derivative_params
239         params.require(:security_derivative).permit(
240           :type, :direction, :id_security_underlying, :time_inception, :time_end,
241           :strike_price, :subscription_ratio, :is_leveraged, :is_dead, :comment
242         )
243     end
245     def security_index_params
246         params.require(:security_index).permit(
247           :comment
248         )
249     end