1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-19 13:19:39 +02:00

Integrate money-rails gem (#268)

* Integrate money-rails gem

* Fix Lint issues

* Basic test for monetize feature

* Merge main branch

* Changes to monetize balance field

---------

Co-authored-by: Zach Gollwitzer <zach.gollwitzer@gmail.com>
This commit is contained in:
Nidhi Sarvaiya 2024-02-06 12:30:51 -05:00 committed by GitHub
parent 323a8ccf50
commit 1182ab39bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 176 additions and 14 deletions

View file

@ -27,6 +27,7 @@ gem "bcrypt", "~> 3.1.7"
gem "inline_svg"
gem "jbuilder"
gem "tzinfo-data", platforms: %i[ windows jruby ]
gem "money-rails", "~> 1.12"
group :development, :test do
gem "debug", platforms: %i[ mri windows ]

View file

@ -202,6 +202,15 @@ GEM
matrix (0.4.2)
mini_mime (1.1.5)
minitest (5.21.2)
monetize (1.13.0)
money (~> 6.12)
money (6.16.0)
i18n (>= 0.6.4, <= 2)
money-rails (1.15.0)
activesupport (>= 3.0)
monetize (~> 1.9)
money (~> 6.13)
railties (>= 3.0)
msgpack (1.7.2)
net-imap (0.4.10)
date
@ -382,6 +391,7 @@ DEPENDENCIES
inline_svg
jbuilder
letter_opener
money-rails (~> 1.12)
pg (~> 1.1)
propshaft
puma (>= 5.0)

View file

@ -30,7 +30,7 @@ class AccountsController < ApplicationController
private
def account_params
params.require(:account).permit(:name, :accountable_type, :balance, :subtype)
params.require(:account).permit(:name, :accountable_type, :balance, :balance_cents, :subtype)
end
def account_type_class

View file

@ -4,4 +4,6 @@ class Account < ApplicationRecord
delegated_type :accountable, types: %w[ Account::Credit Account::Depository Account::Investment Account::Loan Account::OtherAsset Account::OtherLiability Account::Property Account::Vehicle], dependent: :destroy
delegate :type_name, to: :accountable
monetize :balance_cents
end

View file

@ -11,7 +11,7 @@
<%= account.accountable %>
</div>
<p class="text-sm text-right">
<span class="block mb-1"><%= number_to_currency account.balance %></span>
<span class="block mb-1"><%= humanized_money_with_symbol account.balance %></span>
</p>
</div>
<% end %>

View file

@ -33,7 +33,7 @@
<div class="relative p-4 border border-gray-100 bg-offwhite rounded-xl focus-within:bg-white focus-within:shadow focus-within:opacity-100">
<label for="account_balance" class="block text-sm font-medium opacity-50 focus-within:opacity-100">Balance</label>
<div class="flex">
<%= f.number_field :balance, placeholder: "$0.00", in: 0.00..100000000.00, required: 'required', class: "p-0 mt-1 bg-transparent border-none opacity-50 focus:outline-none focus:ring-0 focus-within:opacity-100" %>
<%= f.number_field :balance, placeholder: "$0.00", in: 0.00..100000000.00, step: :any, required: 'required', class: "p-0 mt-1 bg-transparent border-none opacity-50 focus:outline-none focus:ring-0 focus-within:opacity-100" %>
</div>
</div>

View file

@ -70,7 +70,7 @@
<%= account.name %>
</div>
<p class="text-sm text-right">
<span class="block mb-1"><%= number_to_currency account.balance %></span>
<span class="block mb-1"><%= humanized_money_with_symbol account.balance %></span>
</p>
</div>
<% end %>

View file

@ -0,0 +1,114 @@
# encoding : utf-8
MoneyRails.configure do |config|
# To set the default currency
#
config.default_currency = :usd
# Set default bank object
#
# Example:
# config.default_bank = EuCentralBank.new
# Add exchange rates to current money bank object.
# (The conversion rate refers to one direction only)
#
# Example:
# config.add_rate "USD", "CAD", 1.24515
# config.add_rate "CAD", "USD", 0.803115
# To handle the inclusion of validations for monetized fields
# The default value is true
#
# config.include_validations = true
# Default ActiveRecord migration configuration values for columns:
#
# config.amount_column = { prefix: '', # column name prefix
# postfix: '_cents', # column name postfix
# column_name: nil, # full column name (overrides prefix, postfix and accessor name)
# type: :integer, # column type
# present: true, # column will be created
# null: false, # other options will be treated as column options
# default: 0
# }
#
# config.currency_column = { prefix: '',
# postfix: '_currency',
# column_name: nil,
# type: :string,
# present: true,
# null: false,
# default: 'USD'
# }
# Register a custom currency
#
# Example:
# config.register_currency = {
# priority: 1,
# iso_code: "EU4",
# name: "Euro with subunit of 4 digits",
# symbol: "€",
# symbol_first: true,
# subunit: "Subcent",
# subunit_to_unit: 10000,
# thousands_separator: ".",
# decimal_mark: ","
# }
# Specify a rounding mode
# Any one of:
#
# BigDecimal::ROUND_UP,
# BigDecimal::ROUND_DOWN,
# BigDecimal::ROUND_HALF_UP,
# BigDecimal::ROUND_HALF_DOWN,
# BigDecimal::ROUND_HALF_EVEN,
# BigDecimal::ROUND_CEILING,
# BigDecimal::ROUND_FLOOR
#
# set to BigDecimal::ROUND_HALF_EVEN by default
#
config.rounding_mode = BigDecimal::ROUND_HALF_UP
# Set default money format globally.
# Default value is nil meaning "ignore this option".
# Example:
#
# config.default_format = {
# no_cents_if_whole: nil,
# symbol: nil,
# sign_before_symbol: nil
# }
# If you would like to use I18n localization (formatting depends on the
# locale):
config.locale_backend = :i18n
#
# Example (using default localization from rails-i18n):
#
# I18n.locale = :en
# Money.new(10_000_00, 'USD').format # => $10,000.00
# I18n.locale = :es
# Money.new(10_000_00, 'USD').format # => $10.000,00
#
# For the legacy behaviour of "per currency" localization (formatting depends
# only on currency):
# config.locale_backend = :currency
#
# Example:
# Money.new(10_000_00, 'USD').format # => $10,000.00
# Money.new(10_000_00, 'EUR').format # => €10.000,00
#
# In case you don't need localization and would like to use default values
# (can be redefined using config.default_format):
# config.locale_backend = nil
# Set default raise_error_on_money_parsing option
# It will be raise error if assigned different currency
# The default value is false
#
# Example:
# config.raise_error_on_money_parsing = false
end

View file

@ -0,0 +1,14 @@
class ReplaceMoneyField < ActiveRecord::Migration[7.2]
def change
add_monetize :accounts, :balance
change_column :accounts, :balance_cents, :integer, limit: 8
Account.reset_column_information
Account.find_each do |account|
account.update_columns(balance_cents: Money.from_amount(account.balance, account.currency).cents)
end
remove_column :accounts, :balance
end
end

5
db/schema.rb generated
View file

@ -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_02_03_050018) do
ActiveRecord::Schema[7.2].define(version: 2024_02_06_031739) do
# These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto"
enable_extension "plpgsql"
@ -59,12 +59,13 @@ ActiveRecord::Schema[7.2].define(version: 2024_02_03_050018) do
t.string "subtype"
t.uuid "family_id", null: false
t.string "name"
t.bigint "balance", default: 0
t.string "currency", default: "USD"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "accountable_type"
t.uuid "accountable_id"
t.bigint "balance_cents", default: 0, null: false
t.string "balance_currency", default: "USD", null: false
t.index ["accountable_type"], name: "index_accounts_on_accountable_type"
t.index ["family_id"], name: "index_accounts_on_family_id"
end

