From 6ef89aa646605caf0863c7f1881dbcc1a5f684fe Mon Sep 17 00:00:00 2001 From: Leo Huang <77544794+leogjhuang@users.noreply.github.com> Date: Sun, 10 Dec 2023 23:04:59 -0700 Subject: [PATCH] [Release] Version 0.2.0 (#337) * [Improvement] Update donation receipt spacing (#326) * Fix validation schema for other gender field (#327) * Adjust schema to evaluate date at validation time (#328) * [Fix] Make replacement requests clearer (#325) * Add new contributor to seeding script (#330) * ignore the .yarn file for > v2.0.0 (#331) * [Misc] Create initial baseline migration file (#333) * [Doc] Update README with prisma migrate deploy command (#334) * [Fix] Fix replacement request otherGender and lostTimestamp form validations (#335) * [Misc] Add holiday closure banner (#336) --- .gitignore | 1 + README.md | 2 +- .../permit-holder-information/Card.tsx | 2 - .../requests/reason-for-replacement/Form.tsx | 48 +- lib/applications/resolvers.ts | 2 +- lib/applications/validation.ts | 20 +- lib/invoices/utils.ts | 114 +++-- lib/physicians/validation.ts | 16 +- pages/index.tsx | 8 +- prisma/dev-seed-utils/employees.ts | 5 + .../20231123031908_init/migration.sql | 440 ++++++++++++++++++ prisma/migrations/migration_lock.toml | 3 + 12 files changed, 579 insertions(+), 82 deletions(-) create mode 100644 prisma/migrations/20231123031908_init/migration.sql create mode 100644 prisma/migrations/migration_lock.toml diff --git a/.gitignore b/.gitignore index 5571467e..8d71df35 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # dependencies /node_modules +/.yarn* /.pnp .pnp.js diff --git a/README.md b/README.md index 1b65755f..87b24bcf 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ yarn dev 3. Deploy prisma schema ```bash -npx prisma db push +npx prisma migrate deploy ``` 4. Seed database diff --git a/components/admin/requests/permit-holder-information/Card.tsx b/components/admin/requests/permit-holder-information/Card.tsx index a64b95c5..2f0aee3a 100644 --- a/components/admin/requests/permit-holder-information/Card.tsx +++ b/components/admin/requests/permit-holder-information/Card.tsx @@ -94,8 +94,6 @@ const Card: FC = props => { | null; if (type === 'NEW') { const validatedData = await permitHolderInformationSchema.validate(permitHolderData); - // TODO: Remove this once schema is updated - validatedData.otherGender = ''; ({ data } = await updateNewPermitHolderInformation({ variables: { input: { id: applicationId, ...validatedData } }, diff --git a/components/admin/requests/reason-for-replacement/Form.tsx b/components/admin/requests/reason-for-replacement/Form.tsx index c3dfe86b..d2d6f316 100644 --- a/components/admin/requests/reason-for-replacement/Form.tsx +++ b/components/admin/requests/reason-for-replacement/Form.tsx @@ -13,9 +13,10 @@ import NumberField from '@components/form/NumberField'; import RadioGroupField from '@components/form/RadioGroupField'; import TextArea from '@components/form/TextAreaField'; import TextField from '@components/form/TextField'; -import { formatDate } from '@lib/utils/date'; // Date formatter util +import { formatDateYYYYMMDDLocal } from '@lib/utils/date'; // Date formatter util import { ReasonForReplacementFormData } from '@tools/admin/requests/reason-for-replacement'; import { useFormikContext } from 'formik'; +import moment from 'moment'; type ReasonForReplacementProps = { readonly reasonForReplacement: ReasonForReplacementFormData; @@ -36,9 +37,30 @@ export default function ReasonForReplacementForm({ - {'Lost'} - {'Stolen'} - {'Other'} + { + setFieldValue('paymentInformation.processingFee', '31'); + }} + > + {'Lost'} + + { + setFieldValue('paymentInformation.processingFee', '31'); + }} + > + {'Stolen'} + + { + setFieldValue('paymentInformation.processingFee', '0'); + }} + > + {'Mail Lost'} + @@ -54,7 +76,10 @@ export default function ReasonForReplacementForm({ required value={ reasonForReplacement.lostTimestamp - ? formatDate(new Date(reasonForReplacement.lostTimestamp), true) + ? // lostTimestamp is the date in the LOCAL TIMEZONE, in YYYY-MM-DD format + // use moment to get Date object in local timezone as + // Date constructor defaults to UTC when given YYYY-MM-DD string + formatDateYYYYMMDDLocal(moment(reasonForReplacement.lostTimestamp).toDate()) : '' } /> @@ -70,18 +95,21 @@ export default function ReasonForReplacementForm({ { - const updatedlostTimestamp = new Date(reasonForReplacement.lostTimestamp); - updatedlostTimestamp.setHours(parseInt(event.target.value.substring(0, 2))); - updatedlostTimestamp.setMinutes(parseInt(event.target.value.substring(3, 5))); + const updatedlostTimestamp = moment(reasonForReplacement.lostTimestamp); + updatedlostTimestamp.set('hour', parseInt(event.target.value.substring(0, 2))); + updatedlostTimestamp.set('minute', parseInt(event.target.value.substring(3, 5))); - setFieldValue('reasonForReplacement.lostTimestamp', updatedlostTimestamp); + setFieldValue( + 'reasonForReplacement.lostTimestamp', + updatedlostTimestamp.toDate() + ); }} /> {'Example: HH:MM AM/PM'} diff --git a/lib/applications/resolvers.ts b/lib/applications/resolvers.ts index 10d5e1c7..fe11116d 100644 --- a/lib/applications/resolvers.ts +++ b/lib/applications/resolvers.ts @@ -1192,7 +1192,7 @@ export const updateNewApplicationGeneralInformation: Resolver< const { input } = args; try { - await requestPermitHolderInformationMutationSchema.validate(input); + await requestPermitHolderInformationMutationSchema.validate({ type: 'NEW', ...input }); } catch (err) { if (err instanceof ValidationError) { return { diff --git a/lib/applications/validation.ts b/lib/applications/validation.ts index b3b93581..bc0e4447 100644 --- a/lib/applications/validation.ts +++ b/lib/applications/validation.ts @@ -8,12 +8,13 @@ import { requestPhysicianInformationSchema, } from '@lib/physicians/validation'; import { PaymentType, Province, ReasonForReplacement, ShopifyPaymentStatus } from '@prisma/client'; -import { bool, date, mixed, number, object, string } from 'yup'; +import { bool, date, lazy, mixed, number, object, string } from 'yup'; import { AccessibleConvertedVanLoadingMethod, RequiresWiderParkingSpaceReason, } from '@lib/graphql/types'; import { monetaryValueRegex, phoneNumberRegex, postalCodeRegex } from '@lib/utils/validation'; +import moment from 'moment'; /** * Additional Questions form validation schema @@ -215,13 +216,16 @@ export const reasonForReplacementFormSchema = object({ .default(null) .when('reason', { is: 'LOST', - then: date() - .transform((_value, originalValue) => { - return new Date(originalValue); - }) - .typeError('Please enter date APP was lost') - .max(new Date(), 'Date must be in the past') - .required('Please enter date APP was lost'), + then: lazy(() => + date() + .transform((_value, originalValue) => { + // convert YYYY-MM-DD string in local timezone to a Date object in UTC + return moment.utc(moment(originalValue).toDate()).toDate(); + }) + .typeError('Please enter date APP was lost') + .max(new Date(), 'Date must be in the past') + .required('Please enter date APP was lost') + ), otherwise: date() .transform(_ => null) .nullable(), diff --git a/lib/invoices/utils.ts b/lib/invoices/utils.ts index b803a424..dad788b3 100644 --- a/lib/invoices/utils.ts +++ b/lib/invoices/utils.ts @@ -404,57 +404,74 @@ const donationPdfDefinition = (input: { pageBreak: 'before', text: [ { text: 'RICHMOND CENTRE FOR DISABILITY', style: 'header' }, - '\n\n', + '\n', { text: `Official Donation Receipt for Income Tax Purposes - ${dateIssued.getFullYear()}`, - style: 'subheaderDonation', + style: 'subheader', }, ], }, + { columns: [ { - table: { - heights: 20, - body: [ - [ - { text: 'Tax Receipt #:' }, - `PPD_${dateIssued.getFullYear()}${dateIssued.getMonth()}${dateIssued.getDate()}_${appNumber}`, - ], - [ - { text: 'Donated by:' }, - { - text: [ - `${applicantName}\n`, - `${address.addressLine2 ? `${address.addressLine2} - ` : ''}${ - address.addressLine1 - }\n`, - `${address.city} ${address.province} ${formatPostalCode(address.postalCode)}`, + stack: [ + { + table: { + heights: 18, + body: [ + [ + { text: 'Tax Receipt #:' }, + `PPD_${dateIssued.getFullYear()}${dateIssued.getMonth()}${dateIssued.getDate()}_${appNumber}`, ], - fontSize: 12, - lineHeight: 1.5, - }, - ], - [{ text: '' }, ''], - [{ text: '' }, ''], - [{ text: '' }, ''], - [{ text: 'Email:' }, nonNullEmail], - [{ text: 'Date Receipt Issued:' }, formatDateYYYYMMDD(dateIssued)], - [{ text: 'Location Receipt Issued:' }, 'Richmond, BC'], - [{ text: 'Authorized Signature:' }, { image: 'signature', width: 150 }], - ], - }, - layout: 'noBorders', - margin: [0, 0, 20, 0], + [ + { text: 'Donated by:' }, + { + text: [ + `${applicantName}\n`, + `${address.addressLine2 ? `${address.addressLine2} - ` : ''}${ + address.addressLine1 + }\n`, + `${address.city} ${address.province} ${formatPostalCode( + address.postalCode + )}`, + ], + lineHeight: 1.4, + }, + ], + ], + }, + layout: 'noBorders', + margin: [0, 0, 0, 40], + }, + { + text: [`Email: ${nonNullEmail}`], + margin: [0, 0, 0, 8], + }, + { + table: { + heights: 18, + body: [ + [{ text: 'Date Receipt Issued:' }, formatDateYYYYMMDD(dateIssued)], + [{ text: 'Location Receipt Issued:' }, 'Richmond, BC'], + ], + }, + margin: [0, 0, 0, 15], + layout: 'noBorders', + }, + { image: 'signature', width: 200, margin: [0, 0, 0, 5] }, + { text: 'Authorized Signature:' }, + ], }, + { table: { - heights: 20, + heights: 18, body: [ [{ text: 'Date Donation Received:' }, formatDateYYYYMMDD(dateDonationRecevied)], [{ text: 'Donor Number:' }, `P${appNumber}`], [{ text: 'Total Amount:' }, `$${donationAmount.toString()}`], - [{ text: 'Value of Product / Services:' }, ''], + [{ text: 'Value of Product / Services:\n\n' }, ''], [ { text: 'Eligible Amount of Donation for Tax Purposes:' }, `$${donationAmount.toString()}`, @@ -469,26 +486,26 @@ const donationPdfDefinition = (input: { 'Address of Appraiser:\n\n', ], }, - { image: 'stamp', width: 85 }, + { image: 'stamp', width: 80 }, ], ], }, layout: 'noBorders', - margin: [20, 0, 0, 0], + margin: [15, 0, 0, 0], }, ], - margin: [0, 35, 0, 25], + margin: [0, 25, 0, 0], }, { text: [ - `Dear ${applicantName}\n\n`, + `Dear ${applicantName}\n\n\n`, 'On behalf of the Richmond Centre for Disability (RCD), we would like to extend our sincere and\n', 'heartfelt thanks and appreciation for your donation. Please find your official tax receipt enclosed.\n\n', 'Through RCD services and support, we have seen the lives of people with disabilities and their\n', 'families changed for the better. Your generosity does make a difference in the delivery of much\n', 'coveted services to people with disabilities. The work being undertaken through the RCD is only\n', - 'possible because of caring people like you.\n\n', - 'Thank you again for your valued support.\n\n', + 'possible because of caring people like you.\n\n\n', + 'Thank you again for your valued support.\n\n\n', 'Sincerely,\n\n\n', 'RICHMOND CENTRE FOR DISABILITY\n', '(Charity Number: 88832-8432-RR0001)\n', @@ -498,35 +515,32 @@ const donationPdfDefinition = (input: { 'Website:www.rcdrichmond.org\n', ], margin: [0, 15, 0, 0], - fontSize: 12, }, ]), styles: { header: { - fontSize: 28, + fontSize: 25.5, bold: true, alignment: 'center', + lineHeight: 1.5, }, tableHeader: { bold: true, alignment: 'center', }, subheader: { - fontSize: 20, - bold: false, - alignment: 'center', - }, - subheaderDonation: { - fontSize: 19, + fontSize: 17.5, alignment: 'center', }, footer: { - fontSize: 8, + fontSize: 7.5, alignment: 'center', }, }, defaultStyle: { font: 'Helvetica', + fontSize: 11, + lineHeight: 1.2, }, images: { rcd: 'public/assets/logo.png', diff --git a/lib/physicians/validation.ts b/lib/physicians/validation.ts index 10ffe333..178c7e20 100644 --- a/lib/physicians/validation.ts +++ b/lib/physicians/validation.ts @@ -1,18 +1,20 @@ import { phoneNumberRegex, postalCodeRegex } from '@lib/utils/validation'; import { MobilityAid, PatientCondition, PermitType } from '@prisma/client'; -import { date, mixed, object, string, array, number } from 'yup'; +import { date, lazy, mixed, object, string, array, number } from 'yup'; /** * Validation schema for physician assessment form */ export const physicianAssessmentSchema = object({ disability: string().required('Please enter a disabling condition'), - disabilityCertificationDate: date() - .transform((_value, originalValue) => { - return new Date(originalValue); - }) - .max(new Date(), 'Date must be in the past') - .required('Please enter a valid certification date'), + disabilityCertificationDate: lazy(() => + date() + .transform((_value, originalValue) => { + return new Date(originalValue); + }) + .max(new Date(), 'Date must be in the past') + .required('Please enter a valid certification date') + ), patientCondition: array( mixed() .oneOf(Object.values(PatientCondition)) diff --git a/pages/index.tsx b/pages/index.tsx index c0cbc6df..84bb7713 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -22,13 +22,15 @@ export default function Landing() { return ( - {Date.now() < new Date('2023-11-23T06:00:00.000Z').getTime() && ( + {Date.now() < new Date('2024-01-02T08:00:00.000Z').getTime() && ( - Please note that this site will be offline for planned maintenance on Nov 22, 2023 - from 7:00pm to 10:00pm PST. We apologize for any inconvenience. + Please note that the RCD office will be closed between Dec 18 and Jan 1 and will + resume regular business hours on Jan 2. We will process applications received during + the holidays, but all other services will be unavailable. We apologize for any + inconvenience. diff --git a/prisma/dev-seed-utils/employees.ts b/prisma/dev-seed-utils/employees.ts index 3b1a557f..cbdd596a 100644 --- a/prisma/dev-seed-utils/employees.ts +++ b/prisma/dev-seed-utils/employees.ts @@ -79,6 +79,11 @@ const employees = [ lastName: 'Kapadia', email: 'adilkapadia+employee@uwblueprint.org', }, + { + firstName: 'Keane', + lastName: 'Moraes', + email: 'keanejonathan3+employee@gmail.com', + }, ]; /** diff --git a/prisma/migrations/20231123031908_init/migration.sql b/prisma/migrations/20231123031908_init/migration.sql new file mode 100644 index 00000000..b2c3f600 --- /dev/null +++ b/prisma/migrations/20231123031908_init/migration.sql @@ -0,0 +1,440 @@ +-- CreateEnum +CREATE TYPE "applicantstatus" AS ENUM ('ACTIVE', 'INACTIVE'); + +-- CreateEnum +CREATE TYPE "gender" AS ENUM ('MALE', 'FEMALE', 'OTHER'); + +-- CreateEnum +CREATE TYPE "paymenttype" AS ENUM ('MASTERCARD', 'VISA', 'ETRANSFER', 'CASH', 'CHEQUE', 'DEBIT', 'SHOPIFY'); + +-- CreateEnum +CREATE TYPE "physicianstatus" AS ENUM ('ACTIVE', 'INACTIVE'); + +-- CreateEnum +CREATE TYPE "province" AS ENUM ('BC', 'AB', 'SK', 'MB', 'ON', 'QC', 'NS', 'PE', 'NL', 'NB', 'NU', 'NT', 'YT'); + +-- CreateEnum +CREATE TYPE "role" AS ENUM ('ADMIN', 'ACCOUNTING', 'SECRETARY'); + +-- CreateEnum +CREATE TYPE "applicationstatus" AS ENUM ('PENDING', 'IN_PROGRESS', 'REJECTED', 'COMPLETED'); + +-- CreateEnum +CREATE TYPE "reasonforreplacement" AS ENUM ('LOST', 'STOLEN', 'OTHER'); + +-- CreateEnum +CREATE TYPE "permittype" AS ENUM ('PERMANENT', 'TEMPORARY'); + +-- CreateEnum +CREATE TYPE "accessibleconvertedvanloadingmethod" AS ENUM ('SIDE_LOADING', 'END_LOADING'); + +-- CreateEnum +CREATE TYPE "applicationtype" AS ENUM ('NEW', 'RENEWAL', 'REPLACEMENT'); + +-- CreateEnum +CREATE TYPE "mobilityaid" AS ENUM ('CANE', 'ELECTRIC_CHAIR', 'MANUAL_CHAIR', 'SCOOTER', 'WALKER', 'CRUTCHES', 'OTHERS'); + +-- CreateEnum +CREATE TYPE "patientcondition" AS ENUM ('AFFECTS_MOBILITY', 'MOBILITY_AID_REQUIRED', 'CANNOT_WALK_100M', 'OTHER'); + +-- CreateEnum +CREATE TYPE "requireswiderparkingspacereason" AS ENUM ('HAS_ACCESSIBLE_VAN', 'MEDICAL_REASONS', 'OTHER'); + +-- CreateEnum +CREATE TYPE "shopifypaymentstatus" AS ENUM ('PENDING', 'RECEIVED'); + +-- CreateTable +CREATE TABLE "applicants" ( + "id" SERIAL NOT NULL, + "first_name" VARCHAR(255) NOT NULL, + "middle_name" VARCHAR(255), + "last_name" VARCHAR(255) NOT NULL, + "date_of_birth" DATE NOT NULL, + "gender" "gender" NOT NULL, + "other_gender" VARCHAR(255), + "phone" VARCHAR(50) NOT NULL, + "email" VARCHAR(255), + "receive_email_updates" BOOLEAN NOT NULL, + "address_line_1" VARCHAR(255) NOT NULL, + "address_line_2" VARCHAR(255), + "city" VARCHAR(255) NOT NULL, + "province" "province" NOT NULL DEFAULT E'BC', + "country" VARCHAR(255) NOT NULL DEFAULT E'Canada', + "postal_code" VARCHAR(6) NOT NULL, + "status" "applicantstatus" NOT NULL DEFAULT E'ACTIVE', + "inactive_reason" VARCHAR(255), + "accepted_tos" TIMESTAMPTZ(6), + "notes" TEXT, + "guardian_id" INTEGER, + "medical_information_id" INTEGER NOT NULL, + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "applications" ( + "id" SERIAL NOT NULL, + "first_name" VARCHAR(255) NOT NULL, + "middle_name" VARCHAR(255), + "last_name" VARCHAR(255) NOT NULL, + "phone" VARCHAR(50) NOT NULL, + "email" VARCHAR(255), + "receive_email_updates" BOOLEAN NOT NULL DEFAULT false, + "address_line_1" VARCHAR(255) NOT NULL, + "address_line_2" VARCHAR(255), + "city" VARCHAR(255) NOT NULL, + "province" "province" NOT NULL DEFAULT E'BC', + "country" VARCHAR(255) NOT NULL DEFAULT E'Canada', + "postal_code" VARCHAR(6) NOT NULL, + "permit_type" "permittype" NOT NULL DEFAULT E'PERMANENT', + "payment_method" "paymenttype" NOT NULL, + "processing_fee" MONEY NOT NULL, + "donation_amount" MONEY NOT NULL DEFAULT 0.00, + "paid_through_shopify" BOOLEAN NOT NULL DEFAULT false, + "shopify_payment_status" "shopifypaymentstatus" DEFAULT E'PENDING', + "shopify_confirmation_number" VARCHAR(255), + "shopify_order_number" VARCHAR(255), + "shipping_address_same_as_home_address" BOOLEAN NOT NULL, + "shipping_full_name" VARCHAR(255), + "shipping_address_line_1" VARCHAR(255), + "shipping_address_line_2" VARCHAR(255), + "shipping_city" VARCHAR(255), + "shipping_province" "province", + "shipping_country" VARCHAR(255), + "shipping_postal_code" VARCHAR(6), + "billing_address_same_as_home_address" BOOLEAN NOT NULL, + "billing_full_name" VARCHAR(255), + "billing_address_line_1" VARCHAR(255), + "billing_address_line_2" VARCHAR(255), + "billing_city" VARCHAR(255), + "billing_province" "province", + "billing_country" VARCHAR(255), + "billing_postal_code" VARCHAR(6), + "type" "applicationtype" NOT NULL, + "notes" TEXT, + "applicant_id" INTEGER, + "application_processing_id" INTEGER NOT NULL, + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "employees" ( + "id" SERIAL NOT NULL, + "first_name" VARCHAR(255) NOT NULL, + "last_name" VARCHAR(255) NOT NULL, + "email" VARCHAR(255) NOT NULL, + "email_verified" TIMESTAMPTZ(6), + "role" "role" NOT NULL, + "active" BOOLEAN NOT NULL DEFAULT true, + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "guardians" ( + "id" SERIAL NOT NULL, + "first_name" VARCHAR(255) NOT NULL, + "middle_name" VARCHAR(255), + "last_name" VARCHAR(255) NOT NULL, + "phone" VARCHAR(50) NOT NULL, + "address_line_1" VARCHAR(255) NOT NULL, + "address_line_2" VARCHAR(255), + "city" VARCHAR(255) NOT NULL, + "province" "province" NOT NULL DEFAULT E'BC', + "country" VARCHAR(255) NOT NULL DEFAULT E'Canada', + "postal_code" VARCHAR(6) NOT NULL, + "relationship" VARCHAR(255) NOT NULL, + "poa_form_s3_object_key" VARCHAR(255), + "notes" TEXT, + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "medical_information" ( + "id" SERIAL NOT NULL, + "disability" VARCHAR(255) NOT NULL, + "disability_certification_date" DATE NOT NULL, + "patient_condition" "patientcondition"[], + "mobility_aids" "mobilityaid"[], + "other_patient_condition" VARCHAR(255), + "notes" TEXT, + "physician_msp_number" VARCHAR(50) NOT NULL, + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "permits" ( + "rcd_permit_id" INTEGER NOT NULL, + "type" "permittype" NOT NULL, + "expiry_date" DATE NOT NULL, + "active" BOOLEAN NOT NULL DEFAULT true, + "application_id" INTEGER NOT NULL, + "applicant_id" INTEGER NOT NULL, + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY ("rcd_permit_id") +); + +-- CreateTable +CREATE TABLE "physicians" ( + "msp_number" VARCHAR(50) NOT NULL, + "first_name" VARCHAR(255) NOT NULL, + "last_name" VARCHAR(255) NOT NULL, + "phone" VARCHAR(50) NOT NULL, + "address_line_1" VARCHAR(255) NOT NULL, + "address_line_2" VARCHAR(255), + "city" VARCHAR(255) NOT NULL, + "province" "province" NOT NULL DEFAULT E'BC', + "country" VARCHAR(255) NOT NULL DEFAULT E'Canada', + "postal_code" VARCHAR(6) NOT NULL, + "status" "physicianstatus" NOT NULL DEFAULT E'ACTIVE', + "notes" TEXT, + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY ("msp_number") +); + +-- CreateTable +CREATE TABLE "verification_requests" ( + "id" SERIAL NOT NULL, + "identifier" VARCHAR(255) NOT NULL, + "token" VARCHAR(255) NOT NULL, + "expires" TIMESTAMPTZ(6) NOT NULL, + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "application_processing" ( + "id" SERIAL NOT NULL, + "status" "applicationstatus" NOT NULL DEFAULT E'PENDING', + "rejected_reason" VARCHAR(255), + "app_number" INTEGER, + "app_number_employee_id" INTEGER, + "app_number_updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "app_holepunched" BOOLEAN NOT NULL DEFAULT false, + "app_holepunched_employee_id" INTEGER, + "app_holepunched_updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "wallet_card_created" BOOLEAN NOT NULL DEFAULT false, + "wallet_card_created_employee_id" INTEGER, + "wallet_card_created_updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "review_request_completed" BOOLEAN NOT NULL DEFAULT false, + "review_request_completed_employee_id" INTEGER, + "review_request_completed_updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "invoice_number" INTEGER, + "documents_s3_object_key" TEXT, + "documents_url_employee_id" INTEGER, + "documents_url_updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "app_mailed" BOOLEAN NOT NULL DEFAULT false, + "app_mailed_employee_id" INTEGER, + "app_mailed_updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "payment_refunded" BOOLEAN NOT NULL DEFAULT false, + "payment_refunded_employee_id" INTEGER, + "payment_refunded_updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "new_applications" ( + "application_id" INTEGER NOT NULL, + "date_of_birth" DATE NOT NULL, + "gender" "gender" NOT NULL, + "other_gender" VARCHAR(255), + "disability" VARCHAR(255) NOT NULL, + "disability_certification_date" DATE NOT NULL, + "patient_condition" "patientcondition"[], + "mobility_aids" "mobilityaid"[], + "other_mobility_aids" VARCHAR(255), + "other_patient_condition" VARCHAR(255), + "temporary_permit_expiry" DATE, + "physician_first_name" VARCHAR(255) NOT NULL, + "physician_last_name" VARCHAR(255) NOT NULL, + "physician_msp_number" VARCHAR(50) NOT NULL, + "physician_phone" VARCHAR(50) NOT NULL, + "physician_address_line_1" VARCHAR(255) NOT NULL, + "physician_address_line_2" VARCHAR(255), + "physician_city" VARCHAR(255) NOT NULL, + "physician_province" "province" NOT NULL DEFAULT E'BC', + "physician_country" VARCHAR(255) NOT NULL DEFAULT E'Canada', + "physician_postal_code" VARCHAR(6) NOT NULL, + "guardian_first_name" VARCHAR(255), + "guardian_middle_name" VARCHAR(255), + "guardian_last_name" VARCHAR(255), + "guardian_phone" VARCHAR(50), + "guardian_relationship" VARCHAR(50), + "guardian_address_line_1" VARCHAR(255), + "guardian_address_line_2" VARCHAR(255), + "guardian_city" VARCHAR(255), + "guardian_province" "province" DEFAULT E'BC', + "guardian_country" VARCHAR(255) DEFAULT E'Canada', + "guardian_postal_code" VARCHAR(6), + "poa_form_s3_object_key" VARCHAR(255), + "uses_accessible_converted_van" BOOLEAN NOT NULL, + "accessible_converted_van_loading_method" "accessibleconvertedvanloadingmethod", + "requires_wider_parking_space" BOOLEAN NOT NULL, + "requires_wider_parking_space_reason" "requireswiderparkingspacereason", + "other_requires_wider_parking_space_reason" VARCHAR(255), + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY ("application_id") +); + +-- CreateTable +CREATE TABLE "renewal_applications" ( + "application_id" INTEGER NOT NULL, + "physician_first_name" VARCHAR(255) NOT NULL, + "physician_last_name" VARCHAR(255) NOT NULL, + "physician_msp_number" VARCHAR(50) NOT NULL, + "physician_phone" VARCHAR(50) NOT NULL, + "physician_address_line_1" VARCHAR(255) NOT NULL, + "physician_address_line_2" VARCHAR(255), + "physician_city" VARCHAR(255) NOT NULL, + "physician_province" "province" NOT NULL DEFAULT E'BC', + "physician_country" VARCHAR(255) NOT NULL DEFAULT E'Canada', + "physician_postal_code" VARCHAR(6) NOT NULL, + "uses_accessible_converted_van" BOOLEAN NOT NULL, + "accessible_converted_van_loading_method" "accessibleconvertedvanloadingmethod", + "requires_wider_parking_space" BOOLEAN NOT NULL, + "requires_wider_parking_space_reason" "requireswiderparkingspacereason", + "other_requires_wider_parking_space_reason" VARCHAR(255), + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY ("application_id") +); + +-- CreateTable +CREATE TABLE "replacement_applications" ( + "application_id" INTEGER NOT NULL, + "reason" "reasonforreplacement" NOT NULL, + "lost_timestamp" TIMESTAMPTZ(6), + "lost_location" VARCHAR(255), + "stolen_police_file_number" INTEGER, + "stolen_jurisdiction" VARCHAR(255), + "stolen_police_officer_name" VARCHAR(255), + "event_description" TEXT, + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY ("application_id") +); + +-- CreateTable +CREATE TABLE "application_invoices" ( + "invoice_number" SERIAL NOT NULL, + "s3_object_key" VARCHAR(255), + "s3_object_url" TEXT, + "employee_id" INTEGER NOT NULL, + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY ("invoice_number") +); + +-- CreateIndex +CREATE UNIQUE INDEX "applicants.guardian_id_unique" ON "applicants"("guardian_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "applicants.medical_information_id_unique" ON "applicants"("medical_information_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "applications.shopify_confirmation_number_unique" ON "applications"("shopify_confirmation_number"); + +-- CreateIndex +CREATE UNIQUE INDEX "applications.shopify_order_number_unique" ON "applications"("shopify_order_number"); + +-- CreateIndex +CREATE UNIQUE INDEX "applications.application_processing_id_unique" ON "applications"("application_processing_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "employees.email_unique" ON "employees"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "permits.application_id_unique" ON "permits"("application_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "verification_requests.token_unique" ON "verification_requests"("token"); + +-- CreateIndex +CREATE UNIQUE INDEX "application_processing.app_number_unique" ON "application_processing"("app_number"); + +-- CreateIndex +CREATE UNIQUE INDEX "application_processing.invoice_number_unique" ON "application_processing"("invoice_number"); + +-- AddForeignKey +ALTER TABLE "applicants" ADD FOREIGN KEY ("guardian_id") REFERENCES "guardians"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "applicants" ADD FOREIGN KEY ("medical_information_id") REFERENCES "medical_information"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "applications" ADD FOREIGN KEY ("applicant_id") REFERENCES "applicants"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "applications" ADD FOREIGN KEY ("application_processing_id") REFERENCES "application_processing"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "medical_information" ADD FOREIGN KEY ("physician_msp_number") REFERENCES "physicians"("msp_number") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "permits" ADD FOREIGN KEY ("applicant_id") REFERENCES "applicants"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "permits" ADD FOREIGN KEY ("application_id") REFERENCES "applications"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "application_processing" ADD FOREIGN KEY ("app_holepunched_employee_id") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "application_processing" ADD FOREIGN KEY ("app_mailed_employee_id") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "application_processing" ADD FOREIGN KEY ("app_number_employee_id") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "application_processing" ADD FOREIGN KEY ("documents_url_employee_id") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "application_processing" ADD FOREIGN KEY ("invoice_number") REFERENCES "application_invoices"("invoice_number") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "application_processing" ADD FOREIGN KEY ("payment_refunded_employee_id") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "application_processing" ADD FOREIGN KEY ("review_request_completed_employee_id") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "application_processing" ADD FOREIGN KEY ("wallet_card_created_employee_id") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "new_applications" ADD FOREIGN KEY ("application_id") REFERENCES "applications"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "renewal_applications" ADD FOREIGN KEY ("application_id") REFERENCES "applications"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "replacement_applications" ADD FOREIGN KEY ("application_id") REFERENCES "applications"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "application_invoices" ADD FOREIGN KEY ("employee_id") REFERENCES "employees"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 00000000..fbffa92c --- /dev/null +++ b/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" \ No newline at end of file