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

Account namespace updates: part 4 (transfers, singular namespacing) (#896)

* Move Transfer to Account namespace

* Fix partial resolution due to namespacing plurality

* Make category and tag controllers consistent with namespacing convention

* Update stale partial reference
This commit is contained in:
Zach Gollwitzer 2024-06-20 13:32:44 -04:00 committed by GitHub
parent dc3147c101
commit bddaab0192
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
50 changed files with 227 additions and 127 deletions

View file

@ -1,4 +1,4 @@
class Accounts::LogosController < ApplicationController class Account::LogosController < ApplicationController
def show def show
@account = Current.family.accounts.find(params[:account_id]) @account = Current.family.accounts.find(params[:account_id])
render_placeholder render_placeholder

View file

@ -1,17 +1,17 @@
class TransfersController < ApplicationController class Account::TransfersController < ApplicationController
layout "with_sidebar" layout "with_sidebar"
before_action :set_transfer, only: :destroy before_action :set_transfer, only: :destroy
def new def new
@transfer = Transfer.new @transfer = Account::Transfer.new
end end
def create def create
from_account = Current.family.accounts.find(transfer_params[:from_account_id]) from_account = Current.family.accounts.find(transfer_params[:from_account_id])
to_account = Current.family.accounts.find(transfer_params[:to_account_id]) to_account = Current.family.accounts.find(transfer_params[:to_account_id])
@transfer = Transfer.build_from_accounts from_account, to_account, \ @transfer = Account::Transfer.build_from_accounts from_account, to_account, \
date: transfer_params[:date], date: transfer_params[:date],
amount: transfer_params[:amount].to_d, amount: transfer_params[:amount].to_d,
currency: transfer_params[:currency], currency: transfer_params[:currency],
@ -20,7 +20,10 @@ class TransfersController < ApplicationController
if @transfer.save if @transfer.save
redirect_to transactions_path, notice: t(".success") redirect_to transactions_path, notice: t(".success")
else else
render :new, status: :unprocessable_entity # TODO: this is not an ideal way to handle errors and should eventually be improved.
# See: https://github.com/hotwired/turbo-rails/pull/367
flash[:error] = @transfer.errors.full_messages.to_sentence
redirect_to transactions_path
end end
end end
@ -32,10 +35,10 @@ class TransfersController < ApplicationController
private private
def set_transfer def set_transfer
@transfer = Transfer.find(params[:id]) @transfer = Account::Transfer.find(params[:id])
end end
def transfer_params def transfer_params
params.require(:transfer).permit(:from_account_id, :to_account_id, :amount, :currency, :date, :name) params.require(:account_transfer).permit(:from_account_id, :to_account_id, :amount, :currency, :date, :name)
end end
end end

View file

@ -1,4 +1,4 @@
class Categories::DeletionsController < ApplicationController class Category::DeletionsController < ApplicationController
layout "with_sidebar" layout "with_sidebar"
before_action :set_category before_action :set_category

View file

@ -1,4 +1,4 @@
class Categories::DropdownsController < ApplicationController class Category::DropdownsController < ApplicationController
before_action :set_from_params before_action :set_from_params
def show def show

View file

@ -1,4 +1,4 @@
class Tags::DeletionsController < ApplicationController class Tag::DeletionsController < ApplicationController
layout "with_sidebar" layout "with_sidebar"
before_action :set_tag before_action :set_tag

View file

@ -1,4 +1,4 @@
class Transactions::RowsController < ApplicationController class Transaction::RowsController < ApplicationController
before_action :set_transaction, only: %i[ show update ] before_action :set_transaction, only: %i[ show update ]
def show def show

View file

@ -0,0 +1,6 @@
class Transaction::RulesController < ApplicationController
layout "with_sidebar"
def index
end
end

View file

@ -1,6 +0,0 @@
class Transactions::RulesController < ApplicationController
layout "with_sidebar"
def index
end
end

View file

@ -1,4 +1,4 @@
class Transfer < ApplicationRecord class Account::Transfer < ApplicationRecord
has_many :transactions, dependent: :nullify has_many :transactions, dependent: :nullify
validate :transaction_count, :from_different_accounts, :net_zero_flows, :all_transactions_marked validate :transaction_count, :from_different_accounts, :net_zero_flows, :all_transactions_marked

View file

@ -4,7 +4,7 @@ class Transaction < ApplicationRecord
monetize :amount monetize :amount
belongs_to :account belongs_to :account
belongs_to :transfer, optional: true belongs_to :transfer, optional: true, class_name: "Account::Transfer"
belongs_to :category, optional: true belongs_to :category, optional: true
belongs_to :merchant, optional: true belongs_to :merchant, optional: true
has_many :taggings, as: :taggable, dependent: :destroy has_many :taggings, as: :taggable, dependent: :destroy
@ -70,7 +70,7 @@ class Transaction < ApplicationRecord
update_all marked_as_transfer: true update_all marked_as_transfer: true
# Attempt to "auto match" and save a transfer if 2 transactions selected # Attempt to "auto match" and save a transfer if 2 transactions selected
Transfer.new(transactions: all).save if all.count == 2 Account::Transfer.new(transactions: all).save if all.count == 2
end end
def daily_totals(transactions, period: Period.last_30_days, currency: Current.family.currency) def daily_totals(transactions, period: Period.last_30_days, currency: Current.family.currency)

View file

Before

Width:  |  Height:  |  Size: 653 B

After

Width:  |  Height:  |  Size: 653 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<%= form_with model: transfer do |f| %> <%= form_with model: transfer, data: { turbo_frame: "_top" } do |f| %>
<section> <section>
<fieldset class="bg-gray-50 rounded-lg p-1 grid grid-flow-col justify-stretch gap-x-2"> <fieldset class="bg-gray-50 rounded-lg p-1 grid grid-flow-col justify-stretch gap-x-2">
<%= link_to new_transaction_path(nature: "expense"), data: { turbo_frame: :modal }, class: "flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-gray-400" do %> <%= link_to new_transaction_path(nature: "expense"), data: { turbo_frame: :modal }, class: "flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-gray-400" do %>

View file

@ -2,7 +2,7 @@
<details class="group flex items-center text-gray-900 p-4 text-sm font-medium"> <details class="group flex items-center text-gray-900 p-4 text-sm font-medium">
<summary class="flex items-center justify-between"> <summary class="flex items-center justify-between">
<div class="flex items-center gap-4"> <div class="flex items-center gap-4">
<%= button_to transfer_path(transfer), <%= button_to account_transfer_path(transfer),
method: :delete, method: :delete,
class: "flex items-center group/transfer", class: "flex items-center group/transfer",
data: { data: {

View file

@ -78,7 +78,7 @@
<%= f.hidden_field :accountable_type %> <%= f.hidden_field :accountable_type %>
<%= f.text_field :name, placeholder: t(".name.placeholder"), required: "required", label: t(".name.label"), autofocus: true %> <%= f.text_field :name, placeholder: t(".name.placeholder"), required: "required", label: t(".name.label"), autofocus: true %>
<%= f.collection_select :institution_id, Current.family.institutions.alphabetically, :id, :name, { include_blank: t(".ungrouped"), label: t(".institution") } %> <%= f.collection_select :institution_id, Current.family.institutions.alphabetically, :id, :name, { include_blank: t(".ungrouped"), label: t(".institution") } %>
<%= render "accounts/account/#{permitted_accountable_partial(@account.accountable_type)}", f: f %> <%= render "accounts/accountables/#{permitted_accountable_partial(@account.accountable_type)}", f: f %>
<%= f.money_field :balance_money, label: t(".balance"), required: "required" %> <%= f.money_field :balance_money, label: t(".balance"), required: "required" %>
<div> <div>

View file

@ -11,7 +11,7 @@
<%= t(".no_categories") %> <%= t(".no_categories") %>
</div> </div>
<% @categories.each do |category| %> <% @categories.each do |category| %>
<%= render partial: "categories/dropdowns/row", locals: { category: } %> <%= render partial: "category/dropdowns/row", locals: { category: } %>
<% end %> <% end %>
</div> </div>
<hr> <hr>

View file

@ -1,5 +1,5 @@
<%# locals: (date:, group:) %> <%# locals: (date:, group:) %>
<div class="bg-gray-25 rounded-xl p-1 w-full" data-bulk-select-target="group"> <div id="date-group-<%= date %>" class="bg-gray-25 rounded-xl p-1 w-full" data-bulk-select-target="group">
<div class="py-2 px-4 flex items-center justify-between font-medium text-xs text-gray-500"> <div class="py-2 px-4 flex items-center justify-between font-medium text-xs text-gray-500">
<div class="flex pl-0.5 items-center gap-4"> <div class="flex pl-0.5 items-center gap-4">
<%= check_box_tag "#{date}_transactions_selection", <%= check_box_tag "#{date}_transactions_selection",

View file

@ -3,7 +3,7 @@
<fieldset class="bg-gray-50 rounded-lg p-1 grid grid-flow-col justify-stretch gap-x-2"> <fieldset class="bg-gray-50 rounded-lg p-1 grid grid-flow-col justify-stretch gap-x-2">
<%= radio_tab_tag form: f, name: :nature, value: :expense, label: t(".expense"), icon: "minus-circle", checked: params[:nature] == "expense" || params[:nature].nil? %> <%= radio_tab_tag form: f, name: :nature, value: :expense, label: t(".expense"), icon: "minus-circle", checked: params[:nature] == "expense" || params[:nature].nil? %>
<%= radio_tab_tag form: f, name: :nature, value: :income, label: t(".income"), icon: "plus-circle", checked: params[:nature] == "income" %> <%= radio_tab_tag form: f, name: :nature, value: :income, label: t(".income"), icon: "plus-circle", checked: params[:nature] == "income" %>
<%= link_to new_transfer_path, data: { turbo_frame: :modal }, class: "flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-gray-400 group-has-[:checked]:bg-white group-has-[:checked]:text-gray-800 group-has-[:checked]:shadow-sm" do %> <%= link_to new_account_transfer_path, data: { turbo_frame: :modal }, class: "flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-gray-400 group-has-[:checked]:bg-white group-has-[:checked]:text-gray-800 group-has-[:checked]:shadow-sm" do %>
<%= lucide_icon "arrow-right-left", class: "w-5 h-5" %> <%= lucide_icon "arrow-right-left", class: "w-5 h-5" %>
<%= tag.span t(".transfer") %> <%= tag.span t(".transfer") %>
<% end %> <% end %>

View file

@ -18,7 +18,7 @@
accept: t(".mark_transfers_confirm"), accept: t(".mark_transfers_confirm"),
} }
} do |f| %> } do |f| %>
<button type="button" data-bulk-select-scope-param="bulk_update" data-action="bulk-select#submitBulkRequest" class="p-1.5 group hover:bg-gray-700 flex items-center justify-center rounded-md" title="Mark as transfer"> <button id="bulk-transfer-btn" type="button" data-bulk-select-scope-param="bulk_update" data-action="bulk-select#submitBulkRequest" class="p-1.5 group hover:bg-gray-700 flex items-center justify-center rounded-md" title="Mark as transfer">
<%= lucide_icon "arrow-right-left", class: "w-5 group-hover:text-white" %> <%= lucide_icon "arrow-right-left", class: "w-5 group-hover:text-white" %>
</button> </button>
<% end %> <% end %>

View file

@ -0,0 +1,28 @@
---
en:
account:
transfers:
create:
success: Transfer created
destroy:
success: Transfer removed
form:
amount: Amount
date: Date
description: Description
description_placeholder: Transfer from Checking to Savings
expense: Expense
from: From
income: Income
select_account: Select account
submit: Create transfer
to: To
transfer: Transfer
new:
title: New transfer
transfer:
remove_body: This will NOT delete the underlying transactions. It will just
remove the transfer.
remove_confirm: Confirm
remove_title: Remove transfer?
transfer_name: Transfer from %{from_account} to %{to_account}

View file

@ -3,27 +3,6 @@ en:
categories: categories:
create: create:
success: New transaction category created successfully success: New transaction category created successfully
deletions:
create:
success: Transaction category deleted successfully
new:
category: Category
delete_and_leave_uncategorized: Delete "%{category_name}" and leave uncategorized
delete_and_recategorize: Delete "%{category_name}" and assign new category
delete_category: Delete category?
explanation: By deleting this category, every transaction that has the "%{category_name}"
category will be uncategorized. Instead of leaving them uncategorized, you
can also assign a new category below.
replacement_category_prompt: Select category
dropdowns:
row:
delete: Delete category
edit: Edit category
show:
add_new: Add new
clear: Clear
no_categories: No categories found
search_placeholder: Search
edit: edit:
edit: Edit category edit: Edit category
form: form:

