import * as uuid from "uuid"; import { Model } from "mongoose"; import { mongooseLeanVirtuals } from "mongoose-lean-virtuals"; import { AccountIndustry, FireMapperLayers, } from "../constants"; import { currentDate, MongooseModule, retrieveCurrentUnixTime, } from "../helpers"; // Schemas import ColorModule from "./schema/color"; import { ReportNumberSchema } from "./schema/common-incident"; import { GeoPolygonSchema } from "./schema/geojson"; import { FireMapperAuthV2Schema } from "./schema/firemapper-auth"; import PubNubTokenSchema from "./schema/pubnub-token"; import { WebhookSchema } from "./schema/webhook"; import { WSFeedSchema } from "./schema/ws-feed"; // Types import { ColorSchemaType } from "../types/color"; import { AccountConfigurationCallerLocation, ADSBConfigType, AccountConfigurationCallerLocationResolver, AudioStreamAuthType, AudioStreamGroupType, AudioStreamType, CADGetLocationSettingsType, CADToCADConfigType, CADToCADType, CustomButtonsType, DepartmentType, FireMapperConfigurationType, FireMapperLayerType, FireMapperOutlineType, FirstArrivingConfigType, ForwardFieldsType, ForwardingConfigType, ForwardingConnectionFilterType, ForwardingConnectionType, GSTConfigType, GeotabConfigType, IncidentReplayType, IncidentShareRuleTypeV2, IncidentTypeType, IncidentVehicleStatusConfigType, IntterraConfigType, IntterraConnectionType, IntterraFieldsType, LicensingType, IntegrationTypes, ManagedIncidentMode, ManagedIncidentModeItem, ManagedIncidentPriority, ManagedIncidentPriorityItem, GMRConfigType, Mark43ConfigType, Mark43ProcessCommentConfigType, Mark43ProcessConfigType, Mark43ProcessLocationConfigType, Mark43ProcessVehicleStatusConfigType, ReplayOptionType, RestrictedCommentsType, SafetyPriorityKeywordType, PersonnelWebhookType, SamsaraConfigurationType, ShareIncidentRuleTypeConfigurationArea, ShareIncidentRuleTypeV2, SimpleSenseConfigType, SkymiraConfigType, SkytracConfigType, SomewearType, StatusMappingConfigType, StatusMappingObjectConfigType, UnitStatusCodesConfigType, OneStepConfigurationType, DroneSenseConfigurationType, DronesConfigurationType, DronesVideoType, DronesVideoUrlsType, USFTConfigurationType, VehicleStatusWebhookConfigType, VehicleStatusWebhookConnectionType, WebDisclaimerType, SharedToDestinationType, } from "../types/department"; export interface Department extends DepartmentType, Record { } export const Mark43StatusConfigDefault: UnitStatusCodesConfigType = { TimeDispatched: ["D"], TimeEnroute: ["EN"], TimeStaged: ["ST"], TimeCleared: ["AV", "AVF", "AOR"], TimeAtHospital: ["AH"], TimeTransporting: ["T", "EH"], TimeArrived: ["ATS", "A"], }; export const GMRStatusConfigDefault: UnitStatusCodesConfigType = { TimeDispatched: ["SentToVehicle"], TimeEnroute: ["EnRouteToPickup"], TimeStaged: [], TimeCleared: ["Finished"], TimeAtHospital: [], TimeTransporting: [], TimeArrived: ["ArrivedToPickup"], }; export const IntterraFieldsDefault = [ { key: "IncidentNumber", value: "incidentId", required: true, enabled: true, transformationRequired: false, }, { key: "AgencyIncidentCallTypeDescription", value: "incidentTypeDescription", required: false, enabled: true, transformationRequired: false, }, { key: "units", value: "assignedUnits", required: false, enabled: true, transformationRequired: true, }, { key: "Longitude", value: "longitude", required: false, enabled: true, transformationRequired: false, }, { key: "Latitude", value: "latitude", required: false, enabled: true, transformationRequired: false, }, { key: "full_address", value: "fullAddress", required: false, enabled: true, transformationRequired: false, }, { key: "EntryDateTime", value: "alarmDatetime", // cspell:disable-line required: false, enabled: true, transformationRequired: false, } ]; // If any of the following fields are updated/added/deleted, // make sure to update the database records, before/after release (script/query) export const FireMapperConfigurationDefault: FireMapperConfigurationType = { enabled: false, layerRefreshInterval: 15, proLicenseCount: 0, host: "", layer: FireMapperLayers, staticLayer: [], auth: { account: "", // Empty, would be read from their system uuid: "", host: "", apiKeyManagement: undefined, apiKeyReadOnly: undefined, licenseCode: undefined } }; export const LicensingDefault = { tcPro2Way: 0, tcPro1Way: 0, tcMobile: 0, tcWeb: 0, fireMapperPro: 0, sendToCAD: 0, tcStreams: 0 }; export const SafetyPriorityKeywordDefault = [ { keywords: [], priority: 0, hexColor: "FF3B30" }, { keywords: [], priority: 1, hexColor: "FEC309" }, { keywords: [], priority: 2, hexColor: "0A60FF" } ]; export const FirstArrivingConfigDefault = { token: "", apiUrl: "", }; export const IntterraConfigDefault = { enabled: false, connections: [], incidentWebhookEnabled: false, }; export const CADGetLocationSettingsDefault = { includeModems: false, selectModemsManually: false, includeGeotab: false, selectGeotabManually: false, }; export const CADToCADDefault = { enabled: false, allowedDepartments: [], }; export const ForwardingConfigDefault = { enabled: false, connections: [], incidentWebhookEnabled: false, }; export const VehicleStatusWebhookConfigDefault = { enabled: false, connections: [], }; export const IncidentReplayDefault = { enabled: false, replays: [], }; export const SomewearDefault = { enabled: false, }; export const PersonnelWebhookDefault = { enabled: false, }; export const GSTConfigDefault = { enabled: false, code: "", }; export const SkymiraConfigDefault = { enabled: false, token: "", locationsUrl: "", }; export const ADSBConfigDefault = { enabled: false, token: "", locationsUrl: "", tailNumbersAllowed: [], squawkCodes: [], }; export const GeotabConfigDefault = { enabled: false, username: "", password: "", database: "", path: "", }; export const Mark43ConfigDefault = { baseUrl: "", authToken: "", apiToken: "", userId: 0, enabled: false, }; export const GMRConfigDefault = { baseUrl: "", authToken: "", apiToken: "", enabled: false, webhookSecret: "", agencyId: "", radioNamePrefixesToStrip: [], }; export const WebhookConfigDefault = { enabled: false, bulkProcessingEnabled: false, type: "", auth: { type: "", key: "", keySecret: "", endpoint: "", } }; export const WSFeedConfigDefault = { enabled: false, incident: { enabled: false, url: "", handshakeUrl: "", token: "", authType: "", source: "", pingIntervalSeconds: 10, maxReconnectAttempts: 3, reconnectDelayMS: 1000, socketTTLSeconds: 30, incidentTypesMap: {}, unitStatusCodes: { TimeDispatched: [], TimeEnroute: [], TimeStaged: [], TimeCleared: [], TimeAtHospital: [], TimeTransporting: [], TimeArrived: [], }, }, location: { enabled: false, url: "", handshakeUrl: "", token: "", authType: "", source: "", pingIntervalSeconds: 10, maxReconnectAttempts: 3, reconnectDelayMS: 1000, socketTTLSeconds: 30, isMirrored: false, mirrorToDepartmentIds: [], }, unit: { enabled: false, url: "", handshakeUrl: "", token: "", authType: "", source: "", pingIntervalSeconds: 10, maxReconnectAttempts: 3, reconnectDelayMS: 1000, socketTTLSeconds: 30, } }; export const SimpleSenseConfigDefault = { token: "", }; export const WebDisclaimerDefault = { message: "", enabled: false }; export const RestrictedCommentsDefault = { enabled: false, callTypesAllowed: [], statusesAllowed: [], restrictedFields: [ "LocationComment", "AgencyIncidentCallTypeDescription", "Comment" ], restrictedMessage: "RESTRICTED" }; export const StatusMappingConfigDefault = { TimeDispatched: { status: "Unit Dispatched", statusCode: "DSP" }, TimeEnroute: { status: "Unit is Enroute", statusCode: "ENR" }, TimeStaged: { status: "Unit is Staging", statusCode: "STG" }, TimeArrived: { status: "Unit is On Scene", statusCode: "ONS" }, TimeCleared: { status: "Available on Radio", statusCode: "AOR" }, TimeAtHospital: { status: "Transport Arrive", statusCode: "TAR" }, // added to exclusions unused TimePatient: { status: "Available", statusCode: "AV" }, TimeTransporting: { status: "Transporting", statusCode: "TRN" }, TimeTransportComplete: { status: "Transport Complete", statusCode: "TCM" } }; export const ForwardFieldsDefault = [ { key: "IncidentNumber", value: "IncidentNumber", required: true, enabled: true, transformationRequired: false, }, { key: "AgencyIncidentCallTypeDescription", value: "AgencyIncidentCallTypeDescription", required: false, enabled: true, transformationRequired: false, }, { key: "units", value: "units", required: false, enabled: true, transformationRequired: true, }, { key: "Longitude", value: "Longitude", required: false, enabled: true, transformationRequired: false, }, { key: "Latitude", value: "Latitude", required: false, enabled: true, transformationRequired: false, }, { key: "full_address", value: "full_address", required: false, enabled: true, transformationRequired: false, }, { key: "EntryDateTime", value: "EntryDateTime", // cspell:disable-line required: false, enabled: true, transformationRequired: false, } ]; export const VehicleStatusWebhookFieldsDefault = [ { key: "responseTime", value: "responseTime", required: true, enabled: true, transformationRequired: false, }, { key: "responseTimeAt", value: "responseTimeAt", required: true, enabled: true, transformationRequired: false, }, { key: "radioName", value: "radioName", required: true, enabled: true, transformationRequired: false, }, { key: "vehicleId", value: "vehicleId", required: true, enabled: true, transformationRequired: false, }, { key: "statusCode", value: "statusCode", required: true, enabled: true, transformationRequired: false, }, { key: "status", value: "status", required: true, enabled: true, transformationRequired: false, } ]; export const SamsaraConfigurationDefault = { enabled: false, token: "", tagIds: [] as string[], }; export const USFTConfigurationDefault = { enabled: false, key: "", secret: "", radioNameMappings: {}, }; export const OneStepConfigurationDefault = { enabled: false, apiKey: "", radioNameMappings: {}, }; export const DroneSenseConfigurationDefault = { enabled: false, apiKey: "", }; export const DronesVideoDefault: DronesVideoType = { sources: [], urls: { web: "" }, }; export const DronesConfigurationDefault: DronesConfigurationType = { enabled: false, providers: [], video: DronesVideoDefault, }; export const OrientationMarkerColorDefault: ColorSchemaType = { background: "#FC2125", text: "#FFFFFF", }; export const ManagedIncidentModeItemsDefault: ManagedIncidentModeItem[] = [ { title: "Investigative", color: { background: "#0066FF", text: "#F9E2D9" }, position: 1 }, { title: "Offensive", color: { background: "#336633", text: "#F9E2D9" }, position: 2 }, { title: "Defensive", color: { background: "#CC3333", text: "#F9E2D9" }, position: 3 }, { title: "Combination", color: { background: "#CC6633", text: "#F5EFF9" }, position: 4 }, { title: "Marginal", color: { background: "#FFCC66", text: "#330000" }, position: 5 }, { title: "Transitional", color: { background: "#00FFE1", text: "#330000" }, position: 6 }, ]; export const ManagedIncidentModeDefault: ManagedIncidentMode = { label: "Incident Mode", items: ManagedIncidentModeItemsDefault, }; export const ManagedIncidentPriorityItemsDefault: ManagedIncidentPriorityItem[] = [ { title: "Life", color: { background: "#006600", text: "#FFFFCC" }, position: 1 }, { title: "Incident Stabilization", color: { background: "#FFC300", text: "#333333" }, position: 2 }, { title: "Property", color: { background: "#333333", text: "#FFC300" }, position: 3 }, { title: "Environment", color: { background: "#003399", text: "#FFFFCC" }, position: 4 }, ]; export const ManagedIncidentPriorityDefault: ManagedIncidentPriority = { label: "Incident Priority", items: ManagedIncidentPriorityItemsDefault, }; export default async function DepartmentModule(mongoose: MongooseModule) { const { Schema } = mongoose; const Color = ColorModule(mongoose); const FireMapperAuth = FireMapperAuthV2Schema(mongoose); const GeoPolygon = GeoPolygonSchema(mongoose); const PubNubToken = PubNubTokenSchema(mongoose); const ReportNumber = ReportNumberSchema(mongoose); const WebhookConfig = WebhookSchema(mongoose); const WSFeedConfig = WSFeedSchema(mongoose); const UnitStatusCodesConfig = new Schema({ TimeDispatched: { type: [String], default: [] }, TimeEnroute: { type: [String], default: [] }, TimeStaged: { type: [String], default: [] }, TimeCleared: { type: [String], default: [] }, TimeAtHospital: { type: [String], default: [] }, TimeTransporting: { type: [String], default: [] }, TimeArrived: { type: [String], default: [] }, }, { _id: false, id: false, }); const Mark43ProcessLocationConfig = new Schema({ enabled: { type: Boolean, default: false, }, locationUrl: { type: String, default: "", } }, { _id: false, id: false, }); const Mark43ProcessCommentConfig = new Schema({ enabled: { type: Boolean, default: false, }, commentUrl: { type: String, default: "" }, usersUrl: { type: String, default: "", }, defaultUserId: { type: Number, default: 0, }, }, { _id: false, id: false, }); const Mark43ProcessVehicleStatusConfig = new Schema({ enabled: { type: Boolean, default: false, }, vehicleStatusUrl: { type: String, default: "" }, vehicleStatusListUrl: { type: String, default: "" }, }, { _id: false, id: false, }); const Mark43ProcessConfig = new Schema({ location: { type: Mark43ProcessLocationConfig, }, comment: { type: Mark43ProcessCommentConfig, }, vehicleStatus: { type: Mark43ProcessVehicleStatusConfig, }, }, { _id: false, id: false, }); const Mark43Config = new Schema({ baseUrl: { type: String, default: "", }, authToken: { type: String, default: "", }, apiToken: { type: String, default: "", }, userId: { type: Number, default: 0, }, enabled: { type: Boolean, default: false, }, unitStatusCodes: { type: UnitStatusCodesConfig, default: Mark43StatusConfigDefault, }, process: { type: Mark43ProcessConfig, }, }, { _id: false, id: false, }); const GMRConfig = new Schema({ baseUrl: { type: String, default: "", }, authToken: { type: String, default: "", }, apiToken: { type: String, default: "", }, enabled: { type: Boolean, default: false, }, unitStatusCodes: { type: UnitStatusCodesConfig, default: GMRStatusConfigDefault, }, webhookSecret: { type: String, default: "", }, agencyId: { type: String, default: "", }, radioNamePrefixesToStrip: { type: [String], default: [], }, }, { _id: false, id: false, }); const IntterraFields = new Schema({ key: { type: String, default: "", }, value: { type: String, default: "", }, transformationRequired: { type: Boolean, default: false, }, required: { type: Boolean, default: false, }, enabled: { type: Boolean, default: true, }, }, { _id: false, id: false, }); const IntterraConnection = new Schema({ active: { type: Boolean, default: false, }, fields: { type: [IntterraFields], default: IntterraFieldsDefault, }, callTypes: { type: [String], default: [], }, authKey: { type: String, default: "", }, authKeySecret: { type: String, default: "" }, agency: { type: String, default: "", }, description: { type: String, default: "", }, }, { _id: false, id: false, }); const ForwardFields = new Schema({ key: { type: String, default: "", }, value: { type: String, default: "", }, transformationRequired: { type: Boolean, default: false, }, transformationType: { type: String, }, required: { type: Boolean, default: false, }, enabled: { type: Boolean, default: true, }, }, { _id: false, id: false, }); const ForwardingConnection = new Schema({ active: { type: Boolean, default: false, }, connectionType: { type: String, default: "", }, fields: { type: [ForwardFields], default: ForwardFieldsDefault, }, callTypes: { type: [String], default: [], }, forwardAll: { type: Boolean, default: false, }, apiUrl: { type: String, default: "", }, authType: { type: String, default: "", }, authHeader: { type: String, default: "", }, authUser: { type: String, default: "", }, authKey: { type: String, default: "", }, authKeySecret: { type: String, default: "" }, label: { type: String, default: "", }, description: { type: String, default: "", }, // Extended properties for SOAP and other protocols timeout: { type: Number, default: undefined, }, namespace: { type: String, default: "", }, soapVersion: { type: String, enum: ["1.1", "1.2"], default: undefined, }, customHeaders: { type: Map, of: String, default: {}, }, filter: { type: new Schema({ radioNames: { type: [{ type: String, trim: true }], default: [], }, }, { _id: false, id: false }), default: {}, }, }, { _id: false, id: false, }); const VehicleStatusWebhookConnection = new Schema({ active: { type: Boolean, default: false, }, connectionType: { type: String, default: "", }, fields: { type: [ForwardFields], default: VehicleStatusWebhookFieldsDefault, }, apiUrl: { type: String, default: "", }, apiKey: { type: String, default: "", }, authType: { type: String, default: "", }, authHeader: { type: String, default: "", }, description: { type: String, default: "", }, includeStation: { type: Boolean, default: false, }, }, { _id: false, id: false, }); const IntterraConfig = new Schema({ enabled: { type: Boolean, default: false, }, connections: { type: [IntterraConnection], default: [], }, incidentWebhookEnabled: { type: Boolean, default: false, }, }, { _id: false, id: false, }); const ForwardingConfig = new Schema({ enabled: { type: Boolean, default: false, }, connections: { type: [ForwardingConnection], default: [], }, }, { _id: false, id: false, }); const VehicleStatusWebhookConfig = new Schema({ enabled: { type: Boolean, default: false, }, connections: { type: [VehicleStatusWebhookConnection], default: [], }, }, { _id: false, id: false, }); const SkymiraConfig = new Schema({ enabled: { type: Boolean, default: false, }, token: { type: String, default: "", }, locationsUrl: { type: String, default: "", }, }, { _id: false, id: false, }); const ADSBConfig = new Schema({ enabled: { type: Boolean, default: false, }, token: { type: String, default: "", }, locationsUrl: { type: String, default: "", }, tailNumbersAllowed: { type: [String], default: [], }, squawkCodes: { type: [String], default: [], }, }, { _id: false, id: false, }); const GeotabConfig = new Schema({ enabled: { type: Boolean, default: false, }, username: { type: String, default: "", }, password: { type: String, default: "", }, database: { type: String, default: "", }, path: { type: String, default: "", }, }, { _id: false, id: false, }); const GSTConfig = new Schema({ enabled: { type: Boolean, default: false, }, code: { type: String, default: "", }, }, { _id: false, id: false, }); const ReplayOption = new Schema({ departmentId: { type: String, default: "", }, url: { type: String, default: "", }, }, { _id: false, id: false, }); const IncidentReplay = new Schema({ enabled: { type: Boolean, default: false, }, replays: { type: [ReplayOption], default: [], }, }, { _id: false, id: false, }); const Somewear = new Schema({ enabled: { type: Boolean, default: false, }, }, { _id: false, id: false, }); const PersonnelWebhook = new Schema({ enabled: { type: Boolean, default: false, }, }, { _id: false, id: false, }); const SkytracConfig = new Schema({ enabled: { type: Boolean, default: false, }, licenseKey: { type: String, default: "", }, username: { type: String, default: "", }, secret: { type: String, default: "", }, serviceUrl: { type: String, default: "", }, configTag: { type: String, default: "" }, }, { _id: false, id: false, }); const SimpleSenseConfig = new Schema({ token: { type: String, default: "", }, }, { _id: false, id: false, }); const StatusMappingObjectConfig = new Schema({ status: { type: String, default: "", }, statusCode: { type: String, default: "", } }, { _id: false, id: false, }); const StatusMappingConfig = new Schema({ TimeDispatched: { type: StatusMappingObjectConfig, }, TimeEnroute: { type: StatusMappingObjectConfig, }, TimeStaged: { type: StatusMappingObjectConfig, }, TimeArrived: { type: StatusMappingObjectConfig, }, TimeCleared: { type: StatusMappingObjectConfig, }, TimeAtHospital: { type: StatusMappingObjectConfig, }, TimePatient: { type: StatusMappingObjectConfig, }, TimeTransporting: { type: StatusMappingObjectConfig, }, TimeTransportComplete: { type: StatusMappingObjectConfig, }, }, { _id: false, id: false, }); const IncidentVehicleStatusConfig = new Schema({ enabled: { type: Boolean, default: false, }, statusMappings: { type: StatusMappingConfig, default: StatusMappingConfigDefault, }, statusExclusions: { type: [String], default: [], } }, { _id: false, id: false, }); const FirstArrivingConfig = new Schema({ token: { type: String, default: "", }, apiUrl: { type: String, default: "" } }, { _id: false, id: false, }); const SafetyPriorityKeyword = new Schema({ priority: { type: Number, default: 6, }, keywords: { type: [String], default: [], }, hexColor: { type: String, }, }, { _id: false, id: false, }); const WebDisclaimer = new Schema({ message: { type: String, default: "", }, enabled: { type: Boolean, default: false, }, }, { _id: false, id: false, }); const AudioStreamAuth = new Schema({ authId: { type: Schema.Types.ObjectId, ref: "AudioStreamAuthentication", required: true, }, path: { type: String, required: true, }, }, { _id: false, id: false, }); const AudioStream = new Schema({ // e.g. Central Dispatch Talk Group or also Available on 89.5 MHz description: { type: String, default: "", }, // e.g. B2 or CH99 channel: { type: String, default: "", }, url: { type: String, default: "", }, order: { type: Number, default: 0, }, authentication: { type: AudioStreamAuth, default: undefined, }, }, { _id: false, id: false, }); const AudioStreamGroup = new Schema({ group: { type: String, default: "", }, streams: { type: [AudioStream], default: [], }, order: { type: Number, default: 0, } }, { _id: false, id: false, }); const RestrictedComments = new Schema({ enabled: { type: Boolean, default: false, }, callTypesAllowed: { type: [String], default: [], }, statusesAllowed: { type: [String], default: [], }, restrictedFields: { type: [String], default: [], }, restrictedMessage: { type: String, default: "" }, }, { _id: false, id: false, }); const CustomButtons = new Schema({ name: { type: String, default: "", }, url: { type: String, default: "", }, order: { type: Number, default: 0, }, allowExternal: { type: Boolean, default: false, }, defaultExternal: { type: Boolean, default: false, }, allowFloating: { type: Boolean, default: false, }, color: { type: Color, default: null, }, }, { _id: false, id: false, }); const FireMapperLayer = new Schema({ pathname: { type: String, default: "", // Eg. /api/rest/services/features/FeatureServer/0 (including 0) }, name: { type: String, // eg. FireMapper - Symbols default: "", }, }, { _id: false, id: false, }); const FireMapperOutline = new Schema({ uuid: { type: String, default: "", }, name: { type: String, default: "", }, layer: { type: [FireMapperLayer], default: [], }, }, { _id: false, id: false, }); const SamsaraConfiguration = new Schema({ enabled: { type: Boolean, default: false, }, token: { type: String, default: "", }, tagIds: { type: [String], default: [], }, }, { _id: false, id: false, }); const USFTConfiguration = new Schema({ enabled: { type: Boolean, default: false, }, key: { type: String, default: "", }, secret: { type: String, default: "", }, }, { _id: false, id: false, }); const OneStepConfiguration = new Schema({ enabled: { type: Boolean, default: false, }, apiKey: { type: String, default: "", }, radioNameMappings: { type: Object, default: {}, }, }, { _id: false, id: false, }); const DroneSenseConfiguration = new Schema({ enabled: { type: Boolean, default: false, }, apiKey: { type: String, default: "", }, }, { _id: false, id: false, }); const DronesVideoUrls = new Schema({ web: { type: String, default: "", }, }, { _id: false, id: false, }); const DronesVideo = new Schema({ sources: { type: [String], default: [], }, urls: { type: DronesVideoUrls, default: () => ({ web: "" }), }, }, { _id: false, id: false, }); const DronesConfiguration = new Schema({ enabled: { type: Boolean, default: false, }, // No enum: a service on an older build must still save a department that names a // provider it does not know. server-admin validates the values on write. providers: { type: [{ type: String, lowercase: true }], default: [], }, video: { type: DronesVideo, default: () => ({ sources: [], urls: { web: "" } }), }, }, { _id: false, id: false, }); const FireMapperConfiguration = new Schema({ enabled: { type: Boolean, default: false, }, layerRefreshInterval: { type: Number, default: 15, }, // Number of available FM Pro licenses for this department proLicenseCount: { type: Number, default: 0, }, host: { // when empty, portal.firefront.com.au // when staging, staging.firefront.com.au // when us, us.firemapper.app type: String, default: "us", }, layer: { type: [FireMapperLayer], default: [], }, // A list of items that will be added to each map staticLayer: { type: [FireMapperOutline], default: [], }, // Auth auth: { type: FireMapperAuth, default: {}, }, }, { _id: false, id: false, }); const Licensing = new Schema({ tcPro2Way: { type: Number, default: 0, }, tcPro1Way: { type: Number, default: 0, }, tcMobile: { type: Number, default: 0, }, tcWeb: { type: Number, default: 0, }, fireMapperPro: { type: Number, default: 0, }, sendToCAD: { type: Number, default: 0, }, tcStreams: { type: Number, default: 0, }, }, { _id: false, id: false, }); const IncidentType = new Schema({ name: { type: String, default: "Any", }, value: { type: String, default: "any", }, // If true, instead of exact match (===), use title.includes(value) allowPartialMatch: { type: Boolean, default: false, }, // For AgencyIncidentCallTypeDescription callTypeDescription: { type: [String], default: [], }, // For AgencyIncidentCallType callType: { type: [String], default: [], } }, { _id: false, id: false, }); const ShareIncidentArea = new Schema({ name: String, objectId: Number, area: { type: GeoPolygon, default: { type: "Polygon", coordinates: [], }, } }, { _id: false, id: false, }); const optsIncidentShareRuleTypeV2Dis = { _id: false, id: false, discriminatorKey: "type", }; const IncidentShareRuleTypeV2Schema = new Schema({ type: { type: String, required: true, }, }, optsIncidentShareRuleTypeV2Dis); const ShareIncidentRuleTypeV2AssignedUnitSchema = new Schema({ radioNames: { type: [String], default: [], } }, optsIncidentShareRuleTypeV2Dis); IncidentShareRuleTypeV2Schema.discriminator("AssignedUnit", ShareIncidentRuleTypeV2AssignedUnitSchema); const ShareIncidentRuleTypeV2IncidentTypeSchema = new Schema({ callTypeDescription: { type: [String], default: [], } }, optsIncidentShareRuleTypeV2Dis); IncidentShareRuleTypeV2Schema.discriminator("IncidentType", ShareIncidentRuleTypeV2IncidentTypeSchema); const ShareIncidentRuleTypeV2ReportNumberSchema = new Schema({ startsWith: { type: [ReportNumber], default: [], }, }, optsIncidentShareRuleTypeV2Dis); IncidentShareRuleTypeV2Schema.discriminator("ReportNumber", ShareIncidentRuleTypeV2ReportNumberSchema); const ShareIncidentRuleTypeV2AreaSchema = new Schema({ area: { type: [ShareIncidentArea], default: [], }, }, optsIncidentShareRuleTypeV2Dis); IncidentShareRuleTypeV2Schema.discriminator("Area", ShareIncidentRuleTypeV2AreaSchema); const ShareIncidentRuleTypeV2ComplexANDxORSchema = new Schema({ operands: { type: [IncidentShareRuleTypeV2Schema], default: [], }, }, optsIncidentShareRuleTypeV2Dis); IncidentShareRuleTypeV2Schema.discriminator("ComplexAND", ShareIncidentRuleTypeV2ComplexANDxORSchema); IncidentShareRuleTypeV2Schema.discriminator("ComplexOR", ShareIncidentRuleTypeV2ComplexANDxORSchema); const SharedToDestinationTypeSchema = new Schema({ departmentId: { type: String, default: "", }, name: { type: String, default: "", }, }, { _id: false, id: false, }); const ShareIncidentRuleV2 = new Schema({ name: { type: String, default: "", }, accounts: { type: [SharedToDestinationTypeSchema], default: [], }, // v3 rules: { type: [IncidentShareRuleTypeV2Schema], default: [], }, sendNotification: { type: Boolean, default: false, }, }, { _id: false, id: false, }); const ManagedIncidentModeItemSchema = new Schema({ title: { type: String, }, color: { type: Color, }, position: { type: Number, default: 1, } }, { _id: false, id: false, }); const ManagedIncidentModeSchema = new Schema({ label: { type: String, }, items: { type: [ManagedIncidentModeItemSchema], default: [], } }, { _id: false, id: false, }); const ManagedIncidentPriorityItemSchema = new Schema({ title: { type: String, }, color: { type: Color, }, position: { type: Number, default: 1, }, }, { _id: false, id: false, }); const ManagedIncidentPrioritySchema = new Schema({ label: { type: String, }, items: { type: [ManagedIncidentPriorityItemSchema], default: [], }, }, { _id: false, id: false, }); const AccountConfigurationCallerLocationResolverSchema = new Schema({ type: { type: String, }, opts: { type: Object, }, }, { _id: false, id: false, }); const AccountConfigurationCallerLocationSchema = new Schema({ enabled: { type: Boolean, default: false, }, resolvers: { type: [AccountConfigurationCallerLocationResolverSchema], default: [], }, }, { _id: false, id: false, }); const CADGetLocationSettingsSchema = new Schema({ includeModems: { type: Boolean, default: false, }, selectModemsManually: { type: Boolean, default: false, }, includeGeotab: { type: Boolean, default: false, }, selectGeotabManually: { type: Boolean, default: false, }, }, { _id: false, id: false, }); const CADToCADConfig = new Schema({ departmentId: { type: String, default: "", }, defaultAgencyId: { type: String, default: "", }, cadTransferCode: { type: String, default: "", }, transferUsers: { type: Boolean, default: false, }, transferModems: { type: Boolean, default: false, }, }, { _id: false, id: false, }); const CADToCADSchema = new Schema({ enabled: { type: Boolean, default: false, }, allowedDepartments: { type: [CADToCADConfig], default: [], }, }, { _id: false, id: false, }); // Main schema const modelSchema = new Schema({ _id: { type: Schema.Types.ObjectId, auto: true, }, uuid: { type: String, default: uuid.v4, }, department: { type: String, default: "", }, fdid: { type: String, default: "", }, addressDetails: { address: { type: String, default: "", }, city: { type: String, default: "", }, state: { type: String, default: "", }, zipCode: { type: String, default: "", }, country: { type: String, default: "", }, }, contact: { department: { type: String, default: "", }, name: { type: String, default: "", }, phone: { type: String, default: "", }, email: { type: String, default: "", }, }, modified_unix_date: { type: Number, default: retrieveCurrentUnixTime, }, modified: { type: Date, default: currentDate, }, active: { type: Boolean, default: false, }, apikey: { type: String, default: "", select: false, }, partialApiKey: { type: String, default: "", }, cadEmailUsername: { type: String, default: "", }, notificationEmails: { type: [String], default: [] }, orientationMarkerColor: { type: Color, default: OrientationMarkerColorDefault, }, rosteringEnabled: { type: Boolean, default: false, }, rosteringShiftDefault: { type: Number, default: 777600, }, externalNotificationsEnabled: { type: Boolean, default: false }, // CAD Features cadToCAD: { type: CADToCADSchema, default: CADToCADDefault, }, cadBidirectionalEnabled: { type: Boolean, default: false, }, cadOneWayVehiclesEnabled: { type: Boolean, default: false, }, cadBidirectionalException: { type: Boolean, default: false, }, cadAllowedIPAddresses: { type: [String], default: [], }, cadGetLocationEnabled: { type: Boolean, default: false }, cadGetLocationSettings: { type: CADGetLocationSettingsSchema, default: CADGetLocationSettingsDefault, }, cadAllowIgnoreAfterDays: { type: Number, default: 21, }, // Incident History Item Type sent back to CAD // These correspond to IncidentHistoryType from iOS cadIncidentHistoryType: { type: [Number], default: [], }, // Incident Event Item Type sent back to CAD // These correspond to IncidentEvent.type from backend/iOS cadIncidentEventType: { type: [String], default: [ "userackcomment", "usercomment", ], }, connectivity: { incident: { enabled: { type: Boolean, default: false, }, staleMinutes: { type: Number, default: 30, }, heartbeatMinutes: { type: Number, default: 5 } }, location: { enabled: { type: Boolean, default: false, }, staleMinutes: { type: Number, default: 30, }, heartbeatMinutes: { type: Number, default: 5 } }, status: { enabled: { type: Boolean, default: false, }, staleMinutes: { type: Number, default: 30, }, heartbeatMinutes: { type: Number, default: 5 }, ackUnitsCount: { type: Number, default: 3 } } }, selfAssignmentEnabled: { type: Boolean, default: false, }, userContributionEnabled: { type: Boolean, default: false, }, vehicleSwapEnabled: { type: Boolean, default: false, }, personnelStaffingEnabled: { type: Boolean, default: false, }, // Inbound personnel-location webhook (server-webhook /api/webhook/personnel) personnelWebhook: { type: PersonnelWebhook, default: PersonnelWebhookDefault, }, // values: password, saml, o-google, later o-microsoft, etc authSource: { type: [String], default: ["password"], }, defaultMapPosition: { longitude: { type: Number, default: 0, }, latitude: { type: Number, default: 0, }, }, fireMapPDFReader: { type: String, default: "", }, locationStaleMinutes: { type: Number, default: 1440, // 24h }, locationAircraftStaleMinutes: { type: Number, default: 60, // 1h }, beaconEnabled: { type: Boolean, default: false, }, firstArrivingEnabled: { type: Boolean, default: false, }, firstArriving: { type: FirstArrivingConfig, default: FirstArrivingConfigDefault, }, simpleSenseEnabled: { type: Boolean, default: false, }, simpleSense: { type: SimpleSenseConfig, default: SimpleSenseConfigDefault, }, incidentVehicleStatus: { type: IncidentVehicleStatusConfig, }, // When set to true, a vehicle update will propagate to user.vehicle using the radioName (changing the vehicleId) // By default (false), a vehicleId change will keep the same user.vehicle vehicleId and update the radioName vehicleRadioNameIsStable: { type: Boolean, default: false }, fireMapper: { type: FireMapperConfiguration, default: FireMapperConfigurationDefault, }, // Uses ArcGIS maps, requires ArcGIS accounts // Set this to default=enabled until we figure out why we need the flag. arcGISMapsEnabled: { type: Boolean, default: true, }, beansAIEnabled: { type: Boolean, default: false, }, // MOWS - Mobile Only Web Security mowsEnabled: { type: Boolean, default: false }, // RTS rtsEnabled: { type: Boolean, default: true, }, rtsChannelPrefix: { type: String, default: "", }, pubNubV3: { type: PubNubToken, default: null, }, socketIO: { type: PubNubToken, default: null, }, // Move this to a different collection esriGeoJSONFilename: { type: String, default: "" }, // Incident Type APN incidentTypes: { type: [IncidentType], default: [], }, ackDelimiter: { type: String, default: "" }, // incident. AgencyIncidentCallTypeDescription OR AgencyIncidentCallType callTypeBlock: { type: [String], default: [], }, agencyIds: [{ type: mongoose.Schema.Types.ObjectId, ref: "Agency", default: [], }], cadInterfaceMetaDataId: { type: mongoose.Schema.Types.ObjectId, ref: "CADInterfaceMetaData", default: null, }, integrationType: { type: String, enum: [...IntegrationTypes, ""], default: "", }, // Signup signupKey: { type: String, default: "", }, signupDomains: { type: [String], default: [], }, safetyPriorityKeywords: { type: [SafetyPriorityKeyword], default: SafetyPriorityKeywordDefault, }, shareLocationPhones: { type: Boolean, default: false, }, shareLocationTablets: { type: Boolean, default: true, }, shareAVL: { enabled: { type: Boolean, default: false, }, opAreaName: { type: String, default: "", }, opAreaCode: { type: String, default: "", }, fadeZoomLevel: { type: Number, default: 45000, }, area: { type: [GeoPolygon], default: [], } }, shareIncident: { enabled: { type: Boolean, default: false, }, rulesV2: { type: [ShareIncidentRuleV2], default: [], } }, speedReportingEnabled: { type: Boolean, default: false, }, accountType: { type: String, default: "production" }, timeZone: { type: String, default: "America/Los_Angeles" }, remoteLoggingEnabled: { type: Boolean, default: false, }, logOffEnabled: { type: Boolean, default: false, }, licensing: { type: Licensing, default: LicensingDefault, }, webDisclaimer: { type: WebDisclaimer, default: WebDisclaimerDefault, }, addUserInstructions: { type: String, default: "", }, // Other values, status, comment, status-comment reportOdometer: { type: String, default: "", }, restrictedComments: { type: RestrictedComments, default: RestrictedCommentsDefault, }, customButtons: { type: [CustomButtons], default: [] }, reportNumberEnabled: { type: Boolean, default: false, }, audioConfiguration: { type: [AudioStreamGroup], default: [], }, minPasswordLength: { type: Number, default: 8, }, zonehaven: { enabled: { type: Boolean, default: false, }, visible: { type: Boolean, default: true, }, layerUrl: { type: String, default: "", }, fadeZoomLevel: { type: Number, default: 45000, }, accountName: { type: String, default: "", }, }, watchDuty: { enabled: { type: Boolean, default: false, }, visible: { type: Boolean, default: false, }, }, activeUserCount: { type: Number, default: 0, }, samsara: { type: SamsaraConfiguration, default: SamsaraConfigurationDefault, }, usft: { type: USFTConfiguration, default: USFTConfigurationDefault, }, onestep: { // cspell:disable-line type: OneStepConfiguration, default: OneStepConfigurationDefault, }, dronesense: { type: DroneSenseConfiguration, default: DroneSenseConfigurationDefault, }, drones: { type: DronesConfiguration, // Cloned per document so no department shares the default's arrays. default: () => structuredClone(DronesConfigurationDefault), }, mark43: { type: Mark43Config, default: Mark43ConfigDefault }, gmr: { type: GMRConfig, default: GMRConfigDefault }, webhook: { type: WebhookConfig, default: WebhookConfigDefault, }, wsFeed: { type: WSFeedConfig, default: WSFeedConfigDefault, }, intterra: { type: IntterraConfig, default: IntterraConfigDefault, }, skymira: { type: SkymiraConfig, default: SkymiraConfigDefault, }, adsb: { type: ADSBConfig, default: ADSBConfigDefault, }, geotab: { type: GeotabConfig, default: GeotabConfigDefault, }, skytrac: { type: [SkytracConfig], default: [], }, gst: { type: GSTConfig, default: GSTConfigDefault, }, incidentReplay: { type: IncidentReplay, default: IncidentReplayDefault, }, somewear: { type: Somewear, default: SomewearDefault, }, forwarding: { type: ForwardingConfig, default: ForwardingConfigDefault, }, vehicleStatusWebhook: { type: VehicleStatusWebhookConfig, default: VehicleStatusWebhookConfigDefault, }, managedIncidentMode: { type: ManagedIncidentModeSchema, default: ManagedIncidentModeDefault, }, managedIncidentPriority: { type: ManagedIncidentPrioritySchema, default: ManagedIncidentPriorityDefault, }, industry: { type: String, default: AccountIndustry.Fire, }, callerLocation: { type: AccountConfigurationCallerLocationSchema, }, inAppRoutingEnabled: { type: Boolean, default: false, }, allowShareWith3rdParties: { type: Boolean, default: false, }, }, { autoIndex: false, timestamps: { updatedAt: "modified", }, toJSON: { virtuals: true, versionKey: false, } }); modelSchema.index({ apikey: 1, }, { name: "apikey_1", unique: true, }); modelSchema.index({ department: 1, }, { name: "department_1_unique", unique: true, }); modelSchema.index({ rtsChannelPrefix: 1, }, { name: "rtsChannelPrefix_1_unique", unique: true, }); // TODO: Create this // modelSchema.index({ // uuid: 1, // }, { // name: "uuid_1_unique", // unique: true, // }); modelSchema.virtual("id").get(function(this: Department) { return this._id.toHexString(); }); modelSchema.plugin(mongooseLeanVirtuals); return mongoose.model("Department", modelSchema, "massive_admin", { overwriteModels: true }); } export interface DepartmentModel extends Model { }