feat: add total balance calculation and display in account management; update account card to show calculated balance
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 1m26s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 1m26s
This commit is contained in:
168
scripts/merge-duplicate-accounts.ts
Normal file
168
scripts/merge-duplicate-accounts.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
import { prisma } from "../lib/prisma";
|
||||
|
||||
async function main() {
|
||||
const accountNumber = process.argv[2];
|
||||
|
||||
if (!accountNumber) {
|
||||
console.error("Usage: tsx scripts/merge-duplicate-accounts.ts <accountNumber>");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Fusion des comptes dupliqués pour: ${accountNumber}\n`);
|
||||
|
||||
// Trouver tous les comptes avec ce numéro
|
||||
const accounts = await prisma.account.findMany({
|
||||
where: {
|
||||
accountNumber: accountNumber,
|
||||
},
|
||||
include: {
|
||||
transactions: {
|
||||
select: {
|
||||
id: true,
|
||||
date: true,
|
||||
amount: true,
|
||||
},
|
||||
orderBy: {
|
||||
date: "desc",
|
||||
},
|
||||
},
|
||||
folder: true,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "desc", // Le plus récent en premier
|
||||
},
|
||||
});
|
||||
|
||||
if (accounts.length < 2) {
|
||||
console.log("Aucun doublon trouvé.");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Trouvé ${accounts.length} comptes à fusionner:\n`);
|
||||
accounts.forEach((acc, idx) => {
|
||||
console.log(`Compte ${idx + 1}:`);
|
||||
console.log(` ID: ${acc.id}`);
|
||||
console.log(` Bank ID: ${acc.bankId}`);
|
||||
console.log(` Balance: ${acc.balance}`);
|
||||
console.log(` Transactions: ${acc.transactions.length}`);
|
||||
console.log(` Folder: ${acc.folder?.name || "Aucun"}`);
|
||||
console.log(` Created: ${acc.createdAt}`);
|
||||
console.log("");
|
||||
});
|
||||
|
||||
// Le compte avec bankId numérique (pas "FR") est le bon - le garder comme principal
|
||||
// Si pas de bankId numérique, garder le plus récent
|
||||
const primaryAccount = accounts.find(acc => acc.bankId !== "FR" && acc.bankId !== "") || accounts[0];
|
||||
const accountsToMerge = accounts.filter(acc => acc.id !== primaryAccount.id);
|
||||
|
||||
console.log(`\nCompte principal (conservé): ${primaryAccount.id} (bankId: ${primaryAccount.bankId})`);
|
||||
console.log(`Comptes à fusionner: ${accountsToMerge.map((a) => `${a.id} (bankId: ${a.bankId})`).join(", ")}\n`);
|
||||
|
||||
// Calculer l'initialBalance total (somme des initialBalance)
|
||||
const totalInitialBalance = accounts.reduce(
|
||||
(sum, acc) => sum + acc.initialBalance,
|
||||
0,
|
||||
);
|
||||
|
||||
console.log(`Initial balance totale: ${totalInitialBalance}\n`);
|
||||
|
||||
// Fusionner les transactions
|
||||
let totalTransactionsMoved = 0;
|
||||
for (const accountToMerge of accountsToMerge) {
|
||||
console.log(
|
||||
`Déplacement des transactions du compte ${accountToMerge.id}...`,
|
||||
);
|
||||
|
||||
// Déplacer toutes les transactions vers le compte principal
|
||||
const updateResult = await prisma.transaction.updateMany({
|
||||
where: {
|
||||
accountId: accountToMerge.id,
|
||||
},
|
||||
data: {
|
||||
accountId: primaryAccount.id,
|
||||
},
|
||||
});
|
||||
|
||||
totalTransactionsMoved += updateResult.count;
|
||||
console.log(` → ${updateResult.count} transactions déplacées`);
|
||||
|
||||
// Supprimer le compte fusionné
|
||||
await prisma.account.delete({
|
||||
where: {
|
||||
id: accountToMerge.id,
|
||||
},
|
||||
});
|
||||
|
||||
console.log(` → Compte ${accountToMerge.id} supprimé\n`);
|
||||
}
|
||||
|
||||
// Recalculer le solde à partir de toutes les transactions du compte fusionné
|
||||
const allTransactions = await prisma.transaction.findMany({
|
||||
where: {
|
||||
accountId: primaryAccount.id,
|
||||
},
|
||||
select: {
|
||||
amount: true,
|
||||
},
|
||||
});
|
||||
|
||||
const calculatedBalance = allTransactions.reduce(
|
||||
(sum, t) => sum + t.amount,
|
||||
0,
|
||||
);
|
||||
|
||||
console.log(`Balance calculée à partir des transactions: ${calculatedBalance}`);
|
||||
|
||||
// Mettre à jour la balance du compte principal
|
||||
// Garder le bankId du compte principal (celui qui est correct)
|
||||
await prisma.account.update({
|
||||
where: {
|
||||
id: primaryAccount.id,
|
||||
},
|
||||
data: {
|
||||
balance: calculatedBalance,
|
||||
initialBalance: totalInitialBalance,
|
||||
// Garder le bankId du compte principal (le bon)
|
||||
bankId: primaryAccount.bankId,
|
||||
// Garder le dernier import le plus récent parmi tous les comptes
|
||||
lastImport:
|
||||
accounts.reduce((latest, acc) => {
|
||||
if (!acc.lastImport) return latest;
|
||||
if (!latest) return acc.lastImport;
|
||||
return acc.lastImport > latest ? acc.lastImport : latest;
|
||||
}, null as string | null),
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`\n✅ Fusion terminée:`);
|
||||
console.log(` - Compte principal: ${primaryAccount.id}`);
|
||||
console.log(` - Transactions totales déplacées: ${totalTransactionsMoved}`);
|
||||
console.log(` - Nouvelle balance (calculée): ${calculatedBalance}`);
|
||||
console.log(` - Comptes supprimés: ${accountsToMerge.length}`);
|
||||
|
||||
// Vérification finale
|
||||
const finalAccount = await prisma.account.findUnique({
|
||||
where: { id: primaryAccount.id },
|
||||
include: {
|
||||
transactions: {
|
||||
select: { id: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (finalAccount) {
|
||||
console.log(`\nVérification finale:`);
|
||||
console.log(` - Transactions dans le compte: ${finalAccount.transactions.length}`);
|
||||
console.log(` - Balance: ${finalAccount.balance}`);
|
||||
console.log(` - Bank ID: ${finalAccount.bankId}`);
|
||||
}
|
||||
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error("Erreur:", e);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user