Skip to content

Commit

Permalink
feat(prisma): Add CampaignApplication model (podkrepi-bg#643)
Browse files Browse the repository at this point in the history
- issue 1843 - start with adding the required tables in the db model
 - why separate object
    - the campaign application will contain sensitive and personal documents that should not be made public
    - the lifecycle of the CampaignApplication is dictated by a process of ensuring the potential campaign is transparent and legitimate
  • Loading branch information
gparlakov committed Jun 30, 2024
1 parent 5fabc1e commit e86bd01
Show file tree
Hide file tree
Showing 16 changed files with 315 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export class ConnectCampaignApplicationDto {
id?: string
organizerEmail?: string
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { CampaignTypeCategory } from '@prisma/client'
import { ApiProperty } from '@nestjs/swagger'

export class CreateCampaignApplicationDto {
organizerName: string
organizerEmail?: string
organizerPhone?: string
beneficiary: string
organizerBeneficiaryRel: string
campaignName: string
goal: string
history?: string
amount: string
description?: string
campaignGuarantee?: string
otherFinanceSources?: string
otherNotes?: string
@ApiProperty({ enum: CampaignTypeCategory })
category?: CampaignTypeCategory
ticketURL?: string
archived?: boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './connect-campaignApplication.dto'
export * from './create-campaignApplication.dto'
export * from './update-campaignApplication.dto'
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { CampaignTypeCategory } from '@prisma/client'
import { ApiProperty } from '@nestjs/swagger'

export class UpdateCampaignApplicationDto {
organizerName?: string
organizerEmail?: string
organizerPhone?: string
beneficiary?: string
organizerBeneficiaryRel?: string
campaignName?: string
goal?: string
history?: string
amount?: string
description?: string
campaignGuarantee?: string
otherFinanceSources?: string
otherNotes?: string
@ApiProperty({ enum: CampaignTypeCategory })
category?: CampaignTypeCategory
ticketURL?: string
archived?: boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { CampaignApplicationState, CampaignTypeCategory } from '@prisma/client'
import { Organizer } from '../../organizer/entities/organizer.entity'
import { CampaignApplicationFile } from '../../campaignApplicationFile/entities/campaignApplicationFile.entity'

export class CampaignApplication {
id: string
createdAt: Date
updatedAt: Date | null
organizerId: string | null
organizer?: Organizer | null
organizerName: string
organizerEmail: string | null
organizerPhone: string | null
beneficiary: string
organizerBeneficiaryRel: string
campaignName: string
goal: string
history: string | null
amount: string
description: string | null
documents?: CampaignApplicationFile[]
campaignGuarantee: string | null
otherFinanceSources: string | null
otherNotes: string | null
state: CampaignApplicationState
category: CampaignTypeCategory | null
ticketURL: string | null
archived: boolean | null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './campaignApplication.entity'
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export class ConnectCampaignApplicationFileDto {
id: string
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { CampaignApplicationFileRole } from '@prisma/client'
import { ApiProperty } from '@nestjs/swagger'

export class CreateCampaignApplicationFileDto {
filename: string
campaignApplicationId: string
personId: string
mimetype: string
@ApiProperty({ enum: CampaignApplicationFileRole })
role: CampaignApplicationFileRole
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './connect-campaignApplicationFile.dto'
export * from './create-campaignApplicationFile.dto'
export * from './update-campaignApplicationFile.dto'
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { CampaignApplicationFileRole } from '@prisma/client'
import { ApiProperty } from '@nestjs/swagger'

export class UpdateCampaignApplicationFileDto {
filename?: string
campaignApplicationId?: string
personId?: string
mimetype?: string
@ApiProperty({ enum: CampaignApplicationFileRole })
role?: CampaignApplicationFileRole
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { CampaignApplicationFileRole } from '@prisma/client'
import { CampaignApplication } from '../../campaignApplication/entities/campaignApplication.entity'

export class CampaignApplicationFile {
id: string
filename: string
campaignApplicationId: string
personId: string
mimetype: string
role: CampaignApplicationFileRole
campaignApplication?: CampaignApplication[]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './campaignApplicationFile.entity'
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Person } from '../../person/entities/person.entity'
import { Beneficiary } from '../../beneficiary/entities/beneficiary.entity'
import { Campaign } from '../../campaign/entities/campaign.entity'
import { CampaignApplication } from '../../campaignApplication/entities/campaignApplication.entity'

export class Organizer {
id: string
Expand All @@ -10,4 +11,5 @@ export class Organizer {
person?: Person
beneficiaries?: Beneficiary[]
campaigns?: Campaign[]
campaignApplication?: CampaignApplication[]
}
68 changes: 68 additions & 0 deletions migrations/20240615135940_add_campaign_application/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
-- CreateEnum
CREATE TYPE "CampaignApplicationState" AS ENUM ('review', 'requestInfo', 'forCommitteeReview', 'approved', 'denied', 'abandoned');

-- CreateEnum
CREATE TYPE "CampaignApplicationFileRole" AS ENUM ('document', 'image');

-- CreateTable
CREATE TABLE "campaign_applications" (
"id" UUID NOT NULL DEFAULT gen_random_uuid(),
"created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ(6),
"organizer_id" UUID NOT NULL,
"organizer_name" VARCHAR(200) NOT NULL,
"organizer_email" CITEXT,
"organizer_phone" VARCHAR(50),
"beneficiary" VARCHAR(1500) NOT NULL,
"organizer_beneficiary_relationship" TEXT NOT NULL,
"campaign_name" VARCHAR(200) NOT NULL,
"goal" TEXT NOT NULL,
"history" TEXT,
"amount" VARCHAR(200) NOT NULL,
"description" TEXT,
"campaignGuarantee" VARCHAR(500),
"otherFinanceSources" TEXT,
"otherNotes" TEXT,
"state" "CampaignApplicationState" NOT NULL DEFAULT 'review',
"category" "campaign_type_category" DEFAULT 'others',
"ticketURL" VARCHAR(500),
"archived" BOOLEAN DEFAULT false,

CONSTRAINT "campaign_applications_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "campaign_application_files" (
"id" UUID NOT NULL DEFAULT gen_random_uuid(),
"filename" VARCHAR(200) NOT NULL,
"campaign_application_id" UUID NOT NULL,
"person_id" UUID NOT NULL,
"mimetype" VARCHAR(100) NOT NULL,
"role" "CampaignApplicationFileRole" NOT NULL,

CONSTRAINT "campaign_application_files_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "_CampaignApplicationToCampaignApplicationFile" (
"A" UUID NOT NULL,
"B" UUID NOT NULL
);

-- CreateIndex
CREATE UNIQUE INDEX "campaign_applications_organizer_email_key" ON "campaign_applications"("organizer_email");

-- CreateIndex
CREATE UNIQUE INDEX "_CampaignApplicationToCampaignApplicationFile_AB_unique" ON "_CampaignApplicationToCampaignApplicationFile"("A", "B");

-- CreateIndex
CREATE INDEX "_CampaignApplicationToCampaignApplicationFile_B_index" ON "_CampaignApplicationToCampaignApplicationFile"("B");

-- AddForeignKey
ALTER TABLE "campaign_applications" ADD CONSTRAINT "campaign_applications_organizer_id_fkey" FOREIGN KEY ("organizer_id") REFERENCES "organizers"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "_CampaignApplicationToCampaignApplicationFile" ADD CONSTRAINT "_CampaignApplicationToCampaignApplicationFile_A_fkey" FOREIGN KEY ("A") REFERENCES "campaign_applications"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "_CampaignApplicationToCampaignApplicationFile" ADD CONSTRAINT "_CampaignApplicationToCampaignApplicationFile_B_fkey" FOREIGN KEY ("B") REFERENCES "campaign_application_files"("id") ON DELETE CASCADE ON UPDATE CASCADE;
55 changes: 54 additions & 1 deletion podkrepi.dbml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ Table organizers {
person people [not null]
beneficiaries beneficiaries [not null]
campaigns campaigns [not null]
campaignApplication campaign_applications [not null]

Note: 'Organizer is the person who manages the campaign on behalf of the Beneficiary'
}
Expand Down Expand Up @@ -575,6 +576,42 @@ Table bank_transactions_files {
personId String [not null]
}

Table campaign_applications {
id String [pk]
createdAt DateTime [default: `now()`, not null]
updatedAt DateTime
organizerId String [not null]
organizer organizers
organizerName String [not null]
organizerEmail String [unique]
organizerPhone String
beneficiary String [not null]
organizerBeneficiaryRel String [not null]
campaignName String [not null]
goal String [not null]
history String
amount String [not null]
description String
documents campaign_application_files [not null]
campaignGuarantee String
otherFinanceSources String
otherNotes String
state CampaignApplicationState [not null, default: 'review']
category CampaignTypeCategory [default: 'others']
ticketURL String
archived Boolean [default: false]
}

Table campaign_application_files {
id String [pk]
filename String [not null]
campaignApplicationId String [not null]
personId String [not null]
mimetype String [not null]
role CampaignApplicationFileRole [not null]
campaignApplication campaign_applications [not null]
}

Enum BeneficiaryType {
individual
company
Expand Down Expand Up @@ -819,6 +856,20 @@ Enum EmailType {
raised100
}

Enum CampaignApplicationState {
review
requestInfo
forCommitteeReview
approved
denied
abandoned
}

Enum CampaignApplicationFileRole {
document
image
}

Ref: people.companyId - companies.id

Ref: affiliates.companyId - companies.id
Expand Down Expand Up @@ -933,4 +984,6 @@ Ref: expense_files.expenseId > expenses.id

Ref: expense_files.uploaderId > people.id

Ref: documents.ownerId > people.id
Ref: documents.ownerId > people.id

Ref: campaign_applications.organizerId > organizers.id
76 changes: 69 additions & 7 deletions schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,14 @@ model Affiliate {

/// Organizer is the person who manages the campaign on behalf of the Beneficiary
model Organizer {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
personId String @unique @map("person_id") @db.Uuid
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6)
person Person @relation(fields: [personId], references: [id])
beneficiaries Beneficiary[]
campaigns Campaign[]
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
personId String @unique @map("person_id") @db.Uuid
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6)
person Person @relation(fields: [personId], references: [id])
beneficiaries Beneficiary[]
campaigns Campaign[]
campaignApplication CampaignApplication[]
@@map("organizers")
}
Expand Down Expand Up @@ -1004,3 +1005,64 @@ enum EmailType {
@@map("email_type")
}

/// 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)
// organizer editable fields
// need to be logged in to create a campaign application
organizerId String @map("organizer_id") @db.Uuid
organizer Organizer? @relation(fields: [organizerId], references: [id])
organizerName String @map("organizer_name") @db.VarChar(200)
organizerEmail String? @unique @map("organizer_email") @db.Citext
organizerPhone String? @map("organizer_phone") @db.VarChar(50)
// will create a beneficiary after approve of campaign application
beneficiary String @db.VarChar(1500)
organizerBeneficiaryRel String @map("organizer_beneficiary_relationship") @db.Text
campaignName String @map("campaign_name") @db.VarChar(200)
goal String @db.Text
history String? @db.Text
amount String @db.VarChar(200)
description String? @db.Text
documents CampaignApplicationFile[]
campaignGuarantee String? @db.VarChar(500)
otherFinanceSources String? @db.Text
otherNotes String? @db.Text
// operator editable fields
state CampaignApplicationState @default(review)
category CampaignTypeCategory? @default(others)
ticketURL String? @db.VarChar(500)
archived Boolean? @default(false)
@@map("campaign_applications")
}

enum CampaignApplicationState {
review
requestInfo
forCommitteeReview
approved
denied
abandoned
}

model CampaignApplicationFile {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
filename String @db.VarChar(200)
campaignApplicationId String @map("campaign_application_id") @db.Uuid
personId String @map("person_id") @db.Uuid
mimetype String @db.VarChar(100)
role CampaignApplicationFileRole
campaignApplication CampaignApplication[]
@@map("campaign_application_files")
}

enum CampaignApplicationFileRole {
document
image
}

0 comments on commit e86bd01

Please sign in to comment.