View file

@ -0,0 +1,15 @@
---
en:
category:
deletions:
create:
success: Transaction category deleted successfully
new:
category: Category
delete_and_leave_uncategorized: Delete "%{category_name}" and leave uncategorized
delete_and_recategorize: Delete "%{category_name}" and assign new category
delete_category: Delete category?
explanation: By deleting this category, every transaction that has the "%{category_name}"
category will be uncategorized. Instead of leaving them uncategorized, you
can also assign a new category below.
replacement_category_prompt: Select category

View file

@ -0,0 +1,12 @@
---
en:
category:
dropdowns:
row:
delete: Delete category
edit: Edit category
show:
add_new: Add new
clear: Clear
no_categories: No categories found
search_placeholder: Search

View file

@ -0,0 +1,15 @@
---
en:
tag:
deletions:
create:
deleted: Tag deleted
new:
delete_and_leave_uncategorized: Delete "%{tag_name}"
delete_and_recategorize: Delete "%{tag_name}" and assign new tag
delete_tag: Delete tag?
explanation: "%{tag_name} will be removed from transactions and other taggable
entities. Instead of leaving them untagged, you can also assign a new tag
below."
replacement_tag_prompt: Select tag
tag: Tag

View file

@ -3,18 +3,6 @@ en:
tags: tags:
create: create:
created: Tag created created: Tag created
deletions:
create:
deleted: Tag deleted
new:
delete_and_leave_uncategorized: Delete "%{tag_name}"
delete_and_recategorize: Delete "%{tag_name}" and assign new tag
delete_tag: Delete tag?
explanation: "%{tag_name} will be removed from transactions and other taggable
entities. Instead of leaving them untagged, you can also assign a new tag
below."
replacement_tag_prompt: Select tag
tag: Tag
edit: edit:
edit: Edit tag edit: Edit tag
form: form:

