refactor: replace direct Prisma calls with service layer methods for banking operations
This commit is contained in:
91
services/transaction.service.ts
Normal file
91
services/transaction.service.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import type { Transaction } from "@/lib/types"
|
||||
|
||||
export interface CreateManyResult {
|
||||
count: number
|
||||
transactions: Transaction[]
|
||||
}
|
||||
|
||||
export const transactionService = {
|
||||
async createMany(transactions: Transaction[]): Promise<CreateManyResult> {
|
||||
// Filter out duplicates based on fitId (business rule)
|
||||
const existingTransactions = await prisma.transaction.findMany({
|
||||
where: {
|
||||
accountId: { in: transactions.map((t) => t.accountId) },
|
||||
fitId: { in: transactions.map((t) => t.fitId) },
|
||||
},
|
||||
select: {
|
||||
accountId: true,
|
||||
fitId: true,
|
||||
},
|
||||
})
|
||||
|
||||
const existingSet = new Set(
|
||||
existingTransactions.map((t) => `${t.accountId}-${t.fitId}`),
|
||||
)
|
||||
|
||||
const newTransactions = transactions.filter(
|
||||
(t) => !existingSet.has(`${t.accountId}-${t.fitId}`),
|
||||
)
|
||||
|
||||
if (newTransactions.length === 0) {
|
||||
return { count: 0, transactions: [] }
|
||||
}
|
||||
|
||||
const created = await prisma.transaction.createMany({
|
||||
data: newTransactions.map((t) => ({
|
||||
accountId: t.accountId,
|
||||
date: t.date,
|
||||
amount: t.amount,
|
||||
description: t.description,
|
||||
type: t.type,
|
||||
categoryId: t.categoryId,
|
||||
isReconciled: t.isReconciled,
|
||||
fitId: t.fitId,
|
||||
memo: t.memo,
|
||||
checkNum: t.checkNum,
|
||||
})),
|
||||
})
|
||||
|
||||
return { count: created.count, transactions: newTransactions }
|
||||
},
|
||||
|
||||
async update(id: string, data: Partial<Omit<Transaction, "id">>): Promise<Transaction> {
|
||||
const updated = await prisma.transaction.update({
|
||||
where: { id },
|
||||
data: {
|
||||
accountId: data.accountId,
|
||||
date: data.date,
|
||||
amount: data.amount,
|
||||
description: data.description,
|
||||
type: data.type,
|
||||
categoryId: data.categoryId,
|
||||
isReconciled: data.isReconciled,
|
||||
fitId: data.fitId,
|
||||
memo: data.memo,
|
||||
checkNum: data.checkNum,
|
||||
},
|
||||
})
|
||||
|
||||
return {
|
||||
id: updated.id,
|
||||
accountId: updated.accountId,
|
||||
date: updated.date,
|
||||
amount: updated.amount,
|
||||
description: updated.description,
|
||||
type: updated.type as Transaction["type"],
|
||||
categoryId: updated.categoryId,
|
||||
isReconciled: updated.isReconciled,
|
||||
fitId: updated.fitId,
|
||||
memo: updated.memo ?? undefined,
|
||||
checkNum: updated.checkNum ?? undefined,
|
||||
}
|
||||
},
|
||||
|
||||
async delete(id: string): Promise<void> {
|
||||
await prisma.transaction.delete({
|
||||
where: { id },
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user