mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 02:51:46 +00:00
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>
102 lines
2.5 KiB
TypeScript
102 lines
2.5 KiB
TypeScript
import { and, desc, eq, type SQL, sql } from "drizzle-orm";
|
|
import {
|
|
cards,
|
|
categories,
|
|
financialAccounts,
|
|
payerShares,
|
|
payers,
|
|
transactionAttachments,
|
|
transactions,
|
|
user as usersTable,
|
|
} from "@/db/schema";
|
|
import { db } from "@/shared/lib/db";
|
|
|
|
export type ShareData = {
|
|
id: string;
|
|
userId: string;
|
|
name: string;
|
|
email: string;
|
|
createdAt: string;
|
|
};
|
|
|
|
export async function fetchPayerShares(payerId: string): Promise<ShareData[]> {
|
|
const shareRows = await db
|
|
.select({
|
|
id: payerShares.id,
|
|
sharedWithUserId: payerShares.sharedWithUserId,
|
|
createdAt: payerShares.createdAt,
|
|
userName: usersTable.name,
|
|
userEmail: usersTable.email,
|
|
})
|
|
.from(payerShares)
|
|
.innerJoin(usersTable, eq(payerShares.sharedWithUserId, usersTable.id))
|
|
.where(eq(payerShares.payerId, payerId));
|
|
|
|
return shareRows.map((share) => ({
|
|
id: share.id,
|
|
userId: share.sharedWithUserId,
|
|
name: share.userName ?? "Usuário",
|
|
email: share.userEmail ?? "email não informado",
|
|
createdAt: share.createdAt?.toISOString() ?? new Date().toISOString(),
|
|
}));
|
|
}
|
|
|
|
export async function fetchCurrentUserShare(
|
|
payerId: string,
|
|
userId: string,
|
|
): Promise<{ id: string; createdAt: string } | null> {
|
|
const shareRow = await db.query.payerShares.findFirst({
|
|
columns: {
|
|
id: true,
|
|
createdAt: true,
|
|
},
|
|
where: and(
|
|
eq(payerShares.payerId, payerId),
|
|
eq(payerShares.sharedWithUserId, userId),
|
|
),
|
|
});
|
|
|
|
if (!shareRow) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
id: shareRow.id,
|
|
createdAt: shareRow.createdAt?.toISOString() ?? new Date().toISOString(),
|
|
};
|
|
}
|
|
|
|
export async function fetchPagadorLancamentos(filters: SQL[]) {
|
|
const transactionRows = await db
|
|
.select({
|
|
transaction: transactions,
|
|
payer: payers,
|
|
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))
|
|
.leftJoin(
|
|
financialAccounts,
|
|
eq(transactions.accountId, financialAccounts.id),
|
|
)
|
|
.leftJoin(cards, eq(transactions.cardId, cards.id))
|
|
.leftJoin(categories, eq(transactions.categoryId, categories.id))
|
|
.where(and(...filters))
|
|
.orderBy(desc(transactions.purchaseDate), desc(transactions.createdAt));
|
|
|
|
return transactionRows.map((row) => ({
|
|
...row.transaction,
|
|
payer: row.payer,
|
|
financialAccount: row.financialAccount,
|
|
card: row.card,
|
|
category: row.category,
|
|
hasAttachments: row.hasAttachments,
|
|
}));
|
|
}
|