View file

@ -1,27 +0,0 @@
---
en:
transfers:
create:
success: Transfer created
destroy:
success: Transfer removed
form:
amount: Amount
date: Date
description: Description
description_placeholder: Transfer from Checking to Savings
expense: Expense
from: From
income: Income
select_account: Select account
submit: Create transfer
to: To
transfer: Transfer
new:
title: New transfer
transfer:
remove_body: This will NOT delete the underlying transactions. It will just
remove the transfer.
remove_confirm: Confirm
remove_title: Remove transfer?
transfer_name: Transfer from %{from_account} to %{to_account}

View file

@ -38,18 +38,24 @@ Rails.application.routes.draw do
end end
resources :tags, except: %i[ show destroy ] do resources :tags, except: %i[ show destroy ] do
resources :deletions, only: %i[ new create ], module: :tags resources :deletions, only: %i[ new create ], module: :tag
end
namespace :category do
resource :dropdown, only: :show
end end
resources :categories do resources :categories do
resources :deletions, only: %i[ new create ], module: :categories resources :deletions, only: %i[ new create ], module: :category
collection do
resource :dropdown, only: :show, module: :categories, as: :category_dropdown
end
end end
resources :merchants, only: %i[ index new create edit update destroy ] resources :merchants, only: %i[ index new create edit update destroy ]
namespace :transaction do
resources :rows, only: %i[ show update ]
resources :rules, only: %i[ index ]
end
resources :transactions do resources :transactions do
collection do collection do
post "bulk_delete" post "bulk_delete"
@ -57,17 +63,14 @@ Rails.application.routes.draw do
post "bulk_update" post "bulk_update"
post "mark_transfers" post "mark_transfers"
post "unmark_transfers" post "unmark_transfers"
scope module: :transactions, as: :transaction do
resources :rows, only: %i[ show update ]
resources :rules, only: %i[ index ]
end
end end
end end
namespace :account do
resources :transfers, only: %i[ new create destroy ] resources :transfers, only: %i[ new create destroy ]
end
resources :accounts, shallow: true do resources :accounts do
collection do collection do
get :summary get :summary
get :list get :list
@ -77,11 +80,8 @@ Rails.application.routes.draw do
post :sync post :sync
end end
scope module: :accounts do resource :logo, only: :show, module: :account
resource :logo, only: :show resources :valuations, shallow: true
end
resources :valuations
end end
resources :institutions, except: %i[ index show ] resources :institutions, except: %i[ index show ]

View file

@ -0,0 +1,5 @@
class RenameTransferTable < ActiveRecord::Migration[7.2]
def change
rename_table :transfers, :account_transfers
end
end