View file

@ -1,14 +1,14 @@
dylan_checking:
family: dylan_family
name: Bob's Checking
balance: 1200
balance_cents: 1200
dylan_roth:
family: dylan_family
name: Bob's Roth IRA
balance: 1200
balance_cents: 1200
richards_savings:
family: richards_family
name: Keef's HYSA
balance: 1500
balance_cents: 1500

View file

@ -1,11 +1,31 @@
require "test_helper"
class AccountTest < ActiveSupport::TestCase
test "new account should be valid" do
def setup
depository = Account::Depository.create!
account = Account.create!(family: families(:dylan_family), name: "Explicit Checking", balance: 1200, accountable: depository)
assert account.valid?
assert_not_nil account.accountable_id
assert_not_nil account.accountable
@account = Account.create!(family: families(:dylan_family), name: "Explicit Checking", balance_cents: 1200, accountable: depository)
end
test "new account should be valid" do
assert @account.valid?
assert_not_nil @account.accountable_id
assert_not_nil @account.accountable
end
test "balance returns Money object" do
@account.balance = 10
assert_instance_of Money, @account.balance
assert_equal :usd, @account.balance.currency.id
end
test "correctly assigns Money objects to the attribute" do
@account.balance = Money.new(2500, "USD")
assert_equal 2500, @account.balance_cents
end
test "balance_cents can be updated" do
new_balance = Money.new(10000, "USD")
@account.balance = new_balance
assert_equal new_balance, @account.balance
end
end