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
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 'uploaded_file'
19 # Controller for AssetPosition
21 # This also cares about orders and other things since an AssetPosition
22 # is more than just the Position model.
23 class PositionController < ApplicationController
26 # Show details about a SmrPosition.
28 @position = Smr::AssetPosition.new(params[:id].to_i, current_user.id, smr_browse_date)
29 redirect_to root_path if @position.is_cash_position?
31 if @position.is_new? then
32 smr_menu_addsubitem('assets', {
33 '+ order'=>new_position_path + '?id_position=%i'%params[:id],
34 '- sell off'=>'/close?id=%i' % params[:id]
36 elsif not @position.is_closed?
37 smr_menu_addsubitem('assets', {
38 '+ order'=>new_position_path + '?id_position=%i' % params[:id],
39 '+ dividend'=>position_path + '?add_dividend=true',
40 '- sell off'=>'/close?id=%i' % params[:id],
41 '+ document'=>position_path + '?add_document=true',
46 @documents, @total_pages = smr_paginate(@page, Smr::UploadedFiles.new(current_user.id, @position.id))
48 if params[:add_dividend] then
49 @dividend = Dividend.new(:exdate=>smr_browse_date - 2.days, :id_position=>@position.id)
54 # conditionally make a new position
56 # Most of the time this will not create a new position but rather add an
57 # order to an existing position. It can perform one of these things
60 # 1) make a new order on existing position
61 # 2) make new position in given portfolio with new order
62 # 3) make new position in selectable portfolio holding selectable stock
65 # make new order on selected existing position
67 # In any case the +session+ is checked for :position_prefilled_order which
68 # will be used as basis for the new order, if present.
70 if session[:position_prefilled_order] and session[:position_prefilled_order].is_a?(Order) then
71 @order = session[:position_prefilled_order]
73 @order = Order.new(:issued => smr_browse_date, :expire => (smr_browse_date+1.month).end_of_day)
76 if params[:id_position] then
78 @position = Smr::AssetPosition.new(params[:id_position], current_user.id, smr_browse_date)
79 elsif params[:id_portfolio] then
81 @portfolio = Portfolio.find_by_id(params[:id_portfolio])
82 @stocks = Stock.select(:id, :name).where.not(:id=>Smr::ID_CASH_SECURITY).all
85 @portfolios = Portfolio.select(:id, :name).where(:id_user=>current_user.id).order(order: :desc)
86 @open_positions = Smr::Asset.new(current_user.id, smr_browse_date, :skip_cash_positions=>true).open_positions
87 @stocks = Stock.select(:id, :name).where.not(:id=>Smr::ID_CASH_SECURITY).all
92 # creates an position/order by taking POST
94 # FIXME: Gummicode! Test carefully, ie issue on closed position?
98 order = Order.new(order_params)
99 order.issued = Time.parse(params[:order_issued]).to_i
100 order.expire = Time.parse(params[:order_expire]).to_i
102 if not params[:id_position].empty? then
104 order.id_position = params[:id_position].to_i
105 redirect = position_path(order.id_position)
106 elsif params[:id_portfolio].empty? or params[:id_stock].empty? then
107 redirect_to :back, :notice=>'Please select some Security and Portfolio or use an existing Position to order.'
111 position = Position.new(
112 :id_portfolio=>params[:id_portfolio].to_i,
113 :id_stock=>params[:id_stock].to_i,
118 order.id_position=position.id
120 redirect = position_path(position.id)
126 if params[:execute_now].to_i == 1 and params[:execute_quote].to_f > 0.0 then
127 t = Smr::Transaction.new(
128 Position.find(order.id_position),
132 t.execute(params[:execute_quote].to_f, Time.parse(params[:execute_time]))
135 if params[:close_position].to_i == 1 then
136 pstat = Smr::AssetPosition.new(order.id_position, current_user.id, smr_browse_date).close
137 n += ' Closed position because all shares were sold.' if pstat.is_a?(TrueClass)
140 n = 'Issued new Order to %s %f shares.' % [order.type, order.shares]
144 if params[:order][:document] then
145 doc = Smr::UploadedFile.store(current_user.id, params[:order][:document])
146 doc.assign(:order=>order.id)
149 redirect_to redirect, :notice=>n
153 # update Position details
154 # - that is things that wont change the positions` status
156 if params[:id] and params[:comment]
157 p = Position.find(params[:id])
158 p.comment = params[:comment]
165 # close this position at smr_browse_date
167 p = Smr::AssetPosition.new(params[:id].to_i, current_user.id, smr_browse_date)
168 stat = p.close(smr_browse_date)
169 if stat.is_a?(TrueClass) then
170 n='Closed position #%i as of %s.' % [p.id, p.time_closed]
172 elsif stat.is_a?(Order) then
173 session[:position_prefilled_order] = stat
174 n='Position holds shares. Can not close it right away. A new '\
175 +'order to sell them off has been pre-filled, please edit and '\
177 r=new_position_path + '?id_position=%i' % p.id
179 n='Can not close position #%i because it is closed already.' % p.id
182 redirect_to r, :notice=>n
192 # apply Order to Position at #smr_browse_date
194 p = Smr::AssetPosition.new(params[:id], current_user.id)
195 t = Smr::Transaction.new(p, current_user, :order=>Order.find(params[:id_order]))
196 t.execute(params[:execute_quote].to_f, Time.parse(params[:execute_time]))
198 # try to close the position, it may remain open unless empty
199 p.close if t.order.is_sale?
201 redirect_to :back, :notice=>t.to_s
205 # cancel pending order by setting the canceled flag
207 o = Order.find_by_id(params[:id_order])
210 redirect_to :back, :notice=>'Order #%i has been canceled' % o.id
216 # internal helper defining which parameters to accept for an order
218 params.require(:order).permit(
219 :exchange, :shares, :limit, :addon, :provision, :courtage, :type,
220 :comment, :expense, :accrued_interest