14
db/schema.rb generated
View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.2].define(version: 2024_06_20_122201) do ActiveRecord::Schema[7.2].define(version: 2024_06_20_125026) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto" enable_extension "pgcrypto"
enable_extension "plpgsql" enable_extension "plpgsql"
@ -32,6 +32,11 @@ ActiveRecord::Schema[7.2].define(version: 2024_06_20_122201) do
t.index ["account_id"], name: "index_account_balances_on_account_id" t.index ["account_id"], name: "index_account_balances_on_account_id"
end end
create_table "account_transfers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "accounts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table "accounts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.string "subtype" t.string "subtype"
t.uuid "family_id", null: false t.uuid "family_id", null: false
@ -313,11 +318,6 @@ ActiveRecord::Schema[7.2].define(version: 2024_06_20_122201) do
t.index ["transfer_id"], name: "index_transactions_on_transfer_id" t.index ["transfer_id"], name: "index_transactions_on_transfer_id"
end end
create_table "transfers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table "users", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "family_id", null: false t.uuid "family_id", null: false
t.string "first_name" t.string "first_name"
@ -362,10 +362,10 @@ ActiveRecord::Schema[7.2].define(version: 2024_06_20_122201) do
add_foreign_key "merchants", "families" add_foreign_key "merchants", "families"
add_foreign_key "taggings", "tags" add_foreign_key "taggings", "tags"
add_foreign_key "tags", "families" add_foreign_key "tags", "families"
add_foreign_key "transactions", "account_transfers", column: "transfer_id"
add_foreign_key "transactions", "accounts", on_delete: :cascade add_foreign_key "transactions", "accounts", on_delete: :cascade
add_foreign_key "transactions", "categories", on_delete: :nullify add_foreign_key "transactions", "categories", on_delete: :nullify
add_foreign_key "transactions", "merchants" add_foreign_key "transactions", "merchants"
add_foreign_key "transactions", "transfers"
add_foreign_key "users", "families" add_foreign_key "users", "families"
add_foreign_key "valuations", "accounts", on_delete: :cascade add_foreign_key "valuations", "accounts", on_delete: :cascade
end end

View file

