1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-10 16:05:22 +02:00

Transfer and Payment auto-matching, model and UI improvements (#1585)

* Transfer data model migration

* Transfers and payment modeling and UI improvements

* Fix CI

* Transfer matching flow

* Better UI for transfers

* Auto transfer matching, approve, reject flow

* Mark transfers created from form as confirmed

* Account filtering

* Excluded rejected transfers from calculations

* Calculation tweaks with transfer exclusions

* Clean up migration
This commit is contained in:
Zach Gollwitzer 2025-01-07 09:41:24 -05:00 committed by GitHub
parent 46e129308f
commit 307a3687e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
78 changed files with 1161 additions and 682 deletions

View file

@ -0,0 +1,44 @@
<%# locals: (form:, entry:, candidates:, accounts:) %>
<% if candidates.any? %>
<div data-controller="transfer-match" class="space-y-2">
<p class="text-sm text-gray-500">
Select a method for matching your transactions.
</p>
<%= form.select :method,
[
["Match existing transaction (recommended)", "existing"],
["Create new transaction", "new"]
],
{ selected: "existing", label: "Matching method" },
data: { action: "change->transfer-match#update" } %>
<div data-transfer-match-target="existingSelect">
<%= form.select :matched_entry_id,
candidates.map { |entry|
[entry_name_detailed(entry), entry.id]
},
{ label: "Matching transaction" } %>
</div>
<div data-transfer-match-target="newSelect" class="hidden">
<%= form.select :target_account_id,
accounts.map { |account| [account.name, account.id] },
{ label: "Target account" } %>
</div>
</div>
<% else %>
<p class="text-sm text-gray-500">
We couldn't find any transactions to match from your other accounts.
Please select an account and we will create a new inflow transaction for you.
</p>
<%= form.hidden_field :method, value: "new" %>
<div>
<%= form.select :target_account_id,
accounts.map { |account| [account.name, account.id] },
{ label: "Target account" } %>
</div>
<% end %>

View file

@ -0,0 +1,60 @@
<%= modal_form_wrapper title: "Match transfer or payment" do %>
<%= styled_form_with(
url: account_transaction_transfer_match_path(@entry),
scope: :transfer_match,
class: "space-y-8",
data: { turbo_frame: :_top }
) do |f| %>
<section class="space-y-4">
<div class="space-y-2">
<h2 class="text-sm font-medium text-gray-700">
<%= @entry.amount.positive? ? "From account: #{@entry.account.name}" : "From account" %>
</h2>
<% if @entry.amount.positive? %>
<%= f.select(
:entry_id,
[[entry_name_detailed(@entry), @entry.id]],
{
label: "Outflow transaction",
selected: @entry.id,
},
disabled: true
) %>
<% else %>
<%= render "account/transfer_matches/matching_fields",
form: f, entry: @entry, candidates: @transfer_match_candidates, accounts: @accounts %>
<% end %>
</div>
</section>
<div class="flex justify-center py-2">
<%= lucide_icon "arrow-down", class: "w-5 h-5" %>
</div>
<section class="space-y-4">
<div class="space-y-2">
<h2 class="text-sm font-medium text-gray-700">
<%= @entry.amount.negative? ? "To account: #{@entry.account.name}" : "To account" %>
</h2>
<% if @entry.amount.negative? %>
<%= f.select(
:entry_id,
[[entry_name_detailed(@entry), @entry.id]],
{
label: "Inflow transaction",
selected: @entry.id,
},
disabled: true
) %>
<% else %>
<%= render "account/transfer_matches/matching_fields",
form: f, entry: @entry, candidates: @transfer_match_candidates, accounts: @accounts %>
<% end %>
</div>
</section>
<%= f.submit "Create transfer match", data: { turbo_submits_with: "Saving..."} %>
<% end %>
<% end %>