mirror of
https://github.com/we-promise/sure.git
synced 2026-04-08 23:04:49 +00:00
* Add cost basis tracking and management to holdings - Added migration to introduce `cost_basis_source` and `cost_basis_locked` fields to `holdings`. - Implemented backfill for existing holdings to set `cost_basis_source` based on heuristics. - Introduced `Holding::CostBasisReconciler` to manage cost basis resolution logic. - Added user interface components for editing and locking cost basis in holdings. - Updated `materializer` to integrate reconciliation logic and respect locked holdings. - Extended tests for cost basis-related workflows to ensure accuracy and reliability. * Fix cost basis calculation in holdings controller - Ensure `cost_basis` is converted to decimal for accurate arithmetic. - Fix conditional check to properly validate positive `cost_basis`. * Improve cost basis validation and error handling in holdings controller - Allow zero as a valid cost basis for gifted/inherited shares. - Add error handling with user feedback for invalid cost basis values. --------- Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
59 lines
1.7 KiB
Ruby
59 lines
1.7 KiB
Ruby
class HoldingsController < ApplicationController
|
|
before_action :set_holding, only: %i[show update destroy unlock_cost_basis]
|
|
|
|
def index
|
|
@account = Current.family.accounts.find(params[:account_id])
|
|
end
|
|
|
|
def show
|
|
end
|
|
|
|
def update
|
|
total_cost_basis = holding_params[:cost_basis].to_d
|
|
|
|
if total_cost_basis >= 0 && @holding.qty.positive?
|
|
# Convert total cost basis to per-share cost (the cost_basis field stores per-share)
|
|
# Zero is valid for gifted/inherited shares
|
|
per_share_cost = total_cost_basis / @holding.qty
|
|
@holding.set_manual_cost_basis!(per_share_cost)
|
|
flash[:notice] = t(".success")
|
|
else
|
|
flash[:alert] = t(".error")
|
|
end
|
|
|
|
# Redirect to account page holdings tab to refresh list and close drawer
|
|
redirect_to account_path(@holding.account, tab: "holdings")
|
|
end
|
|
|
|
def unlock_cost_basis
|
|
@holding.unlock_cost_basis!
|
|
flash[:notice] = t(".success")
|
|
|
|
# Redirect to account page holdings tab to refresh list and close drawer
|
|
redirect_to account_path(@holding.account, tab: "holdings")
|
|
end
|
|
|
|
def destroy
|
|
if @holding.account.can_delete_holdings?
|
|
@holding.destroy_holding_and_entries!
|
|
flash[:notice] = t(".success")
|
|
else
|
|
flash[:alert] = "You cannot delete this holding"
|
|
end
|
|
|
|
respond_to do |format|
|
|
format.html { redirect_back_or_to account_path(@holding.account) }
|
|
format.turbo_stream { render turbo_stream: turbo_stream.action(:redirect, account_path(@holding.account)) }
|
|
end
|
|
end
|
|
|
|
private
|
|
def set_holding
|
|
@holding = Current.family.holdings.find(params[:id])
|
|
end
|
|
|
|
def holding_params
|
|
params.require(:holding).permit(:cost_basis)
|
|
end
|
|
end
|