@ -1,19 +1,19 @@
require "test_helper" require "test_helper"
class TransfersControllerTest < ActionDispatch::IntegrationTest class Account::TransfersControllerTest < ActionDispatch::IntegrationTest
setup do setup do
sign_in users(:family_admin) sign_in users(:family_admin)
end end
test "should get new" do test "should get new" do
get new_transfer_url get new_account_transfer_url
assert_response :success assert_response :success
end end
test "can create transfers" do test "can create transfers" do
assert_difference "Transfer.count", 1 do assert_difference "Account::Transfer.count", 1 do
post transfers_url, params: { post account_transfers_url, params: {
transfer: { account_transfer: {
from_account_id: accounts(:checking).id, from_account_id: accounts(:checking).id,
to_account_id: accounts(:savings).id, to_account_id: accounts(:savings).id,
date: Date.current, date: Date.current,
@ -26,8 +26,8 @@ class TransfersControllerTest < ActionDispatch::IntegrationTest
end end
test "can destroy transfer" do test "can destroy transfer" do
assert_difference -> { Transfer.count } => -1, -> { Transaction.count } => 0 do assert_difference -> { Account::Transfer.count } => -1, -> { Transaction.count } => 0 do
delete transfer_url(transfers(:credit_card_payment)) delete account_transfer_url(account_transfers(:credit_card_payment))
end end
end end
end end

View file

@ -1,6 +1,6 @@
require "test_helper" require "test_helper"
class Categories::DeletionsControllerTest < ActionDispatch::IntegrationTest class Category::DeletionsControllerTest < ActionDispatch::IntegrationTest
setup do setup do
sign_in users(:family_admin) sign_in users(:family_admin)
@category = categories(:food_and_drink) @category = categories(:food_and_drink)

View file

@ -1,6 +1,6 @@
require "test_helper" require "test_helper"
class Tags::DeletionsControllerTest < ActionDispatch::IntegrationTest class Tag::DeletionsControllerTest < ActionDispatch::IntegrationTest
setup do setup do
sign_in @user = users(:family_admin) sign_in @user = users(:family_admin)
@user_tags = @user.family.tags @user_tags = @user.family.tags

View file

@ -22,7 +22,7 @@ checking:
savings: savings:
family: dylan_family family: dylan_family
name: Savings account with valuation overrides name: Savings account
balance: 19700 balance: 19700
accountable_type: Depository accountable_type: Depository
accountable: depository_savings accountable: depository_savings

View file

@ -8,14 +8,14 @@ class TransferTest < ActiveSupport::TestCase
end end
test "transfer valid if it has inflow and outflow from different accounts for the same amount" do test "transfer valid if it has inflow and outflow from different accounts for the same amount" do
transfer = Transfer.create! transactions: [ @inflow, @outflow ] transfer = Account::Transfer.create! transactions: [ @inflow, @outflow ]
assert transfer.valid? assert transfer.valid?
end end
test "transfer must have 2 transactions" do test "transfer must have 2 transactions" do
invalid_transfer_1 = Transfer.new transactions: [ @outflow ] invalid_transfer_1 = Account::Transfer.new transactions: [ @outflow ]
invalid_transfer_2 = Transfer.new transactions: [ @inflow, @outflow, transactions(:savings_four) ] invalid_transfer_2 = Account::Transfer.new transactions: [ @inflow, @outflow, transactions(:savings_four) ]
assert invalid_transfer_1.invalid? assert invalid_transfer_1.invalid?
assert invalid_transfer_2.invalid? assert invalid_transfer_2.invalid?
@ -27,7 +27,7 @@ class TransferTest < ActiveSupport::TestCase
outflow = account.transactions.create! date: Date.current, name: "Outflow", amount: 100 outflow = account.transactions.create! date: Date.current, name: "Outflow", amount: 100
assert_raise ActiveRecord::RecordInvalid do assert_raise ActiveRecord::RecordInvalid do
Transfer.create! transactions: [ inflow, outflow ] Account::Transfer.create! transactions: [ inflow, outflow ]
end end
end end
@ -35,7 +35,7 @@ class TransferTest < ActiveSupport::TestCase
@inflow.update! marked_as_transfer: false @inflow.update! marked_as_transfer: false
assert_raise ActiveRecord::RecordInvalid do assert_raise ActiveRecord::RecordInvalid do
Transfer.create! transactions: [ @inflow, @outflow ] Account::Transfer.create! transactions: [ @inflow, @outflow ]
end end
end end
@ -43,7 +43,7 @@ class TransferTest < ActiveSupport::TestCase
@outflow.update! amount: 105 @outflow.update! amount: 105
assert_raises ActiveRecord::RecordInvalid do assert_raises ActiveRecord::RecordInvalid do
Transfer.create! transactions: [ @inflow, @outflow ] Account::Transfer.create! transactions: [ @inflow, @outflow ]
end end
end end
end end

View file

@ -0,0 +1,82 @@
require "application_system_test_case"
class TransfersTest < ApplicationSystemTestCase
setup do
sign_in @user = users(:family_admin)
visit transactions_url
end
test "can create a transfer" do
checking_name = accounts(:checking).name
savings_name = accounts(:savings).name
transfer_date = Date.current
click_on "New transaction"
# Will navigate to different route in same modal
click_on "Transfer"
assert_text "New transfer"
fill_in "Description", with: "Transfer txn name"
select checking_name, from: "From"
select savings_name, from: "To"
fill_in "account_transfer[amount]", with: 500
fill_in "Date", with: transfer_date
click_button "Create transfer"
within "#date-group-" + transfer_date.to_s do
transfer_name = "Transfer from #{checking_name} to #{savings_name}"
find("details", text: transfer_name).click
assert_text "Transfer txn name", count: 2
end
end
test "can match 2 transactions and create a transfer" do
transfer_date = Date.current
outflow = Transaction.create! name: "Outflow from savings account", date: transfer_date, account: accounts(:savings), amount: 100
inflow = Transaction.create! name: "Inflow to checking account", date: transfer_date, account: accounts(:checking), amount: -100
visit transactions_url
transaction_checkbox(inflow).check
transaction_checkbox(outflow).check
bulk_transfer_action_button.click
click_on "Mark as transfers"
within "#date-group-" + transfer_date.to_s do
transfer_name = "Transfer from #{outflow.account.name} to #{inflow.account.name}"
find("details", text: transfer_name).click
assert_text inflow.name
assert_text outflow.name
end
end
test "can mark a single transaction as a transfer" do
txn = @user.family.transactions.ordered.first
within "#" + dom_id(txn) do
assert_text "Uncategorized"
end
transaction_checkbox(txn).check
bulk_transfer_action_button.click
click_on "Mark as transfers"
within "#" + dom_id(txn) do
assert_no_text "Uncategorized"
end
end
private
def transaction_checkbox(transaction)
find("#" + dom_id(transaction, "selection"))
end
def bulk_transfer_action_button
find("#bulk-transfer-btn")
end
end