mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-18 20:59:39 +02:00
Vehicle view (#1117)
This commit is contained in:
parent
e856691c86
commit
359bceb58e
15 changed files with 259 additions and 8 deletions
42
app/controllers/vehicles_controller.rb
Normal file
42
app/controllers/vehicles_controller.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
class VehiclesController < ApplicationController
|
||||
before_action :set_account, only: :update
|
||||
|
||||
def create
|
||||
account = Current.family
|
||||
.accounts
|
||||
.create_with_optional_start_balance! \
|
||||
attributes: account_params.except(:start_date, :start_balance),
|
||||
start_date: account_params[:start_date],
|
||||
start_balance: account_params[:start_balance]
|
||||
|
||||
account.sync_later
|
||||
redirect_to account, notice: t(".success")
|
||||
end
|
||||
|
||||
def update
|
||||
@account.update!(account_params)
|
||||
@account.sync_later
|
||||
redirect_to @account, notice: t(".success")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_account
|
||||
@account = Current.family.accounts.find(params[:id])
|
||||
end
|
||||
|
||||
def account_params
|
||||
params.require(:account)
|
||||
.permit(
|
||||
:name, :balance, :start_date, :start_balance, :currency, :accountable_type,
|
||||
accountable_attributes: [
|
||||
:id,
|
||||
:make,
|
||||
:model,
|
||||
:year,
|
||||
:mileage_value,
|
||||
:mileage_unit
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
|
@ -29,6 +29,8 @@ module AccountsHelper
|
|||
case account.accountable_type
|
||||
when "Property"
|
||||
properties_path
|
||||
when "Vehicle"
|
||||
vehicles_path
|
||||
else
|
||||
accounts_path
|
||||
end
|
||||
|
@ -38,6 +40,8 @@ module AccountsHelper
|
|||
case account.accountable_type
|
||||
when "Property"
|
||||
property_path(account)
|
||||
when "Vehicle"
|
||||
vehicle_path(account)
|
||||
else
|
||||
account_path(account)
|
||||
end
|
||||
|
@ -51,7 +55,7 @@ module AccountsHelper
|
|||
transactions_tab = { key: "transactions", label: t("accounts.show.transactions"), path: account_path(account, tab: "transactions"), route: account_transactions_path(account) }
|
||||
trades_tab = { key: "trades", label: t("accounts.show.trades"), path: account_path(account, tab: "trades"), route: account_trades_path(account) }
|
||||
|
||||
return [ overview_tab, value_tab ] if account.property?
|
||||
return [ overview_tab, value_tab ] if account.property? || account.vehicle?
|
||||
return [ holdings_tab, cash_tab, trades_tab ] if account.investment?
|
||||
|
||||
[ value_tab, transactions_tab ]
|
||||
|
|
2
app/helpers/vehicles_helper.rb
Normal file
2
app/helpers/vehicles_helper.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
module VehiclesHelper
|
||||
end
|
|
@ -3,7 +3,7 @@ class Measurement
|
|||
|
||||
attr_reader :value, :unit
|
||||
|
||||
VALID_UNITS = %w[sqft sqm]
|
||||
VALID_UNITS = %w[sqft sqm mi km]
|
||||
|
||||
validates :unit, inclusion: { in: VALID_UNITS }
|
||||
validates :value, presence: true
|
||||
|
|
|
@ -15,10 +15,6 @@ class Property < ApplicationRecord
|
|||
first_valuation_amount
|
||||
end
|
||||
|
||||
def equity_value
|
||||
account.balance_money
|
||||
end
|
||||
|
||||
def trend
|
||||
TimeSeries::Trend.new(current: account.balance_money, previous: first_valuation_amount)
|
||||
end
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
class Vehicle < ApplicationRecord
|
||||
include Accountable
|
||||
|
||||
attribute :mileage_unit, :string, default: "mi"
|
||||
|
||||
def mileage
|
||||
Measurement.new(mileage_value, mileage_unit) if mileage_value.present?
|
||||
end
|
||||
|
||||
def purchase_price
|
||||
first_valuation_amount
|
||||
end
|
||||
|
||||
def trend
|
||||
TimeSeries::Trend.new(current: account.balance_money, previous: first_valuation_amount)
|
||||
end
|
||||
|
||||
private
|
||||
def first_valuation_amount
|
||||
account.entries.account_valuations.order(:date).first&.amount_money || account.balance_money
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<%# locals: (f:) %>
|
||||
|
||||
<div>
|
||||
<hr class="my-4">
|
||||
|
||||
<div class="space-y-2">
|
||||
<%= f.fields_for :accountable do |vehicle_form| %>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<%= vehicle_form.text_field :make, label: t(".make"), placeholder: t(".make_placeholder") %>
|
||||
<%= vehicle_form.text_field :model, label: t(".model"), placeholder: t(".model_placeholder") %>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<%= vehicle_form.text_field :year, label: t(".year"), placeholder: t(".year_placeholder") %>
|
||||
<%= vehicle_form.text_field :mileage_value, label: t(".mileage"), placeholder: t(".mileage_placeholder") %>
|
||||
<%= vehicle_form.select :mileage_unit,
|
||||
[["Miles", "mi"], ["Kilometers", "km"]],
|
||||
{ label: t(".mileage_unit") } %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
49
app/views/accounts/accountables/vehicle/_overview.html.erb
Normal file
49
app/views/accounts/accountables/vehicle/_overview.html.erb
Normal file
|
@ -0,0 +1,49 @@
|
|||
<%# locals: (account:) %>
|
||||
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
<div class="rounded-xl bg-white shadow-xs border border-alpha-black-25 p-4">
|
||||
<h4 class="text-gray-500 text-sm"><%= t(".make_model") %></h4>
|
||||
<p class="text-xl font-medium text-gray-900">
|
||||
<%= [account.vehicle.make, account.vehicle.model].compact.join(" ").presence || t(".unknown") %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl bg-white shadow-xs border border-alpha-black-25 p-4">
|
||||
<h4 class="text-gray-500 text-sm"><%= t(".year") %></h4>
|
||||
<p class="text-xl font-medium text-gray-900">
|
||||
<%= account.vehicle.year || t(".unknown") %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl bg-white shadow-xs border border-alpha-black-25 p-4">
|
||||
<h4 class="text-gray-500 text-sm flex items-center gap-1"><%= t(".mileage") %></h4>
|
||||
<p class="text-xl font-medium text-gray-900">
|
||||
<%= account.vehicle.mileage || t(".unknown") %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl bg-white shadow-xs border border-alpha-black-25 p-4">
|
||||
<h4 class="text-gray-500 text-sm"><%= t(".purchase_price") %></h4>
|
||||
<p class="text-xl font-medium text-gray-900">
|
||||
<%= format_money account.vehicle.purchase_price %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl bg-white shadow-xs border border-alpha-black-25 p-4">
|
||||
<h4 class="text-gray-500 text-sm"><%= t(".current_price") %></h4>
|
||||
<p class="text-xl font-medium text-gray-900">
|
||||
<%= format_money account.balance_money %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl bg-white shadow-xs border border-alpha-black-25 p-4">
|
||||
<h4 class="text-gray-500 text-sm"><%= t(".trend") %></h4>
|
||||
<div class="flex items-center gap-1" style="color: <%= account.vehicle.trend.color %>">
|
||||
<p class="text-xl font-medium">
|
||||
<%= account.vehicle.trend.value %>
|
||||
</p>
|
||||
|
||||
<p>(<%= account.vehicle.trend.percent %>%)</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -19,6 +19,24 @@ en:
|
|||
postal_code: Postal code (optional)
|
||||
state: State
|
||||
year_built: Year built (optional)
|
||||
vehicle:
|
||||
make: Make
|
||||
make_placeholder: Toyota
|
||||
mileage: Mileage
|
||||
mileage_placeholder: '15000'
|
||||
mileage_unit: Unit
|
||||
model: Model
|
||||
model_placeholder: Camry
|
||||
overview:
|
||||
current_price: Current Price
|
||||
make_model: Make & Model
|
||||
mileage: Mileage
|
||||
purchase_price: Purchase Price
|
||||
trend: Trend
|
||||
unknown: Unknown
|
||||
year: Year
|
||||
year: Year
|
||||
year_placeholder: '2023'
|
||||
create:
|
||||
success: New account created successfully
|
||||
destroy:
|
||||
|
|
7
config/locales/views/vehicles/en.yml
Normal file
7
config/locales/views/vehicles/en.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
en:
|
||||
vehicles:
|
||||
create:
|
||||
success: Vehicle created successfully
|
||||
update:
|
||||
success: Vehicle updated successfully
|
|
@ -90,6 +90,7 @@ Rails.application.routes.draw do
|
|||
end
|
||||
|
||||
resources :properties, only: %i[ create update ]
|
||||
resources :vehicles, only: %i[ create update ]
|
||||
|
||||
resources :transactions, only: %i[ index new create ] do
|
||||
collection do
|
||||
|
|
9
db/migrate/20240823125526_add_details_to_vehicle.rb
Normal file
9
db/migrate/20240823125526_add_details_to_vehicle.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
class AddDetailsToVehicle < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
add_column :vehicles, :year, :integer
|
||||
add_column :vehicles, :mileage_value, :integer
|
||||
add_column :vehicles, :mileage_unit, :string
|
||||
add_column :vehicles, :make, :string
|
||||
add_column :vehicles, :model, :string
|
||||
end
|
||||
end
|
7
db/schema.rb
generated
7
db/schema.rb
generated
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.2].define(version: 2024_08_22_180845) do
|
||||
ActiveRecord::Schema[7.2].define(version: 2024_08_23_125526) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pgcrypto"
|
||||
enable_extension "plpgsql"
|
||||
|
@ -441,6 +441,11 @@ ActiveRecord::Schema[7.2].define(version: 2024_08_22_180845) do
|
|||
create_table "vehicles", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "year"
|
||||
t.integer "mileage_value"
|
||||
t.string "mileage_unit"
|
||||
t.string "make"
|
||||
t.string "model"
|
||||
end
|
||||
|
||||
add_foreign_key "account_balances", "accounts", on_delete: :cascade
|
||||
|
|
71
test/controllers/vehicles_controller_test.rb
Normal file
71
test/controllers/vehicles_controller_test.rb
Normal file
|
@ -0,0 +1,71 @@
|
|||
require "test_helper"
|
||||
|
||||
class VehiclesControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
sign_in @user = users(:family_admin)
|
||||
@account = accounts(:vehicle)
|
||||
end
|
||||
|
||||
test "creates vehicle" do
|
||||
assert_difference -> { Account.count } => 1,
|
||||
-> { Vehicle.count } => 1,
|
||||
-> { Account::Valuation.count } => 2,
|
||||
-> { Account::Entry.count } => 2 do
|
||||
post vehicles_path, params: {
|
||||
account: {
|
||||
name: "Vehicle",
|
||||
balance: 30000,
|
||||
currency: "USD",
|
||||
accountable_type: "Vehicle",
|
||||
start_date: 1.year.ago.to_date,
|
||||
start_balance: 35000,
|
||||
accountable_attributes: {
|
||||
make: "Toyota",
|
||||
model: "Camry",
|
||||
year: 2020,
|
||||
mileage_value: 15000,
|
||||
mileage_unit: "mi"
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
created_account = Account.order(:created_at).last
|
||||
|
||||
assert_equal "Toyota", created_account.vehicle.make
|
||||
assert_equal "Camry", created_account.vehicle.model
|
||||
assert_equal 2020, created_account.vehicle.year
|
||||
assert_equal 15000, created_account.vehicle.mileage_value
|
||||
assert_equal "mi", created_account.vehicle.mileage_unit
|
||||
|
||||
assert_redirected_to account_path(created_account)
|
||||
assert_equal "Vehicle created successfully", flash[:notice]
|
||||
assert_enqueued_with(job: AccountSyncJob)
|
||||
end
|
||||
|
||||
test "updates vehicle" do
|
||||
assert_no_difference [ "Account.count", "Vehicle.count", "Account::Valuation.count", "Account::Entry.count" ] do
|
||||
patch vehicle_path(@account), params: {
|
||||
account: {
|
||||
name: "Updated Vehicle",
|
||||
balance: 28000,
|
||||
currency: "USD",
|
||||
accountable_type: "Vehicle",
|
||||
accountable_attributes: {
|
||||
id: @account.accountable_id,
|
||||
make: "Honda",
|
||||
model: "Accord",
|
||||
year: 2021,
|
||||
mileage_value: 20000,
|
||||
mileage_unit: "mi",
|
||||
purchase_price: 32000
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
assert_redirected_to account_path(@account)
|
||||
assert_equal "Vehicle updated successfully", flash[:notice]
|
||||
assert_enqueued_with(job: AccountSyncJob)
|
||||
end
|
||||
end
|
|
@ -34,7 +34,12 @@ class AccountsTest < ApplicationSystemTestCase
|
|||
end
|
||||
|
||||
test "can create vehicle account" do
|
||||
assert_account_created("Vehicle")
|
||||
assert_account_created "Vehicle" do
|
||||
fill_in "Make", with: "Toyota"
|
||||
fill_in "Model", with: "Camry"
|
||||
fill_in "Year", with: "2020"
|
||||
fill_in "Mileage", with: "30000"
|
||||
end
|
||||
end
|
||||
|
||||
test "can create other asset account" do
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue