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

feat: add Subrecipient and Project to the schema #42

Merged
merged 2 commits into from
Dec 10, 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
-- CreateTable
CREATE TABLE "Subrecipient" (
"id" SERIAL NOT NULL,
"name" TEXT NOT NULL,
"organizationId" INTEGER NOT NULL,
"startDate" DATE NOT NULL,
"endDate" DATE NOT NULL,
"certifiedAt" TIMESTAMPTZ(6),
"certifiedById" INTEGER,
"originationUploadId" INTEGER NOT NULL,
"createdAt" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(6) NOT NULL,

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

-- CreateTable
CREATE TABLE "Project" (
"id" SERIAL NOT NULL,
"code" TEXT NOT NULL,
"name" TEXT NOT NULL,
"agencyId" INTEGER NOT NULL,
"organizationId" INTEGER NOT NULL,
"status" TEXT NOT NULL,
"description" TEXT NOT NULL,
"originationPeriodId" INTEGER NOT NULL,
"createdAt" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(6) NOT NULL,

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

-- AddForeignKey
ALTER TABLE "Subrecipient" ADD CONSTRAINT "Subrecipient_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Subrecipient" ADD CONSTRAINT "Subrecipient_certifiedById_fkey" FOREIGN KEY ("certifiedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Subrecipient" ADD CONSTRAINT "Subrecipient_originationUploadId_fkey" FOREIGN KEY ("originationUploadId") REFERENCES "Upload"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Project" ADD CONSTRAINT "Project_agencyId_fkey" FOREIGN KEY ("agencyId") REFERENCES "Agency"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Project" ADD CONSTRAINT "Project_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Project" ADD CONSTRAINT "Project_originationPeriodId_fkey" FOREIGN KEY ("originationPeriodId") REFERENCES "ReportingPeriod"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
38 changes: 38 additions & 0 deletions api/db/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ model Agency {
users User[]
uploads Upload[]
uploadValidations UploadValidation[]
projects Project[]
}

model Organization {
Expand All @@ -28,6 +29,8 @@ model Organization {
name String
uploads Upload[]
uploadValidations UploadValidation[]
subrecipients Subrecipient[]
projects Project[]
}

model User {
Expand All @@ -46,6 +49,7 @@ model User {
uploaded Upload[]
validated UploadValidation[] @relation("ValidatedUploads")
invalidated UploadValidation[] @relation("InvalidatedUploads")
subrecipients Subrecipient[]
}

model Role {
Expand Down Expand Up @@ -95,6 +99,7 @@ model ReportingPeriod {
createdAt DateTime @default(now()) @db.Timestamptz(6)
updatedAt DateTime @db.Timestamptz(6)
uploads Upload[]
projects Project[]
}

model ExpenditureCategory {
Expand Down Expand Up @@ -122,6 +127,7 @@ model Upload {
createdAt DateTime @default(now()) @db.Timestamptz(6)
updatedAt DateTime @db.Timestamptz(6)
validations UploadValidation[]
subrecipients Subrecipient[]
}

model UploadValidation {
Expand All @@ -144,4 +150,36 @@ model UploadValidation {
invalidatedBy User? @relation("InvalidatedUploads", fields: [invalidatedById], references: [id])
createdAt DateTime @default(now()) @db.Timestamptz(6)
updatedAt DateTime @db.Timestamptz(6)
}

model Subrecipient {
id Int @id @default(autoincrement())
name String
organizationId Int
organization Organization @relation(fields: [organizationId], references: [id])
startDate DateTime @db.Date
endDate DateTime @db.Date
certifiedAt DateTime? @db.Timestamptz(6)
certifiedById Int?
certifiedBy User? @relation(fields: [certifiedById], references: [id])
originationUploadId Int
originationUpload Upload @relation(fields: [originationUploadId], references: [id])
createdAt DateTime @default(now()) @db.Timestamptz(6)
updatedAt DateTime @db.Timestamptz(6)
}

model Project {
id Int @id @default(autoincrement())
code String
name String
agencyId Int
agency Agency @relation(fields: [agencyId], references: [id])
organizationId Int
organization Organization @relation(fields: [organizationId], references: [id])
status String
description String
originationPeriodId Int
originationPeriod ReportingPeriod @relation(fields: [originationPeriodId], references: [id])
createdAt DateTime @default(now()) @db.Timestamptz(6)
updatedAt DateTime @db.Timestamptz(6)
}
48 changes: 48 additions & 0 deletions api/src/graphql/projects.sdl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
export const schema = gql`
type Project {
id: Int!
code: String!
name: String!
agencyId: Int!
agency: Agency!
organizationId: Int!
organization: Organization!
status: String!
description: String!
originationPeriodId: Int!
originationPeriod: ReportingPeriod!
createdAt: DateTime!
updatedAt: DateTime!
}

type Query {
projects: [Project!]! @requireAuth
project(id: Int!): Project @requireAuth
}

input CreateProjectInput {
code: String!
name: String!
agencyId: Int!
organizationId: Int!
status: String!
description: String!
originationPeriodId: Int!
}

input UpdateProjectInput {
code: String
name: String
agencyId: Int
organizationId: Int
status: String
description: String
originationPeriodId: Int
}

type Mutation {
createProject(input: CreateProjectInput!): Project! @requireAuth
updateProject(id: Int!, input: UpdateProjectInput!): Project! @requireAuth
deleteProject(id: Int!): Project! @requireAuth
}
`
52 changes: 52 additions & 0 deletions api/src/graphql/subrecipients.sdl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
export const schema = gql`
type Subrecipient {
id: Int!
name: String!
organizationId: Int!
organization: Organization!
startDate: DateTime!
endDate: DateTime!
certifiedAt: DateTime
certifiedById: Int
certifiedBy: User
originationUploadId: Int!
originationUpload: Upload!
createdAt: DateTime!
updatedAt: DateTime!
}

type Query {
subrecipients: [Subrecipient!]! @requireAuth
subrecipient(id: Int!): Subrecipient @requireAuth
}

input CreateSubrecipientInput {
name: String!
organizationId: Int!
startDate: DateTime!
endDate: DateTime!
certifiedAt: DateTime
certifiedById: Int
originationUploadId: Int!
}

input UpdateSubrecipientInput {
name: String
organizationId: Int
startDate: DateTime
endDate: DateTime
certifiedAt: DateTime
certifiedById: Int
originationUploadId: Int
}

type Mutation {
createSubrecipient(input: CreateSubrecipientInput!): Subrecipient!
@requireAuth
updateSubrecipient(
id: Int!
input: UpdateSubrecipientInput!
): Subrecipient! @requireAuth
deleteSubrecipient(id: Int!): Subrecipient! @requireAuth
}
`
79 changes: 79 additions & 0 deletions api/src/services/projects/projects.scenarios.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import type { Prisma, Project } from '@prisma/client'

Check failure on line 1 in api/src/services/projects/projects.scenarios.ts

View workflow job for this annotation

GitHub Actions / qa / Lint JavaScript

There should be at least one empty line between import groups
import type { ScenarioData } from '@redwoodjs/testing/api'

export const standard = defineScenario<Prisma.ProjectCreateArgs>({
project: {
one: {
data: {
code: 'String',
name: 'String',
status: 'String',
description: 'String',
updatedAt: '2023-12-09T14:50:29.322Z',
agency: { create: { name: 'String', code: 'String' } },
organization: { create: { name: 'String' } },
originationPeriod: {
create: {
name: 'String',
startDate: '2023-12-09T14:50:29.322Z',
endDate: '2023-12-09T14:50:29.322Z',
updatedAt: '2023-12-09T14:50:29.322Z',
inputTemplate: {
create: {
name: 'String',
version: 'String',
effectiveDate: '2023-12-09T14:50:29.322Z',
updatedAt: '2023-12-09T14:50:29.322Z',
},
},
outputTemplate: {
create: {
name: 'String',
version: 'String',
effectiveDate: '2023-12-09T14:50:29.322Z',
updatedAt: '2023-12-09T14:50:29.322Z',
},
},
},
},
},
},
two: {
data: {
code: 'String',
name: 'String',
status: 'String',
description: 'String',
updatedAt: '2023-12-09T14:50:29.322Z',
agency: { create: { name: 'String', code: 'String' } },
organization: { create: { name: 'String' } },
originationPeriod: {
create: {
name: 'String',
startDate: '2023-12-09T14:50:29.322Z',
endDate: '2023-12-09T14:50:29.322Z',
updatedAt: '2023-12-09T14:50:29.322Z',
inputTemplate: {
create: {
name: 'String',
version: 'String',
effectiveDate: '2023-12-09T14:50:29.322Z',
updatedAt: '2023-12-09T14:50:29.322Z',
},
},
outputTemplate: {
create: {
name: 'String',
version: 'String',
effectiveDate: '2023-12-09T14:50:29.322Z',
updatedAt: '2023-12-09T14:50:29.322Z',
},
},
},
},
},
},
},
})

export type StandardScenario = ScenarioData<Project, 'project'>
75 changes: 75 additions & 0 deletions api/src/services/projects/projects.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import type { Project } from '@prisma/client'

import {
projects,
project,
createProject,
updateProject,
deleteProject,
} from './projects'
import type { StandardScenario } from './projects.scenarios'

// Generated boilerplate tests do not account for all circumstances
// and can fail without adjustments, e.g. Float.
// Please refer to the RedwoodJS Testing Docs:
// https://redwoodjs.com/docs/testing#testing-services
// https://redwoodjs.com/docs/testing#jest-expect-type-considerations

describe('projects', () => {
scenario('returns all projects', async (scenario: StandardScenario) => {
const result = await projects()

expect(result.length).toEqual(Object.keys(scenario.project).length)
})

scenario('returns a single project', async (scenario: StandardScenario) => {
const result = await project({ id: scenario.project.one.id })

expect(result).toEqual(scenario.project.one)
})

scenario('creates a project', async (scenario: StandardScenario) => {
const result = await createProject({
input: {
code: 'String',
name: 'String',
agencyId: scenario.project.two.agencyId,
organizationId: scenario.project.two.organizationId,
status: 'String',
description: 'String',
originationPeriodId: scenario.project.two.originationPeriodId,
updatedAt: '2023-12-09T14:50:29.223Z',
},
})

expect(result.code).toEqual('String')
expect(result.name).toEqual('String')
expect(result.agencyId).toEqual(scenario.project.two.agencyId)
expect(result.organizationId).toEqual(scenario.project.two.organizationId)
expect(result.status).toEqual('String')
expect(result.description).toEqual('String')
expect(result.originationPeriodId).toEqual(
scenario.project.two.originationPeriodId
)
expect(result.updatedAt).toEqual(new Date('2023-12-09T14:50:29.223Z'))
})

scenario('updates a project', async (scenario: StandardScenario) => {
const original = (await project({ id: scenario.project.one.id })) as Project
const result = await updateProject({
id: original.id,
input: { code: 'String2' },
})

expect(result.code).toEqual('String2')
})

scenario('deletes a project', async (scenario: StandardScenario) => {
const original = (await deleteProject({
id: scenario.project.one.id,
})) as Project
const result = await project({ id: original.id })

expect(result).toEqual(null)
})
})
Loading
Loading