Skip to content

Commit

Permalink
feat(api): [Transaction] add update transaction api (#45)
Browse files Browse the repository at this point in the history
  • Loading branch information
duongdev committed Jun 8, 2024
1 parent dd3ab33 commit d8d57be
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 5 deletions.
44 changes: 43 additions & 1 deletion apps/api/v1/routes/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import { getAuthUserStrict } from '../middlewares/auth'
import { canUserReadBudget, findBudget } from '../services/budget.service'
import {
canUserCreateTransaction,
canUserReadTransaction,
canUserUpdateTransaction,
createTransaction,
findTransaction,
updateTransaction,
} from '../services/transaction.service'
import { findUserWallet } from '../services/wallet.service'
import {
Expand Down Expand Up @@ -75,7 +79,45 @@ router.put(
),
zValidator('json', zUpdateTransaction),
async (c) => {
return c.json({ message: 'not implemented' })
const { transactionId } = c.req.valid('param')
const user = getAuthUserStrict(c)
const data = c.req.valid('json')
const { budgetId, walletAccountId: walletId } = data

const transaction = await findTransaction({ transactionId })

if (
!(transaction && (await canUserReadTransaction({ user, transaction })))
) {
return c.json({ message: 'transaction not found' }, 404)
}

const wallet = walletId ? await findUserWallet({ user, walletId }) : null
if (walletId && !wallet) {
return c.json({ message: 'wallet not found' }, 404)
}

if (
!(await canUserUpdateTransaction({
user,
transaction,
walletAccount: wallet,
}))
) {
return c.json({ message: 'user cannot update transaction' }, 403)
}

const budget = budgetId ? await findBudget({ budgetId }) : null
if (budgetId && (!budget || !(await canUserReadBudget({ user, budget })))) {
return c.json({ message: 'budget not found' }, 404)
}

const updatedTransaction = await updateTransaction({
transactionId,
data,
})

return c.json(updatedTransaction)
},
)

Expand Down
96 changes: 93 additions & 3 deletions apps/api/v1/services/transaction.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import prisma from '@/lib/prisma'
import type { Budget, User, UserWalletAccount } from '@prisma/client'
import type { CreateTransaction } from '../validation/transaction.zod'
import { isUserBudgetMember } from './budget.service'
import type {
Budget,
Transaction,
User,
UserWalletAccount,
} from '@prisma/client'
import type {
CreateTransaction,
UpdateTransaction,
} from '../validation/transaction.zod'
import {
findBudget,
isUserBudgetMember,
isUserBudgetOwner,
} from './budget.service'

export async function canUserCreateTransaction({
user,
Expand All @@ -25,6 +37,67 @@ export async function canUserCreateTransaction({
return true
}

export async function canUserReadTransaction({
user,
transaction,
}: {
user: User
transaction: Transaction
}) {
// If user is the creator of the transaction, they can read it
if (transaction.createdByUserId === user.id) {
return true
}

// If user is the member of the budget of the transaction, they can read it
if (transaction.budgetId) {
const budget = await findBudget({ budgetId: transaction.budgetId })
return budget && (await isUserBudgetMember({ user, budget }))
}

return false
}

export async function canUserUpdateTransaction({
user,
transaction,
walletAccount,
}: {
user: User
transaction: Transaction
walletAccount: UserWalletAccount | null
}) {
// If wallet is provided, user must own the wallet
if (walletAccount && walletAccount.userId !== user.id) {
return false
}

// If user is the creator of the transaction, they can update it
if (transaction.createdByUserId === user.id) {
return true
}

// If user owns the budget of the transaction, they can update it
if (transaction.budgetId) {
const budget = await findBudget({ budgetId: transaction.budgetId })
return budget && (await isUserBudgetOwner({ user, budget }))
}

return false
}

export async function findTransaction({
transactionId,
}: {
transactionId: string
}) {
return prisma.transaction.findUnique({
where: {
id: transactionId,
},
})
}

export async function createTransaction({
user,
data,
Expand All @@ -41,3 +114,20 @@ export async function createTransaction({

return transaction
}

export async function updateTransaction({
transactionId,
data,
}: {
transactionId: string
data: UpdateTransaction
}) {
const transaction = await prisma.transaction.update({
where: {
id: transactionId,
},
data,
})

return transaction
}
2 changes: 1 addition & 1 deletion apps/api/v1/validation/transaction.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ export const zUpdateTransaction = z.object({
currency: z.string().optional(),
note: z.string().optional(),
budgetId: z.string().optional(),
walletId: z.string().optional(),
walletAccountId: z.string().optional(),
})
export type UpdateTransaction = z.infer<typeof zUpdateTransaction>

0 comments on commit d8d57be

Please sign in to comment.