From 8fa012be75bd9976ea6d68ccc22d5e8387c3405a Mon Sep 17 00:00:00 2001 From: Dan Gowans Date: Wed, 26 Mar 2025 13:21:28 -0400 Subject: [PATCH] linting and polish --- app.js | 29 +- app.ts | 44 ++- database/addRecord.js | 11 +- database/addRecord.ts | 11 +- database/getBurialSite.d.ts | 2 +- database/getBurialSite.js | 20 +- database/getBurialSite.ts | 50 ++-- database/moveRecord.d.ts | 2 +- database/moveRecord.js | 31 +-- database/moveRecord.ts | 53 ++-- database/updateContractType.ts | 1 + database/updateContractTypeField.d.ts | 8 +- database/updateContractTypeField.ts | 9 +- database/updateFeeCategory.ts | 1 + database/updateFuneralHome.d.ts | 2 +- database/updateFuneralHome.js | 3 +- database/updateFuneralHome.ts | 7 +- database/updateRecord.js | 21 +- database/updateRecord.ts | 21 +- database/updateRecordOrderNumber.d.ts | 2 +- database/updateRecordOrderNumber.js | 25 +- database/updateRecordOrderNumber.ts | 37 +-- database/updateWorkOrder.d.ts | 2 +- database/updateWorkOrder.ts | 3 +- database/updateWorkOrderComment.d.ts | 4 +- database/updateWorkOrderComment.ts | 5 +- database/updateWorkOrderMilestone.d.ts | 6 +- database/updateWorkOrderMilestone.ts | 7 +- handlers/permissions.d.ts | 2 +- handlers/permissions.js | 20 +- handlers/permissions.ts | 28 +- helpers/burialSites.helpers.ts | 6 +- helpers/contracts.helpers.d.ts | 2 +- helpers/contracts.helpers.js | 18 +- helpers/contracts.helpers.ts | 36 +-- helpers/functions.authentication.js | 32 +-- helpers/functions.authentication.ts | 42 +-- helpers/functions.cache.d.ts | 24 +- helpers/functions.cache.js | 172 ++++++------ helpers/functions.cache.ts | 282 +++++++++----------- helpers/functions.dynamicsGP.js | 135 +++++----- helpers/functions.dynamicsGP.ts | 191 ++++++------- helpers/functions.print.js | 20 +- helpers/functions.print.ts | 20 +- helpers/functions.user.d.ts | 14 +- helpers/functions.user.js | 14 +- helpers/functions.user.ts | 26 +- package-lock.json | 86 +++--- package.json | 2 +- public/html/contract-addInterment.html | 1 + public/html/contract-editInterment.html | 1 + routes/login.js | 2 +- routes/login.ts | 4 +- temp/legacyImportFromCsv/data.cemeteries.js | 4 +- temp/legacyImportFromCsv/data.cemeteries.ts | 9 +- temp/legacyImportFromCsv/index.js | 2 +- temp/legacyImportFromCsv/index.ts | 2 +- types/applicationTypes.d.ts | 18 +- types/applicationTypes.ts | 23 +- types/configTypes.d.ts | 16 +- types/configTypes.ts | 17 +- windowsService.ts | 1 + 62 files changed, 832 insertions(+), 857 deletions(-) diff --git a/app.js b/app.js index 382f615f..79f5a0a7 100644 --- a/app.js +++ b/app.js @@ -27,6 +27,7 @@ import routerPrint from './routes/print.js'; import routerReports from './routes/reports.js'; import routerWorkOrders from './routes/workOrders.js'; import { version } from './version.js'; +import { secondsToMillis } from '@cityssm/to-millis'; const debug = Debug(`${DEBUG_NAMESPACE}:app:${process.pid}`); /* * INITIALIZE APP @@ -52,15 +53,17 @@ app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); -app.use(csurf({ +app.use( +// eslint-disable-next-line sonarjs/insecure-cookie, sonarjs/cookie-no-httponly +csurf({ cookie: true })); /* * Rate Limiter */ app.use(rateLimit({ - windowMs: 10_000, - max: useTestDatabases ? 1_000_000 : 200 + max: useTestDatabases ? 1_000_000 : 200, + windowMs: secondsToMillis(10) })); /* * STATIC ROUTES @@ -86,20 +89,20 @@ const sessionCookieName = configFunctions.getConfigProperty('session.cookieName' const FileStoreSession = FileStore(session); // Initialize session app.use(session({ - store: new FileStoreSession({ - path: './data/sessions', - logFn: Debug(`${DEBUG_NAMESPACE}:session:${process.pid}`), - retries: 20 - }), name: sessionCookieName, - secret: configFunctions.getConfigProperty('session.secret'), - resave: true, - saveUninitialized: false, - rolling: true, cookie: { maxAge: configFunctions.getConfigProperty('session.maxAgeMillis'), sameSite: 'strict' - } + }, + secret: configFunctions.getConfigProperty('session.secret'), + store: new FileStoreSession({ + logFn: Debug(`${DEBUG_NAMESPACE}:session:${process.pid}`), + path: './data/sessions', + retries: 20 + }), + resave: true, + rolling: true, + saveUninitialized: false })); // Clear cookie if no corresponding session app.use((request, response, next) => { diff --git a/app.ts b/app.ts index e60ea184..4eefc12c 100644 --- a/app.ts +++ b/app.ts @@ -29,6 +29,7 @@ import routerPrint from './routes/print.js' import routerReports from './routes/reports.js' import routerWorkOrders from './routes/workOrders.js' import { version } from './version.js' +import { secondsToMillis } from '@cityssm/to-millis' const debug = Debug(`${DEBUG_NAMESPACE}:app:${process.pid}`) @@ -69,6 +70,7 @@ app.use( app.use(cookieParser()) app.use( + // eslint-disable-next-line sonarjs/insecure-cookie, sonarjs/cookie-no-httponly csurf({ cookie: true }) @@ -80,8 +82,8 @@ app.use( app.use( rateLimit({ - windowMs: 10_000, - max: useTestDatabases ? 1_000_000 : 200 + max: useTestDatabases ? 1_000_000 : 200, + windowMs: secondsToMillis(10) }) ) @@ -99,16 +101,12 @@ app.use(urlPrefix, express.static(path.join('public'))) app.use( `${urlPrefix}/lib/bulma`, - express.static( - path.join('node_modules', 'bulma', 'css') - ) + express.static(path.join('node_modules', 'bulma', 'css')) ) app.use( `${urlPrefix}/lib/bulma-tooltip`, - express.static( - path.join('node_modules', 'bulma-tooltip', 'dist', 'css') - ) + express.static(path.join('node_modules', 'bulma-tooltip', 'dist', 'css')) ) app.use( @@ -120,16 +118,12 @@ app.use( app.use( `${urlPrefix}/lib/cityssm-fa-glow`, - express.static( - path.join('node_modules', '@cityssm', 'fa-glow') - ) + express.static(path.join('node_modules', '@cityssm', 'fa-glow')) ) app.use( `${urlPrefix}/lib/cityssm-bulma-sticky-table`, - express.static( - path.join('node_modules', '@cityssm', 'bulma-sticky-table') - ) + express.static(path.join('node_modules', '@cityssm', 'bulma-sticky-table')) ) app.use( @@ -166,20 +160,22 @@ const FileStoreSession = FileStore(session) // Initialize session app.use( session({ - store: new FileStoreSession({ - path: './data/sessions', - logFn: Debug(`${DEBUG_NAMESPACE}:session:${process.pid}`), - retries: 20 - }), name: sessionCookieName, - secret: configFunctions.getConfigProperty('session.secret'), - resave: true, - saveUninitialized: false, - rolling: true, + cookie: { maxAge: configFunctions.getConfigProperty('session.maxAgeMillis'), sameSite: 'strict' - } + }, + secret: configFunctions.getConfigProperty('session.secret'), + store: new FileStoreSession({ + logFn: Debug(`${DEBUG_NAMESPACE}:session:${process.pid}`), + path: './data/sessions', + retries: 20 + }), + + resave: true, + rolling: true, + saveUninitialized: false }) ) diff --git a/database/addRecord.js b/database/addRecord.js index 4e45c5f3..12854a14 100644 --- a/database/addRecord.js +++ b/database/addRecord.js @@ -1,10 +1,11 @@ import { clearCacheByTableName } from '../helpers/functions.cache.js'; import { acquireConnection } from './pool.js'; -const recordNameColumns = new Map(); -recordNameColumns.set('BurialSiteStatuses', 'burialSiteStatus'); -recordNameColumns.set('BurialSiteTypes', 'burialSiteType'); -recordNameColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneType'); -recordNameColumns.set('WorkOrderTypes', 'workOrderType'); +const recordNameColumns = new Map([ + ['BurialSiteStatuses', 'burialSiteStatus'], + ['BurialSiteTypes', 'burialSiteType'], + ['WorkOrderMilestoneTypes', 'workOrderMilestoneType'], + ['WorkOrderTypes', 'workOrderType'] +]); export default async function addRecord(recordTable, recordName, orderNumber, user) { const database = await acquireConnection(); const rightNowMillis = Date.now(); diff --git a/database/addRecord.ts b/database/addRecord.ts index d38b0a25..93856271 100644 --- a/database/addRecord.ts +++ b/database/addRecord.ts @@ -8,11 +8,12 @@ type RecordTable = | 'WorkOrderMilestoneTypes' | 'WorkOrderTypes' -const recordNameColumns = new Map() -recordNameColumns.set('BurialSiteStatuses', 'burialSiteStatus') -recordNameColumns.set('BurialSiteTypes', 'burialSiteType') -recordNameColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneType') -recordNameColumns.set('WorkOrderTypes', 'workOrderType') +const recordNameColumns = new Map([ + ['BurialSiteStatuses', 'burialSiteStatus'], + ['BurialSiteTypes', 'burialSiteType'], + ['WorkOrderMilestoneTypes', 'workOrderMilestoneType'], + ['WorkOrderTypes', 'workOrderType'] +]) export default async function addRecord( recordTable: RecordTable, diff --git a/database/getBurialSite.d.ts b/database/getBurialSite.d.ts index 01b95d74..a43e7226 100644 --- a/database/getBurialSite.d.ts +++ b/database/getBurialSite.d.ts @@ -1,3 +1,3 @@ import type { BurialSite } from '../types/recordTypes.js'; -export declare function getBurialSiteByBurialSiteName(burialSiteName: string): Promise; export default function getBurialSite(burialSiteId: number | string): Promise; +export declare function getBurialSiteByBurialSiteName(burialSiteName: string): Promise; diff --git a/database/getBurialSite.js b/database/getBurialSite.js index 51def221..d37b2716 100644 --- a/database/getBurialSite.js +++ b/database/getBurialSite.js @@ -20,6 +20,12 @@ const baseSQL = `select l.burialSiteId, left join BurialSiteStatuses s on l.burialSiteStatusId = s.burialSiteStatusId left join Cemeteries m on l.cemeteryId = m.cemeteryId where l.recordDelete_timeMillis is null`; +export default async function getBurialSite(burialSiteId) { + return await _getBurialSite(`${baseSQL} and l.burialSiteId = ?`, burialSiteId); +} +export async function getBurialSiteByBurialSiteName(burialSiteName) { + return await _getBurialSite(`${baseSQL} and l.burialSiteName = ?`, burialSiteName); +} async function _getBurialSite(sql, burialSiteIdOrLotName) { const database = await acquireConnection(); const burialSite = database.prepare(sql).get(burialSiteIdOrLotName); @@ -27,11 +33,11 @@ async function _getBurialSite(sql, burialSiteIdOrLotName) { const contracts = await getContracts({ burialSiteId: burialSite.burialSiteId }, { - includeInterments: true, - includeFees: false, - includeTransactions: false, limit: -1, - offset: 0 + offset: 0, + includeFees: false, + includeInterments: true, + includeTransactions: false }, database); burialSite.contracts = contracts.contracts; burialSite.burialSiteFields = await getBurialSiteFields(burialSite.burialSiteId, database); @@ -40,9 +46,3 @@ async function _getBurialSite(sql, burialSiteIdOrLotName) { database.release(); return burialSite; } -export async function getBurialSiteByBurialSiteName(burialSiteName) { - return await _getBurialSite(`${baseSQL} and l.burialSiteName = ?`, burialSiteName); -} -export default async function getBurialSite(burialSiteId) { - return await _getBurialSite(`${baseSQL} and l.burialSiteId = ?`, burialSiteId); -} diff --git a/database/getBurialSite.ts b/database/getBurialSite.ts index 21b70ed7..4e9cb0ea 100644 --- a/database/getBurialSite.ts +++ b/database/getBurialSite.ts @@ -24,13 +24,30 @@ const baseSQL = `select l.burialSiteId, left join Cemeteries m on l.cemeteryId = m.cemeteryId where l.recordDelete_timeMillis is null` +export default async function getBurialSite( + burialSiteId: number | string +): Promise { + return await _getBurialSite(`${baseSQL} and l.burialSiteId = ?`, burialSiteId) +} + +export async function getBurialSiteByBurialSiteName( + burialSiteName: string +): Promise { + return await _getBurialSite( + `${baseSQL} and l.burialSiteName = ?`, + burialSiteName + ) +} + async function _getBurialSite( sql: string, burialSiteIdOrLotName: number | string ): Promise { const database = await acquireConnection() - const burialSite = database.prepare(sql).get(burialSiteIdOrLotName) as BurialSite | undefined + const burialSite = database.prepare(sql).get(burialSiteIdOrLotName) as + | BurialSite + | undefined if (burialSite !== undefined) { const contracts = await getContracts( @@ -38,35 +55,30 @@ async function _getBurialSite( burialSiteId: burialSite.burialSiteId }, { - includeInterments: true, - includeFees: false, - includeTransactions: false, limit: -1, - offset: 0 + offset: 0, + + includeFees: false, + includeInterments: true, + includeTransactions: false }, database ) burialSite.contracts = contracts.contracts - burialSite.burialSiteFields = await getBurialSiteFields(burialSite.burialSiteId, database) + burialSite.burialSiteFields = await getBurialSiteFields( + burialSite.burialSiteId, + database + ) - burialSite.burialSiteComments = await getBurialSiteComments(burialSite.burialSiteId, database) + burialSite.burialSiteComments = await getBurialSiteComments( + burialSite.burialSiteId, + database + ) } database.release() return burialSite } - -export async function getBurialSiteByBurialSiteName( - burialSiteName: string -): Promise { - return await _getBurialSite(`${baseSQL} and l.burialSiteName = ?`, burialSiteName) -} - -export default async function getBurialSite( - burialSiteId: number | string -): Promise { - return await _getBurialSite(`${baseSQL} and l.burialSiteId = ?`, burialSiteId) -} diff --git a/database/moveRecord.d.ts b/database/moveRecord.d.ts index 49d35c9e..ad573221 100644 --- a/database/moveRecord.d.ts +++ b/database/moveRecord.d.ts @@ -1,4 +1,4 @@ -type RecordTable = 'FeeCategories' | 'BurialSiteStatuses' | 'BurialSiteTypes' | 'ContractTypes' | 'WorkOrderMilestoneTypes' | 'WorkOrderTypes'; +type RecordTable = 'BurialSiteStatuses' | 'BurialSiteTypes' | 'ContractTypes' | 'FeeCategories' | 'WorkOrderMilestoneTypes' | 'WorkOrderTypes'; export declare function moveRecordDown(recordTable: RecordTable, recordId: number | string): Promise; export declare function moveRecordDownToBottom(recordTable: RecordTable, recordId: number | string): Promise; export declare function moveRecordUp(recordTable: RecordTable, recordId: number | string): Promise; diff --git a/database/moveRecord.js b/database/moveRecord.js index 315b802c..9654ca62 100644 --- a/database/moveRecord.js +++ b/database/moveRecord.js @@ -1,21 +1,14 @@ import { clearCacheByTableName } from '../helpers/functions.cache.js'; import { acquireConnection } from './pool.js'; import { updateRecordOrderNumber } from './updateRecordOrderNumber.js'; -const recordIdColumns = new Map(); -recordIdColumns.set('FeeCategories', 'feeCategoryId'); -recordIdColumns.set('BurialSiteStatuses', 'burialSiteStatusId'); -recordIdColumns.set('BurialSiteTypes', 'burialSiteTypeId'); -recordIdColumns.set('ContractTypes', 'contractTypeId'); -recordIdColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'); -recordIdColumns.set('WorkOrderTypes', 'workOrderTypeId'); -function getCurrentOrderNumber(recordTable, recordId, database) { - const currentOrderNumber = database - .prepare(`select orderNumber - from ${recordTable} - where ${recordIdColumns.get(recordTable)} = ?`) - .get(recordId).orderNumber; - return currentOrderNumber; -} +const recordIdColumns = new Map([ + ['BurialSiteStatuses', 'burialSiteStatusId'], + ['BurialSiteTypes', 'burialSiteTypeId'], + ['ContractTypes', 'contractTypeId'], + ['FeeCategories', 'feeCategoryId'], + ['WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'], + ['WorkOrderTypes', 'workOrderTypeId'] +]); export async function moveRecordDown(recordTable, recordId) { const database = await acquireConnection(); const currentOrderNumber = getCurrentOrderNumber(recordTable, recordId, database); @@ -85,3 +78,11 @@ export async function moveRecordUpToTop(recordTable, recordId) { clearCacheByTableName(recordTable); return true; } +function getCurrentOrderNumber(recordTable, recordId, database) { + const currentOrderNumber = database + .prepare(`select orderNumber + from ${recordTable} + where ${recordIdColumns.get(recordTable)} = ?`) + .get(recordId).orderNumber; + return currentOrderNumber; +} diff --git a/database/moveRecord.ts b/database/moveRecord.ts index b294bf3c..e7e2e783 100644 --- a/database/moveRecord.ts +++ b/database/moveRecord.ts @@ -6,38 +6,21 @@ import { acquireConnection } from './pool.js' import { updateRecordOrderNumber } from './updateRecordOrderNumber.js' type RecordTable = - | 'FeeCategories' | 'BurialSiteStatuses' | 'BurialSiteTypes' | 'ContractTypes' + | 'FeeCategories' | 'WorkOrderMilestoneTypes' | 'WorkOrderTypes' -const recordIdColumns = new Map() -recordIdColumns.set('FeeCategories', 'feeCategoryId') -recordIdColumns.set('BurialSiteStatuses', 'burialSiteStatusId') -recordIdColumns.set('BurialSiteTypes', 'burialSiteTypeId') -recordIdColumns.set('ContractTypes', 'contractTypeId') -recordIdColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId') -recordIdColumns.set('WorkOrderTypes', 'workOrderTypeId') - -function getCurrentOrderNumber( - recordTable: RecordTable, - recordId: number | string, - database: sqlite.Database -): number { - const currentOrderNumber: number = ( - database - .prepare( - `select orderNumber - from ${recordTable} - where ${recordIdColumns.get(recordTable)} = ?` - ) - .get(recordId) as { orderNumber: number } - ).orderNumber - - return currentOrderNumber -} +const recordIdColumns = new Map([ + ['BurialSiteStatuses', 'burialSiteStatusId'], + ['BurialSiteTypes', 'burialSiteTypeId'], + ['ContractTypes', 'contractTypeId'], + ['FeeCategories', 'feeCategoryId'], + ['WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'], + ['WorkOrderTypes', 'workOrderTypeId'] +]) export async function moveRecordDown( recordTable: RecordTable, @@ -187,3 +170,21 @@ export async function moveRecordUpToTop( return true } + +function getCurrentOrderNumber( + recordTable: RecordTable, + recordId: number | string, + database: sqlite.Database +): number { + const currentOrderNumber: number = ( + database + .prepare( + `select orderNumber + from ${recordTable} + where ${recordIdColumns.get(recordTable)} = ?` + ) + .get(recordId) as { orderNumber: number } + ).orderNumber + + return currentOrderNumber +} diff --git a/database/updateContractType.ts b/database/updateContractType.ts index c0fb9963..02c11688 100644 --- a/database/updateContractType.ts +++ b/database/updateContractType.ts @@ -4,6 +4,7 @@ import { acquireConnection } from './pool.js' export interface UpdateForm { contractTypeId: number | string + contractType: string isPreneed?: string } diff --git a/database/updateContractTypeField.d.ts b/database/updateContractTypeField.d.ts index 92187fdc..25e19502 100644 --- a/database/updateContractTypeField.d.ts +++ b/database/updateContractTypeField.d.ts @@ -1,11 +1,11 @@ export interface UpdateContractTypeFieldForm { contractTypeFieldId: number | string; contractTypeField: string; - isRequired: '0' | '1'; fieldType?: string; - minLength?: string; - maxLength?: string; - pattern?: string; fieldValues: string; + isRequired: '0' | '1'; + maxLength?: string; + minLength?: string; + pattern?: string; } export default function updateContractTypeField(updateForm: UpdateContractTypeFieldForm, user: User): Promise; diff --git a/database/updateContractTypeField.ts b/database/updateContractTypeField.ts index 580d3b4c..b0a84e37 100644 --- a/database/updateContractTypeField.ts +++ b/database/updateContractTypeField.ts @@ -4,13 +4,14 @@ import { acquireConnection } from './pool.js' export interface UpdateContractTypeFieldForm { contractTypeFieldId: number | string + contractTypeField: string - isRequired: '0' | '1' fieldType?: string - minLength?: string - maxLength?: string - pattern?: string fieldValues: string + isRequired: '0' | '1' + maxLength?: string + minLength?: string + pattern?: string } export default async function updateContractTypeField( diff --git a/database/updateFeeCategory.ts b/database/updateFeeCategory.ts index cda6c08c..fe896403 100644 --- a/database/updateFeeCategory.ts +++ b/database/updateFeeCategory.ts @@ -2,6 +2,7 @@ import { acquireConnection } from './pool.js' export interface UpdateFeeCategoryForm { feeCategoryId: number | string + feeCategory: string isGroupedFee?: '1' } diff --git a/database/updateFuneralHome.d.ts b/database/updateFuneralHome.d.ts index dee8c5e8..b872fe7b 100644 --- a/database/updateFuneralHome.d.ts +++ b/database/updateFuneralHome.d.ts @@ -4,8 +4,8 @@ export interface UpdateForm { funeralHomeAddress1: string; funeralHomeAddress2: string; funeralHomeCity: string; - funeralHomeProvince: string; funeralHomePostalCode: string; + funeralHomeProvince: string; funeralHomePhoneNumber: string; } export default function updateFuneralHome(updateForm: UpdateForm, user: User): Promise; diff --git a/database/updateFuneralHome.js b/database/updateFuneralHome.js index b0b6aa99..98d1243e 100644 --- a/database/updateFuneralHome.js +++ b/database/updateFuneralHome.js @@ -6,7 +6,8 @@ export default async function updateFuneralHome(updateForm, user) { .prepare(`update FuneralHomes set funeralHomeName = ?, funeralHomeAddress1 = ?, funeralHomeAddress2 = ?, - funeralHomeCity = ?, funeralHomeProvince = ?, funeralHomePostalCode = ?, funeralHomePhoneNumber = ?, + funeralHomeCity = ?, funeralHomeProvince = ?, funeralHomePostalCode = ?, + funeralHomePhoneNumber = ?, recordUpdate_userName = ?, recordUpdate_timeMillis = ? where recordDelete_timeMillis is null and funeralHomeId = ?`) diff --git a/database/updateFuneralHome.ts b/database/updateFuneralHome.ts index 2354fe33..4bd88c05 100644 --- a/database/updateFuneralHome.ts +++ b/database/updateFuneralHome.ts @@ -3,11 +3,13 @@ import { acquireConnection } from './pool.js' export interface UpdateForm { funeralHomeId: number | string funeralHomeName: string + funeralHomeAddress1: string funeralHomeAddress2: string funeralHomeCity: string - funeralHomeProvince: string funeralHomePostalCode: string + funeralHomeProvince: string + funeralHomePhoneNumber: string } @@ -24,7 +26,8 @@ export default async function updateFuneralHome( `update FuneralHomes set funeralHomeName = ?, funeralHomeAddress1 = ?, funeralHomeAddress2 = ?, - funeralHomeCity = ?, funeralHomeProvince = ?, funeralHomePostalCode = ?, funeralHomePhoneNumber = ?, + funeralHomeCity = ?, funeralHomeProvince = ?, funeralHomePostalCode = ?, + funeralHomePhoneNumber = ?, recordUpdate_userName = ?, recordUpdate_timeMillis = ? where recordDelete_timeMillis is null and funeralHomeId = ?` diff --git a/database/updateRecord.js b/database/updateRecord.js index ebc4bdf3..7c4763a6 100644 --- a/database/updateRecord.js +++ b/database/updateRecord.js @@ -1,19 +1,14 @@ import { clearCacheByTableName } from '../helpers/functions.cache.js'; import { acquireConnection } from './pool.js'; -const recordNameIdColumns = new Map(); -recordNameIdColumns.set('BurialSiteStatuses', [ - 'burialSiteStatus', - 'burialSiteStatusId' +const recordNameIdColumns = new Map([ + ['BurialSiteStatuses', ['burialSiteStatus', 'burialSiteStatusId']], + ['BurialSiteTypes', ['burialSiteType', 'burialSiteTypeId']], + [ + 'WorkOrderMilestoneTypes', + ['workOrderMilestoneType', 'workOrderMilestoneTypeId'] + ], + ['WorkOrderTypes', ['workOrderType', 'workOrderTypeId']] ]); -recordNameIdColumns.set('BurialSiteTypes', [ - 'burialSiteType', - 'burialSiteTypeId' -]); -recordNameIdColumns.set('WorkOrderMilestoneTypes', [ - 'workOrderMilestoneType', - 'workOrderMilestoneTypeId' -]); -recordNameIdColumns.set('WorkOrderTypes', ['workOrderType', 'workOrderTypeId']); export async function updateRecord(recordTable, recordId, recordName, user) { const database = await acquireConnection(); const result = database diff --git a/database/updateRecord.ts b/database/updateRecord.ts index 7312f8f9..ed0202f9 100644 --- a/database/updateRecord.ts +++ b/database/updateRecord.ts @@ -8,20 +8,15 @@ type RecordTable = | 'WorkOrderMilestoneTypes' | 'WorkOrderTypes' -const recordNameIdColumns = new Map() -recordNameIdColumns.set('BurialSiteStatuses', [ - 'burialSiteStatus', - 'burialSiteStatusId' +const recordNameIdColumns = new Map([ + ['BurialSiteStatuses', ['burialSiteStatus', 'burialSiteStatusId']], + ['BurialSiteTypes', ['burialSiteType', 'burialSiteTypeId']], + [ + 'WorkOrderMilestoneTypes', + ['workOrderMilestoneType', 'workOrderMilestoneTypeId'] + ], + ['WorkOrderTypes', ['workOrderType', 'workOrderTypeId']] ]) -recordNameIdColumns.set('BurialSiteTypes', [ - 'burialSiteType', - 'burialSiteTypeId' -]) -recordNameIdColumns.set('WorkOrderMilestoneTypes', [ - 'workOrderMilestoneType', - 'workOrderMilestoneTypeId' -]) -recordNameIdColumns.set('WorkOrderTypes', ['workOrderType', 'workOrderTypeId']) export async function updateRecord( recordTable: RecordTable, diff --git a/database/updateRecordOrderNumber.d.ts b/database/updateRecordOrderNumber.d.ts index bf2cd125..6c59b578 100644 --- a/database/updateRecordOrderNumber.d.ts +++ b/database/updateRecordOrderNumber.d.ts @@ -1,4 +1,4 @@ import type { PoolConnection } from 'better-sqlite-pool'; -type RecordTable = 'FeeCategories' | 'Fees' | 'BurialSiteStatuses' | 'BurialSiteTypes' | 'BurialSiteTypeFields' | 'IntermentContainerTypes' | 'CommittalTypes' | 'ContractTypes' | 'ContractTypeFields' | 'WorkOrderMilestoneTypes' | 'WorkOrderTypes'; +type RecordTable = 'BurialSiteStatuses' | 'BurialSiteTypeFields' | 'BurialSiteTypes' | 'CommittalTypes' | 'ContractTypeFields' | 'ContractTypes' | 'FeeCategories' | 'Fees' | 'IntermentContainerTypes' | 'WorkOrderMilestoneTypes' | 'WorkOrderTypes'; export declare function updateRecordOrderNumber(recordTable: RecordTable, recordId: number | string, orderNumber: number | string, connectedDatabase: PoolConnection): boolean; export {}; diff --git a/database/updateRecordOrderNumber.js b/database/updateRecordOrderNumber.js index 1cca7340..e36eb045 100644 --- a/database/updateRecordOrderNumber.js +++ b/database/updateRecordOrderNumber.js @@ -1,15 +1,16 @@ -const recordIdColumns = new Map(); -recordIdColumns.set('FeeCategories', 'feeCategoryId'); -recordIdColumns.set('Fees', 'feeId'); -recordIdColumns.set('BurialSiteStatuses', 'burialSiteStatusId'); -recordIdColumns.set('BurialSiteTypes', 'burialSiteTypeId'); -recordIdColumns.set('BurialSiteTypeFields', 'burialSiteTypeFieldId'); -recordIdColumns.set('IntermentContainerTypes', 'intermentContainerTypeId'); -recordIdColumns.set('CommittalTypes', 'committalTypeId'); -recordIdColumns.set('ContractTypes', 'contractTypeId'); -recordIdColumns.set('ContractTypeFields', 'contractTypeFieldId'); -recordIdColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'); -recordIdColumns.set('WorkOrderTypes', 'workOrderTypeId'); +const recordIdColumns = new Map([ + ['BurialSiteStatuses', 'burialSiteStatusId'], + ['BurialSiteTypeFields', 'burialSiteTypeFieldId'], + ['BurialSiteTypes', 'burialSiteTypeId'], + ['CommittalTypes', 'committalTypeId'], + ['ContractTypeFields', 'contractTypeFieldId'], + ['ContractTypes', 'contractTypeId'], + ['FeeCategories', 'feeCategoryId'], + ['Fees', 'feeId'], + ['IntermentContainerTypes', 'intermentContainerTypeId'], + ['WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'], + ['WorkOrderTypes', 'workOrderTypeId'] +]); export function updateRecordOrderNumber(recordTable, recordId, orderNumber, connectedDatabase) { const result = connectedDatabase .prepare(`update ${recordTable} diff --git a/database/updateRecordOrderNumber.ts b/database/updateRecordOrderNumber.ts index 6b9d3993..720f5f0f 100644 --- a/database/updateRecordOrderNumber.ts +++ b/database/updateRecordOrderNumber.ts @@ -1,30 +1,31 @@ import type { PoolConnection } from 'better-sqlite-pool' type RecordTable = + | 'BurialSiteStatuses' + | 'BurialSiteTypeFields' + | 'BurialSiteTypes' + | 'CommittalTypes' + | 'ContractTypeFields' + | 'ContractTypes' | 'FeeCategories' | 'Fees' - | 'BurialSiteStatuses' - | 'BurialSiteTypes' - | 'BurialSiteTypeFields' | 'IntermentContainerTypes' - | 'CommittalTypes' - | 'ContractTypes' - | 'ContractTypeFields' | 'WorkOrderMilestoneTypes' | 'WorkOrderTypes' -const recordIdColumns = new Map() -recordIdColumns.set('FeeCategories', 'feeCategoryId') -recordIdColumns.set('Fees', 'feeId') -recordIdColumns.set('BurialSiteStatuses', 'burialSiteStatusId') -recordIdColumns.set('BurialSiteTypes', 'burialSiteTypeId') -recordIdColumns.set('BurialSiteTypeFields', 'burialSiteTypeFieldId') -recordIdColumns.set('IntermentContainerTypes', 'intermentContainerTypeId') -recordIdColumns.set('CommittalTypes', 'committalTypeId') -recordIdColumns.set('ContractTypes', 'contractTypeId') -recordIdColumns.set('ContractTypeFields', 'contractTypeFieldId') -recordIdColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId') -recordIdColumns.set('WorkOrderTypes', 'workOrderTypeId') +const recordIdColumns = new Map([ + ['BurialSiteStatuses', 'burialSiteStatusId'], + ['BurialSiteTypeFields', 'burialSiteTypeFieldId'], + ['BurialSiteTypes', 'burialSiteTypeId'], + ['CommittalTypes', 'committalTypeId'], + ['ContractTypeFields', 'contractTypeFieldId'], + ['ContractTypes', 'contractTypeId'], + ['FeeCategories', 'feeCategoryId'], + ['Fees', 'feeId'], + ['IntermentContainerTypes', 'intermentContainerTypeId'], + ['WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'], + ['WorkOrderTypes', 'workOrderTypeId'] +]) export function updateRecordOrderNumber( recordTable: RecordTable, diff --git a/database/updateWorkOrder.d.ts b/database/updateWorkOrder.d.ts index 1319306d..96e44134 100644 --- a/database/updateWorkOrder.d.ts +++ b/database/updateWorkOrder.d.ts @@ -2,8 +2,8 @@ import { type DateString } from '@cityssm/utils-datetime'; export interface UpdateWorkOrderForm { workOrderId: string; workOrderNumber: string; - workOrderTypeId: string; workOrderDescription: string; workOrderOpenDateString: DateString; + workOrderTypeId: string; } export default function updateWorkOrder(workOrderForm: UpdateWorkOrderForm, user: User): Promise; diff --git a/database/updateWorkOrder.ts b/database/updateWorkOrder.ts index 68fa8210..65130991 100644 --- a/database/updateWorkOrder.ts +++ b/database/updateWorkOrder.ts @@ -5,9 +5,10 @@ import { acquireConnection } from './pool.js' export interface UpdateWorkOrderForm { workOrderId: string workOrderNumber: string - workOrderTypeId: string + workOrderDescription: string workOrderOpenDateString: DateString + workOrderTypeId: string } export default async function updateWorkOrder( diff --git a/database/updateWorkOrderComment.d.ts b/database/updateWorkOrderComment.d.ts index efeac9f5..ce8eb3a0 100644 --- a/database/updateWorkOrderComment.d.ts +++ b/database/updateWorkOrderComment.d.ts @@ -1,8 +1,8 @@ import { type DateString, type TimeString } from '@cityssm/utils-datetime'; export interface UpdateWorkOrderCommentForm { - workOrderCommentId: string | number; + workOrderCommentId: number | string; + comment: string; commentDateString: DateString; commentTimeString: TimeString; - comment: string; } export default function updateWorkOrderComment(commentForm: UpdateWorkOrderCommentForm, user: User): Promise; diff --git a/database/updateWorkOrderComment.ts b/database/updateWorkOrderComment.ts index ad865c17..3e752f9b 100644 --- a/database/updateWorkOrderComment.ts +++ b/database/updateWorkOrderComment.ts @@ -8,10 +8,11 @@ import { import { acquireConnection } from './pool.js' export interface UpdateWorkOrderCommentForm { - workOrderCommentId: string | number + workOrderCommentId: number | string + + comment: string commentDateString: DateString commentTimeString: TimeString - comment: string } export default async function updateWorkOrderComment( diff --git a/database/updateWorkOrderMilestone.d.ts b/database/updateWorkOrderMilestone.d.ts index 1d763f43..6521e13e 100644 --- a/database/updateWorkOrderMilestone.d.ts +++ b/database/updateWorkOrderMilestone.d.ts @@ -1,8 +1,8 @@ export interface UpdateWorkOrderMilestoneForm { - workOrderMilestoneId: string | number; - workOrderMilestoneTypeId: number | string; + workOrderMilestoneId: number | string; workOrderMilestoneDateString: string; - workOrderMilestoneTimeString?: string; workOrderMilestoneDescription: string; + workOrderMilestoneTimeString?: string; + workOrderMilestoneTypeId: number | string; } export default function updateWorkOrderMilestone(milestoneForm: UpdateWorkOrderMilestoneForm, user: User): Promise; diff --git a/database/updateWorkOrderMilestone.ts b/database/updateWorkOrderMilestone.ts index 750d6eea..8ceb3c12 100644 --- a/database/updateWorkOrderMilestone.ts +++ b/database/updateWorkOrderMilestone.ts @@ -6,11 +6,12 @@ import { import { acquireConnection } from './pool.js' export interface UpdateWorkOrderMilestoneForm { - workOrderMilestoneId: string | number - workOrderMilestoneTypeId: number | string + workOrderMilestoneId: number | string + workOrderMilestoneDateString: string - workOrderMilestoneTimeString?: string workOrderMilestoneDescription: string + workOrderMilestoneTimeString?: string + workOrderMilestoneTypeId: number | string } export default async function updateWorkOrderMilestone( diff --git a/handlers/permissions.d.ts b/handlers/permissions.d.ts index ada22b9c..bd4f8254 100644 --- a/handlers/permissions.d.ts +++ b/handlers/permissions.d.ts @@ -1,6 +1,6 @@ import type { NextFunction, Request, Response } from 'express'; export declare function adminGetHandler(request: Request, response: Response, next: NextFunction): void; export declare function adminPostHandler(request: Request, response: Response, next: NextFunction): void; +export declare function apiGetHandler(request: Request, response: Response, next: NextFunction): Promise; export declare function updateGetHandler(request: Request, response: Response, next: NextFunction): void; export declare function updatePostHandler(request: Request, response: Response, next: NextFunction): void; -export declare function apiGetHandler(request: Request, response: Response, next: NextFunction): Promise; diff --git a/handlers/permissions.js b/handlers/permissions.js index 63f769b2..47d50801 100644 --- a/handlers/permissions.js +++ b/handlers/permissions.js @@ -3,8 +3,8 @@ import { apiKeyIsValid, userCanUpdate, userIsAdmin } from '../helpers/functions. const urlPrefix = getConfigProperty('reverseProxy.urlPrefix'); const forbiddenStatus = 403; const forbiddenJSON = { - success: false, - message: 'Forbidden' + message: 'Forbidden', + success: false }; const forbiddenRedirectURL = `${urlPrefix}/dashboard/?error=accessDenied`; export function adminGetHandler(request, response, next) { @@ -21,6 +21,14 @@ export function adminPostHandler(request, response, next) { } response.status(forbiddenStatus).json(forbiddenJSON); } +export async function apiGetHandler(request, response, next) { + if (await apiKeyIsValid(request)) { + next(); + } + else { + response.redirect(`${urlPrefix}/login`); + } +} export function updateGetHandler(request, response, next) { if (userCanUpdate(request)) { next(); @@ -35,11 +43,3 @@ export function updatePostHandler(request, response, next) { } response.status(forbiddenStatus).json(forbiddenJSON); } -export async function apiGetHandler(request, response, next) { - if (await apiKeyIsValid(request)) { - next(); - } - else { - response.redirect(`${urlPrefix}/login`); - } -} diff --git a/handlers/permissions.ts b/handlers/permissions.ts index bb345b1e..62e3695b 100644 --- a/handlers/permissions.ts +++ b/handlers/permissions.ts @@ -12,8 +12,8 @@ const urlPrefix = getConfigProperty('reverseProxy.urlPrefix') const forbiddenStatus = 403 const forbiddenJSON = { - success: false, - message: 'Forbidden' + message: 'Forbidden', + success: false } const forbiddenRedirectURL = `${urlPrefix}/dashboard/?error=accessDenied` @@ -44,6 +44,18 @@ export function adminPostHandler( response.status(forbiddenStatus).json(forbiddenJSON) } +export async function apiGetHandler( + request: Request, + response: Response, + next: NextFunction +): Promise { + if (await apiKeyIsValid(request)) { + next() + } else { + response.redirect(`${urlPrefix}/login`) + } +} + export function updateGetHandler( request: Request, response: Response, @@ -69,15 +81,3 @@ export function updatePostHandler( response.status(forbiddenStatus).json(forbiddenJSON) } - -export async function apiGetHandler( - request: Request, - response: Response, - next: NextFunction -): Promise { - if (await apiKeyIsValid(request)) { - next() - } else { - response.redirect(`${urlPrefix}/login`) - } -} diff --git a/helpers/burialSites.helpers.ts b/helpers/burialSites.helpers.ts index d4b5ebb0..96a0a38b 100644 --- a/helpers/burialSites.helpers.ts +++ b/helpers/burialSites.helpers.ts @@ -7,14 +7,14 @@ import { minutesToSeconds } from '@cityssm/to-millis' import Debug from 'debug' import NodeCache from 'node-cache' +import getNextBurialSiteIdFromDatabase from '../database/getNextBurialSiteId.js' +import getPreviousBurialSiteIdFromDatabase from '../database/getPreviousBurialSiteId.js' +import { DEBUG_NAMESPACE } from '../debug.config.js' import type { CacheBurialSiteIdsWorkerMessage, ClearNextPreviousBurialSiteIdsCacheWorkerMessage } from '../types/applicationTypes.js' -import getNextBurialSiteIdFromDatabase from '../database/getNextBurialSiteId.js' -import getPreviousBurialSiteIdFromDatabase from '../database/getPreviousBurialSiteId.js' -import { DEBUG_NAMESPACE } from '../debug.config.js' import { getConfigProperty } from './config.helpers.js' const debug = Debug(`${DEBUG_NAMESPACE}:burialSites.helpers:${process.pid}`) diff --git a/helpers/contracts.helpers.d.ts b/helpers/contracts.helpers.d.ts index a81164aa..fee85ebd 100644 --- a/helpers/contracts.helpers.d.ts +++ b/helpers/contracts.helpers.d.ts @@ -1,4 +1,4 @@ import type { Contract, ContractFee } from '../types/recordTypes.js'; -export declare function getFieldValueByContractTypeField(contract: Contract, contractTypeField: string): string | undefined; export declare function getFeesByFeeCategory(contract: Contract, feeCategory: string, feeCategoryContains?: boolean): ContractFee[]; +export declare function getFieldValueByContractTypeField(contract: Contract, contractTypeField: string): string | undefined; export declare function getTransactionTotal(contract: Contract): number; diff --git a/helpers/contracts.helpers.js b/helpers/contracts.helpers.js index 0e85e817..5cf19c6b 100644 --- a/helpers/contracts.helpers.js +++ b/helpers/contracts.helpers.js @@ -1,12 +1,3 @@ -export function getFieldValueByContractTypeField(contract, contractTypeField) { - const contractTypeFieldLowerCase = contractTypeField.toLowerCase(); - const field = (contract.contractFields ?? []).find((possibleField) => possibleField.contractTypeField.toLowerCase() === - contractTypeFieldLowerCase); - if (field === undefined) { - return undefined; - } - return field.fieldValue; -} export function getFeesByFeeCategory(contract, feeCategory, feeCategoryContains = false) { const feeCategoryLowerCase = feeCategory.toLowerCase(); return (contract.contractFees ?? []).filter((possibleFee) => feeCategoryContains @@ -16,6 +7,15 @@ export function getFeesByFeeCategory(contract, feeCategory, feeCategoryContains : possibleFee.feeCategory.toLowerCase() === feeCategoryLowerCase); } +export function getFieldValueByContractTypeField(contract, contractTypeField) { + const contractTypeFieldLowerCase = contractTypeField.toLowerCase(); + const field = (contract.contractFields ?? []).find((possibleField) => possibleField.contractTypeField.toLowerCase() === + contractTypeFieldLowerCase); + if (field === undefined) { + return undefined; + } + return field.fieldValue; +} export function getTransactionTotal(contract) { let transactionTotal = 0; for (const transaction of contract.contractTransactions ?? diff --git a/helpers/contracts.helpers.ts b/helpers/contracts.helpers.ts index 3d051699..8ee765d9 100644 --- a/helpers/contracts.helpers.ts +++ b/helpers/contracts.helpers.ts @@ -3,6 +3,24 @@ import type { ContractFee } from '../types/recordTypes.js' +export function getFeesByFeeCategory( + contract: Contract, + feeCategory: string, + feeCategoryContains = false +): ContractFee[] { + const feeCategoryLowerCase = feeCategory.toLowerCase() + + return (contract.contractFees ?? []).filter( + (possibleFee) => + feeCategoryContains + ? (possibleFee.feeCategory as string) + .toLowerCase() + .includes(feeCategoryLowerCase) + : (possibleFee.feeCategory as string).toLowerCase() === + feeCategoryLowerCase + ) +} + export function getFieldValueByContractTypeField( contract: Contract, contractTypeField: string @@ -22,24 +40,6 @@ export function getFieldValueByContractTypeField( return field.fieldValue } -export function getFeesByFeeCategory( - contract: Contract, - feeCategory: string, - feeCategoryContains = false -): ContractFee[] { - const feeCategoryLowerCase = feeCategory.toLowerCase() - - return (contract.contractFees ?? []).filter( - (possibleFee) => - feeCategoryContains - ? (possibleFee.feeCategory as string) - .toLowerCase() - .includes(feeCategoryLowerCase) - : (possibleFee.feeCategory as string).toLowerCase() === - feeCategoryLowerCase - ) -} - export function getTransactionTotal( contract: Contract ): number { diff --git a/helpers/functions.authentication.js b/helpers/functions.authentication.js index 62bde639..424b1c56 100644 --- a/helpers/functions.authentication.js +++ b/helpers/functions.authentication.js @@ -2,6 +2,12 @@ import ActiveDirectory from 'activedirectory2'; import { getConfigProperty } from './config.helpers.js'; const userDomain = getConfigProperty('application.userDomain'); const activeDirectoryConfig = getConfigProperty('activeDirectory'); +export async function authenticate(userName, password) { + if ((userName ?? '') === '' || (password ?? '') === '') { + return false; + } + return await authenticateViaActiveDirectory(userName ?? '', password ?? ''); +} async function authenticateViaActiveDirectory(userName, password) { return await new Promise((resolve) => { try { @@ -19,33 +25,27 @@ async function authenticateViaActiveDirectory(userName, password) { } }); } -export async function authenticate(userName, password) { - if ((userName ?? '') === '' || (password ?? '') === '') { - return false; - } - return await authenticateViaActiveDirectory(userName ?? '', password ?? ''); -} /* eslint-disable @cspell/spellchecker */ const safeRedirects = new Set([ - '/admin/cleanup', - '/admin/fees', '/admin/burialsitetypes', + '/admin/cleanup', '/admin/contracttypes', + '/admin/fees', '/admin/tables', - '/contracts', - '/contracts/new', - '/burialSites', - '/burialSites/new', + '/burialsites', + '/burialsites/new', '/cemeteries', '/cemeteries/new', + '/contracts', + '/contracts/new', + '/reports', '/workorders', - '/workorders/new', '/workorders/milestonecalendar', - '/workorders/outlook', - '/reports' + '/workorders/new', + '/workorders/outlook' ]); /* eslint-enable @cspell/spellchecker */ -const recordUrl = /^\/(?:cemeteries|burialSites|contracts|workorders)\/\d+(?:\/edit)?$/; +const recordUrl = /^\/(?:cemeteries|burialsites|contracts|workorders)\/\d+(?:\/edit)?$/; const printUrl = /^\/print\/(?:pdf|screen)\/[\d/=?A-Za-z-]+$/; export function getSafeRedirectURL(possibleRedirectURL = '') { const urlPrefix = getConfigProperty('reverseProxy.urlPrefix'); diff --git a/helpers/functions.authentication.ts b/helpers/functions.authentication.ts index 6e82974d..6b733885 100644 --- a/helpers/functions.authentication.ts +++ b/helpers/functions.authentication.ts @@ -6,6 +6,17 @@ const userDomain = getConfigProperty('application.userDomain') const activeDirectoryConfig = getConfigProperty('activeDirectory') +export async function authenticate( + userName: string | undefined, + password: string | undefined +): Promise { + if ((userName ?? '') === '' || (password ?? '') === '') { + return false + } + + return await authenticateViaActiveDirectory(userName ?? '', password ?? '') +} + async function authenticateViaActiveDirectory( userName: string, password: string @@ -29,41 +40,30 @@ async function authenticateViaActiveDirectory( }) } -export async function authenticate( - userName: string | undefined, - password: string | undefined -): Promise { - if ((userName ?? '') === '' || (password ?? '') === '') { - return false - } - - return await authenticateViaActiveDirectory(userName ?? '', password ?? '') -} - /* eslint-disable @cspell/spellchecker */ const safeRedirects = new Set([ - '/admin/cleanup', - '/admin/fees', '/admin/burialsitetypes', + '/admin/cleanup', '/admin/contracttypes', + '/admin/fees', '/admin/tables', - '/contracts', - '/contracts/new', - '/burialSites', - '/burialSites/new', + '/burialsites', + '/burialsites/new', '/cemeteries', '/cemeteries/new', + '/contracts', + '/contracts/new', + '/reports', '/workorders', - '/workorders/new', '/workorders/milestonecalendar', - '/workorders/outlook', - '/reports' + '/workorders/new', + '/workorders/outlook' ]) /* eslint-enable @cspell/spellchecker */ -const recordUrl = /^\/(?:cemeteries|burialSites|contracts|workorders)\/\d+(?:\/edit)?$/ +const recordUrl = /^\/(?:cemeteries|burialsites|contracts|workorders)\/\d+(?:\/edit)?$/ const printUrl = /^\/print\/(?:pdf|screen)\/[\d/=?A-Za-z-]+$/ diff --git a/helpers/functions.cache.d.ts b/helpers/functions.cache.d.ts index 3900b72e..a7ce270e 100644 --- a/helpers/functions.cache.d.ts +++ b/helpers/functions.cache.d.ts @@ -1,26 +1,26 @@ import type { BurialSiteStatus, BurialSiteType, CommittalType, ContractType, ContractTypeField, IntermentContainerType, WorkOrderMilestoneType, WorkOrderType } from '../types/recordTypes.js'; -export declare function getBurialSiteStatuses(): Promise; -export declare function getBurialSiteStatusById(burialSiteStatusId: number): Promise; export declare function getBurialSiteStatusByBurialSiteStatus(burialSiteStatus: string): Promise; -export declare function getBurialSiteTypes(): Promise; +export declare function getBurialSiteStatusById(burialSiteStatusId: number): Promise; +export declare function getBurialSiteStatuses(): Promise; export declare function getBurialSiteTypeById(burialSiteTypeId: number): Promise; +export declare function getBurialSiteTypes(): Promise; export declare function getBurialSiteTypesByBurialSiteType(burialSiteType: string): Promise; -export declare function getContractTypes(): Promise; export declare function getAllContractTypeFields(): Promise; -export declare function getContractTypeById(contractTypeId: number): Promise; export declare function getContractTypeByContractType(contractTypeString: string): Promise; +export declare function getContractTypeById(contractTypeId: number): Promise; export declare function getContractTypePrintsById(contractTypeId: number): Promise; -export declare function getIntermentContainerTypes(): Promise; +export declare function getContractTypes(): Promise; export declare function getIntermentContainerTypeById(intermentContainerTypeId: number): Promise; -export declare function getCommittalTypes(): Promise; +export declare function getIntermentContainerTypes(): Promise; export declare function getCommittalTypeById(committalTypeId: number): Promise; -export declare function getWorkOrderTypes(): Promise; +export declare function getCommittalTypes(): Promise; export declare function getWorkOrderTypeById(workOrderTypeId: number): Promise; -export declare function getWorkOrderMilestoneTypes(): Promise; +export declare function getWorkOrderTypes(): Promise; +type CacheTableNames = 'BurialSiteStatuses' | 'BurialSiteTypeFields' | 'BurialSiteTypes' | 'CommittalTypes' | 'ContractTypeFields' | 'ContractTypePrints' | 'ContractTypes' | 'FeeCategories' | 'Fees' | 'IntermentContainerTypes' | 'WorkOrderMilestoneTypes' | 'WorkOrderTypes'; +export declare function clearCacheByTableName(tableName: CacheTableNames, relayMessage?: boolean): void; +export declare function clearCaches(): void; export declare function getWorkOrderMilestoneTypeById(workOrderMilestoneTypeId: number): Promise; export declare function getWorkOrderMilestoneTypeByWorkOrderMilestoneType(workOrderMilestoneTypeString: string): Promise; +export declare function getWorkOrderMilestoneTypes(): Promise; export declare function preloadCaches(): Promise; -export declare function clearCaches(): void; -type CacheTableNames = 'BurialSiteStatuses' | 'BurialSiteTypes' | 'BurialSiteTypeFields' | 'ContractTypes' | 'ContractTypeFields' | 'ContractTypePrints' | 'IntermentContainerTypes' | 'CommittalTypes' | 'WorkOrderMilestoneTypes' | 'WorkOrderTypes' | 'FeeCategories' | 'Fees'; -export declare function clearCacheByTableName(tableName: CacheTableNames, relayMessage?: boolean): void; export {}; diff --git a/helpers/functions.cache.js b/helpers/functions.cache.js index 09a6748f..25013a99 100644 --- a/helpers/functions.cache.js +++ b/helpers/functions.cache.js @@ -1,5 +1,3 @@ -// eslint-disable-next-line @eslint-community/eslint-comments/disable-enable-pair -/* eslint-disable @typescript-eslint/init-declarations */ import cluster from 'node:cluster'; import Debug from 'debug'; import getBurialSiteStatusesFromDatabase from '../database/getBurialSiteStatuses.js'; @@ -17,20 +15,18 @@ const debug = Debug(`${DEBUG_NAMESPACE}:functions.cache:${process.pid}`); * Burial Site Statuses */ let burialSiteStatuses; -export async function getBurialSiteStatuses() { - if (burialSiteStatuses === undefined) { - burialSiteStatuses = await getBurialSiteStatusesFromDatabase(); - } - return burialSiteStatuses; +export async function getBurialSiteStatusByBurialSiteStatus(burialSiteStatus) { + const cachedStatuses = await getBurialSiteStatuses(); + const statusLowerCase = burialSiteStatus.toLowerCase(); + return cachedStatuses.find((currentStatus) => currentStatus.burialSiteStatus.toLowerCase() === statusLowerCase); } export async function getBurialSiteStatusById(burialSiteStatusId) { const cachedStatuses = await getBurialSiteStatuses(); return cachedStatuses.find((currentStatus) => currentStatus.burialSiteStatusId === burialSiteStatusId); } -export async function getBurialSiteStatusByBurialSiteStatus(burialSiteStatus) { - const cachedStatuses = await getBurialSiteStatuses(); - const statusLowerCase = burialSiteStatus.toLowerCase(); - return cachedStatuses.find((currentStatus) => currentStatus.burialSiteStatus.toLowerCase() === statusLowerCase); +export async function getBurialSiteStatuses() { + burialSiteStatuses ??= await getBurialSiteStatusesFromDatabase(); + return burialSiteStatuses; } function clearBurialSiteStatusesCache() { burialSiteStatuses = undefined; @@ -39,16 +35,14 @@ function clearBurialSiteStatusesCache() { * Burial Site Types */ let burialSiteTypes; -export async function getBurialSiteTypes() { - if (burialSiteTypes === undefined) { - burialSiteTypes = await getBurialSiteTypesFromDatabase(); - } - return burialSiteTypes; -} export async function getBurialSiteTypeById(burialSiteTypeId) { const cachedTypes = await getBurialSiteTypes(); return cachedTypes.find((currentType) => currentType.burialSiteTypeId === burialSiteTypeId); } +export async function getBurialSiteTypes() { + burialSiteTypes ??= await getBurialSiteTypesFromDatabase(); + return burialSiteTypes; +} export async function getBurialSiteTypesByBurialSiteType(burialSiteType) { const cachedTypes = await getBurialSiteTypes(); const typeLowerCase = burialSiteType.toLowerCase(); @@ -62,27 +56,19 @@ function clearBurialSiteTypesCache() { */ let contractTypes; let allContractTypeFields; -export async function getContractTypes() { - if (contractTypes === undefined) { - contractTypes = await getContractTypesFromDatabase(); - } - return contractTypes; -} export async function getAllContractTypeFields() { - if (allContractTypeFields === undefined) { - allContractTypeFields = await getContractTypeFieldsFromDatabase(); - } + allContractTypeFields ??= await getContractTypeFieldsFromDatabase(); return allContractTypeFields; } -export async function getContractTypeById(contractTypeId) { - const cachedTypes = await getContractTypes(); - return cachedTypes.find((currentType) => currentType.contractTypeId === contractTypeId); -} export async function getContractTypeByContractType(contractTypeString) { const cachedTypes = await getContractTypes(); const typeLowerCase = contractTypeString.toLowerCase(); return cachedTypes.find((currentType) => currentType.contractType.toLowerCase() === typeLowerCase); } +export async function getContractTypeById(contractTypeId) { + const cachedTypes = await getContractTypes(); + return cachedTypes.find((currentType) => currentType.contractTypeId === contractTypeId); +} export async function getContractTypePrintsById(contractTypeId) { const contractType = await getContractTypeById(contractTypeId); if (contractType?.contractTypePrints === undefined || @@ -94,6 +80,10 @@ export async function getContractTypePrintsById(contractTypeId) { } return contractType.contractTypePrints ?? []; } +export async function getContractTypes() { + contractTypes ??= await getContractTypesFromDatabase(); + return contractTypes; +} function clearContractTypesCache() { contractTypes = undefined; allContractTypeFields = undefined; @@ -102,16 +92,14 @@ function clearContractTypesCache() { * Interment Container Types */ let intermentContainerTypes; -export async function getIntermentContainerTypes() { - if (intermentContainerTypes === undefined) { - intermentContainerTypes = await getIntermentContainerTypesFromDatabase(); - } - return intermentContainerTypes; -} export async function getIntermentContainerTypeById(intermentContainerTypeId) { const cachedContainerTypes = await getIntermentContainerTypes(); return cachedContainerTypes.find((currentContainerType) => currentContainerType.intermentContainerTypeId === intermentContainerTypeId); } +export async function getIntermentContainerTypes() { + intermentContainerTypes ??= await getIntermentContainerTypesFromDatabase(); + return intermentContainerTypes; +} function clearIntermentContainerTypesCache() { intermentContainerTypes = undefined; } @@ -119,16 +107,14 @@ function clearIntermentContainerTypesCache() { * Committal Types */ let committalTypes; -export async function getCommittalTypes() { - if (committalTypes === undefined) { - committalTypes = await getCommittalTypesFromDatabase(); - } - return committalTypes; -} export async function getCommittalTypeById(committalTypeId) { const cachedCommittalTypes = await getCommittalTypes(); return cachedCommittalTypes.find((currentCommittalType) => currentCommittalType.committalTypeId === committalTypeId); } +export async function getCommittalTypes() { + committalTypes ??= await getCommittalTypesFromDatabase(); + return committalTypes; +} function clearCommittalTypesCache() { committalTypes = undefined; } @@ -136,16 +122,14 @@ function clearCommittalTypesCache() { * Work Order Types */ let workOrderTypes; -export async function getWorkOrderTypes() { - if (workOrderTypes === undefined) { - workOrderTypes = await getWorkOrderTypesFromDatabase(); - } - return workOrderTypes; -} export async function getWorkOrderTypeById(workOrderTypeId) { const cachedWorkOrderTypes = await getWorkOrderTypes(); return cachedWorkOrderTypes.find((currentWorkOrderType) => currentWorkOrderType.workOrderTypeId === workOrderTypeId); } +export async function getWorkOrderTypes() { + workOrderTypes ??= await getWorkOrderTypesFromDatabase(); + return workOrderTypes; +} function clearWorkOrderTypesCache() { workOrderTypes = undefined; } @@ -153,59 +137,24 @@ function clearWorkOrderTypesCache() { * Work Order Milestone Types */ let workOrderMilestoneTypes; -export async function getWorkOrderMilestoneTypes() { - if (workOrderMilestoneTypes === undefined) { - workOrderMilestoneTypes = await getWorkOrderMilestoneTypesFromDatabase(); - } - return workOrderMilestoneTypes; -} -export async function getWorkOrderMilestoneTypeById(workOrderMilestoneTypeId) { - const cachedWorkOrderMilestoneTypes = await getWorkOrderMilestoneTypes(); - return cachedWorkOrderMilestoneTypes.find((currentWorkOrderMilestoneType) => currentWorkOrderMilestoneType.workOrderMilestoneTypeId === - workOrderMilestoneTypeId); -} -export async function getWorkOrderMilestoneTypeByWorkOrderMilestoneType(workOrderMilestoneTypeString) { - const cachedWorkOrderMilestoneTypes = await getWorkOrderMilestoneTypes(); - const workOrderMilestoneTypeLowerCase = workOrderMilestoneTypeString.toLowerCase(); - return cachedWorkOrderMilestoneTypes.find((currentWorkOrderMilestoneType) => currentWorkOrderMilestoneType.workOrderMilestoneType.toLowerCase() === - workOrderMilestoneTypeLowerCase); -} -export async function preloadCaches() { - debug('Preloading caches'); - await getBurialSiteStatuses(); - await getBurialSiteTypes(); - await getContractTypes(); - await getCommittalTypes(); - await getIntermentContainerTypes(); - await getWorkOrderTypes(); - await getWorkOrderMilestoneTypes(); -} -export function clearCaches() { - clearBurialSiteStatusesCache(); - clearBurialSiteTypesCache(); - clearContractTypesCache(); - clearCommittalTypesCache(); - clearIntermentContainerTypesCache(); - clearWorkOrderTypesCache(); - clearWorkOrderMilestoneTypesCache(); -} -function clearWorkOrderMilestoneTypesCache() { - workOrderMilestoneTypes = undefined; -} export function clearCacheByTableName(tableName, relayMessage = true) { switch (tableName) { case 'BurialSiteStatuses': { clearBurialSiteStatusesCache(); break; } - case 'BurialSiteTypes': - case 'BurialSiteTypeFields': { + case 'BurialSiteTypeFields': + case 'BurialSiteTypes': { clearBurialSiteTypesCache(); break; } - case 'ContractTypes': + case 'CommittalTypes': { + clearCommittalTypesCache(); + break; + } case 'ContractTypeFields': - case 'ContractTypePrints': { + case 'ContractTypePrints': + case 'ContractTypes': { clearContractTypesCache(); break; } @@ -213,10 +162,6 @@ export function clearCacheByTableName(tableName, relayMessage = true) { clearIntermentContainerTypesCache(); break; } - case 'CommittalTypes': { - clearCommittalTypesCache(); - break; - } case 'WorkOrderMilestoneTypes': { clearWorkOrderMilestoneTypesCache(); break; @@ -247,6 +192,43 @@ export function clearCacheByTableName(tableName, relayMessage = true) { // ignore } } +export function clearCaches() { + clearBurialSiteStatusesCache(); + clearBurialSiteTypesCache(); + clearContractTypesCache(); + clearCommittalTypesCache(); + clearIntermentContainerTypesCache(); + clearWorkOrderTypesCache(); + clearWorkOrderMilestoneTypesCache(); +} +export async function getWorkOrderMilestoneTypeById(workOrderMilestoneTypeId) { + const cachedWorkOrderMilestoneTypes = await getWorkOrderMilestoneTypes(); + return cachedWorkOrderMilestoneTypes.find((currentWorkOrderMilestoneType) => currentWorkOrderMilestoneType.workOrderMilestoneTypeId === + workOrderMilestoneTypeId); +} +export async function getWorkOrderMilestoneTypeByWorkOrderMilestoneType(workOrderMilestoneTypeString) { + const cachedWorkOrderMilestoneTypes = await getWorkOrderMilestoneTypes(); + const workOrderMilestoneTypeLowerCase = workOrderMilestoneTypeString.toLowerCase(); + return cachedWorkOrderMilestoneTypes.find((currentWorkOrderMilestoneType) => currentWorkOrderMilestoneType.workOrderMilestoneType.toLowerCase() === + workOrderMilestoneTypeLowerCase); +} +export async function getWorkOrderMilestoneTypes() { + workOrderMilestoneTypes ??= await getWorkOrderMilestoneTypesFromDatabase(); + return workOrderMilestoneTypes; +} +export async function preloadCaches() { + debug('Preloading caches'); + await getBurialSiteStatuses(); + await getBurialSiteTypes(); + await getContractTypes(); + await getCommittalTypes(); + await getIntermentContainerTypes(); + await getWorkOrderTypes(); + await getWorkOrderMilestoneTypes(); +} +function clearWorkOrderMilestoneTypesCache() { + workOrderMilestoneTypes = undefined; +} process.on('message', (message) => { if (message.messageType === 'clearCache' && message.pid !== process.pid) { debug(`Clearing cache: ${message.tableName}`); diff --git a/helpers/functions.cache.ts b/helpers/functions.cache.ts index 02e20ac2..95e981f6 100644 --- a/helpers/functions.cache.ts +++ b/helpers/functions.cache.ts @@ -1,6 +1,3 @@ -// eslint-disable-next-line @eslint-community/eslint-comments/disable-enable-pair -/* eslint-disable @typescript-eslint/init-declarations */ - import cluster from 'node:cluster' import Debug from 'debug' @@ -39,24 +36,6 @@ const debug = Debug(`${DEBUG_NAMESPACE}:functions.cache:${process.pid}`) let burialSiteStatuses: BurialSiteStatus[] | undefined -export async function getBurialSiteStatuses(): Promise { - if (burialSiteStatuses === undefined) { - burialSiteStatuses = await getBurialSiteStatusesFromDatabase() - } - - return burialSiteStatuses -} - -export async function getBurialSiteStatusById( - burialSiteStatusId: number -): Promise { - const cachedStatuses = await getBurialSiteStatuses() - - return cachedStatuses.find( - (currentStatus) => currentStatus.burialSiteStatusId === burialSiteStatusId - ) -} - export async function getBurialSiteStatusByBurialSiteStatus( burialSiteStatus: string ): Promise { @@ -70,6 +49,21 @@ export async function getBurialSiteStatusByBurialSiteStatus( ) } +export async function getBurialSiteStatusById( + burialSiteStatusId: number +): Promise { + const cachedStatuses = await getBurialSiteStatuses() + + return cachedStatuses.find( + (currentStatus) => currentStatus.burialSiteStatusId === burialSiteStatusId + ) +} + +export async function getBurialSiteStatuses(): Promise { + burialSiteStatuses ??= await getBurialSiteStatusesFromDatabase() + return burialSiteStatuses +} + function clearBurialSiteStatusesCache(): void { burialSiteStatuses = undefined } @@ -80,14 +74,6 @@ function clearBurialSiteStatusesCache(): void { let burialSiteTypes: BurialSiteType[] | undefined -export async function getBurialSiteTypes(): Promise { - if (burialSiteTypes === undefined) { - burialSiteTypes = await getBurialSiteTypesFromDatabase() - } - - return burialSiteTypes -} - export async function getBurialSiteTypeById( burialSiteTypeId: number ): Promise { @@ -98,6 +84,11 @@ export async function getBurialSiteTypeById( ) } +export async function getBurialSiteTypes(): Promise { + burialSiteTypes ??= await getBurialSiteTypesFromDatabase() + return burialSiteTypes +} + export async function getBurialSiteTypesByBurialSiteType( burialSiteType: string ): Promise { @@ -121,31 +112,11 @@ function clearBurialSiteTypesCache(): void { let contractTypes: ContractType[] | undefined let allContractTypeFields: ContractTypeField[] | undefined -export async function getContractTypes(): Promise { - if (contractTypes === undefined) { - contractTypes = await getContractTypesFromDatabase() - } - - return contractTypes -} - export async function getAllContractTypeFields(): Promise { - if (allContractTypeFields === undefined) { - allContractTypeFields = await getContractTypeFieldsFromDatabase() - } + allContractTypeFields ??= await getContractTypeFieldsFromDatabase() return allContractTypeFields } -export async function getContractTypeById( - contractTypeId: number -): Promise { - const cachedTypes = await getContractTypes() - - return cachedTypes.find( - (currentType) => currentType.contractTypeId === contractTypeId - ) -} - export async function getContractTypeByContractType( contractTypeString: string ): Promise { @@ -158,6 +129,16 @@ export async function getContractTypeByContractType( ) } +export async function getContractTypeById( + contractTypeId: number +): Promise { + const cachedTypes = await getContractTypes() + + return cachedTypes.find( + (currentType) => currentType.contractTypeId === contractTypeId + ) +} + export async function getContractTypePrintsById( contractTypeId: number ): Promise { @@ -177,6 +158,11 @@ export async function getContractTypePrintsById( return contractType.contractTypePrints ?? [] } +export async function getContractTypes(): Promise { + contractTypes ??= await getContractTypesFromDatabase() + return contractTypes +} + function clearContractTypesCache(): void { contractTypes = undefined allContractTypeFields = undefined @@ -188,16 +174,6 @@ function clearContractTypesCache(): void { let intermentContainerTypes: IntermentContainerType[] | undefined -export async function getIntermentContainerTypes(): Promise< - IntermentContainerType[] -> { - if (intermentContainerTypes === undefined) { - intermentContainerTypes = await getIntermentContainerTypesFromDatabase() - } - - return intermentContainerTypes -} - export async function getIntermentContainerTypeById( intermentContainerTypeId: number ): Promise { @@ -209,6 +185,13 @@ export async function getIntermentContainerTypeById( ) } +export async function getIntermentContainerTypes(): Promise< + IntermentContainerType[] +> { + intermentContainerTypes ??= await getIntermentContainerTypesFromDatabase() + return intermentContainerTypes +} + function clearIntermentContainerTypesCache(): void { intermentContainerTypes = undefined } @@ -219,16 +202,6 @@ function clearIntermentContainerTypesCache(): void { let committalTypes: CommittalType[] | undefined -export async function getCommittalTypes(): Promise< - CommittalType[] -> { - if (committalTypes === undefined) { - committalTypes = await getCommittalTypesFromDatabase() - } - - return committalTypes -} - export async function getCommittalTypeById( committalTypeId: number ): Promise { @@ -240,6 +213,11 @@ export async function getCommittalTypeById( ) } +export async function getCommittalTypes(): Promise { + committalTypes ??= await getCommittalTypesFromDatabase() + return committalTypes +} + function clearCommittalTypesCache(): void { committalTypes = undefined } @@ -250,14 +228,6 @@ function clearCommittalTypesCache(): void { let workOrderTypes: WorkOrderType[] | undefined -export async function getWorkOrderTypes(): Promise { - if (workOrderTypes === undefined) { - workOrderTypes = await getWorkOrderTypesFromDatabase() - } - - return workOrderTypes -} - export async function getWorkOrderTypeById( workOrderTypeId: number ): Promise { @@ -269,6 +239,11 @@ export async function getWorkOrderTypeById( ) } +export async function getWorkOrderTypes(): Promise { + workOrderTypes ??= await getWorkOrderTypesFromDatabase() + return workOrderTypes +} + function clearWorkOrderTypesCache(): void { workOrderTypes = undefined } @@ -279,81 +254,19 @@ function clearWorkOrderTypesCache(): void { let workOrderMilestoneTypes: WorkOrderMilestoneType[] | undefined -export async function getWorkOrderMilestoneTypes(): Promise< - WorkOrderMilestoneType[] -> { - if (workOrderMilestoneTypes === undefined) { - workOrderMilestoneTypes = await getWorkOrderMilestoneTypesFromDatabase() - } - - return workOrderMilestoneTypes -} - -export async function getWorkOrderMilestoneTypeById( - workOrderMilestoneTypeId: number -): Promise { - const cachedWorkOrderMilestoneTypes = await getWorkOrderMilestoneTypes() - - return cachedWorkOrderMilestoneTypes.find( - (currentWorkOrderMilestoneType) => - currentWorkOrderMilestoneType.workOrderMilestoneTypeId === - workOrderMilestoneTypeId - ) -} - -export async function getWorkOrderMilestoneTypeByWorkOrderMilestoneType( - workOrderMilestoneTypeString: string -): Promise { - const cachedWorkOrderMilestoneTypes = await getWorkOrderMilestoneTypes() - - const workOrderMilestoneTypeLowerCase = - workOrderMilestoneTypeString.toLowerCase() - - return cachedWorkOrderMilestoneTypes.find( - (currentWorkOrderMilestoneType) => - currentWorkOrderMilestoneType.workOrderMilestoneType.toLowerCase() === - workOrderMilestoneTypeLowerCase - ) -} - -export async function preloadCaches(): Promise { - debug('Preloading caches') - await getBurialSiteStatuses() - await getBurialSiteTypes() - await getContractTypes() - await getCommittalTypes() - await getIntermentContainerTypes() - await getWorkOrderTypes() - await getWorkOrderMilestoneTypes() -} - -export function clearCaches(): void { - clearBurialSiteStatusesCache() - clearBurialSiteTypesCache() - clearContractTypesCache() - clearCommittalTypesCache() - clearIntermentContainerTypesCache() - clearWorkOrderTypesCache() - clearWorkOrderMilestoneTypesCache() -} - -function clearWorkOrderMilestoneTypesCache(): void { - workOrderMilestoneTypes = undefined -} - type CacheTableNames = | 'BurialSiteStatuses' - | 'BurialSiteTypes' | 'BurialSiteTypeFields' - | 'ContractTypes' + | 'BurialSiteTypes' + | 'CommittalTypes' | 'ContractTypeFields' | 'ContractTypePrints' - | 'IntermentContainerTypes' - | 'CommittalTypes' - | 'WorkOrderMilestoneTypes' - | 'WorkOrderTypes' + | 'ContractTypes' | 'FeeCategories' | 'Fees' + | 'IntermentContainerTypes' + | 'WorkOrderMilestoneTypes' + | 'WorkOrderTypes' export function clearCacheByTableName( tableName: CacheTableNames, @@ -365,15 +278,20 @@ export function clearCacheByTableName( break } - case 'BurialSiteTypes': - case 'BurialSiteTypeFields': { + case 'BurialSiteTypeFields': + case 'BurialSiteTypes': { clearBurialSiteTypesCache() break } - case 'ContractTypes': + case 'CommittalTypes': { + clearCommittalTypesCache() + break + } + case 'ContractTypeFields': - case 'ContractTypePrints': { + case 'ContractTypePrints': + case 'ContractTypes': { clearContractTypesCache() break } @@ -383,11 +301,6 @@ export function clearCacheByTableName( break } - case 'CommittalTypes': { - clearCommittalTypesCache() - break - } - case 'WorkOrderMilestoneTypes': { clearWorkOrderMilestoneTypesCache() break @@ -423,6 +336,65 @@ export function clearCacheByTableName( } } +export function clearCaches(): void { + clearBurialSiteStatusesCache() + clearBurialSiteTypesCache() + clearContractTypesCache() + clearCommittalTypesCache() + clearIntermentContainerTypesCache() + clearWorkOrderTypesCache() + clearWorkOrderMilestoneTypesCache() +} + +export async function getWorkOrderMilestoneTypeById( + workOrderMilestoneTypeId: number +): Promise { + const cachedWorkOrderMilestoneTypes = await getWorkOrderMilestoneTypes() + + return cachedWorkOrderMilestoneTypes.find( + (currentWorkOrderMilestoneType) => + currentWorkOrderMilestoneType.workOrderMilestoneTypeId === + workOrderMilestoneTypeId + ) +} + +export async function getWorkOrderMilestoneTypeByWorkOrderMilestoneType( + workOrderMilestoneTypeString: string +): Promise { + const cachedWorkOrderMilestoneTypes = await getWorkOrderMilestoneTypes() + + const workOrderMilestoneTypeLowerCase = + workOrderMilestoneTypeString.toLowerCase() + + return cachedWorkOrderMilestoneTypes.find( + (currentWorkOrderMilestoneType) => + currentWorkOrderMilestoneType.workOrderMilestoneType.toLowerCase() === + workOrderMilestoneTypeLowerCase + ) +} + +export async function getWorkOrderMilestoneTypes(): Promise< + WorkOrderMilestoneType[] +> { + workOrderMilestoneTypes ??= await getWorkOrderMilestoneTypesFromDatabase() + return workOrderMilestoneTypes +} + +export async function preloadCaches(): Promise { + debug('Preloading caches') + await getBurialSiteStatuses() + await getBurialSiteTypes() + await getContractTypes() + await getCommittalTypes() + await getIntermentContainerTypes() + await getWorkOrderTypes() + await getWorkOrderMilestoneTypes() +} + +function clearWorkOrderMilestoneTypesCache(): void { + workOrderMilestoneTypes = undefined +} + process.on('message', (message: WorkerMessage) => { if (message.messageType === 'clearCache' && message.pid !== process.pid) { debug(`Clearing cache: ${(message as ClearCacheWorkerMessage).tableName}`) diff --git a/helpers/functions.dynamicsGP.js b/helpers/functions.dynamicsGP.js index c8470a27..223fa6fa 100644 --- a/helpers/functions.dynamicsGP.js +++ b/helpers/functions.dynamicsGP.js @@ -1,74 +1,25 @@ import { DynamicsGP } from '@cityssm/dynamics-gp'; import { getConfigProperty } from './config.helpers.js'; -// eslint-disable-next-line @typescript-eslint/init-declarations let gp; if (getConfigProperty('settings.dynamicsGP.integrationIsEnabled')) { gp = new DynamicsGP(getConfigProperty('settings.dynamicsGP.mssqlConfig')); } -function filterCashReceipt(cashReceipt) { - const accountCodes = getConfigProperty('settings.dynamicsGP.accountCodes'); - if (accountCodes.length > 0) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - for (const detail of cashReceipt?.details ?? []) { - if (accountCodes.includes(detail.accountCode)) { - return cashReceipt; - } - } - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - for (const distribution of cashReceipt?.distributions ?? []) { - if (accountCodes.includes(distribution.accountCode)) { - return cashReceipt; - } - } +export async function getDynamicsGPDocument(documentNumber) { + if (!getConfigProperty('settings.dynamicsGP.integrationIsEnabled')) { return undefined; } - return cashReceipt; -} -function filterInvoice(invoice) { - const itemNumbers = getConfigProperty('settings.dynamicsGP.itemNumbers'); - for (const itemNumber of itemNumbers) { - const found = invoice.lineItems.some((itemRecord) => itemRecord.itemNumber === itemNumber); - if (!found) { - return undefined; + let document; + for (const lookupType of getConfigProperty('settings.dynamicsGP.lookupOrder')) { + document = await _getDynamicsGPDocument(documentNumber, lookupType); + if (document !== undefined) { + break; } } - return invoice; -} -function filterExtendedInvoice(invoice) { - if (filterInvoice(invoice) === undefined) { - return undefined; - } - const trialBalanceCodes = getConfigProperty('settings.dynamicsGP.trialBalanceCodes'); - if (trialBalanceCodes.length > 0 && - trialBalanceCodes.includes(invoice.trialBalanceCode ?? '')) { - return invoice; - } - return undefined; + return document; } async function _getDynamicsGPDocument(documentNumber, lookupType) { let document; switch (lookupType) { - case 'invoice': { - let invoice = await gp.getInvoiceByInvoiceNumber(documentNumber); - if (invoice !== undefined) { - invoice = filterInvoice(invoice); - } - if (invoice !== undefined) { - document = { - documentType: 'Invoice', - documentNumber: invoice.invoiceNumber, - documentDate: invoice.documentDate, - documentDescription: [ - invoice.comment1, - invoice.comment2, - invoice.comment3, - invoice.comment4 - ], - documentTotal: invoice.documentAmount - }; - } - break; - } case 'diamond/cashReceipt': { let receipt = await gp.getDiamondCashReceiptByDocumentNumber(documentNumber); if (receipt !== undefined) { @@ -112,19 +63,67 @@ async function _getDynamicsGPDocument(documentNumber, lookupType) { } break; } - } - return document; -} -export async function getDynamicsGPDocument(documentNumber) { - if (!getConfigProperty('settings.dynamicsGP.integrationIsEnabled')) { - return undefined; - } - let document; - for (const lookupType of getConfigProperty('settings.dynamicsGP.lookupOrder')) { - document = await _getDynamicsGPDocument(documentNumber, lookupType); - if (document !== undefined) { + case 'invoice': { + let invoice = await gp.getInvoiceByInvoiceNumber(documentNumber); + if (invoice !== undefined) { + invoice = filterInvoice(invoice); + } + if (invoice !== undefined) { + document = { + documentType: 'Invoice', + documentNumber: invoice.invoiceNumber, + documentDate: invoice.documentDate, + documentDescription: [ + invoice.comment1, + invoice.comment2, + invoice.comment3, + invoice.comment4 + ], + documentTotal: invoice.documentAmount + }; + } break; } } return document; } +function filterCashReceipt(cashReceipt) { + const accountCodes = getConfigProperty('settings.dynamicsGP.accountCodes'); + if (accountCodes.length > 0) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + for (const detail of cashReceipt?.details ?? []) { + if (accountCodes.includes(detail.accountCode)) { + return cashReceipt; + } + } + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + for (const distribution of cashReceipt?.distributions ?? []) { + if (accountCodes.includes(distribution.accountCode)) { + return cashReceipt; + } + } + return undefined; + } + return cashReceipt; +} +function filterExtendedInvoice(invoice) { + if (filterInvoice(invoice) === undefined) { + return undefined; + } + const trialBalanceCodes = getConfigProperty('settings.dynamicsGP.trialBalanceCodes'); + if (trialBalanceCodes.length > 0 && + trialBalanceCodes.includes(invoice.trialBalanceCode ?? '')) { + return invoice; + } + return undefined; +} +function filterInvoice(invoice) { + const itemNumbers = getConfigProperty('settings.dynamicsGP.itemNumbers'); + for (const itemNumber of itemNumbers) { + const found = invoice.lineItems.some((itemRecord) => itemRecord.itemNumber === itemNumber); + if (!found) { + return undefined; + } + } + return invoice; +} diff --git a/helpers/functions.dynamicsGP.ts b/helpers/functions.dynamicsGP.ts index 0b38284a..a276457c 100644 --- a/helpers/functions.dynamicsGP.ts +++ b/helpers/functions.dynamicsGP.ts @@ -1,8 +1,8 @@ import { type DiamondCashReceipt, type DiamondExtendedGPInvoice, - DynamicsGP, - type GPInvoice + type GPInvoice, + DynamicsGP } from '@cityssm/dynamics-gp' import type { DynamicsGPLookup } from '../types/configTypes.js' @@ -10,72 +10,32 @@ import type { DynamicsGPDocument } from '../types/recordTypes.js' import { getConfigProperty } from './config.helpers.js' -// eslint-disable-next-line @typescript-eslint/init-declarations let gp: DynamicsGP if (getConfigProperty('settings.dynamicsGP.integrationIsEnabled')) { gp = new DynamicsGP(getConfigProperty('settings.dynamicsGP.mssqlConfig')) } -function filterCashReceipt( - cashReceipt: DiamondCashReceipt -): DiamondCashReceipt | undefined { - const accountCodes = getConfigProperty('settings.dynamicsGP.accountCodes') - - if (accountCodes.length > 0) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - for (const detail of cashReceipt?.details ?? []) { - if (accountCodes.includes(detail.accountCode)) { - return cashReceipt - } - } - - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - for (const distribution of cashReceipt?.distributions ?? []) { - if (accountCodes.includes(distribution.accountCode)) { - return cashReceipt - } - } - +export async function getDynamicsGPDocument( + documentNumber: string +): Promise { + if (!getConfigProperty('settings.dynamicsGP.integrationIsEnabled')) { return undefined } - return cashReceipt -} + let document: DynamicsGPDocument | undefined -function filterInvoice(invoice: GPInvoice): GPInvoice | undefined { - const itemNumbers = getConfigProperty('settings.dynamicsGP.itemNumbers') + for (const lookupType of getConfigProperty( + 'settings.dynamicsGP.lookupOrder' + )) { + document = await _getDynamicsGPDocument(documentNumber, lookupType) - for (const itemNumber of itemNumbers) { - const found = invoice.lineItems.some((itemRecord) => itemRecord.itemNumber === itemNumber) - - if (!found) { - return undefined + if (document !== undefined) { + break } } - return invoice -} - -function filterExtendedInvoice( - invoice: DiamondExtendedGPInvoice -): DiamondExtendedGPInvoice | undefined { - if (filterInvoice(invoice) === undefined) { - return undefined - } - - const trialBalanceCodes = getConfigProperty( - 'settings.dynamicsGP.trialBalanceCodes' - ) - - if ( - trialBalanceCodes.length > 0 && - trialBalanceCodes.includes(invoice.trialBalanceCode ?? '') - ) { - return invoice - } - - return undefined + return document } async function _getDynamicsGPDocument( @@ -85,30 +45,6 @@ async function _getDynamicsGPDocument( let document: DynamicsGPDocument | undefined switch (lookupType) { - case 'invoice': { - let invoice = await gp.getInvoiceByInvoiceNumber(documentNumber) - - if (invoice !== undefined) { - invoice = filterInvoice(invoice) - } - - if (invoice !== undefined) { - document = { - documentType: 'Invoice', - documentNumber: invoice.invoiceNumber, - documentDate: invoice.documentDate, - documentDescription: [ - invoice.comment1, - invoice.comment2, - invoice.comment3, - invoice.comment4 - ], - documentTotal: invoice.documentAmount - } - } - - break - } case 'diamond/cashReceipt': { let receipt: DiamondCashReceipt | undefined = await gp.getDiamondCashReceiptByDocumentNumber(documentNumber) @@ -160,29 +96,94 @@ async function _getDynamicsGPDocument( break } - } + case 'invoice': { + let invoice = await gp.getInvoiceByInvoiceNumber(documentNumber) - return document -} + if (invoice !== undefined) { + invoice = filterInvoice(invoice) + } -export async function getDynamicsGPDocument( - documentNumber: string -): Promise { - if (!getConfigProperty('settings.dynamicsGP.integrationIsEnabled')) { - return undefined - } + if (invoice !== undefined) { + document = { + documentType: 'Invoice', + documentNumber: invoice.invoiceNumber, + documentDate: invoice.documentDate, + documentDescription: [ + invoice.comment1, + invoice.comment2, + invoice.comment3, + invoice.comment4 + ], + documentTotal: invoice.documentAmount + } + } - let document: DynamicsGPDocument | undefined - - for (const lookupType of getConfigProperty( - 'settings.dynamicsGP.lookupOrder' - )) { - document = await _getDynamicsGPDocument(documentNumber, lookupType) - - if (document !== undefined) { break } } return document } + +function filterCashReceipt( + cashReceipt: DiamondCashReceipt +): DiamondCashReceipt | undefined { + const accountCodes = getConfigProperty('settings.dynamicsGP.accountCodes') + + if (accountCodes.length > 0) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + for (const detail of cashReceipt?.details ?? []) { + if (accountCodes.includes(detail.accountCode)) { + return cashReceipt + } + } + + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + for (const distribution of cashReceipt?.distributions ?? []) { + if (accountCodes.includes(distribution.accountCode)) { + return cashReceipt + } + } + + return undefined + } + + return cashReceipt +} + +function filterExtendedInvoice( + invoice: DiamondExtendedGPInvoice +): DiamondExtendedGPInvoice | undefined { + if (filterInvoice(invoice) === undefined) { + return undefined + } + + const trialBalanceCodes = getConfigProperty( + 'settings.dynamicsGP.trialBalanceCodes' + ) + + if ( + trialBalanceCodes.length > 0 && + trialBalanceCodes.includes(invoice.trialBalanceCode ?? '') + ) { + return invoice + } + + return undefined +} + +function filterInvoice(invoice: GPInvoice): GPInvoice | undefined { + const itemNumbers = getConfigProperty('settings.dynamicsGP.itemNumbers') + + for (const itemNumber of itemNumbers) { + const found = invoice.lineItems.some( + (itemRecord) => itemRecord.itemNumber === itemNumber + ) + + if (!found) { + return undefined + } + } + + return invoice +} diff --git a/helpers/functions.print.js b/helpers/functions.print.js index 1138c1b1..38c6cd25 100644 --- a/helpers/functions.print.js +++ b/helpers/functions.print.js @@ -8,8 +8,8 @@ import * as configFunctions from './config.helpers.js'; import * as contractFunctions from './contracts.helpers.js'; const screenPrintConfigs = { contract: { - title: "Burial Site Contract Print", - params: ['contractId'] + params: ['contractId'], + title: "Burial Site Contract Print" } }; export function getScreenPrintConfig(printName) { @@ -17,21 +17,21 @@ export function getScreenPrintConfig(printName) { } const pdfPrintConfigs = { workOrder: { - title: 'Work Order Field Sheet', - params: ['workOrderId'] + params: ['workOrderId'], + title: 'Work Order Field Sheet' }, 'workOrder-commentLog': { - title: 'Work Order Field Sheet - Comment Log', - params: ['workOrderId'] + params: ['workOrderId'], + title: 'Work Order Field Sheet - Comment Log' }, // Occupancy 'ssm.cemetery.burialPermit': { - title: 'Burial Permit', - params: ['contractId'] + params: ['contractId'], + title: 'Burial Permit' }, 'ssm.cemetery.contract': { - title: 'Contract for Purchase of Interment Rights', - params: ['contractId'] + params: ['contractId'], + title: 'Contract for Purchase of Interment Rights' } }; export function getPdfPrintConfig(printName) { diff --git a/helpers/functions.print.ts b/helpers/functions.print.ts index c90e3c54..200480a8 100644 --- a/helpers/functions.print.ts +++ b/helpers/functions.print.ts @@ -30,8 +30,8 @@ interface ReportData { const screenPrintConfigs: Record = { contract: { - title: "Burial Site Contract Print", - params: ['contractId'] + params: ['contractId'], + title: "Burial Site Contract Print" } } @@ -43,22 +43,22 @@ export function getScreenPrintConfig( const pdfPrintConfigs: Record = { workOrder: { - title: 'Work Order Field Sheet', - params: ['workOrderId'] + params: ['workOrderId'], + title: 'Work Order Field Sheet' }, 'workOrder-commentLog': { - title: 'Work Order Field Sheet - Comment Log', - params: ['workOrderId'] + params: ['workOrderId'], + title: 'Work Order Field Sheet - Comment Log' }, // Occupancy 'ssm.cemetery.burialPermit': { - title: 'Burial Permit', - params: ['contractId'] + params: ['contractId'], + title: 'Burial Permit' }, 'ssm.cemetery.contract': { - title: 'Contract for Purchase of Interment Rights', - params: ['contractId'] + params: ['contractId'], + title: 'Contract for Purchase of Interment Rights' } } diff --git a/helpers/functions.user.d.ts b/helpers/functions.user.d.ts index df5cdc51..218a7ef1 100644 --- a/helpers/functions.user.d.ts +++ b/helpers/functions.user.d.ts @@ -1,13 +1,13 @@ -export interface UserRequest { - session?: { - user?: User; - }; -} export interface APIRequest { params?: { apiKey?: string; }; } -export declare function userIsAdmin(request: UserRequest): boolean; -export declare function userCanUpdate(request: UserRequest): boolean; +export interface UserRequest { + session?: { + user?: User; + }; +} export declare function apiKeyIsValid(request: APIRequest): Promise; +export declare function userCanUpdate(request: UserRequest): boolean; +export declare function userIsAdmin(request: UserRequest): boolean; diff --git a/helpers/functions.user.js b/helpers/functions.user.js index 0863eba2..d9c98d50 100644 --- a/helpers/functions.user.js +++ b/helpers/functions.user.js @@ -1,11 +1,5 @@ -import { getUserNameFromApiKey } from './functions.api.js'; import { getConfigProperty } from './config.helpers.js'; -export function userIsAdmin(request) { - return request.session?.user?.userProperties?.isAdmin ?? false; -} -export function userCanUpdate(request) { - return request.session?.user?.userProperties?.canUpdate ?? false; -} +import { getUserNameFromApiKey } from './functions.api.js'; export async function apiKeyIsValid(request) { const apiKey = request.params?.apiKey; if (apiKey === undefined) { @@ -17,3 +11,9 @@ export async function apiKeyIsValid(request) { } return getConfigProperty('users.canLogin').some((currentUserName) => userName === currentUserName.toLowerCase()); } +export function userCanUpdate(request) { + return request.session?.user?.userProperties?.canUpdate ?? false; +} +export function userIsAdmin(request) { + return request.session?.user?.userProperties?.isAdmin ?? false; +} diff --git a/helpers/functions.user.ts b/helpers/functions.user.ts index 2533ab1a..1149cf2b 100644 --- a/helpers/functions.user.ts +++ b/helpers/functions.user.ts @@ -1,11 +1,5 @@ -import { getUserNameFromApiKey } from './functions.api.js' import { getConfigProperty } from './config.helpers.js' - -export interface UserRequest { - session?: { - user?: User - } -} +import { getUserNameFromApiKey } from './functions.api.js' export interface APIRequest { params?: { @@ -13,12 +7,10 @@ export interface APIRequest { } } -export function userIsAdmin(request: UserRequest): boolean { - return request.session?.user?.userProperties?.isAdmin ?? false -} - -export function userCanUpdate(request: UserRequest): boolean { - return request.session?.user?.userProperties?.canUpdate ?? false +export interface UserRequest { + session?: { + user?: User + } } export async function apiKeyIsValid(request: APIRequest): Promise { @@ -38,3 +30,11 @@ export async function apiKeyIsValid(request: APIRequest): Promise { (currentUserName) => userName === currentUserName.toLowerCase() ) } + +export function userCanUpdate(request: UserRequest): boolean { + return request.session?.user?.userProperties?.canUpdate ?? false +} + +export function userIsAdmin(request: UserRequest): boolean { + return request.session?.user?.userProperties?.isAdmin ?? false +} diff --git a/package-lock.json b/package-lock.json index 42feec6d..f80efa4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,7 +65,7 @@ "@types/randomcolor": "^0.5.9", "@types/session-file-store": "^1.2.5", "axe-core": "^4.10.3", - "cypress": "^14.2.0", + "cypress": "^14.2.1", "cypress-axe": "^1.6.0", "eslint-config-cityssm": "^22.2.2", "nodemon": "^3.1.9", @@ -334,15 +334,6 @@ "node": ">=16" } }, - "node_modules/@azure/msal-node/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@babel/code-frame": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", @@ -1141,9 +1132,9 @@ } }, "node_modules/@cypress/request": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.7.tgz", - "integrity": "sha512-LzxlLEMbBOPYB85uXrDqvD4MgcenjRBLIns3zyhx7vTPj/0u2eQhzXvPiGcaJrV38Q9dbkExWp6cOHPJ+EtFYg==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.8.tgz", + "integrity": "sha512-h0NFgh1mJmm1nr4jCwkGHwKneVYKghUyWe6TMNrk0B9zsjAJxpg8C4/+BAcmLgCPa1vj1V8rNUaILl+zYRUWBQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1160,7 +1151,7 @@ "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", - "qs": "6.13.1", + "qs": "6.14.0", "safe-buffer": "^5.1.2", "tough-cookie": "^5.0.0", "tunnel-agent": "^0.6.0", @@ -1171,13 +1162,13 @@ } }, "node_modules/@cypress/request/node_modules/qs": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", - "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -1186,16 +1177,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@cypress/request/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@cypress/xvfb": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", @@ -4126,14 +4107,14 @@ "license": "ISC" }, "node_modules/cypress": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-14.2.0.tgz", - "integrity": "sha512-u7fuc9JEpSYLOdu8mzZDZ/JWsHUzR5pc8i1TeSqMz/bafXp+6IweMAeyphsEJ6/13qbB6nwTEY1m+GUAp6GqCQ==", + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-14.2.1.tgz", + "integrity": "sha512-5xd0E7fUp0pjjib1D7ljkmCwFDgMkWuW06jWiz8dKrI7MNRrDo0C65i4Sh+oZ9YHjMHZRJBR0XZk1DfekOhOUw==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { - "@cypress/request": "^3.0.7", + "@cypress/request": "^3.0.8", "@cypress/xvfb": "^1.2.4", "@types/sinonjs__fake-timers": "8.1.1", "@types/sizzle": "^2.3.2", @@ -4170,7 +4151,7 @@ "process": "^0.11.10", "proxy-from-env": "1.0.0", "request-progress": "^3.0.0", - "semver": "^7.5.3", + "semver": "^7.7.1", "supports-color": "^8.1.1", "tmp": "~0.2.3", "tree-kill": "1.2.2", @@ -5855,7 +5836,8 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/extract-zip": { "version": "2.0.1", @@ -6145,14 +6127,15 @@ } }, "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" }, "engines": { @@ -11813,22 +11796,22 @@ "dev": true }, "node_modules/tldts": { - "version": "6.1.76", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.76.tgz", - "integrity": "sha512-6U2ti64/nppsDxQs9hw8ephA3nO6nSQvVVfxwRw8wLQPFtLI1cFI1a1eP22g+LUP+1TA2pKKjUTwWB+K2coqmQ==", + "version": "6.1.85", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.85.tgz", + "integrity": "sha512-gBdZ1RjCSevRPFix/hpaUWeak2/RNUZB4/8frF1r5uYMHjFptkiT0JXIebWvgI/0ZHXvxaUDDJshiA0j6GdL3w==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.76" + "tldts-core": "^6.1.85" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.76", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.76.tgz", - "integrity": "sha512-uzhJ02RaMzgQR3yPoeE65DrcHI6LoM4saUqXOt/b5hmb3+mc4YWpdSeAQqVqRUlQ14q8ZuLRWyBR1ictK1dzzg==", + "version": "6.1.85", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.85.tgz", + "integrity": "sha512-DTjUVvxckL1fIoPSb3KE7ISNtkWSawZdpfxGxwiIrZoO6EbHVDXXUIlIuWympPaeS+BLGyggozX/HTMsRAdsoA==", "dev": true, "license": "MIT" }, @@ -11885,9 +11868,9 @@ } }, "node_modules/tough-cookie": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.0.tgz", - "integrity": "sha512-rvZUv+7MoBYTiDmFPBrhL7Ujx9Sk+q9wwm22x8c8T5IJaR+Wsyc7TNxbVxo84kZoRJZZMazowFLqpankBEQrGg==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -12338,6 +12321,15 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/uuid-random": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/uuid-random/-/uuid-random-1.3.2.tgz", diff --git a/package.json b/package.json index 594f60d5..ec737d6b 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "@types/randomcolor": "^0.5.9", "@types/session-file-store": "^1.2.5", "axe-core": "^4.10.3", - "cypress": "^14.2.0", + "cypress": "^14.2.1", "cypress-axe": "^1.6.0", "eslint-config-cityssm": "^22.2.2", "nodemon": "^3.1.9", diff --git a/public/html/contract-addInterment.html b/public/html/contract-addInterment.html index d2d5392d..0411310b 100644 --- a/public/html/contract-addInterment.html +++ b/public/html/contract-addInterment.html @@ -82,6 +82,7 @@ name="deceasedCity" type="text" maxlength="20" + list="datalist--cityDefault" /> diff --git a/public/html/contract-editInterment.html b/public/html/contract-editInterment.html index e3e6b403..252fa86b 100644 --- a/public/html/contract-editInterment.html +++ b/public/html/contract-editInterment.html @@ -89,6 +89,7 @@ name="deceasedCity" type="text" maxlength="20" + list="datalist--cityDefault" /> diff --git a/routes/login.js b/routes/login.js index 6f823918..02c81163 100644 --- a/routes/login.js +++ b/routes/login.js @@ -64,9 +64,9 @@ async function postHandler(request, response) { } else { response.render('login', { - userName, message: 'Login Failed', redirect: redirectURL, + userName, useTestDatabases }); } diff --git a/routes/login.ts b/routes/login.ts index eee9a88f..6197d7dd 100644 --- a/routes/login.ts +++ b/routes/login.ts @@ -40,7 +40,7 @@ async function postHandler( request: Request< unknown, unknown, - { userName: string; password: string; redirect: string } + { password: string; redirect: string; userName: string; } >, response: Response ): Promise { @@ -109,9 +109,9 @@ async function postHandler( response.redirect(redirectURL) } else { response.render('login', { - userName, message: 'Login Failed', redirect: redirectURL, + userName, useTestDatabases }) } diff --git a/temp/legacyImportFromCsv/data.cemeteries.js b/temp/legacyImportFromCsv/data.cemeteries.js index 056be487..1f2dd395 100644 --- a/temp/legacyImportFromCsv/data.cemeteries.js +++ b/temp/legacyImportFromCsv/data.cemeteries.js @@ -33,16 +33,16 @@ export async function getCemeteryIdByKey(cemeteryKey, user) { console.log(`Creating cemetery: ${cemeteryKey}`); const cemeteryId = await addCemetery({ cemeteryName: cemeteryToCemeteryName[cemeteryKey] ?? cemeteryKey, - cemeteryKey, cemeteryDescription: '', + cemeteryKey, cemeterySvg: '', cemeteryLatitude: '', cemeteryLongitude: '', cemeteryAddress1: '', cemeteryAddress2: '', cemeteryCity: 'Sault Ste. Marie', - cemeteryProvince: 'ON', cemeteryPostalCode: '', + cemeteryProvince: 'ON', cemeteryPhoneNumber: '' }, user); cemeteryCache.set(cemeteryKey, cemeteryId); diff --git a/temp/legacyImportFromCsv/data.cemeteries.ts b/temp/legacyImportFromCsv/data.cemeteries.ts index 01c250e9..d75a4b74 100644 --- a/temp/legacyImportFromCsv/data.cemeteries.ts +++ b/temp/legacyImportFromCsv/data.cemeteries.ts @@ -45,16 +45,21 @@ export async function getCemeteryIdByKey( const cemeteryId = await addCemetery( { cemeteryName: cemeteryToCemeteryName[cemeteryKey] ?? cemeteryKey, - cemeteryKey, + cemeteryDescription: '', + cemeteryKey, + cemeterySvg: '', + cemeteryLatitude: '', cemeteryLongitude: '', + cemeteryAddress1: '', cemeteryAddress2: '', cemeteryCity: 'Sault Ste. Marie', - cemeteryProvince: 'ON', cemeteryPostalCode: '', + cemeteryProvince: 'ON', + cemeteryPhoneNumber: '' }, user diff --git a/temp/legacyImportFromCsv/index.js b/temp/legacyImportFromCsv/index.js index fd2e3091..ea2c9a6f 100644 --- a/temp/legacyImportFromCsv/index.js +++ b/temp/legacyImportFromCsv/index.js @@ -1,5 +1,5 @@ // eslint-disable-next-line @eslint-community/eslint-comments/disable-enable-pair -/* eslint-disable @cspell/spellchecker, @typescript-eslint/no-non-null-assertion, no-console, max-lines */ +/* eslint-disable @cspell/spellchecker, @typescript-eslint/no-non-null-assertion, no-console, max-lines, perfectionist/sort-interfaces */ import fs from 'node:fs'; import { dateIntegerToString, dateToString } from '@cityssm/utils-datetime'; import sqlite from 'better-sqlite3'; diff --git a/temp/legacyImportFromCsv/index.ts b/temp/legacyImportFromCsv/index.ts index 7e3900f2..2bae6b81 100644 --- a/temp/legacyImportFromCsv/index.ts +++ b/temp/legacyImportFromCsv/index.ts @@ -1,5 +1,5 @@ // eslint-disable-next-line @eslint-community/eslint-comments/disable-enable-pair -/* eslint-disable @cspell/spellchecker, @typescript-eslint/no-non-null-assertion, no-console, max-lines */ +/* eslint-disable @cspell/spellchecker, @typescript-eslint/no-non-null-assertion, no-console, max-lines, perfectionist/sort-interfaces */ import fs from 'node:fs' diff --git a/types/applicationTypes.d.ts b/types/applicationTypes.d.ts index e946681c..89e5d22b 100644 --- a/types/applicationTypes.d.ts +++ b/types/applicationTypes.d.ts @@ -1,18 +1,18 @@ -export interface WorkerMessage { - messageType: string; - timeMillis: number; - pid: number; -} -export interface ClearCacheWorkerMessage extends WorkerMessage { - messageType: 'clearCache'; - tableName: string; -} export interface CacheBurialSiteIdsWorkerMessage extends WorkerMessage { messageType: 'cacheBurialSiteIds'; burialSiteId: number; nextBurialSiteId: number; } +export interface ClearCacheWorkerMessage extends WorkerMessage { + messageType: 'clearCache'; + tableName: string; +} export interface ClearNextPreviousBurialSiteIdsCacheWorkerMessage extends WorkerMessage { messageType: 'clearNextPreviousBurialSiteIdCache'; burialSiteId: number; } +export interface WorkerMessage { + messageType: string; + pid: number; + timeMillis: number; +} diff --git a/types/applicationTypes.ts b/types/applicationTypes.ts index 95f926f3..730eb0c1 100644 --- a/types/applicationTypes.ts +++ b/types/applicationTypes.ts @@ -1,23 +1,26 @@ -export interface WorkerMessage { - messageType: string - timeMillis: number - pid: number +export interface CacheBurialSiteIdsWorkerMessage extends WorkerMessage { + messageType: 'cacheBurialSiteIds' + + burialSiteId: number + nextBurialSiteId: number } export interface ClearCacheWorkerMessage extends WorkerMessage { messageType: 'clearCache' - tableName: string -} -export interface CacheBurialSiteIdsWorkerMessage extends WorkerMessage { - messageType: 'cacheBurialSiteIds' - burialSiteId: number - nextBurialSiteId: number + tableName: string } export interface ClearNextPreviousBurialSiteIdsCacheWorkerMessage extends WorkerMessage { // eslint-disable-next-line no-secrets/no-secrets messageType: 'clearNextPreviousBurialSiteIdCache' + burialSiteId: number } + +export interface WorkerMessage { + messageType: string + pid: number + timeMillis: number +} diff --git a/types/configTypes.d.ts b/types/configTypes.d.ts index 62ec90ff..f34c82d4 100644 --- a/types/configTypes.d.ts +++ b/types/configTypes.d.ts @@ -35,16 +35,16 @@ export interface Config { contracts: { burialSiteIdIsRequired?: boolean; contractEndDateIsRequired?: boolean; - purchaserRelationships?: string[]; deathAgePeriods?: string[]; prints?: string[]; + purchaserRelationships?: string[]; }; workOrders: { - workOrderNumberLength?: number; - workOrderMilestoneDateRecentBeforeDays?: number; - workOrderMilestoneDateRecentAfterDays?: number; calendarEmailAddress?: string; prints?: string[]; + workOrderMilestoneDateRecentAfterDays?: number; + workOrderMilestoneDateRecentBeforeDays?: number; + workOrderNumberLength?: number; }; adminCleanup: { recordDeleteAgeDays?: number; @@ -74,14 +74,14 @@ interface ConfigApplication { maximumProcesses?: number; } export interface ConfigNtfyStartup { - topic: string; server?: string; + topic: string; } interface ConfigSession { cookieName?: string; - secret?: string; - maxAgeMillis?: number; doKeepAlive?: boolean; + maxAgeMillis?: number; + secret?: string; } export interface ConfigActiveDirectory { url: string; @@ -90,7 +90,6 @@ export interface ConfigActiveDirectory { password: string; } export interface ConfigBurialSiteNameSegments { - separator?: string; includeCemeteryKey?: boolean; segments: Partial>; + separator?: string; } export {}; diff --git a/types/configTypes.ts b/types/configTypes.ts index 02ee4f81..377aa82f 100644 --- a/types/configTypes.ts +++ b/types/configTypes.ts @@ -15,6 +15,7 @@ export interface Config { users: { testing?: Array<`*${string}`> + canLogin?: string[] canUpdate?: string[] isAdmin?: string[] @@ -46,17 +47,17 @@ export interface Config { contracts: { burialSiteIdIsRequired?: boolean contractEndDateIsRequired?: boolean - purchaserRelationships?: string[] deathAgePeriods?: string[] prints?: string[] + purchaserRelationships?: string[] } workOrders: { - workOrderNumberLength?: number - workOrderMilestoneDateRecentBeforeDays?: number - workOrderMilestoneDateRecentAfterDays?: number calendarEmailAddress?: string prints?: string[] + workOrderMilestoneDateRecentAfterDays?: number + workOrderMilestoneDateRecentBeforeDays?: number + workOrderNumberLength?: number } adminCleanup: { @@ -95,15 +96,15 @@ interface ConfigApplication { } export interface ConfigNtfyStartup { - topic: string server?: string + topic: string } interface ConfigSession { cookieName?: string - secret?: string - maxAgeMillis?: number doKeepAlive?: boolean + maxAgeMillis?: number + secret?: string } export interface ConfigActiveDirectory { @@ -114,7 +115,6 @@ export interface ConfigActiveDirectory { } export interface ConfigBurialSiteNameSegments { - separator?: string includeCemeteryKey?: boolean segments: Partial< Record< @@ -130,4 +130,5 @@ export interface ConfigBurialSiteNameSegments { } > > + separator?: string } diff --git a/windowsService.ts b/windowsService.ts index 816908c2..debf2726 100644 --- a/windowsService.ts +++ b/windowsService.ts @@ -8,5 +8,6 @@ export const serviceConfig: ServiceConfig = { name: 'Sunrise CMS', description: 'Sunrise Cemetery Management System, a web-based application that allows cemetery managers to manage their cemetery records.', + script: path.join(_dirname, 'bin', 'www.js') }