Skip to content

Commit

Permalink
feat(api): add verify budget period config (#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
duongdev committed Jul 20, 2024
1 parent ad77f7d commit 495094e
Show file tree
Hide file tree
Showing 3 changed files with 248 additions and 113 deletions.
8 changes: 4 additions & 4 deletions apps/api/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ model Budget {
preferredCurrency String
type BudgetType @default(SPENDING)
periodConfig BudgetPeriodConfig?
budgetUsers BudgetUser[]
transactions Transaction[]
invitations BudgetUserInvitation[]
periodConfigs BudgetPeriodConfig[]
budgetUsers BudgetUser[]
transactions Transaction[]
invitations BudgetUserInvitation[]
}

enum BudgetType {
Expand Down
111 changes: 93 additions & 18 deletions apps/api/v1/services/budget.service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import { calculateBudgetPeriodStartEndDates } from '@6pm/utilities'
import {
calculateBudgetPeriodStartEndDates,
dayjsExtended,
} from '@6pm/utilities'
import type { CreateBudget, UpdateBudget } from '@6pm/validation'
import { type Budget, BudgetUserPermission, type User } from '@prisma/client'
import {
type Budget,
BudgetUserPermission,
type Prisma,
type User,
} from '@prisma/client'
import prisma from '../../lib/prisma'
import { inviteUserToBudget } from './budget-invitation.service'

const BUDGET_INCLUDE: Prisma.BudgetInclude = {
periodConfigs: true,
}

export async function canUserCreateBudget({
// biome-ignore lint/correctness/noUnusedVariables: <explanation>
user,
Expand Down Expand Up @@ -85,12 +97,16 @@ export async function isUserBudgetOwner({
}

export async function findBudget({ budgetId }: { budgetId: string }) {
return prisma.budget.findUnique({
const budget = await prisma.budget.findUnique({
where: { id: budgetId },
include: {
periodConfig: true,
},
include: BUDGET_INCLUDE,
})

if (!budget) {
return null
}

return verifyBudgetPeriods({ budget })
}

export async function createBudget({
Expand Down Expand Up @@ -122,7 +138,7 @@ export async function createBudget({
type,
description,
preferredCurrency,
periodConfig: {
periodConfigs: {
create: {
type: period.type,
amount: period.amount,
Expand All @@ -137,6 +153,7 @@ export async function createBudget({
},
},
},
include: BUDGET_INCLUDE,
})

// Invite users as members
Expand All @@ -156,7 +173,7 @@ export async function createBudget({
throw error
}

return budget
return verifyBudgetPeriods({ budget })
}

export async function updateBudget({
Expand All @@ -168,25 +185,37 @@ export async function updateBudget({
}) {
const { name, description, type, preferredCurrency, period } = data

const latestPeriodConfig = await findBudgetLatestPeriodConfig({ budgetId })

const budget = await prisma.budget.update({
where: { id: budgetId },
data: {
name,
description,
type,
preferredCurrency,
periodConfig: {
periodConfigs: {
update: {
type: period?.type,
amount: period?.amount,
startDate: period?.startDate,
endDate: period?.endDate,
where: {
id: latestPeriodConfig?.id,
},
data: {
type: period?.type,
amount: period?.amount,
startDate: period?.startDate,
endDate: period?.endDate,
},
},
},
},
include: BUDGET_INCLUDE,
})

return budget
if (!budget) {
return null
}

return verifyBudgetPeriods({ budget })
}

export async function deleteBudget({ budgetId }: { budgetId: string }) {
Expand All @@ -199,7 +228,7 @@ export async function findBudgetsOfUser({
user,
permission,
}: { user: User; permission?: BudgetUserPermission }) {
return prisma.budget.findMany({
const budgets = await prisma.budget.findMany({
where: {
budgetUsers: {
some: {
Expand All @@ -208,10 +237,10 @@ export async function findBudgetsOfUser({
},
},
},
include: {
periodConfig: true,
},
include: BUDGET_INCLUDE,
})

return Promise.all(budgets.map((budget) => verifyBudgetPeriods({ budget })))
}

export async function createBudgetUser({
Expand All @@ -231,3 +260,49 @@ export async function createBudgetUser({
},
})
}

async function findBudgetLatestPeriodConfig({
budgetId,
}: {
budgetId: string
}) {
return prisma.budgetPeriodConfig.findFirst({
where: {
budgetId,
},
orderBy: {
startDate: 'desc',
},
})
}

async function verifyBudgetPeriods({ budget }: { budget: Budget }) {
const latestPeriodConfig = await findBudgetLatestPeriodConfig({
budgetId: budget.id,
})

if (!latestPeriodConfig) {
return budget
}

if (
latestPeriodConfig.type === 'MONTHLY' &&
latestPeriodConfig.endDate &&
latestPeriodConfig.endDate < new Date()
) {
await prisma.budgetPeriodConfig.create({
data: {
type: 'MONTHLY',
amount: 1,
startDate: latestPeriodConfig.endDate,
endDate: dayjsExtended().endOf('month').toDate(),
budgetId: budget.id,
},
})
}

return prisma.budget.findUnique({
where: { id: budget.id },
include: BUDGET_INCLUDE,
})
}
Loading

0 comments on commit 495094e

Please sign in to comment.