reverted budget allocation for credit cards
This commit is contained in:
35
src/app/api/admin/fix-cc-types/route.ts
Normal file
35
src/app/api/admin/fix-cc-types/route.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { auth } from '@/lib/auth'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
|
||||
// One-time migration: flips DEBIT↔CREDIT on all CREDIT_CARD account transactions.
|
||||
// CC CSVs have inverted sign semantics (CREDIT = charge, DEBIT = refund), but we now
|
||||
// normalise them to standard semantics (DEBIT = spend) at upload time. Existing rows
|
||||
// uploaded before that fix need their type flipped.
|
||||
export async function POST() {
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
|
||||
const userId = session.user.id
|
||||
|
||||
const ccAccounts = await prisma.account.findMany({
|
||||
where: { userId, type: 'CREDIT_CARD' },
|
||||
select: { id: true },
|
||||
})
|
||||
|
||||
if (ccAccounts.length === 0) {
|
||||
return NextResponse.json({ updated: 0, message: 'No credit card accounts found' })
|
||||
}
|
||||
|
||||
const ccIds = ccAccounts.map((a) => a.id)
|
||||
|
||||
// Flip both directions in one raw statement to avoid stepping on our own update
|
||||
const result = await prisma.$executeRaw`
|
||||
UPDATE "Transaction"
|
||||
SET type = CASE WHEN type = 'DEBIT' THEN 'CREDIT'::"TransactionType"
|
||||
ELSE 'DEBIT'::"TransactionType" END
|
||||
WHERE "accountId" = ANY(${ccIds}::text[])
|
||||
`
|
||||
|
||||
return NextResponse.json({ updated: result })
|
||||
}
|
||||
@@ -124,6 +124,22 @@ export async function POST(req: Request) {
|
||||
})),
|
||||
skipDuplicates: true,
|
||||
})
|
||||
|
||||
// For CC accounts, also correct the type on any rows that already existed
|
||||
// (uploaded before the CREDIT↔DEBIT flip was introduced).
|
||||
if (account.type === 'CREDIT_CARD') {
|
||||
const debitHashes = rowsWithBudgets.filter((r) => r.type === 'DEBIT').map((r) => r.dedupeHash)
|
||||
const creditHashes = rowsWithBudgets.filter((r) => r.type === 'CREDIT').map((r) => r.dedupeHash)
|
||||
await Promise.all([
|
||||
debitHashes.length > 0
|
||||
? prisma.transaction.updateMany({ where: { dedupeHash: { in: debitHashes }, type: 'CREDIT' }, data: { type: 'DEBIT' } })
|
||||
: Promise.resolve(),
|
||||
creditHashes.length > 0
|
||||
? prisma.transaction.updateMany({ where: { dedupeHash: { in: creditHashes }, type: 'DEBIT' }, data: { type: 'CREDIT' } })
|
||||
: Promise.resolve(),
|
||||
])
|
||||
}
|
||||
|
||||
const skippedCount = normalized.length - importedCount
|
||||
|
||||
// Recompute current balance
|
||||
|
||||
Reference in New Issue
Block a user