Skip to content

Commit

Permalink
Implement signing field groups and assigned groups (#273)
Browse files Browse the repository at this point in the history
* Implement signing field groups and assigned groups

* Refactor seeding

* Fix lint

* Fix frontend

* eslint

* Add field type

* fix tsc

* Fix test

* Remove metadata?
  • Loading branch information
elvincheng3 authored Feb 9, 2025
1 parent c43677f commit aa4dd5f
Show file tree
Hide file tree
Showing 68 changed files with 2,720 additions and 3,454 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
Warnings:
- You are about to drop the `Signature` table. If the table is not empty, all the data it contains will be lost.
- You are about to drop the `SignatureField` table. If the table is not empty, all the data it contains will be lost.
*/
-- CreateEnum
CREATE TYPE "SignatureBoxFieldType" AS ENUM ('SIGNATURE', 'CHECKBOX', 'TEXT_FIELD');

-- DropForeignKey
ALTER TABLE "Signature" DROP CONSTRAINT "Signature_employeeId_fkey";

-- DropForeignKey
ALTER TABLE "Signature" DROP CONSTRAINT "Signature_formInstanceId_fkey";

-- DropForeignKey
ALTER TABLE "Signature" DROP CONSTRAINT "Signature_signerDepartmentId_fkey";

-- DropForeignKey
ALTER TABLE "Signature" DROP CONSTRAINT "Signature_signerEmployeeId_fkey";

-- DropForeignKey
ALTER TABLE "Signature" DROP CONSTRAINT "Signature_signerPositionId_fkey";

-- DropForeignKey
ALTER TABLE "Signature" DROP CONSTRAINT "Signature_signingEmployeeId_fkey";

-- DropForeignKey
ALTER TABLE "SignatureField" DROP CONSTRAINT "SignatureField_formTemplateId_fkey";

-- DropForeignKey
ALTER TABLE "_signerEmployeeList" DROP CONSTRAINT "_signerEmployeeList_A_fkey";

-- DropForeignKey
ALTER TABLE "_signerEmployeeList" DROP CONSTRAINT "_signerEmployeeList_B_fkey";

-- DropTable
DROP TABLE "Signature";

-- DropTable
DROP TABLE "SignatureField";

-- CreateTable
CREATE TABLE "FieldGroup" (
"id" UUID NOT NULL,
"name" VARCHAR(255) NOT NULL,
"order" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"formTemplateId" UUID NOT NULL,

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

-- CreateTable
CREATE TABLE "TemplateBox" (
"id" UUID NOT NULL,
"type" "SignatureBoxFieldType" NOT NULL,
"x_coordinate" INTEGER NOT NULL,
"y_coordinate" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"fieldGroupId" UUID NOT NULL,

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

-- CreateTable
CREATE TABLE "AssignedGroup" (
"id" UUID NOT NULL,
"order" INTEGER NOT NULL,
"signed" BOOLEAN NOT NULL DEFAULT false,
"signedDocLink" VARCHAR(255),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"signerPositionId" UUID,
"signerDepartmentId" UUID,
"signerEmployeeId" UUID,
"signingEmployeeId" UUID,
"signerType" "SignerType" NOT NULL,
"formInstanceId" UUID NOT NULL,
"fieldGroupId" UUID NOT NULL,

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

-- CreateTable
CREATE TABLE "InstanceBox" (
"id" UUID NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"assignedGroupId" UUID NOT NULL,
"templateBoxId" UUID NOT NULL,

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

-- AddForeignKey
ALTER TABLE "FieldGroup" ADD CONSTRAINT "FieldGroup_formTemplateId_fkey" FOREIGN KEY ("formTemplateId") REFERENCES "FormTemplate"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "TemplateBox" ADD CONSTRAINT "TemplateBox_fieldGroupId_fkey" FOREIGN KEY ("fieldGroupId") REFERENCES "FieldGroup"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "AssignedGroup" ADD CONSTRAINT "AssignedGroup_signerPositionId_fkey" FOREIGN KEY ("signerPositionId") REFERENCES "Position"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "AssignedGroup" ADD CONSTRAINT "AssignedGroup_signerDepartmentId_fkey" FOREIGN KEY ("signerDepartmentId") REFERENCES "Department"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "AssignedGroup" ADD CONSTRAINT "AssignedGroup_signerEmployeeId_fkey" FOREIGN KEY ("signerEmployeeId") REFERENCES "Employee"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "AssignedGroup" ADD CONSTRAINT "AssignedGroup_signingEmployeeId_fkey" FOREIGN KEY ("signingEmployeeId") REFERENCES "Employee"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "AssignedGroup" ADD CONSTRAINT "AssignedGroup_formInstanceId_fkey" FOREIGN KEY ("formInstanceId") REFERENCES "FormInstance"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "AssignedGroup" ADD CONSTRAINT "AssignedGroup_fieldGroupId_fkey" FOREIGN KEY ("fieldGroupId") REFERENCES "FieldGroup"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "InstanceBox" ADD CONSTRAINT "InstanceBox_assignedGroupId_fkey" FOREIGN KEY ("assignedGroupId") REFERENCES "AssignedGroup"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "InstanceBox" ADD CONSTRAINT "InstanceBox_templateBoxId_fkey" FOREIGN KEY ("templateBoxId") REFERENCES "TemplateBox"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "_signerEmployeeList" ADD CONSTRAINT "_signerEmployeeList_A_fkey" FOREIGN KEY ("A") REFERENCES "AssignedGroup"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "_signerEmployeeList" ADD CONSTRAINT "_signerEmployeeList_B_fkey" FOREIGN KEY ("B") REFERENCES "Employee"("id") ON DELETE CASCADE ON UPDATE CASCADE;
191 changes: 117 additions & 74 deletions apps/server/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ enum SignerType {
USER_LIST
}

enum SignatureBoxFieldType {
SIGNATURE
CHECKBOX
TEXT_FIELD
}

enum EmployeeScope {
BASE_USER
ADMIN
Expand All @@ -30,36 +36,11 @@ model Department {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
signatures Signature[]
assignedGroups AssignedGroup[]
positions Position[]
}

// `Employees` represent the people who work at the MFA.
//
// Each `Employee` corresponds to a user who holds a certain position.
model Employee {
id String @id @default(uuid()) @db.Uuid
firstName String @db.VarChar(255)
lastName String @db.VarChar(255)
email String @unique @db.VarChar(255)
signatureLink String @db.VarChar(255)
scope EmployeeScope @default(BASE_USER)
pswdHash String? @db.VarChar(255)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
refreshToken String? @db.Text()
originatedForms FormInstance[]
position Position @relation(fields: [positionId], references: [id])
positionId String @db.Uuid
signerEmployeeSignatures Signature[] @relation("signerEmployee")
signerEmployeeListSignatures Signature[] @relation("signerEmployeeList")
signingEmployeeSignatures Signature[] @relation("signingEmployee")
}

// `Positions` represent the various positions that employees at the MFA can hold.
model Position {
id String @id @default(uuid()) @db.Uuid
Expand All @@ -68,34 +49,119 @@ model Position {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
signatures Signature[]
employees Employee[]
assignedGroups AssignedGroup[]
employees Employee[]
department Department @relation(fields: [departmentId], references: [id])
departmentId String @db.Uuid
@@unique([name, departmentId])
}

// `SignatureFields` represent each signature field that is required on a given form.
// A field may have a position specified, indicating that when a user creates an
// instance of the corresponding form, the field should default to the specified position.
// `Employees` represent the people who work at the MFA.
//
// Each `Employee` corresponds to a user who holds a certain position.
model Employee {
id String @id @default(uuid()) @db.Uuid
firstName String @db.VarChar(255)
lastName String @db.VarChar(255)
email String @unique @db.VarChar(255)
signatureLink String @db.VarChar(255)
scope EmployeeScope @default(BASE_USER)
pswdHash String? @db.VarChar(255)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
refreshToken String? @db.Text()
originatedForms FormInstance[]
position Position @relation(fields: [positionId], references: [id])
positionId String @db.Uuid
signerEmployeeAssignedGroups AssignedGroup[] @relation("signerEmployee")
signerEmployeeListAssignedGroups AssignedGroup[] @relation("signerEmployeeList")
signingEmployeeAssignedGroup AssignedGroup[] @relation("signingEmployee")
}

// A `FormTemplate` is a reference for a form that is used when creating forms initiated by users.
model FormTemplate {
id String @id @default(uuid()) @db.Uuid
name String @db.VarChar(255)
formDocLink String @db.VarChar(255)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
fieldGroups FieldGroup[]
formInstances FormInstance[]
}

// `FieldGroups` represent a group of signature fields to be assigned together
// that are required on a given form.
// When new form instances are created, new `AssignedGroups` are also created
// based on the `FieldGroups` found on a form template.
//
// Each `SignatureField` also specifies its order on the form it is on.
// `SignatureFields` are used as subdocuments within `FormTemplates`.
model SignatureField {
// Each `FieldGroup` also specifies its order on the form it is on.
// `FieldGroups` are within `FormTemplates`.
model FieldGroup {
id String @id @default(uuid()) @db.Uuid
name String @db.VarChar(255)
order Int @db.Integer
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
formTemplate FormTemplate @relation(fields: [formTemplateId], references: [id])
formTemplateId String @db.Uuid
templateBoxes TemplateBox[]
assignedGroups AssignedGroup[]
}

// `TemplateBox` represent the actual signature boxes that are to be filled by the employees.
model TemplateBox {
id String @id @default(uuid()) @db.Uuid
type SignatureBoxFieldType
x_coordinate Int @db.Integer
y_coordinate Int @db.Integer
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
fieldGroup FieldGroup @relation(fields: [fieldGroupId], references: [id])
fieldGroupId String @db.Uuid
InstanceBox InstanceBox[]
}

// `FormInstances` represent instances of forms created by employees.
//
// They are created based on a given `FormTemplate`, and contain a
// list of `Signatures` that are to be filled by the requested employees.
//
// A `FormInstance` should be marked completed when all of its signatures
// have been collected and marked as completed.
model FormInstance {
id String @id @default(uuid()) @db.Uuid
name String @db.VarChar(255)
formDocLink String @db.VarChar(255)
completed Boolean @default(false)
markedCompleted Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
completedAt DateTime?
markedCompletedAt DateTime?
assignedGroups AssignedGroup[]
originator Employee @relation(fields: [originatorId], references: [id])
originatorId String @db.Uuid
formTemplate FormTemplate @relation(fields: [formTemplateId], references: [id])
formTemplateId String @db.Uuid
}

// `Signatures` represent the signatures required on a form. Each signature has a
// specified signer and its corresponding status which indicates if it has been signed.
// `AssignedGroups` represent groups of signatures required on a form to be signed by a
// specific employee, position, department, or an employee from a list. Each `AssignedGroup` has a
// corresponding status which indicates if it has been signed.
//
// `AssignedGroups` are derived from `FieldGroups` on a `FormTemplate` and are
// created when a new form instance is created. Each `AssignedGroup` has corresponding `InstanceBoxes`
// which are the actual signature boxes that are to be filled by the employees.
//
// A `Signature` will also carry over its order from the original `FormTemplate` order
// from which the `FormInstance` that the `Signature` belongs to was derived. If a `Signature`
Expand All @@ -104,7 +170,7 @@ model SignatureField {
//
// The signer position and the user signed by are populated when the signature has been
// completed, and are derived from the person who signed at that moment in time.
model Signature {
model AssignedGroup {
id String @id @default(uuid()) @db.Uuid
order Int @db.Integer
signed Boolean @default(false)
Expand All @@ -123,44 +189,21 @@ model Signature {
signingEmployeeId String? @db.Uuid
signerType SignerType
formInstance FormInstance @relation(fields: [formInstanceId], references: [id])
formInstanceId String @db.Uuid
}

// `FormInstances` represent instances of forms created by employees.
//
// They are created based on a given `FormTemplate`, and contain a
// list of `Signatures` that are to be filled by the requested employees.
//
// A `FormInstance` should be marked completed when all of its signatures
// have been collected and marked as completed.
model FormInstance {
id String @id @default(uuid()) @db.Uuid
name String @db.VarChar(255)
formDocLink String @db.VarChar(255)
completed Boolean @default(false)
markedCompleted Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
completedAt DateTime?
markedCompletedAt DateTime?
signatures Signature[]
originator Employee @relation(fields: [originatorId], references: [id])
originatorId String @db.Uuid
formTemplate FormTemplate @relation(fields: [formTemplateId], references: [id])
formTemplateId String @db.Uuid
formInstance FormInstance @relation(fields: [formInstanceId], references: [id])
formInstanceId String @db.Uuid
instanceBoxes InstanceBox[]
fieldGroup FieldGroup @relation(fields: [fieldGroupId], references: [id])
fieldGroupId String @db.Uuid
}

// A `FormTemplate` is a reference for a form that is used when creating forms initiated by users.
model FormTemplate {
id String @id @default(uuid()) @db.Uuid
name String @db.VarChar(255)
formDocLink String @db.VarChar(255)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// `InstanceBox` represent the signature boxes on an instantiated form that are to be filled by the employees.
model InstanceBox {
id String @id @default(uuid()) @db.Uuid
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
signatureFields SignatureField[]
formInstances FormInstance[]
assignedGroup AssignedGroup @relation(fields: [assignedGroupId], references: [id])
assignedGroupId String @db.Uuid
templateBox TemplateBox @relation(fields: [templateBoxId], references: [id])
templateBoxId String @db.Uuid
}
Loading

0 comments on commit aa4dd5f

Please sign in to comment.