1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-25 08:09:38 +02:00

Create tagging system (#792)

* Repro

* Fix

* Update signage

* Create tagging system

* Add tags to transaction imports

* Build tagging UI

* Cleanup

* More cleanup
This commit is contained in:
Zach Gollwitzer 2024-05-23 08:09:33 -04:00 committed by GitHub
parent 41c991384a
commit 457247da8e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 607 additions and 90 deletions

View file

@ -6,7 +6,10 @@ class ImportsControllerTest < ActionDispatch::IntegrationTest
setup do
sign_in @user = users(:family_admin)
@empty_import = imports(:empty_import)
@loaded_import = imports(:loaded_import)
@loaded_import = @empty_import.dup
@loaded_import.update! raw_csv_str: valid_csv_str
@completed_import = imports(:completed_import)
end

View file

@ -0,0 +1,36 @@
require "test_helper"
class Tags::DeletionsControllerTest < ActionDispatch::IntegrationTest
setup do
sign_in @user = users(:family_admin)
@user_tags = @user.family.tags
@tag = tags(:hawaii_trip)
end
test "should get new" do
get new_tag_deletion_url(@tag)
assert_response :success
end
test "create with replacement" do
replacement_tag = tags(:trips)
affected_transaction_count = @tag.transactions.count
assert affected_transaction_count > 0
assert_difference -> { Tag.count } => -1, -> { replacement_tag.transactions.count } => affected_transaction_count do
post tag_deletions_url(@tag), params: { replacement_tag_id: replacement_tag.id }
end
end
test "create without replacement" do
affected_transactions = @tag.transactions
assert affected_transactions.count > 0
assert_difference -> { Tag.count } => -1, -> { Tagging.count } => affected_transactions.count * -1 do
post tag_deletions_url(@tag)
end
end
end

View file

@ -0,0 +1,42 @@
require "test_helper"
class TagsControllerTest < ActionDispatch::IntegrationTest
setup do
sign_in @user = users(:family_admin)
end
test "should get index" do
get tags_url
assert_response :success
@user.family.tags.each do |tag|
assert_select "#" + dom_id(tag), count: 1
end
end
test "should get new" do
get new_tag_url
assert_response :success
end
test "should create tag" do
assert_difference("Tag.count") do
post tags_url, params: { tag: { name: "Test Tag" } }
end
assert_redirected_to tags_url
assert_equal "Tag created", flash[:notice]
end
test "should get edit" do
get edit_tag_url(tags.first)
assert_response :success
end
test "should update tag" do
patch tag_url(tags.first), params: { tag: { name: "Test Tag" } }
assert_redirected_to tags_url
assert_equal "Tag updated", flash[:notice]
end
end

View file

@ -2,22 +2,6 @@ empty_import:
account: checking
created_at: <%= 1.minute.ago %>
loaded_import:
account: checking
raw_csv_str: |
date,name,category,amount
2024-01-01,Starbucks drink,Food & Drink,-8.55
2024-01-01,Etsy,Shopping,-80.98
2024-01-02,Amazon stuff,Shopping,-200
2024-01-03,Paycheck,Income,1000
normalized_csv_str: |
date,name,category,amount
2024-01-01,Starbucks drink,Food & Drink,-8.55
2024-01-01,Etsy,Shopping,-80.98
2024-01-02,Amazon stuff,Shopping,-200
2024-01-03,Paycheck,Income,1000
created_at: <%= 2.days.ago %>
completed_import:
account: checking
column_mappings:
@ -26,11 +10,11 @@ completed_import:
category: category
amount: amount
raw_csv_str: |
date,name,category,amount
2024-01-01,Starbucks drink,Food & Drink,-20
date,name,category,tags,amount
2024-01-01,Starbucks drink,Food & Drink,Test Tag,-20
normalized_csv_str: |
date,name,category,amount
2024-01-01,Starbucks drink,Food & Drink,-20
date,name,category,tags,amount
2024-01-01,Starbucks drink,Food & Drink,Test Tag,-20
created_at: <%= 2.days.ago %>

10
test/fixtures/taggings.yml vendored Normal file
View file

@ -0,0 +1,10 @@
one:
tag: hawaii_trip
taggable: checking_one
taggable_type: Transaction
two:
tag: emergency_fund
taggable: checking_two
taggable_type: Transaction

11
test/fixtures/tags.yml vendored Normal file
View file

@ -0,0 +1,11 @@
trips:
name: Trips
family: dylan_family
hawaii_trip:
name: Hawaii Trip
family: dylan_family
emergency_fund:
name: Emergency Fund
family: dylan_family

View file

@ -5,7 +5,9 @@ class ImportTest < ActiveSupport::TestCase
setup do
@empty_import = imports(:empty_import)
@loaded_import = imports(:loaded_import)
@loaded_import = @empty_import.dup
@loaded_import.update! raw_csv_str: valid_csv_str
end
test "raw csv input must conform to csv spec" do
@ -42,7 +44,11 @@ class ImportTest < ActiveSupport::TestCase
# Import has 3 unique categories: "Food & Drink", "Income", and "Shopping" (x2)
# Fixtures already define "Food & Drink" and "Income", so these should not be created
# "Shopping" is a new category, but should only be created 1x during import
assert_difference -> { Transaction.count } => 4, -> { Transaction::Category.count } => 1 do
assert_difference \
-> { Transaction.count } => 4,
-> { Transaction::Category.count } => 1,
-> { Tagging.count } => 4,
-> { Tag.count } => 2 do
@loaded_import.publish
end

18
test/models/tag_test.rb Normal file
View file

@ -0,0 +1,18 @@
require "test_helper"
class TagTest < ActiveSupport::TestCase
test "replace and destroy" do
old_tag = tags(:hawaii_trip)
new_tag = tags(:trips)
assert_difference "Tag.count", -1 do
old_tag.replace_and_destroy!(new_tag)
end
old_tag.transactions.each do |txn|
txn.reload
assert_includes txn.tags, new_tag
assert_not_includes txn.tags, old_tag
end
end
end

View file

@ -1,17 +1,18 @@
module ImportTestHelper
def valid_csv_str
<<-ROWS
date,name,category,amount
2024-01-01,Starbucks drink,Food,-20
2024-01-02,Amazon stuff,Shopping,-200
2024-01-03,Paycheck,Income,1000
date,name,category,tags,amount
2024-01-01,Starbucks drink,Food & Drink,Tag1|Tag2,-8.55
2024-01-01,Etsy,Shopping,Tag1,-80.98
2024-01-02,Amazon stuff,Shopping,Tag2,-200
2024-01-03,Paycheck,Income,,1000
ROWS
end
def valid_csv_with_invalid_values
<<-ROWS
date,name,category,amount
invalid_date,Starbucks drink,Food,invalid_amount
date,name,category,tags,amount
invalid_date,Starbucks drink,Food,,invalid_amount
ROWS
end

View file

@ -11,6 +11,7 @@ class SettingsTest < ApplicationSystemTestCase
[ "Security", "Security", settings_security_path ],
[ "Billing", "Billing", settings_billing_path ],
[ "Accounts", "Accounts", accounts_path ],
[ "Tags", "Tags", tags_path ],
[ "Categories", "Categories", transaction_categories_path ],
[ "Merchants", "Merchants", transaction_merchants_path ],
[ "Rules", "Rules", transaction_rules_path ],