Skip to content

Instantly share code, notes, and snippets.

@mwawrusch
Created September 8, 2024 00:19
Show Gist options
  • Save mwawrusch/2731658ac62082fd363993a3b01c0cbb to your computer and use it in GitHub Desktop.
Save mwawrusch/2731658ac62082fd363993a3b01c0cbb to your computer and use it in GitHub Desktop.
// prisma/schema.prisma
model User {
id String @id @default(cuid())
// ... other user fields ...
ledger Ledger?
journals Journal[]
}
model Ledger {
id String @id @default(cuid())
userId String @unique
user User @relation(fields: [userId], references: [id])
balance Float @default(0)
lastUpdated DateTime @updatedAt
}
model Journal {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id])
credit Float @default(0)
debit Float @default(0)
runningTotal Float
transactionType TransactionType
description String
createdAt DateTime @default(now())
}
enum TransactionType {
DEPOSIT
USAGE
}
/// CODE:
import { prisma } from '@repo/database'
import { TransactionType } from '@prisma/client'
interface CreditOperation {
userId: string
amount: number
description: string
}
export async function addCredit({ userId, amount, description }: CreditOperation) {
return prisma.$transaction(async (tx) => {
const ledger = await tx.ledger.upsert({
where: { userId },
update: { balance: { increment: amount } },
create: { userId, balance: amount },
})
const journal = await tx.journal.create({
data: {
userId,
credit: amount,
debit: 0,
runningTotal: ledger.balance,
transactionType: TransactionType.DEPOSIT,
description,
},
})
return { ledger, journal }
})
}
export async function debitCredit({ userId, amount, description }: CreditOperation) {
return prisma.$transaction(async (tx) => {
const ledger = await tx.ledger.findUnique({ where: { userId } })
if (!ledger || ledger.balance < amount) {
throw new Error('Insufficient balance')
}
const updatedLedger = await tx.ledger.update({
where: { userId },
data: { balance: { decrement: amount } },
})
const journal = await tx.journal.create({
data: {
userId,
credit: 0,
debit: amount,
runningTotal: updatedLedger.balance,
transactionType: TransactionType.USAGE,
description,
},
})
return { ledger: updatedLedger, journal }
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment