reverted budget allocation for credit cards

This commit is contained in:
2026-04-21 09:47:49 -04:00
parent 7ccd64a7bb
commit e6f5d5a33b
2 changed files with 51 additions and 0 deletions

View 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 })
}

View File

@@ -124,6 +124,22 @@ export async function POST(req: Request) {
})), })),
skipDuplicates: true, 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 const skippedCount = normalized.length - importedCount
// Recompute current balance // Recompute current balance