From 77e21380496136a6b7a3300095a6a0fbf43ec646 Mon Sep 17 00:00:00 2001 From: Georgi Parlakov Date: Sun, 8 Sep 2024 20:29:16 +0300 Subject: [PATCH] fix: campaign type and add files - add files to the campaign application findOne - replace category with campaignTypeId (category is a property of the campaignType and was used incorrectly to define it) - linting fixes --- .../__mocks__/campaign-application-mocks.ts | 50 +++---------------- .../campaign-application.controller.ts | 31 ++++++------ .../campaign-application.service.spec.ts | 14 +++--- .../campaign-application.service.ts | 30 +++++++---- .../dto/create-campaign-application.dto.ts | 7 +-- .../dto/create-campaignApplication.dto.ts | 6 +-- .../dto/update-campaignApplication.dto.ts | 6 +-- .../entities/campaignApplication.entity.ts | 4 +- .../migration.sql | 9 ++++ podkrepi.dbml | 6 ++- schema.prisma | 14 +++--- 11 files changed, 76 insertions(+), 101 deletions(-) create mode 100644 migrations/20240907144954_replace_category_with_campaign_type_id/migration.sql diff --git a/apps/api/src/campaign-application/__mocks__/campaign-application-mocks.ts b/apps/api/src/campaign-application/__mocks__/campaign-application-mocks.ts index c788a891..49dfea32 100644 --- a/apps/api/src/campaign-application/__mocks__/campaign-application-mocks.ts +++ b/apps/api/src/campaign-application/__mocks__/campaign-application-mocks.ts @@ -1,5 +1,4 @@ -import { CampaignApplicationState, CampaignTypeCategory } from '@prisma/client' -import { CreateCampaignApplicationDto } from '../dto/create-campaign-application.dto' +import { CampaignApplicationState } from '@prisma/client' export const mockNewCampaignApplication = { campaignName: 'Test Campaign', @@ -15,7 +14,7 @@ export const mockNewCampaignApplication = { campaignGuarantee: 'Test guarantee', otherFinanceSources: 'Test otherFinanceSources', otherNotes: 'Test otherNotes', - category: CampaignTypeCategory.medical, + campaignTypeId: 'ffdbcc41-85ec-0000-9e59-0662f3b433af', } export const mockSingleCampaignApplication = { @@ -37,7 +36,7 @@ export const mockSingleCampaignApplication = { otherFinanceSources: 'test otherFinanceSources1', otherNotes: 'test otherNotes1', state: CampaignApplicationState.review, - category: CampaignTypeCategory.medical, + campaignTypeId: 'ffdbcc41-85ec-0000-9e59-0662f3b433af', ticketURL: 'testsodifhso1', archived: false, documents: [{ id: 'fileId' }], @@ -63,7 +62,7 @@ export const mockCampaigns = [ otherFinanceSources: 'test otherFinanceSources1', otherNotes: 'test otherNotes1', state: CampaignApplicationState.review, - category: CampaignTypeCategory.medical, + campaignTypeId: 'ffdbcc41-85ec-0000-9e59-0662f3b433af', ticketURL: 'testsodifhso1', archived: false, }, @@ -86,7 +85,7 @@ export const mockCampaigns = [ otherFinanceSources: 'test otherFinanceSources2', otherNotes: 'test otherNotes2', state: CampaignApplicationState.review, - category: CampaignTypeCategory.medical, + campaignTypeId: 'ffdbcc41-85ec-0000-9e59-0662f3b433af', ticketURL: 'testsodifhso2', archived: false, }, @@ -117,42 +116,5 @@ export const mockUpdateCampaignApplication = { campaignGuarantee: 'Test guarantee', otherFinanceSources: 'Test otherFinanceSources', otherNotes: 'Test otherNotes', - category: CampaignTypeCategory.medical, -} - -const mockUpdateCampaignApplicationResponceOrganizer = { - amount: '1000', - beneficiary: 'Test beneficary', - campaignGuarantee: 'Test guarantee', - campaignName: 'Test Campaign', - category: 'medical', - description: 'Test description', - goal: 'Test goal', - history: 'Test history', - organizerBeneficiaryRel: 'Test organizerBeneficiaryRel', - organizerEmail: 'testemail@gmail.com', - organizerName: 'Test Organizer', - organizerPhone: '123456789', - otherFinanceSources: 'Test otherFinanceSources', - otherNotes: 'Test otherNotes', -} - -const mockUpdateCampaignApplicationResponceAdmin = { - amount: '1000', - beneficiary: 'Test beneficary', - campaignGuarantee: 'Test guarantee', - campaignName: 'Test Campaign', - category: 'medical', - description: 'Test description', - goal: 'Test goal', - history: 'Test history', - organizerBeneficiaryRel: 'Test organizerBeneficiaryRel', - organizerEmail: 'testemail@gmail.com', - organizerName: 'Test Organizer', - organizerPhone: '123456789', - otherFinanceSources: 'Test otherFinanceSources', - otherNotes: 'Test otherNotes', - archived: false, - state: 'active', - ticketURL: 'http://test.com/ticket', + campaignTypeId: 'ffdbcc41-85ec-0000-9e59-0662f3b433af', } diff --git a/apps/api/src/campaign-application/campaign-application.controller.ts b/apps/api/src/campaign-application/campaign-application.controller.ts index b3beb2ac..44f73e43 100644 --- a/apps/api/src/campaign-application/campaign-application.controller.ts +++ b/apps/api/src/campaign-application/campaign-application.controller.ts @@ -1,27 +1,26 @@ import { - Controller, - Get, - Post, Body, - Patch, - Param, + Controller, + Delete, ForbiddenException, - NotFoundException, + Get, Logger, + NotFoundException, + Param, + Patch, + Post, UploadedFiles, UseInterceptors, - Delete, } from '@nestjs/common' -import { CampaignApplicationService } from './campaign-application.service' -import { CreateCampaignApplicationDto } from './dto/create-campaign-application.dto' -import { UpdateCampaignApplicationDto } from './dto/update-campaign-application.dto' +import { FilesInterceptor } from '@nestjs/platform-express' import { ApiTags } from '@nestjs/swagger' -import { AuthenticatedUser, RoleMatchingMode, Roles } from 'nest-keycloak-connect' -import { RealmViewSupporters, ViewSupporters } from '@podkrepi-bg/podkrepi-types' +import { AuthenticatedUser } from 'nest-keycloak-connect' import { KeycloakTokenParsed, isAdmin } from '../auth/keycloak' -import { PersonService } from '../person/person.service' -import { FilesInterceptor } from '@nestjs/platform-express' import { validateFileType } from '../common/files' +import { PersonService } from '../person/person.service' +import { CampaignApplicationService } from './campaign-application.service' +import { CreateCampaignApplicationDto } from './dto/create-campaign-application.dto' +import { UpdateCampaignApplicationDto } from './dto/update-campaign-application.dto' @ApiTags('campaign-application') @Controller('campaign-application') @@ -85,7 +84,7 @@ export class CampaignApplicationController { } const isAdminFlag = isAdmin(user) - + return this.campaignApplicationService.findOne(id, isAdminFlag, person) } @@ -98,7 +97,7 @@ export class CampaignApplicationController { } const isAdminFlag = isAdmin(user) - + return this.campaignApplicationService.deleteFile(id, isAdminFlag, person) } diff --git a/apps/api/src/campaign-application/campaign-application.service.spec.ts b/apps/api/src/campaign-application/campaign-application.service.spec.ts index eadf7e94..acca17a3 100644 --- a/apps/api/src/campaign-application/campaign-application.service.spec.ts +++ b/apps/api/src/campaign-application/campaign-application.service.spec.ts @@ -1,11 +1,9 @@ -import { Test, TestingModule } from '@nestjs/testing' -import { CampaignApplicationService } from './campaign-application.service' -import { CreateCampaignApplicationDto } from './dto/create-campaign-application.dto' import { BadRequestException, ForbiddenException, NotFoundException } from '@nestjs/common' -import { CampaignApplicationFileRole, CampaignTypeCategory, Person } from '@prisma/client' -import { prismaMock, MockPrismaService } from '../prisma/prisma-client.mock' +import { Test, TestingModule } from '@nestjs/testing' import { OrganizerService } from '../organizer/organizer.service' import { personMock } from '../person/__mock__/personMock' +import { MockPrismaService, prismaMock } from '../prisma/prisma-client.mock' +import { S3Service } from '../s3/s3.service' import { mockCampaigns, mockCreatedCampaignApplication, @@ -13,12 +11,12 @@ import { mockSingleCampaignApplication, mockUpdateCampaignApplication, } from './__mocks__/campaign-application-mocks' -import { S3Service } from '../s3/s3.service' import { mockCampaignApplicationFileFn, mockCampaignApplicationFilesFn, - mockCampaignApplicationUploadFileFn, } from './__mocks__/campaing-application-file-mocks' +import { CampaignApplicationService } from './campaign-application.service' +import { CreateCampaignApplicationDto } from './dto/create-campaign-application.dto' describe('CampaignApplicationService', () => { let service: CampaignApplicationService @@ -143,7 +141,7 @@ describe('CampaignApplicationService', () => { campaignGuarantee: 'Test guarantee', otherFinanceSources: 'Test otherFinanceSources', otherNotes: 'Test otherNotes', - category: CampaignTypeCategory.medical, + campaignTypeId: 'ffdbcc41-85ec-0000-9e59-0662f3b433af', organizerId: mockOrganizerId, }, }) diff --git a/apps/api/src/campaign-application/campaign-application.service.ts b/apps/api/src/campaign-application/campaign-application.service.ts index ae0fff51..062285d2 100644 --- a/apps/api/src/campaign-application/campaign-application.service.ts +++ b/apps/api/src/campaign-application/campaign-application.service.ts @@ -21,10 +21,6 @@ export class CampaignApplicationService { private s3: S3Service, ) {} - async getCampaignByIdWithPersonIds(id: string): Promise { - throw new Error('Method not implemented.') - } - async create(createCampaignApplicationDto: CreateCampaignApplicationDto, person: Person) { try { if ( @@ -59,7 +55,7 @@ export class CampaignApplicationService { campaignGuarantee: createCampaignApplicationDto.campaignGuarantee, otherFinanceSources: createCampaignApplicationDto.otherFinanceSources, otherNotes: createCampaignApplicationDto.otherNotes, - category: createCampaignApplicationDto.category, + campaignTypeId: createCampaignApplicationDto.campaignTypeId, organizerId: organizer.id, } @@ -96,10 +92,22 @@ export class CampaignApplicationService { } } - async findOne(id: string, isAdminFlag: boolean, person: Prisma.PersonGetPayload<{ include: { organizer: {select:{id:true}}}}>) { + async findOne( + id: string, + isAdminFlag: boolean, + person: Prisma.PersonGetPayload<{ include: { organizer: { select: { id: true } } } }>, + ) { try { const singleCampaignApplication = await this.prisma.campaignApplication.findUnique({ where: { id }, + include: { + documents: { + select: { + id: true, + filename: true, + }, + }, + }, }) if (!singleCampaignApplication) { throw new NotFoundException('Campaign application doesnt exist') @@ -116,7 +124,11 @@ export class CampaignApplicationService { } } - async deleteFile(id: string, isAdminFlag: boolean, person: Prisma.PersonGetPayload<{ include: { organizer: {select:{id:true}}}}>) { + async deleteFile( + id: string, + isAdminFlag: boolean, + person: Prisma.PersonGetPayload<{ include: { organizer: { select: { id: true } } } }>, + ) { try { const campaignApplication = await this.prisma.campaignApplication.findFirst({ where: { @@ -184,7 +196,7 @@ export class CampaignApplicationService { campaignGuarantee: updateCampaignApplicationDto?.campaignGuarantee, otherFinanceSources: updateCampaignApplicationDto?.otherFinanceSources, otherNotes: updateCampaignApplicationDto?.otherNotes, - category: updateCampaignApplicationDto?.category, + campaignTypeId: updateCampaignApplicationDto?.campaignTypeId, }, }) @@ -208,7 +220,7 @@ export class CampaignApplicationService { campaignGuarantee: updateCampaignApplicationDto?.campaignGuarantee, otherFinanceSources: updateCampaignApplicationDto?.otherFinanceSources, otherNotes: updateCampaignApplicationDto?.otherNotes, - category: updateCampaignApplicationDto?.category, + campaignTypeId: updateCampaignApplicationDto?.campaignTypeId, state: updateCampaignApplicationDto?.state, ticketURL: updateCampaignApplicationDto?.ticketURL, archived: updateCampaignApplicationDto?.archived, diff --git a/apps/api/src/campaign-application/dto/create-campaign-application.dto.ts b/apps/api/src/campaign-application/dto/create-campaign-application.dto.ts index 20a84bce..54d29061 100644 --- a/apps/api/src/campaign-application/dto/create-campaign-application.dto.ts +++ b/apps/api/src/campaign-application/dto/create-campaign-application.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger' -import { CampaignTypeCategory, Prisma } from '@prisma/client' +import { Prisma } from '@prisma/client' import { Expose } from 'class-transformer' import { IsBoolean, IsNotEmpty, IsOptional, IsString } from 'class-validator' @@ -116,10 +116,11 @@ export class CreateCampaignApplicationDto { @IsOptional() otherNotes?: string - @ApiProperty({ enum: CampaignTypeCategory }) + @ApiProperty() @Expose() + @IsString() @IsOptional() - category?: CampaignTypeCategory + campaignTypeId?: string public toEntity(): Prisma.CampaignApplicationCreateInput { return { diff --git a/apps/api/src/domain/generated/campaignApplication/dto/create-campaignApplication.dto.ts b/apps/api/src/domain/generated/campaignApplication/dto/create-campaignApplication.dto.ts index 64443e2f..49485f25 100644 --- a/apps/api/src/domain/generated/campaignApplication/dto/create-campaignApplication.dto.ts +++ b/apps/api/src/domain/generated/campaignApplication/dto/create-campaignApplication.dto.ts @@ -1,6 +1,3 @@ -import { CampaignTypeCategory } from '@prisma/client' -import { ApiProperty } from '@nestjs/swagger' - export class CreateCampaignApplicationDto { organizerName: string organizerEmail?: string @@ -15,8 +12,7 @@ export class CreateCampaignApplicationDto { campaignGuarantee?: string otherFinanceSources?: string otherNotes?: string - @ApiProperty({ enum: CampaignTypeCategory }) - category?: CampaignTypeCategory + campaignTypeId?: string ticketURL?: string archived?: boolean } diff --git a/apps/api/src/domain/generated/campaignApplication/dto/update-campaignApplication.dto.ts b/apps/api/src/domain/generated/campaignApplication/dto/update-campaignApplication.dto.ts index f80c13dc..f679296d 100644 --- a/apps/api/src/domain/generated/campaignApplication/dto/update-campaignApplication.dto.ts +++ b/apps/api/src/domain/generated/campaignApplication/dto/update-campaignApplication.dto.ts @@ -1,6 +1,3 @@ -import { CampaignTypeCategory } from '@prisma/client' -import { ApiProperty } from '@nestjs/swagger' - export class UpdateCampaignApplicationDto { organizerName?: string organizerEmail?: string @@ -15,8 +12,7 @@ export class UpdateCampaignApplicationDto { campaignGuarantee?: string otherFinanceSources?: string otherNotes?: string - @ApiProperty({ enum: CampaignTypeCategory }) - category?: CampaignTypeCategory + campaignTypeId?: string ticketURL?: string archived?: boolean } diff --git a/apps/api/src/domain/generated/campaignApplication/entities/campaignApplication.entity.ts b/apps/api/src/domain/generated/campaignApplication/entities/campaignApplication.entity.ts index db325d73..3064a61d 100644 --- a/apps/api/src/domain/generated/campaignApplication/entities/campaignApplication.entity.ts +++ b/apps/api/src/domain/generated/campaignApplication/entities/campaignApplication.entity.ts @@ -1,4 +1,4 @@ -import { CampaignApplicationState, CampaignTypeCategory } from '@prisma/client' +import { CampaignApplicationState } from '@prisma/client' import { Organizer } from '../../organizer/entities/organizer.entity' import { CampaignApplicationFile } from '../../campaignApplicationFile/entities/campaignApplicationFile.entity' @@ -23,7 +23,7 @@ export class CampaignApplication { otherFinanceSources: string | null otherNotes: string | null state: CampaignApplicationState - category: CampaignTypeCategory | null + campaignTypeId: string | null ticketURL: string | null archived: boolean | null } diff --git a/migrations/20240907144954_replace_category_with_campaign_type_id/migration.sql b/migrations/20240907144954_replace_category_with_campaign_type_id/migration.sql new file mode 100644 index 00000000..bd208282 --- /dev/null +++ b/migrations/20240907144954_replace_category_with_campaign_type_id/migration.sql @@ -0,0 +1,9 @@ +/* + Warnings: + + - You are about to drop the column `category` on the `campaign_applications` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "campaign_applications" DROP COLUMN "category", +ADD COLUMN "campaignTypeId" UUID; diff --git a/podkrepi.dbml b/podkrepi.dbml index f1b8bcdb..ea676f2c 100644 --- a/podkrepi.dbml +++ b/podkrepi.dbml @@ -597,7 +597,7 @@ Table campaign_applications { otherFinanceSources String otherNotes String state CampaignApplicationState [not null, default: 'review'] - category CampaignTypeCategory [default: 'others'] + campaignTypeId String ticketURL String archived Boolean [default: false] @@ -988,4 +988,6 @@ Ref: expense_files.uploaderId > people.id Ref: documents.ownerId > people.id -Ref: campaign_applications.organizerId > organizers.id \ No newline at end of file +Ref: campaign_applications.organizerId > organizers.id + +Ref: campaign_application_files.campaignApplicationId > campaign_applications.id \ No newline at end of file diff --git a/schema.prisma b/schema.prisma index d5bb2c69..5d5b75f5 100644 --- a/schema.prisma +++ b/schema.prisma @@ -1008,9 +1008,9 @@ enum EmailType { /// CampaignApplication represents a request for a new campaign - it is not a Campaign yet and has to proove it needs to be model CampaignApplication { - id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid - createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6) - updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6) + id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid + createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6) + updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6) // organizer editable fields // need to be logged in to create a campaign application @@ -1033,10 +1033,10 @@ model CampaignApplication { otherNotes String? @db.Text // operator editable fields - state CampaignApplicationState @default(review) - category CampaignTypeCategory? @default(others) - ticketURL String? @db.VarChar(500) - archived Boolean? @default(false) + state CampaignApplicationState @default(review) + campaignTypeId String? @db.Uuid + ticketURL String? @db.VarChar(500) + archived Boolean? @default(false) @@map("campaign_applications") }