refactor: remove category rules and related logic from defaults, types, and services for cleaner codebase
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import type { CategoryRule } from "./types"
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// STRUCTURE HIÉRARCHIQUE DES CATÉGORIES
|
||||
@@ -986,58 +985,6 @@ export const defaultCategories: CategoryDefinition[] = [
|
||||
},
|
||||
]
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// RÈGLES DE CATÉGORISATION AVANCÉES
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
export interface CategoryRuleDefinition extends Omit<CategoryRule, "id" | "categoryId"> {
|
||||
categorySlug: string // Référence au slug de la catégorie
|
||||
}
|
||||
|
||||
export const defaultCategoryRules: CategoryRuleDefinition[] = [
|
||||
// Salaire - patterns typiques de virements salaire
|
||||
{ categorySlug: "revenus-salaire", pattern: "^VIR(EMENT)? (RECU )?.*SALAIRE", isRegex: true },
|
||||
{ categorySlug: "revenus-salaire", pattern: "^VIR(EMENT)? (RECU )?.*PAIE", isRegex: true },
|
||||
|
||||
// Loyer - patterns de prélèvement loyer
|
||||
{ categorySlug: "logement-loyer", pattern: "^PRLV.*LOYER", isRegex: true },
|
||||
{ categorySlug: "logement-loyer", pattern: "^PRLV.*FONCIA", isRegex: true },
|
||||
{ categorySlug: "logement-loyer", pattern: "^PRLV.*NEXITY", isRegex: true },
|
||||
|
||||
// EDF/Engie
|
||||
{ categorySlug: "logement-electricite", pattern: "^PRLV.*EDF", isRegex: true },
|
||||
{ categorySlug: "logement-electricite", pattern: "^PRLV.*ENGIE", isRegex: true },
|
||||
{ categorySlug: "logement-electricite", pattern: "^PRLV.*TOTAL.?ENERGIE", isRegex: true },
|
||||
|
||||
// Télécom
|
||||
{ categorySlug: "abonnements-telecom", pattern: "^PRLV.*FREE( MOBILE)?", isRegex: true },
|
||||
{ categorySlug: "abonnements-telecom", pattern: "^PRLV.*ORANGE", isRegex: true },
|
||||
{ categorySlug: "abonnements-telecom", pattern: "^PRLV.*SFR", isRegex: true },
|
||||
{ categorySlug: "abonnements-telecom", pattern: "^PRLV.*BOUYGUES", isRegex: true },
|
||||
|
||||
// Assurances
|
||||
{ categorySlug: "finance-assurance", pattern: "^PRLV.*AXA", isRegex: true },
|
||||
{ categorySlug: "finance-assurance", pattern: "^PRLV.*MAIF", isRegex: true },
|
||||
{ categorySlug: "finance-assurance", pattern: "^PRLV.*MACIF", isRegex: true },
|
||||
{ categorySlug: "finance-assurance", pattern: "^PRLV.*MATMUT", isRegex: true },
|
||||
|
||||
// Impôts
|
||||
{ categorySlug: "finance-impots", pattern: "^PRLV.*DGFIP", isRegex: true },
|
||||
{ categorySlug: "finance-impots", pattern: "^PRLV.*TRESOR PUBLIC", isRegex: true },
|
||||
{ categorySlug: "finance-impots", pattern: "IMPOT", isRegex: false },
|
||||
|
||||
// Remboursements
|
||||
{ categorySlug: "revenus-remboursements", pattern: "^VIR(EMENT)? (RECU )?.*CPAM", isRegex: true },
|
||||
{ categorySlug: "revenus-remboursements", pattern: "^VIR(EMENT)? (RECU )?.*AMELI", isRegex: true },
|
||||
{ categorySlug: "revenus-remboursements", pattern: "REMBOURSEMENT", isRegex: false },
|
||||
|
||||
// CAF
|
||||
{ categorySlug: "revenus-allocations", pattern: "^VIR(EMENT)? (RECU )?.*CAF", isRegex: true },
|
||||
{ categorySlug: "revenus-allocations", pattern: "ALLOCATION", isRegex: false },
|
||||
|
||||
// Retraits
|
||||
{ categorySlug: "divers-retraits", pattern: "^RETRAIT DAB", isRegex: true },
|
||||
{ categorySlug: "divers-retraits", pattern: "^RET DAB", isRegex: true },
|
||||
]
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// DOSSIER RACINE
|
||||
|
||||
@@ -48,7 +48,6 @@ const defaultData: BankingData = {
|
||||
transactions: [],
|
||||
folders: [defaultRootFolder],
|
||||
categories: buildCategoriesFromDefaults(),
|
||||
categoryRules: [],
|
||||
}
|
||||
|
||||
export function loadData(): BankingData {
|
||||
|
||||
@@ -43,19 +43,11 @@ export interface Category {
|
||||
parentId: string | null
|
||||
}
|
||||
|
||||
export interface CategoryRule {
|
||||
id: string
|
||||
categoryId: string
|
||||
pattern: string
|
||||
isRegex: boolean
|
||||
}
|
||||
|
||||
export interface BankingData {
|
||||
accounts: Account[]
|
||||
transactions: Transaction[]
|
||||
folders: Folder[]
|
||||
categories: Category[]
|
||||
categoryRules: CategoryRule[]
|
||||
}
|
||||
|
||||
// OFX Parsed types
|
||||
|
||||
@@ -82,20 +82,6 @@ model Category {
|
||||
parent Category? @relation("CategoryHierarchy", fields: [parentId], references: [id], onDelete: Cascade)
|
||||
children Category[] @relation("CategoryHierarchy")
|
||||
transactions Transaction[]
|
||||
rules CategoryRule[]
|
||||
|
||||
@@index([parentId])
|
||||
}
|
||||
|
||||
model CategoryRule {
|
||||
id String @id @default(cuid())
|
||||
categoryId String
|
||||
pattern String
|
||||
isRegex Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([categoryId])
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
import { defaultCategories, defaultCategoryRules, type CategoryDefinition } from "../lib/defaults"
|
||||
import { defaultCategories, type CategoryDefinition } from "../lib/defaults"
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
@@ -113,51 +113,6 @@ async function main() {
|
||||
else unchanged++
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// PHASE 3: Sync des règles (optionnel)
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
if (defaultCategoryRules.length > 0) {
|
||||
console.log("\n" + "═".repeat(50))
|
||||
console.log("PHASE 3: Règles de catégorisation")
|
||||
console.log("═".repeat(50))
|
||||
|
||||
let rulesCreated = 0
|
||||
let rulesSkipped = 0
|
||||
|
||||
for (const rule of defaultCategoryRules) {
|
||||
const categoryId = slugToId.get(rule.categorySlug)
|
||||
if (!categoryId) {
|
||||
console.log(`⚠️ Catégorie introuvable pour règle: ${rule.categorySlug}`)
|
||||
rulesSkipped++
|
||||
continue
|
||||
}
|
||||
|
||||
// Vérifier si la règle existe déjà
|
||||
const existing = await prisma.categoryRule.findFirst({
|
||||
where: {
|
||||
categoryId,
|
||||
pattern: rule.pattern,
|
||||
},
|
||||
})
|
||||
|
||||
if (!existing) {
|
||||
await prisma.categoryRule.create({
|
||||
data: {
|
||||
categoryId,
|
||||
pattern: rule.pattern,
|
||||
isRegex: rule.isRegex,
|
||||
},
|
||||
})
|
||||
console.log(`✅ Règle créée: ${rule.pattern.substring(0, 40)}...`)
|
||||
rulesCreated++
|
||||
} else {
|
||||
rulesSkipped++
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n📊 Règles: ${rulesCreated} créées, ${rulesSkipped} existantes`)
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// RÉSUMÉ
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
@@ -172,12 +127,10 @@ async function main() {
|
||||
const totalCategories = await prisma.category.count()
|
||||
const parentCount = await prisma.category.count({ where: { parentId: null } })
|
||||
const childCount = await prisma.category.count({ where: { NOT: { parentId: null } } })
|
||||
const totalRules = await prisma.categoryRule.count()
|
||||
const totalKeywords = defaultCategories.reduce((sum, c) => sum + c.keywords.length, 0)
|
||||
|
||||
console.log("\n📈 Base de données:")
|
||||
console.log(` Total catégories: ${totalCategories} (${parentCount} parents, ${childCount} enfants)`)
|
||||
console.log(` Total règles: ${totalRules}`)
|
||||
console.log(` Total keywords: ${totalKeywords}`)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import type { BankingData, Account, Transaction, Folder, Category, CategoryRule } from "@/lib/types"
|
||||
import type { BankingData, Account, Transaction, Folder, Category } from "@/lib/types"
|
||||
|
||||
export const bankingService = {
|
||||
async getAllData(): Promise<BankingData> {
|
||||
const [accounts, transactions, folders, categories, categoryRules] = await Promise.all([
|
||||
const [accounts, transactions, folders, categories] = await Promise.all([
|
||||
prisma.account.findMany({
|
||||
include: {
|
||||
folder: true,
|
||||
@@ -17,7 +17,6 @@ export const bankingService = {
|
||||
}),
|
||||
prisma.folder.findMany(),
|
||||
prisma.category.findMany(),
|
||||
prisma.categoryRule.findMany(),
|
||||
])
|
||||
|
||||
// Transform Prisma models to match our types
|
||||
@@ -61,12 +60,6 @@ export const bankingService = {
|
||||
keywords: JSON.parse(c.keywords) as string[],
|
||||
parentId: c.parentId,
|
||||
})),
|
||||
categoryRules: categoryRules.map((r): CategoryRule => ({
|
||||
id: r.id,
|
||||
categoryId: r.categoryId,
|
||||
pattern: r.pattern,
|
||||
isRegex: r.isRegex,
|
||||
})),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user