Files
sure/app/views/transactions/_split_parent_row.html.erb
soky srm 0cda69ebb0 Split UI (#1245)
* Initial split transaction support

* Add support to unsplit and edit split

* Update show.html.erb

* FIX address reviews

* Improve UX

* Update show.html.erb

* Reviews

* Update edit.html.erb

* Add parent category to dialog

* Update en.yml

* Add UI indication to totals

* FIX ui update

* Add category select like rest of app

* Add split ui

* Add settings configuration for split transactions

- Adds a new settings section for appearance changes
- Also adds extra checks for delete and API calls
- Also adds checks for parent/child changes

* fixes

- split transactions dark mode fix
- add split transactions to context menu

* Update entry.rb

1. New validation split_child_date_matches_parent — prevents saving a split child with a date different from its parent. This is the root-cause fix that
   protects all flows at once.
  2. Bulk update guard — bulk_update! now strips :date from attributes when processing split children, preventing the validation from raising and silently
   skipping the date change instead.

* N+1 fix for split_parent?

* Update entry.rb

  Problem: In bulk_update!, when a split child has :date removed from attrs (line 432) and the remaining attrs is empty (e.g., the bulk update only
  changed the date), entry.update! {} still ran as a no-op. But lock_saved_attributes! and mark_user_modified! at lines 443-444 executed unconditionally,
  incorrectly marking untouched split children as user-modified and opting them out of future syncs.

  Fix:
  1. Added a changed flag to track whether any actual modification happened
  2. Wrapped entry.update! in an if attrs.present? check so no-op updates are skipped
  3. Gated lock_saved_attributes! and mark_user_modified! behind if changed, so they only run when the entry was actually modified (either via attribute
  update or tag update)

* fixes

1. Indentation in show.html.erb Settings section — The split button block and delete block had extra indentation making them appear nested inside guard
  blocks they weren't part of. Fixed to match actual nesting.
  2. Skip @split_parents query when grouping is off — The controller now only loads split parent entries when show_split_grouped? is true, saving a query
  with joins when the feature is disabled.
2026-03-22 12:02:58 +01:00

70 lines
2.7 KiB
Plaintext

<%# locals: (entry:) %>
<% transaction = entry.entryable %>
<div class="group flex lg:grid lg:grid-cols-12 items-center text-sm font-medium p-3 lg:p-4 opacity-50 text-secondary">
<div class="pr-4 lg:pr-10 flex items-center gap-3 lg:gap-4 col-span-8 min-w-0">
<%# Empty space where checkbox would be, for alignment %>
<div class="hidden lg:block w-4 shrink-0"></div>
<div class="max-w-full">
<div class="flex items-center gap-3 lg:gap-4">
<div class="hidden lg:flex">
<% if transaction.merchant&.logo_url.present? %>
<%= image_tag Setting.transform_brand_fetch_url(transaction.merchant.logo_url),
class: "w-9 h-9 rounded-full border border-secondary",
loading: "lazy" %>
<% else %>
<div class="hidden lg:flex">
<%= render DS::FilledIcon.new(
variant: :text,
text: entry.name,
size: "lg",
rounded: true
) %>
</div>
<% end %>
</div>
<div class="truncate">
<div class="space-y-0.5">
<div class="flex items-center gap-1 min-w-0">
<div class="truncate flex-shrink">
<%= link_to entry.name,
entry_path(entry),
data: { turbo_frame: "drawer", turbo_prefetch: false },
class: "hover:underline" %>
</div>
<div class="flex items-center gap-1 flex-shrink-0">
<span class="inline-flex items-center gap-1 text-xs font-medium rounded-full px-1.5 py-0.5 border border-accent bg-accent/10 text-accent">
<%= icon "split", size: "sm", color: "current" %>
<%= t("transactions.split_parent_row.split_label") %>
</span>
</div>
</div>
<div class="text-secondary text-xs font-normal">
<% if transaction.merchant&.present? %>
<span class="hidden lg:inline truncate"><%= transaction.merchant.name %> • </span>
<% end %>
<span class="text-secondary hidden lg:inline">
<%= link_to entry.account.name,
account_path(entry.account, tab: "transactions"),
data: { turbo_frame: "_top" },
class: "hover:underline" %>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="hidden md:flex items-center gap-1 col-span-2">
</div>
<div class="shrink-0 col-span-4 lg:col-span-2 ml-auto flex items-center justify-end gap-2">
<%= content_tag :p, format_money(-entry.amount_money) %>
</div>
</div>