Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix expense seeding #554

Merged
merged 4 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions apps/api/src/expenses/expenses.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import { Test, TestingModule } from '@nestjs/testing'
import { ExpensesController } from './expenses.controller'
import { ExpensesService } from './expenses.service'
import { MockPrismaService, prismaMock } from '../prisma/prisma-client.mock'
import { ExpenseStatus, ExpenseType, Currency } from '@prisma/client'
import { ExpenseStatus, ExpenseType, Currency, Person, Campaign } from '@prisma/client'
import { mockReset } from 'jest-mock-extended'
import { CreateExpenseDto } from './dto/create-expense.dto'
import { UpdateExpenseDto } from './dto/update-expense.dto'
import { S3Service } from '../s3/s3.service'
import { KeycloakTokenParsed } from '../auth/keycloak'

const mockData = [
{
Expand Down Expand Up @@ -69,16 +70,16 @@ describe('ExpensesController', () => {
const campaign = {}
const user = { sub: '00000000-0000-0000-0000-000000000013' }

prismaMock.person.findFirst.mockResolvedValue(person)
prismaMock.campaign.findFirst.mockResolvedValue(campaign)
prismaMock.person.findFirst.mockResolvedValue(person as Person)
prismaMock.campaign.findFirst.mockResolvedValue(campaign as Campaign)
prismaMock.expense.create.mockResolvedValue(expense)
prismaMock.vault.update.mockResolvedValue(vault)
prismaMock.vault.findFirst.mockResolvedValue(vault)
prismaMock.$transaction.mockResolvedValue([expense, vault])

const createDto: CreateExpenseDto = { ...expense }

const result = await controller.create(user, createDto, [])
const result = await controller.create(user as KeycloakTokenParsed, createDto)

expect(result).toEqual(expense)
expect(prismaMock.expense.create).toHaveBeenCalledWith({ data: createDto })
Expand Down Expand Up @@ -132,8 +133,8 @@ describe('ExpensesController', () => {

const campaign = {}

prismaMock.person.findFirst.mockResolvedValue(person)
prismaMock.campaign.findFirst.mockResolvedValue(campaign)
prismaMock.person.findFirst.mockResolvedValue(person as Person)
prismaMock.campaign.findFirst.mockResolvedValue(campaign as Campaign)
prismaMock.vault.findFirstOrThrow.mockResolvedValue(vault)
prismaMock.expense.findFirstOrThrow.mockResolvedValue(expense)
prismaMock.vault.update.mockResolvedValue(vault)
Expand All @@ -147,7 +148,7 @@ describe('ExpensesController', () => {
}

// act
const result = await controller.update(user, expense.id, updateDto)
const result = await controller.update(user as KeycloakTokenParsed, expense.id, updateDto)

// assert
expect(result).toEqual(expense)
Expand Down Expand Up @@ -193,7 +194,9 @@ describe('ExpensesController', () => {
vaultId: vault.id,
}

await expect(controller.update(user, expense.id, updateDto)).rejects.toThrow()
await expect(
controller.update(user as KeycloakTokenParsed, expense.id, updateDto),
).rejects.toThrow()
//expect an exception
expect(prismaMock.expense.update).not.toHaveBeenCalled()
})
Expand Down Expand Up @@ -233,15 +236,23 @@ describe('ExpensesController', () => {
}

// assert
await expect(controller.update(user, approvedExpense.id, updateDto)).rejects.toThrow()
await expect(controller.update(user, cancelledExpense.id, updateDto)).rejects.toThrow()
await expect(
controller.update(user as KeycloakTokenParsed, approvedExpense.id, updateDto),
).rejects.toThrow()
await expect(
controller.update(user as KeycloakTokenParsed, cancelledExpense.id, updateDto),
).rejects.toThrow()
expect(prismaMock.expense.update).not.toHaveBeenCalled()
expect(prismaMock.vault.update).not.toHaveBeenCalled()
})

it('should not update an expense, when its vault is being changed', async () => {
const expense = mockData[0]

const user: KeycloakTokenParsed = {
sub: '00000000-0000-0000-0000-000000000012',
} as KeycloakTokenParsed

const vault = {
id: '00000000-0000-0000-0000-000000000016',
name: 'vault1',
Expand All @@ -262,7 +273,7 @@ describe('ExpensesController', () => {
}

// assert
await expect(controller.update(expense.id, updateDto)).rejects.toThrow()
await expect(controller.update(user, expense.id, updateDto)).rejects.toThrow()
expect(prismaMock.expense.update).not.toHaveBeenCalled()
expect(prismaMock.vault.update).not.toHaveBeenCalled()
})
Expand Down
2 changes: 1 addition & 1 deletion db/seed/campaign/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const prisma = new PrismaClient()
const SEED_ACTIVE_CAMPAIGNS = 5
const SEED_RANDOM_CAMPAIGNS = 5
const SEED_COMPLETED_CAMPAIGNS = 3
const SEED_HEAVILY_FUNDED_CAMPAIGNS = 3
const SEED_HEAVILY_FUNDED_CAMPAIGNS = 1

export async function campaignSeed() {
console.log('Campaigns seed')
Expand Down
19 changes: 14 additions & 5 deletions db/seed/donation/seed.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { PrismaClient, PaymentProvider, DonationStatus, DonationType, Person } from '@prisma/client'
import {
PrismaClient,
PaymentProvider,
DonationStatus,
DonationType,
Person,
CampaignState,
} from '@prisma/client'

import { donationFactory } from './factory'

Expand Down Expand Up @@ -78,8 +85,8 @@ async function seedRandomDonations({ person }: SeedData) {
async function seedDonationsForCompletedCampaign({ person }: SeedData) {
const completedCampaignVault = await prisma.vault.findFirst({
where: {
name: {
contains: 'completed',
campaign: {
state: CampaignState.complete,
},
},
})
Expand Down Expand Up @@ -119,8 +126,10 @@ async function seedDonationsForCompletedCampaign({ person }: SeedData) {
async function seedDonationsForHeavilyFundedCampaign({ person }: SeedData) {
const heavilyFundedCampaignVault = await prisma.vault.findFirst({
where: {
name: {
contains: 'heavily-funded',
campaign: {
title: {
contains: 'heavily-funded',
},
},
},
})
Expand Down
4 changes: 2 additions & 2 deletions db/seed/expense/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export const expenseFactory = Factory.define<Expense>(({ associations }) => ({
vaultId: associations.vaultId || faker.datatype.uuid(),
documentId: associations.documentId || null,
approvedById: associations.approvedById || null,
amount: faker.datatype.number(),
amount: faker.datatype.number({ min: 1, max: 20000 }),
currency: faker.helpers.arrayElement(Object.values(Currency)),
status: faker.helpers.arrayElement(Object.values(ExpenseStatus)),
status: ExpenseStatus.pending,
deleted: faker.datatype.boolean(),
spentAt: faker.date.past(),
}))
19 changes: 17 additions & 2 deletions db/seed/expense/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,33 @@ const prisma = new PrismaClient()
export async function expenseSeed() {
console.log('Expense seed')

const vault = await prisma.vault.findFirst()
const vault = await prisma.vault.findFirst({
where: {
campaign: {
title: {
contains: 'heavily-funded',
},
},
},
})

if (!vault) {
throw new Error('There are no vaults created yet!')
}

const coordinator = await prisma.coordinator.findFirst()

if (!coordinator) {
throw new Error('There are no coordinators created yet!')
}

const expensesData: Expense[] = expenseFactory.buildList(
20,
11,
{},
{
associations: {
vaultId: vault.id,
approvedById: coordinator.personId,
},
},
)
Expand Down
150 changes: 32 additions & 118 deletions db/seed/vault/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,123 +7,37 @@ const prisma = new PrismaClient()
export async function vaultSeed() {
console.log('Vault seed')

await seedVaultsForRandomCampaign()
await seedVaultForCompletedCampaign()
await seedVaultForHeavilyFundedCampaign()
}

async function seedVaultsForRandomCampaign() {
const campaign = await prisma.campaign
.findMany()
.then((campaigns) => faker.helpers.arrayElement(campaigns))

if (!campaign) {
throw new Error('There are no campaigns created yet!')
}

const randomCampaignVaultsData: Vault[] = vaultFactory.buildList(
20,
{
currency: Currency.BGN,
amount: 0, // Initializing with 0 and fill the correct amount after donations have been seeded
},
{
associations: {
campaignId: campaign.id,
},
},
)

const insertRandomCampaignVaults = await prisma.vault.createMany({
data: randomCampaignVaultsData,
skipDuplicates: true,
})

console.log({ insertRandomCampaignVaults })
}

async function seedVaultForCompletedCampaign() {
const completedCampaign = await prisma.campaign.findFirst({
where: {
state: CampaignState.complete,
},
})

if (!completedCampaign) {
throw new Error('There is no completed campaign created')
}

const completedCampaignVault = await prisma.vault.findFirst({
where: {
campaignId: completedCampaign.id,
},
})

if (completedCampaignVault) {
console.log('{ Completed campaign vault already exists }')
return
await seedVaultsForCampaigns()

async function seedVaultsForCampaigns() {
const campaigns = await prisma.campaign.findMany()

if (!campaigns) {
throw new Error('There are no campaigns created yet!')
}

let vaults: Vault[] = []
campaigns.map(async (campaign) => {
vaults.push(
vaultFactory.build(
{
currency: Currency.BGN,
amount: 0, // Initializing with 0 and fill the correct amount after donations have been seeded
},
{
associations: {
campaignId: campaign.id,
},
},
),
)
})

const insertRandomCampaignVaults = await prisma.vault.createMany({
data: vaults,
skipDuplicates: true,
})

console.log({ insertRandomCampaignVaults })
}

const completedCampaignVaultData: Vault = vaultFactory.build(
{
name: faker.finance.accountName() + ' completed',
currency: Currency.BGN,
amount: 0, // Initializing with 0 and fill the correct amount after donations have been seeded
},
{
associations: {
campaignId: completedCampaign.id,
},
},
)

const insertCompletedCampaignVault = await prisma.vault.create({
data: completedCampaignVaultData,
})

console.log(`{ insertCompletedCampaignVault: ${!!insertCompletedCampaignVault} }`)
}

async function seedVaultForHeavilyFundedCampaign() {
const heavilyFundedCampaign = await prisma.campaign.findFirst({
where: {
title: {
contains: 'heavily-funded',
},
},
})

if (!heavilyFundedCampaign) {
throw new Error('There is no heavily funded campaign created')
}

const heavilyFundedCampaignVault = await prisma.vault.findFirst({
where: {
campaignId: heavilyFundedCampaign.id,
},
})

if (heavilyFundedCampaignVault) {
console.log('{ Heavily-funded campaign vault already exists }')
return
}

const heavilyFundedCampaignVaultData: Vault = vaultFactory.build(
{
name: faker.finance.accountName() + ' heavily-funded',
currency: Currency.BGN,
amount: 0, // Initializing with 0 and fill the correct amount after donations have been seeded
},
{
associations: {
campaignId: heavilyFundedCampaign.id,
},
},
)

const insertHeavilyFundedCampaignVault = await prisma.vault.create({
data: heavilyFundedCampaignVaultData,
})

console.log(`{ insertHeavilyFundedCampaignVault: ${!!insertHeavilyFundedCampaignVault} }`)
}