From afd94b68cc017bd67b0a9f5b34e693fb4e17897c Mon Sep 17 00:00:00 2001 From: quantum-grit <91589884+quantum-grit@users.noreply.github.com> Date: Fri, 29 Sep 2023 10:55:29 +0300 Subject: [PATCH] fix expense seeding (#554) * added: env variable for CAMPAIGN_ADMIN_MAIL in deployment config * ensure all campaigns have single vault and heavily-funded campaign has approved expenses * fixed: typescript errors in expense tests --- .../src/expenses/expenses.controller.spec.ts | 33 ++-- db/seed/campaign/seed.ts | 2 +- db/seed/donation/seed.ts | 19 ++- db/seed/expense/factory.ts | 4 +- db/seed/expense/seed.ts | 19 ++- db/seed/vault/seed.ts | 150 ++++-------------- 6 files changed, 88 insertions(+), 139 deletions(-) diff --git a/apps/api/src/expenses/expenses.controller.spec.ts b/apps/api/src/expenses/expenses.controller.spec.ts index 254c36ac9..4f8c5e6f9 100644 --- a/apps/api/src/expenses/expenses.controller.spec.ts +++ b/apps/api/src/expenses/expenses.controller.spec.ts @@ -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 = [ { @@ -69,8 +70,8 @@ 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) @@ -78,7 +79,7 @@ describe('ExpensesController', () => { 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 }) @@ -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) @@ -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) @@ -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() }) @@ -233,8 +236,12 @@ 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() }) @@ -242,6 +249,10 @@ describe('ExpensesController', () => { 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', @@ -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() }) diff --git a/db/seed/campaign/seed.ts b/db/seed/campaign/seed.ts index 6c0ca77f0..9c4204366 100644 --- a/db/seed/campaign/seed.ts +++ b/db/seed/campaign/seed.ts @@ -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') diff --git a/db/seed/donation/seed.ts b/db/seed/donation/seed.ts index e1870d16b..6c0736984 100644 --- a/db/seed/donation/seed.ts +++ b/db/seed/donation/seed.ts @@ -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' @@ -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, }, }, }) @@ -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', + }, }, }, }) diff --git a/db/seed/expense/factory.ts b/db/seed/expense/factory.ts index 07b47c9b9..82a74310a 100644 --- a/db/seed/expense/factory.ts +++ b/db/seed/expense/factory.ts @@ -11,9 +11,9 @@ export const expenseFactory = Factory.define(({ 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(), })) diff --git a/db/seed/expense/seed.ts b/db/seed/expense/seed.ts index f0ed692d4..cb164999f 100644 --- a/db/seed/expense/seed.ts +++ b/db/seed/expense/seed.ts @@ -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, }, }, ) diff --git a/db/seed/vault/seed.ts b/db/seed/vault/seed.ts index 0baadf38b..6cfd2dfe9 100644 --- a/db/seed/vault/seed.ts +++ b/db/seed/vault/seed.ts @@ -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} }`) }