feat(transactions): edição cooperativa e visibilidade de divisões

Adiciona splitGroupId para vincular as duas shares de um lançamento
dividido (schema + índice + migration 0026). Habilita:

- Edição de par dividido com escolha de escopo (apenas este lado ou
  ambos) via novo SplitPairDialog e updateTransactionSplitPairAction
- Filtro "Somente divididos" (isDivided) na tabela de lançamentos
- Visibilidade de anexos para pessoas com acesso compartilhado via
  payerShares; upload e detach em massa expandem para shares irmãs
- Cópia independente de anexos no fluxo "Importar para Minha Conta"
  (novo fileKey, novo userId, S3 CopyObject) com seção read-only
  "Anexos que serão copiados" no dialog de importação
- Ícone de clipe na tabela de lançamentos da página da pessoa via
  EXISTS em fetchPagadorLancamentos

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-04-25 14:45:35 +00:00
parent 5b03824a72
commit b14f487824
20 changed files with 3595 additions and 86 deletions

View File

@@ -1,10 +1,11 @@
import { and, desc, eq, type SQL } from "drizzle-orm";
import { and, desc, eq, type SQL, sql } from "drizzle-orm";
import {
cards,
categories,
financialAccounts,
payerShares,
payers,
transactionAttachments,
transactions,
user as usersTable,
} from "@/db/schema";
@@ -73,6 +74,10 @@ export async function fetchPagadorLancamentos(filters: SQL[]) {
financialAccount: financialAccounts,
card: cards,
category: categories,
hasAttachments: sql<boolean>`EXISTS (
SELECT 1 FROM ${transactionAttachments}
WHERE ${transactionAttachments.transactionId} = ${transactions.id}
)`,
})
.from(transactions)
.leftJoin(payers, eq(transactions.payerId, payers.id))
@@ -85,12 +90,12 @@ export async function fetchPagadorLancamentos(filters: SQL[]) {
.where(and(...filters))
.orderBy(desc(transactions.purchaseDate), desc(transactions.createdAt));
// Transformar resultado para o formato esperado
return transactionRows.map((row) => ({
...row.transaction,
payer: row.payer,
financialAccount: row.financialAccount,
card: row.card,
category: row.category,
hasAttachments: row.hasAttachments,
}));
}