diff --git a/apps/api/prisma/migrations/20230929182215_hunting_fishing_licenses/migration.sql b/apps/api/prisma/migrations/20230929182215_hunting_fishing_licenses/migration.sql new file mode 100644 index 000000000..570fa3ee3 --- /dev/null +++ b/apps/api/prisma/migrations/20230929182215_hunting_fishing_licenses/migration.sql @@ -0,0 +1,51 @@ +-- AlterEnum +-- This migration adds more than one value to an enum. +-- With PostgreSQL versions 11 and earlier, this is not possible +-- in a single migration. This can be worked around by creating +-- multiple migrations, each migration adding only one value to +-- the enum. + + +ALTER TYPE "DriversLicenseCategoryType" ADD VALUE 'HUNTING'; +ALTER TYPE "DriversLicenseCategoryType" ADD VALUE 'FISHING'; + +-- AlterEnum +-- This migration adds more than one value to an enum. +-- With PostgreSQL versions 11 and earlier, this is not possible +-- in a single migration. This can be worked around by creating +-- multiple migrations, each migration adding only one value to +-- the enum. + + +ALTER TYPE "LicenseExamType" ADD VALUE 'HUNTING'; +ALTER TYPE "LicenseExamType" ADD VALUE 'FISHING'; + +-- AlterTable +ALTER TABLE "Citizen" ADD COLUMN "fishingLicenseId" TEXT, +ADD COLUMN "fishingLicenseNumber" TEXT, +ADD COLUMN "huntingLicenseId" TEXT, +ADD COLUMN "huntingLicenseNumber" TEXT; + +-- AlterTable +ALTER TABLE "CitizenLicensePoints" ADD COLUMN "fishingLicensePoints" INTEGER NOT NULL DEFAULT 0, +ADD COLUMN "huntingLicensePoints" INTEGER NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "MiscCadSettings" ADD COLUMN "fishingLicenseMaxPoints" INTEGER DEFAULT 12, +ADD COLUMN "fishingLicenseNumberLength" INTEGER DEFAULT 8, +ADD COLUMN "fishingLicenseTemplate" TEXT, +ADD COLUMN "huntingLicenseMaxPoints" INTEGER DEFAULT 12, +ADD COLUMN "huntingLicenseNumberLength" INTEGER DEFAULT 8, +ADD COLUMN "huntingLicenseTemplate" TEXT; + +-- AlterTable +ALTER TABLE "SuspendedCitizenLicenses" ADD COLUMN "fishingLicense" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "fishingLicenseTimeEnd" TIMESTAMP(3), +ADD COLUMN "huntingLicense" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "huntingLicenseTimeEnd" TIMESTAMP(3); + +-- AddForeignKey +ALTER TABLE "Citizen" ADD CONSTRAINT "Citizen_huntingLicenseId_fkey" FOREIGN KEY ("huntingLicenseId") REFERENCES "Value"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Citizen" ADD CONSTRAINT "Citizen_fishingLicenseId_fkey" FOREIGN KEY ("fishingLicenseId") REFERENCES "Value"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma index c324ff2ca..fafeac910 100644 --- a/apps/api/prisma/schema.prisma +++ b/apps/api/prisma/schema.prisma @@ -100,11 +100,17 @@ model MiscCadSettings { weaponLicenseTemplate String? @db.Text waterLicenseNumberLength Int? @default(8) waterLicenseTemplate String? @db.Text + huntingLicenseNumberLength Int? @default(8) + huntingLicenseTemplate String? @db.Text + fishingLicenseNumberLength Int? @default(8) + fishingLicenseTemplate String? @db.Text driversLicenseMaxPoints Int? @default(12) pilotLicenseMaxPoints Int? @default(12) weaponLicenseMaxPoints Int? @default(12) waterLicenseMaxPoints Int? @default(12) + fishingLicenseMaxPoints Int? @default(12) + huntingLicenseMaxPoints Int? @default(12) lastInactivitySyncTimestamp DateTime? @@ -375,6 +381,12 @@ model Citizen { waterLicense Value? @relation("waterLicenseToValue", fields: [waterLicenseId], references: [id]) waterLicenseId String? waterLicenseNumber String? + huntingLicense Value? @relation("huntingLicenseToValue", fields: [huntingLicenseId], references: [id]) + huntingLicenseId String? + huntingLicenseNumber String? + fishingLicense Value? @relation("fishingLicenseToValue", fields: [fishingLicenseId], references: [id]) + fishingLicenseId String? + fishingLicenseNumber String? ccw Value? @relation("ccwToValue", fields: [ccwId], references: [id]) ccwId String? imageId String? @db.Text @@ -428,6 +440,8 @@ model CitizenLicensePoints { driverLicensePoints Int @default(0) pilotLicensePoints Int @default(0) waterLicensePoints Int @default(0) + huntingLicensePoints Int @default(0) + fishingLicensePoints Int @default(0) firearmsLicensePoints Int @default(0) updatedAt DateTime @default(now()) @updatedAt citizens Citizen[] @@ -441,6 +455,10 @@ model SuspendedCitizenLicenses { pilotLicenseTimeEnd DateTime? waterLicense Boolean @default(false) waterLicenseTimeEnd DateTime? + fishingLicense Boolean @default(false) + fishingLicenseTimeEnd DateTime? + huntingLicense Boolean @default(false) + huntingLicenseTimeEnd DateTime? firearmsLicense Boolean @default(false) firearmsLicenseTimeEnd DateTime? citizens Citizen[] @@ -633,6 +651,8 @@ model Value { VehicleTrimLevels VehicleValue[] @relation("vehicleTrimLevels") RegisteredVehicle RegisteredVehicle[] @relation("registeredVehicleTrimLevels") Weapon Weapon[] @relation("weaponFlags") + fishingLicenseToValue Citizen[] @relation("fishingLicenseToValue") + huntingLicenseToValue Citizen[] @relation("huntingLicenseToValue") @@index([type]) } @@ -1709,6 +1729,8 @@ enum LicenseExamType { FIREARM WATER PILOT + HUNTING + FISHING } enum QualificationValueType { @@ -1798,6 +1820,8 @@ enum DriversLicenseCategoryType { AVIATION WATER FIREARM + HUNTING + FISHING } enum EmployeeAsEnum { diff --git a/apps/api/src/controllers/admin/import/import-citizens-controller.ts b/apps/api/src/controllers/admin/import/import-citizens-controller.ts index dc72fb0ae..396e773eb 100644 --- a/apps/api/src/controllers/admin/import/import-citizens-controller.ts +++ b/apps/api/src/controllers/admin/import/import-citizens-controller.ts @@ -175,6 +175,8 @@ export class ImportCitizensController { gender: true, ethnicity: true, weaponLicense: true, + huntingLicense: true, + fishingLicense: true, driversLicense: true, pilotLicense: true, waterLicense: true, diff --git a/apps/api/src/controllers/admin/manage/cad-settings/CadSettings.ts b/apps/api/src/controllers/admin/manage/cad-settings/CadSettings.ts index 5d029fa5a..20cdbb3de 100644 --- a/apps/api/src/controllers/admin/manage/cad-settings/CadSettings.ts +++ b/apps/api/src/controllers/admin/manage/cad-settings/CadSettings.ts @@ -276,6 +276,12 @@ export class CADSettingsController { waterLicenseNumberLength: data.waterLicenseNumberLength, signal100RepeatAmount: data.signal100RepeatAmount, signal100RepeatIntervalMs: data.signal100RepeatIntervalMs, + huntingLicenseTemplate: data.huntingLicenseTemplate, + huntingLicenseMaxPoints: data.huntingLicenseMaxPoints, + huntingLicenseNumberLength: data.huntingLicenseNumberLength, + fishingLicenseTemplate: data.fishingLicenseTemplate, + fishingLicenseMaxPoints: data.fishingLicenseMaxPoints, + fishingLicenseNumberLength: data.fishingLicenseNumberLength, }, include: { webhooks: true }, }); diff --git a/apps/api/src/controllers/admin/manage/manage-citizens-controller.ts b/apps/api/src/controllers/admin/manage/manage-citizens-controller.ts index a24e19e83..5d08b63cb 100644 --- a/apps/api/src/controllers/admin/manage/manage-citizens-controller.ts +++ b/apps/api/src/controllers/admin/manage/manage-citizens-controller.ts @@ -198,6 +198,8 @@ export class AdminManageCitizensController { driversLicenseId: data.driversLicense, weaponLicenseId: data.weaponLicense, pilotLicenseId: data.pilotLicense, + fishingLicenseId: data.fishingLicense, + huntingLicenseId: data.huntingLicense, phoneNumber: data.phoneNumber, socialSecurityNumber: data.socialSecurityNumber && isEditableSSNEnabled diff --git a/apps/api/src/controllers/citizen/CitizenController.ts b/apps/api/src/controllers/citizen/CitizenController.ts index 2b9bb449a..c403fe49f 100644 --- a/apps/api/src/controllers/citizen/CitizenController.ts +++ b/apps/api/src/controllers/citizen/CitizenController.ts @@ -66,6 +66,8 @@ export const citizenInclude = Prisma.validator()({ gender: true, weaponLicense: true, driversLicense: true, + huntingLicense: true, + fishingLicense: true, pilotLicense: true, waterLicense: true, dlCategory: { include: { value: true } }, diff --git a/apps/api/src/controllers/citizen/LicenseController.ts b/apps/api/src/controllers/citizen/LicenseController.ts index 2fa57c6b3..99df45d25 100644 --- a/apps/api/src/controllers/citizen/LicenseController.ts +++ b/apps/api/src/controllers/citizen/LicenseController.ts @@ -66,6 +66,8 @@ export class LicensesController { pilotLicenseId: suspendedLicenses?.pilotLicense ? undefined : data.pilotLicense, weaponLicenseId: suspendedLicenses?.firearmsLicense ? undefined : data.weaponLicense, waterLicenseId: suspendedLicenses?.waterLicense ? undefined : data.waterLicense, + fishingLicenseId: suspendedLicenses?.fishingLicense ? undefined : data.fishingLicense, + huntingLicenseId: suspendedLicenses?.huntingLicense ? undefined : data.huntingLicense, }, include: citizenInclude, }); diff --git a/apps/api/src/controllers/leo/LicenseExamsController.ts b/apps/api/src/controllers/leo/LicenseExamsController.ts index a235d6aef..b9d1dcde0 100644 --- a/apps/api/src/controllers/leo/LicenseExamsController.ts +++ b/apps/api/src/controllers/leo/LicenseExamsController.ts @@ -216,6 +216,8 @@ export class LicenseExamsController { FIREARM: "weaponLicenseId", WATER: "waterLicenseId", PILOT: "pilotLicenseId", + HUNTING: "huntingLicenseId", + FISHING: "fishingLicenseId", } as const; const prismaName = prismaNames[exam.type]; diff --git a/apps/api/src/controllers/leo/search/SearchActionsController.ts b/apps/api/src/controllers/leo/search/SearchActionsController.ts index c1d0ddb24..98dbb89a1 100644 --- a/apps/api/src/controllers/leo/search/SearchActionsController.ts +++ b/apps/api/src/controllers/leo/search/SearchActionsController.ts @@ -91,6 +91,10 @@ export class SearchActionsController { pilotLicenseTimeEnd: data.suspended.pilotLicenseTimeEnd, waterLicense: data.suspended.waterLicense, waterLicenseTimeEnd: data.suspended.waterLicenseTimeEnd, + fishingLicense: data.suspended.fishingLicense, + fishingLicenseTimeEnd: data.suspended.fishingLicenseTimeEnd, + huntingLicense: data.suspended.huntingLicense, + huntingLicenseTimeEnd: data.suspended.huntingLicenseTimeEnd, }; suspendedLicenses = await prisma.suspendedCitizenLicenses.upsert({ @@ -108,6 +112,8 @@ export class SearchActionsController { driversLicenseId: data.driversLicense, pilotLicenseId: data.pilotLicense, weaponLicenseId: data.weaponLicense, + huntingLicenseId: data.huntingLicense, + fishingLicenseId: data.fishingLicense, waterLicenseId: data.waterLicense, suspendedLicensesId: suspendedLicenses?.id, }, @@ -143,6 +149,8 @@ export class SearchActionsController { pilotLicensePoints: data.pilotLicensePoints, waterLicensePoints: data.waterLicensePoints, firearmsLicensePoints: data.firearmsLicensePoints, + huntingLicensePoints: data.huntingLicensePoints, + fishingLicensePoints: data.fishingLicensePoints, }; const updated = await prisma.citizen.update({ diff --git a/apps/api/src/lib/citizen/citizen-create-data-obj.ts b/apps/api/src/lib/citizen/citizen-create-data-obj.ts index b762501d4..c2e6f5e32 100644 --- a/apps/api/src/lib/citizen/citizen-create-data-obj.ts +++ b/apps/api/src/lib/citizen/citizen-create-data-obj.ts @@ -63,6 +63,16 @@ export async function citizenObjectFromData(options: Options) { template: miscCadSettings?.waterLicenseTemplate, length: miscCadSettings?.waterLicenseNumberLength ?? 8, }), + + huntingLicenseNumber: generateLicenseNumber({ + template: miscCadSettings?.huntingLicenseTemplate, + length: miscCadSettings?.huntingLicenseNumberLength ?? 8, + }), + + fishingLicenseNumber: generateLicenseNumber({ + template: miscCadSettings?.fishingLicenseTemplate, + length: miscCadSettings?.fishingLicenseNumberLength ?? 8, + }), }; if (typeof options.defaultLicenseValueId !== "undefined") { @@ -72,6 +82,8 @@ export async function citizenObjectFromData(options: Options) { weaponLicenseId: options.data.weaponLicense || options.defaultLicenseValueId, pilotLicenseId: options.data.pilotLicense || options.defaultLicenseValueId, waterLicenseId: options.data.waterLicense || options.defaultLicenseValueId, + huntingLicenseId: options.data.huntingLicense || options.defaultLicenseValueId, + fishingLicenseId: options.data.fishingLicense || options.defaultLicenseValueId, }; } diff --git a/apps/client/locales/en/cad-settings.json b/apps/client/locales/en/cad-settings.json index 760fb64ae..2c701824c 100644 --- a/apps/client/locales/en/cad-settings.json +++ b/apps/client/locales/en/cad-settings.json @@ -133,6 +133,10 @@ "weaponLicenseTemplateInfo": "This is the template for weapon license numbers. You can use the following variables: {variables}. Note: this will only apply to newly created citizens.", "waterLicenseTemplate": "Water license number template", "waterLicenseTemplateInfo": "This is the template for water license numbers. You can use the following variables: {variables}. Note: this will only apply to newly created citizens.", + "huntingLicenseTemplate": "Hunting license number template", + "huntingLicenseTemplateInfo": "This is the template for hunting license numbers. You can use the following variables: {variables}. Note: this will only apply to newly created citizens.", + "fishingLicenseTemplate": "Fishing license number template", + "fishingLicenseTemplateInfo": "This is the template for fishing license numbers. You can use the following variables: {variables}. Note: this will only apply to newly created citizens.", "miscSettings": "Miscellaneous Settings", "cadRelated": "CAD Related", "inactivityTimeouts": "Inactivity Timeouts", @@ -156,6 +160,10 @@ "maxPilotLicensePointsDescription": "The maximum amount of license points a citizen can have before their pilots license is suspended (Default: 12)", "maxWeaponLicensePoints": "Max Weapon License Points", "maxWeaponLicensePointsDescription": "The maximum amount of license points a citizen can have before their weapon license is suspended (Default: 12)", + "maxFishingLicensePoints": "Max Fishing License Points", + "maxFishingLicensePointsDescription": "The maximum amount of license points a citizen can have before their fishing license is suspended (Default: 12)", + "maxHuntingLicensePoints": "Max Hunting License Points", + "maxHuntingLicensePointsDescription": "The maximum amount of license points a citizen can have before their hunting license is suspended (Default: 12)", "maxWaterLicensePoints": "Max Water License Points", "maxWaterLicensePointsDescription": "The maximum amount of license points a citizen can have before their water license is suspended (Default: 12)", "other": "Other", @@ -191,6 +199,10 @@ "weaponLicenseNumberLengthDescription": "The length of the weapon license number (Default: 8)", "waterLicenseNumberLength": "Water License Number Length", "waterLicenseNumberLengthDescription": "The length of the water license number (Default: 8)", + "fishingLicenseNumberLength": "Fishing License Number Length", + "fishingLicenseNumberLengthDescription": "The length of the fishing license number (Default: 8)", + "huntingLicenseNumberLength": "Hunting License Number Length", + "huntingLicenseNumberLengthDescription": "The length of the hunting license number (Default: 8)", "seconds": "Seconds", "minutes": "Minutes", "hours": "Hours", diff --git a/apps/client/locales/en/citizen.json b/apps/client/locales/en/citizen.json index 96c73e2cd..92ed22e96 100644 --- a/apps/client/locales/en/citizen.json +++ b/apps/client/locales/en/citizen.json @@ -61,7 +61,13 @@ "createPreviousRecordsStepDescription": "Here you can optionally add previous records this citizen has had. This is useful for when a citizen has been arrested before.", "alert_markCitizenDeceased": "Are you sure you want mark {citizen} as deceased? Only EMS/FD can mark you alive again.", "alert_deleteCitizen": "Are you sure you want to delete {citizen}? This action cannot be undone.", - "id": "Id" + "id": "Id", + "fishingLicense": "Fishing License", + "huntingLicense": "Hunting License", + "fishingLicenseCategory": "Fishing License Categories", + "huntingLicenseCategory": "Hunting License Categories", + "huntingLicensePoints": "Hunting License Points", + "fishingLicensePoints": "Fishing License Points" }, "Vehicles": { "model": "Model", diff --git a/apps/client/locales/en/leo.json b/apps/client/locales/en/leo.json index cc5f7f13e..378b71b43 100644 --- a/apps/client/locales/en/leo.json +++ b/apps/client/locales/en/leo.json @@ -238,6 +238,8 @@ "suspendPilotLicense": "Suspended Pilot license", "suspendWaterLicense": "Suspended Water license", "suspendFirearmsLicense": "Suspended Firearms license", + "suspendedHuntingLicense": "Suspended Hunting license", + "suspendedFishingLicense": "Suspended Fishing license", "endDate": "End Date", "patrolVehicle": "Patrol Vehicle", "callUpdated": "Your call #{caseNumber} has been updated", diff --git a/apps/client/src/components/admin/manage/cad-settings/misc-features/license-number-tab.tsx b/apps/client/src/components/admin/manage/cad-settings/misc-features/license-number-tab.tsx index 7ff4873d3..bb961ebea 100644 --- a/apps/client/src/components/admin/manage/cad-settings/misc-features/license-number-tab.tsx +++ b/apps/client/src/components/admin/manage/cad-settings/misc-features/license-number-tab.tsx @@ -42,6 +42,8 @@ export function LicenseNumbersTab() { weaponLicenseNumberLength: miscSettings.weaponLicenseNumberLength ?? 8, pilotLicenseNumberLength: miscSettings.pilotLicenseNumberLength ?? 6, waterLicenseNumberLength: miscSettings.waterLicenseNumberLength ?? 8, + fishingLicenseNumberLength: miscSettings.fishingLicenseNumberLength ?? 8, + huntingLicenseNumberLength: miscSettings.huntingLicenseNumberLength ?? 8, }; return ( @@ -112,6 +114,34 @@ export function LicenseNumbersTab() { /> + + + + + + + +