linting and polish

pull/3/head
Dan Gowans 2025-03-26 13:21:28 -04:00
parent 061c1fa43a
commit 8fa012be75
62 changed files with 832 additions and 857 deletions

29
app.js
View File

@ -27,6 +27,7 @@ import routerPrint from './routes/print.js';
import routerReports from './routes/reports.js'; import routerReports from './routes/reports.js';
import routerWorkOrders from './routes/workOrders.js'; import routerWorkOrders from './routes/workOrders.js';
import { version } from './version.js'; import { version } from './version.js';
import { secondsToMillis } from '@cityssm/to-millis';
const debug = Debug(`${DEBUG_NAMESPACE}:app:${process.pid}`); const debug = Debug(`${DEBUG_NAMESPACE}:app:${process.pid}`);
/* /*
* INITIALIZE APP * INITIALIZE APP
@ -52,15 +53,17 @@ app.use(express.urlencoded({
extended: false extended: false
})); }));
app.use(cookieParser()); app.use(cookieParser());
app.use(csurf({ app.use(
// eslint-disable-next-line sonarjs/insecure-cookie, sonarjs/cookie-no-httponly
csurf({
cookie: true cookie: true
})); }));
/* /*
* Rate Limiter * Rate Limiter
*/ */
app.use(rateLimit({ app.use(rateLimit({
windowMs: 10_000, max: useTestDatabases ? 1_000_000 : 200,
max: useTestDatabases ? 1_000_000 : 200 windowMs: secondsToMillis(10)
})); }));
/* /*
* STATIC ROUTES * STATIC ROUTES
@ -86,20 +89,20 @@ const sessionCookieName = configFunctions.getConfigProperty('session.cookieName'
const FileStoreSession = FileStore(session); const FileStoreSession = FileStore(session);
// Initialize session // Initialize session
app.use(session({ app.use(session({
store: new FileStoreSession({
path: './data/sessions',
logFn: Debug(`${DEBUG_NAMESPACE}:session:${process.pid}`),
retries: 20
}),
name: sessionCookieName, name: sessionCookieName,
secret: configFunctions.getConfigProperty('session.secret'),
resave: true,
saveUninitialized: false,
rolling: true,
cookie: { cookie: {
maxAge: configFunctions.getConfigProperty('session.maxAgeMillis'), maxAge: configFunctions.getConfigProperty('session.maxAgeMillis'),
sameSite: 'strict' 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 // Clear cookie if no corresponding session
app.use((request, response, next) => { app.use((request, response, next) => {

44
app.ts
View File

@ -29,6 +29,7 @@ import routerPrint from './routes/print.js'
import routerReports from './routes/reports.js' import routerReports from './routes/reports.js'
import routerWorkOrders from './routes/workOrders.js' import routerWorkOrders from './routes/workOrders.js'
import { version } from './version.js' import { version } from './version.js'
import { secondsToMillis } from '@cityssm/to-millis'
const debug = Debug(`${DEBUG_NAMESPACE}:app:${process.pid}`) const debug = Debug(`${DEBUG_NAMESPACE}:app:${process.pid}`)
@ -69,6 +70,7 @@ app.use(
app.use(cookieParser()) app.use(cookieParser())
app.use( app.use(
// eslint-disable-next-line sonarjs/insecure-cookie, sonarjs/cookie-no-httponly
csurf({ csurf({
cookie: true cookie: true
}) })
@ -80,8 +82,8 @@ app.use(
app.use( app.use(
rateLimit({ 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( app.use(
`${urlPrefix}/lib/bulma`, `${urlPrefix}/lib/bulma`,
express.static( express.static(path.join('node_modules', 'bulma', 'css'))
path.join('node_modules', 'bulma', 'css')
)
) )
app.use( app.use(
`${urlPrefix}/lib/bulma-tooltip`, `${urlPrefix}/lib/bulma-tooltip`,
express.static( express.static(path.join('node_modules', 'bulma-tooltip', 'dist', 'css'))
path.join('node_modules', 'bulma-tooltip', 'dist', 'css')
)
) )
app.use( app.use(
@ -120,16 +118,12 @@ app.use(
app.use( app.use(
`${urlPrefix}/lib/cityssm-fa-glow`, `${urlPrefix}/lib/cityssm-fa-glow`,
express.static( express.static(path.join('node_modules', '@cityssm', 'fa-glow'))
path.join('node_modules', '@cityssm', 'fa-glow')
)
) )
app.use( app.use(
`${urlPrefix}/lib/cityssm-bulma-sticky-table`, `${urlPrefix}/lib/cityssm-bulma-sticky-table`,
express.static( express.static(path.join('node_modules', '@cityssm', 'bulma-sticky-table'))
path.join('node_modules', '@cityssm', 'bulma-sticky-table')
)
) )
app.use( app.use(
@ -166,20 +160,22 @@ const FileStoreSession = FileStore(session)
// Initialize session // Initialize session
app.use( app.use(
session({ session({
store: new FileStoreSession({
path: './data/sessions',
logFn: Debug(`${DEBUG_NAMESPACE}:session:${process.pid}`),
retries: 20
}),
name: sessionCookieName, name: sessionCookieName,
secret: configFunctions.getConfigProperty('session.secret'),
resave: true,
saveUninitialized: false,
rolling: true,
cookie: { cookie: {
maxAge: configFunctions.getConfigProperty('session.maxAgeMillis'), maxAge: configFunctions.getConfigProperty('session.maxAgeMillis'),
sameSite: 'strict' 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
}) })
) )

View File

@ -1,10 +1,11 @@
import { clearCacheByTableName } from '../helpers/functions.cache.js'; import { clearCacheByTableName } from '../helpers/functions.cache.js';
import { acquireConnection } from './pool.js'; import { acquireConnection } from './pool.js';
const recordNameColumns = new Map(); const recordNameColumns = new Map([
recordNameColumns.set('BurialSiteStatuses', 'burialSiteStatus'); ['BurialSiteStatuses', 'burialSiteStatus'],
recordNameColumns.set('BurialSiteTypes', 'burialSiteType'); ['BurialSiteTypes', 'burialSiteType'],
recordNameColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneType'); ['WorkOrderMilestoneTypes', 'workOrderMilestoneType'],
recordNameColumns.set('WorkOrderTypes', 'workOrderType'); ['WorkOrderTypes', 'workOrderType']
]);
export default async function addRecord(recordTable, recordName, orderNumber, user) { export default async function addRecord(recordTable, recordName, orderNumber, user) {
const database = await acquireConnection(); const database = await acquireConnection();
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();

View File

@ -8,11 +8,12 @@ type RecordTable =
| 'WorkOrderMilestoneTypes' | 'WorkOrderMilestoneTypes'
| 'WorkOrderTypes' | 'WorkOrderTypes'
const recordNameColumns = new Map<RecordTable, string>() const recordNameColumns = new Map<RecordTable, string>([
recordNameColumns.set('BurialSiteStatuses', 'burialSiteStatus') ['BurialSiteStatuses', 'burialSiteStatus'],
recordNameColumns.set('BurialSiteTypes', 'burialSiteType') ['BurialSiteTypes', 'burialSiteType'],
recordNameColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneType') ['WorkOrderMilestoneTypes', 'workOrderMilestoneType'],
recordNameColumns.set('WorkOrderTypes', 'workOrderType') ['WorkOrderTypes', 'workOrderType']
])
export default async function addRecord( export default async function addRecord(
recordTable: RecordTable, recordTable: RecordTable,

View File

@ -1,3 +1,3 @@
import type { BurialSite } from '../types/recordTypes.js'; import type { BurialSite } from '../types/recordTypes.js';
export declare function getBurialSiteByBurialSiteName(burialSiteName: string): Promise<BurialSite | undefined>;
export default function getBurialSite(burialSiteId: number | string): Promise<BurialSite | undefined>; export default function getBurialSite(burialSiteId: number | string): Promise<BurialSite | undefined>;
export declare function getBurialSiteByBurialSiteName(burialSiteName: string): Promise<BurialSite | undefined>;

View File

@ -20,6 +20,12 @@ const baseSQL = `select l.burialSiteId,
left join BurialSiteStatuses s on l.burialSiteStatusId = s.burialSiteStatusId left join BurialSiteStatuses s on l.burialSiteStatusId = s.burialSiteStatusId
left join Cemeteries m on l.cemeteryId = m.cemeteryId left join Cemeteries m on l.cemeteryId = m.cemeteryId
where l.recordDelete_timeMillis is null`; 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) { async function _getBurialSite(sql, burialSiteIdOrLotName) {
const database = await acquireConnection(); const database = await acquireConnection();
const burialSite = database.prepare(sql).get(burialSiteIdOrLotName); const burialSite = database.prepare(sql).get(burialSiteIdOrLotName);
@ -27,11 +33,11 @@ async function _getBurialSite(sql, burialSiteIdOrLotName) {
const contracts = await getContracts({ const contracts = await getContracts({
burialSiteId: burialSite.burialSiteId burialSiteId: burialSite.burialSiteId
}, { }, {
includeInterments: true,
includeFees: false,
includeTransactions: false,
limit: -1, limit: -1,
offset: 0 offset: 0,
includeFees: false,
includeInterments: true,
includeTransactions: false
}, database); }, database);
burialSite.contracts = contracts.contracts; burialSite.contracts = contracts.contracts;
burialSite.burialSiteFields = await getBurialSiteFields(burialSite.burialSiteId, database); burialSite.burialSiteFields = await getBurialSiteFields(burialSite.burialSiteId, database);
@ -40,9 +46,3 @@ async function _getBurialSite(sql, burialSiteIdOrLotName) {
database.release(); database.release();
return burialSite; 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);
}

View File

@ -24,13 +24,30 @@ const baseSQL = `select l.burialSiteId,
left join Cemeteries m on l.cemeteryId = m.cemeteryId left join Cemeteries m on l.cemeteryId = m.cemeteryId
where l.recordDelete_timeMillis is null` where l.recordDelete_timeMillis is null`
export default async function getBurialSite(
burialSiteId: number | string
): Promise<BurialSite | undefined> {
return await _getBurialSite(`${baseSQL} and l.burialSiteId = ?`, burialSiteId)
}
export async function getBurialSiteByBurialSiteName(
burialSiteName: string
): Promise<BurialSite | undefined> {
return await _getBurialSite(
`${baseSQL} and l.burialSiteName = ?`,
burialSiteName
)
}
async function _getBurialSite( async function _getBurialSite(
sql: string, sql: string,
burialSiteIdOrLotName: number | string burialSiteIdOrLotName: number | string
): Promise<BurialSite | undefined> { ): Promise<BurialSite | undefined> {
const database = await acquireConnection() 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) { if (burialSite !== undefined) {
const contracts = await getContracts( const contracts = await getContracts(
@ -38,35 +55,30 @@ async function _getBurialSite(
burialSiteId: burialSite.burialSiteId burialSiteId: burialSite.burialSiteId
}, },
{ {
includeInterments: true,
includeFees: false,
includeTransactions: false,
limit: -1, limit: -1,
offset: 0 offset: 0,
includeFees: false,
includeInterments: true,
includeTransactions: false
}, },
database database
) )
burialSite.contracts = contracts.contracts 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() database.release()
return burialSite return burialSite
} }
export async function getBurialSiteByBurialSiteName(
burialSiteName: string
): Promise<BurialSite | undefined> {
return await _getBurialSite(`${baseSQL} and l.burialSiteName = ?`, burialSiteName)
}
export default async function getBurialSite(
burialSiteId: number | string
): Promise<BurialSite | undefined> {
return await _getBurialSite(`${baseSQL} and l.burialSiteId = ?`, burialSiteId)
}

View File

@ -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<boolean>; export declare function moveRecordDown(recordTable: RecordTable, recordId: number | string): Promise<boolean>;
export declare function moveRecordDownToBottom(recordTable: RecordTable, recordId: number | string): Promise<boolean>; export declare function moveRecordDownToBottom(recordTable: RecordTable, recordId: number | string): Promise<boolean>;
export declare function moveRecordUp(recordTable: RecordTable, recordId: number | string): Promise<boolean>; export declare function moveRecordUp(recordTable: RecordTable, recordId: number | string): Promise<boolean>;

View File

@ -1,21 +1,14 @@
import { clearCacheByTableName } from '../helpers/functions.cache.js'; import { clearCacheByTableName } from '../helpers/functions.cache.js';
import { acquireConnection } from './pool.js'; import { acquireConnection } from './pool.js';
import { updateRecordOrderNumber } from './updateRecordOrderNumber.js'; import { updateRecordOrderNumber } from './updateRecordOrderNumber.js';
const recordIdColumns = new Map(); const recordIdColumns = new Map([
recordIdColumns.set('FeeCategories', 'feeCategoryId'); ['BurialSiteStatuses', 'burialSiteStatusId'],
recordIdColumns.set('BurialSiteStatuses', 'burialSiteStatusId'); ['BurialSiteTypes', 'burialSiteTypeId'],
recordIdColumns.set('BurialSiteTypes', 'burialSiteTypeId'); ['ContractTypes', 'contractTypeId'],
recordIdColumns.set('ContractTypes', 'contractTypeId'); ['FeeCategories', 'feeCategoryId'],
recordIdColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'); ['WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'],
recordIdColumns.set('WorkOrderTypes', 'workOrderTypeId'); ['WorkOrderTypes', 'workOrderTypeId']
function getCurrentOrderNumber(recordTable, recordId, database) { ]);
const currentOrderNumber = database
.prepare(`select orderNumber
from ${recordTable}
where ${recordIdColumns.get(recordTable)} = ?`)
.get(recordId).orderNumber;
return currentOrderNumber;
}
export async function moveRecordDown(recordTable, recordId) { export async function moveRecordDown(recordTable, recordId) {
const database = await acquireConnection(); const database = await acquireConnection();
const currentOrderNumber = getCurrentOrderNumber(recordTable, recordId, database); const currentOrderNumber = getCurrentOrderNumber(recordTable, recordId, database);
@ -85,3 +78,11 @@ export async function moveRecordUpToTop(recordTable, recordId) {
clearCacheByTableName(recordTable); clearCacheByTableName(recordTable);
return true; return true;
} }
function getCurrentOrderNumber(recordTable, recordId, database) {
const currentOrderNumber = database
.prepare(`select orderNumber
from ${recordTable}
where ${recordIdColumns.get(recordTable)} = ?`)
.get(recordId).orderNumber;
return currentOrderNumber;
}

View File

@ -6,38 +6,21 @@ import { acquireConnection } from './pool.js'
import { updateRecordOrderNumber } from './updateRecordOrderNumber.js' import { updateRecordOrderNumber } from './updateRecordOrderNumber.js'
type RecordTable = type RecordTable =
| 'FeeCategories'
| 'BurialSiteStatuses' | 'BurialSiteStatuses'
| 'BurialSiteTypes' | 'BurialSiteTypes'
| 'ContractTypes' | 'ContractTypes'
| 'FeeCategories'
| 'WorkOrderMilestoneTypes' | 'WorkOrderMilestoneTypes'
| 'WorkOrderTypes' | 'WorkOrderTypes'
const recordIdColumns = new Map<RecordTable, string>() const recordIdColumns = new Map<RecordTable, string>([
recordIdColumns.set('FeeCategories', 'feeCategoryId') ['BurialSiteStatuses', 'burialSiteStatusId'],
recordIdColumns.set('BurialSiteStatuses', 'burialSiteStatusId') ['BurialSiteTypes', 'burialSiteTypeId'],
recordIdColumns.set('BurialSiteTypes', 'burialSiteTypeId') ['ContractTypes', 'contractTypeId'],
recordIdColumns.set('ContractTypes', 'contractTypeId') ['FeeCategories', 'feeCategoryId'],
recordIdColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId') ['WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'],
recordIdColumns.set('WorkOrderTypes', 'workOrderTypeId') ['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
}
export async function moveRecordDown( export async function moveRecordDown(
recordTable: RecordTable, recordTable: RecordTable,
@ -187,3 +170,21 @@ export async function moveRecordUpToTop(
return true 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
}

View File

@ -4,6 +4,7 @@ import { acquireConnection } from './pool.js'
export interface UpdateForm { export interface UpdateForm {
contractTypeId: number | string contractTypeId: number | string
contractType: string contractType: string
isPreneed?: string isPreneed?: string
} }

View File

@ -1,11 +1,11 @@
export interface UpdateContractTypeFieldForm { export interface UpdateContractTypeFieldForm {
contractTypeFieldId: number | string; contractTypeFieldId: number | string;
contractTypeField: string; contractTypeField: string;
isRequired: '0' | '1';
fieldType?: string; fieldType?: string;
minLength?: string;
maxLength?: string;
pattern?: string;
fieldValues: string; fieldValues: string;
isRequired: '0' | '1';
maxLength?: string;
minLength?: string;
pattern?: string;
} }
export default function updateContractTypeField(updateForm: UpdateContractTypeFieldForm, user: User): Promise<boolean>; export default function updateContractTypeField(updateForm: UpdateContractTypeFieldForm, user: User): Promise<boolean>;

View File

@ -4,13 +4,14 @@ import { acquireConnection } from './pool.js'
export interface UpdateContractTypeFieldForm { export interface UpdateContractTypeFieldForm {
contractTypeFieldId: number | string contractTypeFieldId: number | string
contractTypeField: string contractTypeField: string
isRequired: '0' | '1'
fieldType?: string fieldType?: string
minLength?: string
maxLength?: string
pattern?: string
fieldValues: string fieldValues: string
isRequired: '0' | '1'
maxLength?: string
minLength?: string
pattern?: string
} }
export default async function updateContractTypeField( export default async function updateContractTypeField(

View File

@ -2,6 +2,7 @@ import { acquireConnection } from './pool.js'
export interface UpdateFeeCategoryForm { export interface UpdateFeeCategoryForm {
feeCategoryId: number | string feeCategoryId: number | string
feeCategory: string feeCategory: string
isGroupedFee?: '1' isGroupedFee?: '1'
} }

View File

@ -4,8 +4,8 @@ export interface UpdateForm {
funeralHomeAddress1: string; funeralHomeAddress1: string;
funeralHomeAddress2: string; funeralHomeAddress2: string;
funeralHomeCity: string; funeralHomeCity: string;
funeralHomeProvince: string;
funeralHomePostalCode: string; funeralHomePostalCode: string;
funeralHomeProvince: string;
funeralHomePhoneNumber: string; funeralHomePhoneNumber: string;
} }
export default function updateFuneralHome(updateForm: UpdateForm, user: User): Promise<boolean>; export default function updateFuneralHome(updateForm: UpdateForm, user: User): Promise<boolean>;

View File

@ -6,7 +6,8 @@ export default async function updateFuneralHome(updateForm, user) {
.prepare(`update FuneralHomes .prepare(`update FuneralHomes
set funeralHomeName = ?, set funeralHomeName = ?,
funeralHomeAddress1 = ?, funeralHomeAddress2 = ?, funeralHomeAddress1 = ?, funeralHomeAddress2 = ?,
funeralHomeCity = ?, funeralHomeProvince = ?, funeralHomePostalCode = ?, funeralHomePhoneNumber = ?, funeralHomeCity = ?, funeralHomeProvince = ?, funeralHomePostalCode = ?,
funeralHomePhoneNumber = ?,
recordUpdate_userName = ?, recordUpdate_timeMillis = ? recordUpdate_userName = ?, recordUpdate_timeMillis = ?
where recordDelete_timeMillis is null where recordDelete_timeMillis is null
and funeralHomeId = ?`) and funeralHomeId = ?`)

View File

@ -3,11 +3,13 @@ import { acquireConnection } from './pool.js'
export interface UpdateForm { export interface UpdateForm {
funeralHomeId: number | string funeralHomeId: number | string
funeralHomeName: string funeralHomeName: string
funeralHomeAddress1: string funeralHomeAddress1: string
funeralHomeAddress2: string funeralHomeAddress2: string
funeralHomeCity: string funeralHomeCity: string
funeralHomeProvince: string
funeralHomePostalCode: string funeralHomePostalCode: string
funeralHomeProvince: string
funeralHomePhoneNumber: string funeralHomePhoneNumber: string
} }
@ -24,7 +26,8 @@ export default async function updateFuneralHome(
`update FuneralHomes `update FuneralHomes
set funeralHomeName = ?, set funeralHomeName = ?,
funeralHomeAddress1 = ?, funeralHomeAddress2 = ?, funeralHomeAddress1 = ?, funeralHomeAddress2 = ?,
funeralHomeCity = ?, funeralHomeProvince = ?, funeralHomePostalCode = ?, funeralHomePhoneNumber = ?, funeralHomeCity = ?, funeralHomeProvince = ?, funeralHomePostalCode = ?,
funeralHomePhoneNumber = ?,
recordUpdate_userName = ?, recordUpdate_timeMillis = ? recordUpdate_userName = ?, recordUpdate_timeMillis = ?
where recordDelete_timeMillis is null where recordDelete_timeMillis is null
and funeralHomeId = ?` and funeralHomeId = ?`

View File

@ -1,19 +1,14 @@
import { clearCacheByTableName } from '../helpers/functions.cache.js'; import { clearCacheByTableName } from '../helpers/functions.cache.js';
import { acquireConnection } from './pool.js'; import { acquireConnection } from './pool.js';
const recordNameIdColumns = new Map(); const recordNameIdColumns = new Map([
recordNameIdColumns.set('BurialSiteStatuses', [ ['BurialSiteStatuses', ['burialSiteStatus', 'burialSiteStatusId']],
'burialSiteStatus', ['BurialSiteTypes', ['burialSiteType', 'burialSiteTypeId']],
'burialSiteStatusId' [
'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) { export async function updateRecord(recordTable, recordId, recordName, user) {
const database = await acquireConnection(); const database = await acquireConnection();
const result = database const result = database

View File

@ -8,20 +8,15 @@ type RecordTable =
| 'WorkOrderMilestoneTypes' | 'WorkOrderMilestoneTypes'
| 'WorkOrderTypes' | 'WorkOrderTypes'
const recordNameIdColumns = new Map<RecordTable, string[]>() const recordNameIdColumns = new Map<RecordTable, string[]>([
recordNameIdColumns.set('BurialSiteStatuses', [ ['BurialSiteStatuses', ['burialSiteStatus', 'burialSiteStatusId']],
'burialSiteStatus', ['BurialSiteTypes', ['burialSiteType', 'burialSiteTypeId']],
'burialSiteStatusId' [
'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( export async function updateRecord(
recordTable: RecordTable, recordTable: RecordTable,

View File

@ -1,4 +1,4 @@
import type { PoolConnection } from 'better-sqlite-pool'; 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 declare function updateRecordOrderNumber(recordTable: RecordTable, recordId: number | string, orderNumber: number | string, connectedDatabase: PoolConnection): boolean;
export {}; export {};

View File

@ -1,15 +1,16 @@
const recordIdColumns = new Map(); const recordIdColumns = new Map([
recordIdColumns.set('FeeCategories', 'feeCategoryId'); ['BurialSiteStatuses', 'burialSiteStatusId'],
recordIdColumns.set('Fees', 'feeId'); ['BurialSiteTypeFields', 'burialSiteTypeFieldId'],
recordIdColumns.set('BurialSiteStatuses', 'burialSiteStatusId'); ['BurialSiteTypes', 'burialSiteTypeId'],
recordIdColumns.set('BurialSiteTypes', 'burialSiteTypeId'); ['CommittalTypes', 'committalTypeId'],
recordIdColumns.set('BurialSiteTypeFields', 'burialSiteTypeFieldId'); ['ContractTypeFields', 'contractTypeFieldId'],
recordIdColumns.set('IntermentContainerTypes', 'intermentContainerTypeId'); ['ContractTypes', 'contractTypeId'],
recordIdColumns.set('CommittalTypes', 'committalTypeId'); ['FeeCategories', 'feeCategoryId'],
recordIdColumns.set('ContractTypes', 'contractTypeId'); ['Fees', 'feeId'],
recordIdColumns.set('ContractTypeFields', 'contractTypeFieldId'); ['IntermentContainerTypes', 'intermentContainerTypeId'],
recordIdColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'); ['WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'],
recordIdColumns.set('WorkOrderTypes', 'workOrderTypeId'); ['WorkOrderTypes', 'workOrderTypeId']
]);
export function updateRecordOrderNumber(recordTable, recordId, orderNumber, connectedDatabase) { export function updateRecordOrderNumber(recordTable, recordId, orderNumber, connectedDatabase) {
const result = connectedDatabase const result = connectedDatabase
.prepare(`update ${recordTable} .prepare(`update ${recordTable}

View File

@ -1,30 +1,31 @@
import type { PoolConnection } from 'better-sqlite-pool' import type { PoolConnection } from 'better-sqlite-pool'
type RecordTable = type RecordTable =
| 'BurialSiteStatuses'
| 'BurialSiteTypeFields'
| 'BurialSiteTypes'
| 'CommittalTypes'
| 'ContractTypeFields'
| 'ContractTypes'
| 'FeeCategories' | 'FeeCategories'
| 'Fees' | 'Fees'
| 'BurialSiteStatuses'
| 'BurialSiteTypes'
| 'BurialSiteTypeFields'
| 'IntermentContainerTypes' | 'IntermentContainerTypes'
| 'CommittalTypes'
| 'ContractTypes'
| 'ContractTypeFields'
| 'WorkOrderMilestoneTypes' | 'WorkOrderMilestoneTypes'
| 'WorkOrderTypes' | 'WorkOrderTypes'
const recordIdColumns = new Map<RecordTable, string>() const recordIdColumns = new Map<RecordTable, string>([
recordIdColumns.set('FeeCategories', 'feeCategoryId') ['BurialSiteStatuses', 'burialSiteStatusId'],
recordIdColumns.set('Fees', 'feeId') ['BurialSiteTypeFields', 'burialSiteTypeFieldId'],
recordIdColumns.set('BurialSiteStatuses', 'burialSiteStatusId') ['BurialSiteTypes', 'burialSiteTypeId'],
recordIdColumns.set('BurialSiteTypes', 'burialSiteTypeId') ['CommittalTypes', 'committalTypeId'],
recordIdColumns.set('BurialSiteTypeFields', 'burialSiteTypeFieldId') ['ContractTypeFields', 'contractTypeFieldId'],
recordIdColumns.set('IntermentContainerTypes', 'intermentContainerTypeId') ['ContractTypes', 'contractTypeId'],
recordIdColumns.set('CommittalTypes', 'committalTypeId') ['FeeCategories', 'feeCategoryId'],
recordIdColumns.set('ContractTypes', 'contractTypeId') ['Fees', 'feeId'],
recordIdColumns.set('ContractTypeFields', 'contractTypeFieldId') ['IntermentContainerTypes', 'intermentContainerTypeId'],
recordIdColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId') ['WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'],
recordIdColumns.set('WorkOrderTypes', 'workOrderTypeId') ['WorkOrderTypes', 'workOrderTypeId']
])
export function updateRecordOrderNumber( export function updateRecordOrderNumber(
recordTable: RecordTable, recordTable: RecordTable,

View File

@ -2,8 +2,8 @@ import { type DateString } from '@cityssm/utils-datetime';
export interface UpdateWorkOrderForm { export interface UpdateWorkOrderForm {
workOrderId: string; workOrderId: string;
workOrderNumber: string; workOrderNumber: string;
workOrderTypeId: string;
workOrderDescription: string; workOrderDescription: string;
workOrderOpenDateString: DateString; workOrderOpenDateString: DateString;
workOrderTypeId: string;
} }
export default function updateWorkOrder(workOrderForm: UpdateWorkOrderForm, user: User): Promise<boolean>; export default function updateWorkOrder(workOrderForm: UpdateWorkOrderForm, user: User): Promise<boolean>;

View File

@ -5,9 +5,10 @@ import { acquireConnection } from './pool.js'
export interface UpdateWorkOrderForm { export interface UpdateWorkOrderForm {
workOrderId: string workOrderId: string
workOrderNumber: string workOrderNumber: string
workOrderTypeId: string
workOrderDescription: string workOrderDescription: string
workOrderOpenDateString: DateString workOrderOpenDateString: DateString
workOrderTypeId: string
} }
export default async function updateWorkOrder( export default async function updateWorkOrder(

View File

@ -1,8 +1,8 @@
import { type DateString, type TimeString } from '@cityssm/utils-datetime'; import { type DateString, type TimeString } from '@cityssm/utils-datetime';
export interface UpdateWorkOrderCommentForm { export interface UpdateWorkOrderCommentForm {
workOrderCommentId: string | number; workOrderCommentId: number | string;
comment: string;
commentDateString: DateString; commentDateString: DateString;
commentTimeString: TimeString; commentTimeString: TimeString;
comment: string;
} }
export default function updateWorkOrderComment(commentForm: UpdateWorkOrderCommentForm, user: User): Promise<boolean>; export default function updateWorkOrderComment(commentForm: UpdateWorkOrderCommentForm, user: User): Promise<boolean>;

View File

@ -8,10 +8,11 @@ import {
import { acquireConnection } from './pool.js' import { acquireConnection } from './pool.js'
export interface UpdateWorkOrderCommentForm { export interface UpdateWorkOrderCommentForm {
workOrderCommentId: string | number workOrderCommentId: number | string
comment: string
commentDateString: DateString commentDateString: DateString
commentTimeString: TimeString commentTimeString: TimeString
comment: string
} }
export default async function updateWorkOrderComment( export default async function updateWorkOrderComment(

View File

@ -1,8 +1,8 @@
export interface UpdateWorkOrderMilestoneForm { export interface UpdateWorkOrderMilestoneForm {
workOrderMilestoneId: string | number; workOrderMilestoneId: number | string;
workOrderMilestoneTypeId: number | string;
workOrderMilestoneDateString: string; workOrderMilestoneDateString: string;
workOrderMilestoneTimeString?: string;
workOrderMilestoneDescription: string; workOrderMilestoneDescription: string;
workOrderMilestoneTimeString?: string;
workOrderMilestoneTypeId: number | string;
} }
export default function updateWorkOrderMilestone(milestoneForm: UpdateWorkOrderMilestoneForm, user: User): Promise<boolean>; export default function updateWorkOrderMilestone(milestoneForm: UpdateWorkOrderMilestoneForm, user: User): Promise<boolean>;

View File

@ -6,11 +6,12 @@ import {
import { acquireConnection } from './pool.js' import { acquireConnection } from './pool.js'
export interface UpdateWorkOrderMilestoneForm { export interface UpdateWorkOrderMilestoneForm {
workOrderMilestoneId: string | number workOrderMilestoneId: number | string
workOrderMilestoneTypeId: number | string
workOrderMilestoneDateString: string workOrderMilestoneDateString: string
workOrderMilestoneTimeString?: string
workOrderMilestoneDescription: string workOrderMilestoneDescription: string
workOrderMilestoneTimeString?: string
workOrderMilestoneTypeId: number | string
} }
export default async function updateWorkOrderMilestone( export default async function updateWorkOrderMilestone(

View File

@ -1,6 +1,6 @@
import type { NextFunction, Request, Response } from 'express'; import type { NextFunction, Request, Response } from 'express';
export declare function adminGetHandler(request: Request, response: Response, next: NextFunction): void; 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 adminPostHandler(request: Request, response: Response, next: NextFunction): void;
export declare function apiGetHandler(request: Request, response: Response, next: NextFunction): Promise<void>;
export declare function updateGetHandler(request: Request, response: Response, next: NextFunction): void; 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 updatePostHandler(request: Request, response: Response, next: NextFunction): void;
export declare function apiGetHandler(request: Request, response: Response, next: NextFunction): Promise<void>;

View File

@ -3,8 +3,8 @@ import { apiKeyIsValid, userCanUpdate, userIsAdmin } from '../helpers/functions.
const urlPrefix = getConfigProperty('reverseProxy.urlPrefix'); const urlPrefix = getConfigProperty('reverseProxy.urlPrefix');
const forbiddenStatus = 403; const forbiddenStatus = 403;
const forbiddenJSON = { const forbiddenJSON = {
success: false, message: 'Forbidden',
message: 'Forbidden' success: false
}; };
const forbiddenRedirectURL = `${urlPrefix}/dashboard/?error=accessDenied`; const forbiddenRedirectURL = `${urlPrefix}/dashboard/?error=accessDenied`;
export function adminGetHandler(request, response, next) { export function adminGetHandler(request, response, next) {
@ -21,6 +21,14 @@ export function adminPostHandler(request, response, next) {
} }
response.status(forbiddenStatus).json(forbiddenJSON); 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) { export function updateGetHandler(request, response, next) {
if (userCanUpdate(request)) { if (userCanUpdate(request)) {
next(); next();
@ -35,11 +43,3 @@ export function updatePostHandler(request, response, next) {
} }
response.status(forbiddenStatus).json(forbiddenJSON); response.status(forbiddenStatus).json(forbiddenJSON);
} }
export async function apiGetHandler(request, response, next) {
if (await apiKeyIsValid(request)) {
next();
}
else {
response.redirect(`${urlPrefix}/login`);
}
}

View File

@ -12,8 +12,8 @@ const urlPrefix = getConfigProperty('reverseProxy.urlPrefix')
const forbiddenStatus = 403 const forbiddenStatus = 403
const forbiddenJSON = { const forbiddenJSON = {
success: false, message: 'Forbidden',
message: 'Forbidden' success: false
} }
const forbiddenRedirectURL = `${urlPrefix}/dashboard/?error=accessDenied` const forbiddenRedirectURL = `${urlPrefix}/dashboard/?error=accessDenied`
@ -44,6 +44,18 @@ export function adminPostHandler(
response.status(forbiddenStatus).json(forbiddenJSON) response.status(forbiddenStatus).json(forbiddenJSON)
} }
export async function apiGetHandler(
request: Request,
response: Response,
next: NextFunction
): Promise<void> {
if (await apiKeyIsValid(request)) {
next()
} else {
response.redirect(`${urlPrefix}/login`)
}
}
export function updateGetHandler( export function updateGetHandler(
request: Request, request: Request,
response: Response, response: Response,
@ -69,15 +81,3 @@ export function updatePostHandler(
response.status(forbiddenStatus).json(forbiddenJSON) response.status(forbiddenStatus).json(forbiddenJSON)
} }
export async function apiGetHandler(
request: Request,
response: Response,
next: NextFunction
): Promise<void> {
if (await apiKeyIsValid(request)) {
next()
} else {
response.redirect(`${urlPrefix}/login`)
}
}

View File

@ -7,14 +7,14 @@ import { minutesToSeconds } from '@cityssm/to-millis'
import Debug from 'debug' import Debug from 'debug'
import NodeCache from 'node-cache' 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 { import type {
CacheBurialSiteIdsWorkerMessage, CacheBurialSiteIdsWorkerMessage,
ClearNextPreviousBurialSiteIdsCacheWorkerMessage ClearNextPreviousBurialSiteIdsCacheWorkerMessage
} from '../types/applicationTypes.js' } 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' import { getConfigProperty } from './config.helpers.js'
const debug = Debug(`${DEBUG_NAMESPACE}:burialSites.helpers:${process.pid}`) const debug = Debug(`${DEBUG_NAMESPACE}:burialSites.helpers:${process.pid}`)

View File

@ -1,4 +1,4 @@
import type { Contract, ContractFee } from '../types/recordTypes.js'; 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 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; export declare function getTransactionTotal(contract: Contract): number;

View File

@ -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) { export function getFeesByFeeCategory(contract, feeCategory, feeCategoryContains = false) {
const feeCategoryLowerCase = feeCategory.toLowerCase(); const feeCategoryLowerCase = feeCategory.toLowerCase();
return (contract.contractFees ?? []).filter((possibleFee) => feeCategoryContains return (contract.contractFees ?? []).filter((possibleFee) => feeCategoryContains
@ -16,6 +7,15 @@ export function getFeesByFeeCategory(contract, feeCategory, feeCategoryContains
: possibleFee.feeCategory.toLowerCase() === : possibleFee.feeCategory.toLowerCase() ===
feeCategoryLowerCase); 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) { export function getTransactionTotal(contract) {
let transactionTotal = 0; let transactionTotal = 0;
for (const transaction of contract.contractTransactions ?? for (const transaction of contract.contractTransactions ??

View File

@ -3,6 +3,24 @@ import type {
ContractFee ContractFee
} from '../types/recordTypes.js' } 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( export function getFieldValueByContractTypeField(
contract: Contract, contract: Contract,
contractTypeField: string contractTypeField: string
@ -22,24 +40,6 @@ export function getFieldValueByContractTypeField(
return field.fieldValue 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( export function getTransactionTotal(
contract: Contract contract: Contract
): number { ): number {

View File

@ -2,6 +2,12 @@ import ActiveDirectory from 'activedirectory2';
import { getConfigProperty } from './config.helpers.js'; import { getConfigProperty } from './config.helpers.js';
const userDomain = getConfigProperty('application.userDomain'); const userDomain = getConfigProperty('application.userDomain');
const activeDirectoryConfig = getConfigProperty('activeDirectory'); 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) { async function authenticateViaActiveDirectory(userName, password) {
return await new Promise((resolve) => { return await new Promise((resolve) => {
try { 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 */ /* eslint-disable @cspell/spellchecker */
const safeRedirects = new Set([ const safeRedirects = new Set([
'/admin/cleanup',
'/admin/fees',
'/admin/burialsitetypes', '/admin/burialsitetypes',
'/admin/cleanup',
'/admin/contracttypes', '/admin/contracttypes',
'/admin/fees',
'/admin/tables', '/admin/tables',
'/contracts', '/burialsites',
'/contracts/new', '/burialsites/new',
'/burialSites',
'/burialSites/new',
'/cemeteries', '/cemeteries',
'/cemeteries/new', '/cemeteries/new',
'/contracts',
'/contracts/new',
'/reports',
'/workorders', '/workorders',
'/workorders/new',
'/workorders/milestonecalendar', '/workorders/milestonecalendar',
'/workorders/outlook', '/workorders/new',
'/reports' '/workorders/outlook'
]); ]);
/* eslint-enable @cspell/spellchecker */ /* 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-]+$/; const printUrl = /^\/print\/(?:pdf|screen)\/[\d/=?A-Za-z-]+$/;
export function getSafeRedirectURL(possibleRedirectURL = '') { export function getSafeRedirectURL(possibleRedirectURL = '') {
const urlPrefix = getConfigProperty('reverseProxy.urlPrefix'); const urlPrefix = getConfigProperty('reverseProxy.urlPrefix');

View File

@ -6,6 +6,17 @@ const userDomain = getConfigProperty('application.userDomain')
const activeDirectoryConfig = getConfigProperty('activeDirectory') const activeDirectoryConfig = getConfigProperty('activeDirectory')
export async function authenticate(
userName: string | undefined,
password: string | undefined
): Promise<boolean> {
if ((userName ?? '') === '' || (password ?? '') === '') {
return false
}
return await authenticateViaActiveDirectory(userName ?? '', password ?? '')
}
async function authenticateViaActiveDirectory( async function authenticateViaActiveDirectory(
userName: string, userName: string,
password: string password: string
@ -29,41 +40,30 @@ async function authenticateViaActiveDirectory(
}) })
} }
export async function authenticate(
userName: string | undefined,
password: string | undefined
): Promise<boolean> {
if ((userName ?? '') === '' || (password ?? '') === '') {
return false
}
return await authenticateViaActiveDirectory(userName ?? '', password ?? '')
}
/* eslint-disable @cspell/spellchecker */ /* eslint-disable @cspell/spellchecker */
const safeRedirects = new Set([ const safeRedirects = new Set([
'/admin/cleanup',
'/admin/fees',
'/admin/burialsitetypes', '/admin/burialsitetypes',
'/admin/cleanup',
'/admin/contracttypes', '/admin/contracttypes',
'/admin/fees',
'/admin/tables', '/admin/tables',
'/contracts', '/burialsites',
'/contracts/new', '/burialsites/new',
'/burialSites',
'/burialSites/new',
'/cemeteries', '/cemeteries',
'/cemeteries/new', '/cemeteries/new',
'/contracts',
'/contracts/new',
'/reports',
'/workorders', '/workorders',
'/workorders/new',
'/workorders/milestonecalendar', '/workorders/milestonecalendar',
'/workorders/outlook', '/workorders/new',
'/reports' '/workorders/outlook'
]) ])
/* eslint-enable @cspell/spellchecker */ /* 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-]+$/ const printUrl = /^\/print\/(?:pdf|screen)\/[\d/=?A-Za-z-]+$/

View File

@ -1,26 +1,26 @@
import type { BurialSiteStatus, BurialSiteType, CommittalType, ContractType, ContractTypeField, IntermentContainerType, WorkOrderMilestoneType, WorkOrderType } from '../types/recordTypes.js'; import type { BurialSiteStatus, BurialSiteType, CommittalType, ContractType, ContractTypeField, IntermentContainerType, WorkOrderMilestoneType, WorkOrderType } from '../types/recordTypes.js';
export declare function getBurialSiteStatuses(): Promise<BurialSiteStatus[]>;
export declare function getBurialSiteStatusById(burialSiteStatusId: number): Promise<BurialSiteStatus | undefined>;
export declare function getBurialSiteStatusByBurialSiteStatus(burialSiteStatus: string): Promise<BurialSiteStatus | undefined>; export declare function getBurialSiteStatusByBurialSiteStatus(burialSiteStatus: string): Promise<BurialSiteStatus | undefined>;
export declare function getBurialSiteTypes(): Promise<BurialSiteType[]>; export declare function getBurialSiteStatusById(burialSiteStatusId: number): Promise<BurialSiteStatus | undefined>;
export declare function getBurialSiteStatuses(): Promise<BurialSiteStatus[]>;
export declare function getBurialSiteTypeById(burialSiteTypeId: number): Promise<BurialSiteType | undefined>; export declare function getBurialSiteTypeById(burialSiteTypeId: number): Promise<BurialSiteType | undefined>;
export declare function getBurialSiteTypes(): Promise<BurialSiteType[]>;
export declare function getBurialSiteTypesByBurialSiteType(burialSiteType: string): Promise<BurialSiteType | undefined>; export declare function getBurialSiteTypesByBurialSiteType(burialSiteType: string): Promise<BurialSiteType | undefined>;
export declare function getContractTypes(): Promise<ContractType[]>;
export declare function getAllContractTypeFields(): Promise<ContractTypeField[]>; export declare function getAllContractTypeFields(): Promise<ContractTypeField[]>;
export declare function getContractTypeById(contractTypeId: number): Promise<ContractType | undefined>;
export declare function getContractTypeByContractType(contractTypeString: string): Promise<ContractType | undefined>; export declare function getContractTypeByContractType(contractTypeString: string): Promise<ContractType | undefined>;
export declare function getContractTypeById(contractTypeId: number): Promise<ContractType | undefined>;
export declare function getContractTypePrintsById(contractTypeId: number): Promise<string[]>; export declare function getContractTypePrintsById(contractTypeId: number): Promise<string[]>;
export declare function getIntermentContainerTypes(): Promise<IntermentContainerType[]>; export declare function getContractTypes(): Promise<ContractType[]>;
export declare function getIntermentContainerTypeById(intermentContainerTypeId: number): Promise<IntermentContainerType | undefined>; export declare function getIntermentContainerTypeById(intermentContainerTypeId: number): Promise<IntermentContainerType | undefined>;
export declare function getCommittalTypes(): Promise<CommittalType[]>; export declare function getIntermentContainerTypes(): Promise<IntermentContainerType[]>;
export declare function getCommittalTypeById(committalTypeId: number): Promise<CommittalType | undefined>; export declare function getCommittalTypeById(committalTypeId: number): Promise<CommittalType | undefined>;
export declare function getWorkOrderTypes(): Promise<WorkOrderType[]>; export declare function getCommittalTypes(): Promise<CommittalType[]>;
export declare function getWorkOrderTypeById(workOrderTypeId: number): Promise<WorkOrderType | undefined>; export declare function getWorkOrderTypeById(workOrderTypeId: number): Promise<WorkOrderType | undefined>;
export declare function getWorkOrderMilestoneTypes(): Promise<WorkOrderMilestoneType[]>; export declare function getWorkOrderTypes(): Promise<WorkOrderType[]>;
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<WorkOrderMilestoneType | undefined>; export declare function getWorkOrderMilestoneTypeById(workOrderMilestoneTypeId: number): Promise<WorkOrderMilestoneType | undefined>;
export declare function getWorkOrderMilestoneTypeByWorkOrderMilestoneType(workOrderMilestoneTypeString: string): Promise<WorkOrderMilestoneType | undefined>; export declare function getWorkOrderMilestoneTypeByWorkOrderMilestoneType(workOrderMilestoneTypeString: string): Promise<WorkOrderMilestoneType | undefined>;
export declare function getWorkOrderMilestoneTypes(): Promise<WorkOrderMilestoneType[]>;
export declare function preloadCaches(): Promise<void>; export declare function preloadCaches(): Promise<void>;
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 {}; export {};

View File

@ -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 cluster from 'node:cluster';
import Debug from 'debug'; import Debug from 'debug';
import getBurialSiteStatusesFromDatabase from '../database/getBurialSiteStatuses.js'; import getBurialSiteStatusesFromDatabase from '../database/getBurialSiteStatuses.js';
@ -17,20 +15,18 @@ const debug = Debug(`${DEBUG_NAMESPACE}:functions.cache:${process.pid}`);
* Burial Site Statuses * Burial Site Statuses
*/ */
let burialSiteStatuses; let burialSiteStatuses;
export async function getBurialSiteStatuses() { export async function getBurialSiteStatusByBurialSiteStatus(burialSiteStatus) {
if (burialSiteStatuses === undefined) { const cachedStatuses = await getBurialSiteStatuses();
burialSiteStatuses = await getBurialSiteStatusesFromDatabase(); const statusLowerCase = burialSiteStatus.toLowerCase();
} return cachedStatuses.find((currentStatus) => currentStatus.burialSiteStatus.toLowerCase() === statusLowerCase);
return burialSiteStatuses;
} }
export async function getBurialSiteStatusById(burialSiteStatusId) { export async function getBurialSiteStatusById(burialSiteStatusId) {
const cachedStatuses = await getBurialSiteStatuses(); const cachedStatuses = await getBurialSiteStatuses();
return cachedStatuses.find((currentStatus) => currentStatus.burialSiteStatusId === burialSiteStatusId); return cachedStatuses.find((currentStatus) => currentStatus.burialSiteStatusId === burialSiteStatusId);
} }
export async function getBurialSiteStatusByBurialSiteStatus(burialSiteStatus) { export async function getBurialSiteStatuses() {
const cachedStatuses = await getBurialSiteStatuses(); burialSiteStatuses ??= await getBurialSiteStatusesFromDatabase();
const statusLowerCase = burialSiteStatus.toLowerCase(); return burialSiteStatuses;
return cachedStatuses.find((currentStatus) => currentStatus.burialSiteStatus.toLowerCase() === statusLowerCase);
} }
function clearBurialSiteStatusesCache() { function clearBurialSiteStatusesCache() {
burialSiteStatuses = undefined; burialSiteStatuses = undefined;
@ -39,16 +35,14 @@ function clearBurialSiteStatusesCache() {
* Burial Site Types * Burial Site Types
*/ */
let burialSiteTypes; let burialSiteTypes;
export async function getBurialSiteTypes() {
if (burialSiteTypes === undefined) {
burialSiteTypes = await getBurialSiteTypesFromDatabase();
}
return burialSiteTypes;
}
export async function getBurialSiteTypeById(burialSiteTypeId) { export async function getBurialSiteTypeById(burialSiteTypeId) {
const cachedTypes = await getBurialSiteTypes(); const cachedTypes = await getBurialSiteTypes();
return cachedTypes.find((currentType) => currentType.burialSiteTypeId === burialSiteTypeId); return cachedTypes.find((currentType) => currentType.burialSiteTypeId === burialSiteTypeId);
} }
export async function getBurialSiteTypes() {
burialSiteTypes ??= await getBurialSiteTypesFromDatabase();
return burialSiteTypes;
}
export async function getBurialSiteTypesByBurialSiteType(burialSiteType) { export async function getBurialSiteTypesByBurialSiteType(burialSiteType) {
const cachedTypes = await getBurialSiteTypes(); const cachedTypes = await getBurialSiteTypes();
const typeLowerCase = burialSiteType.toLowerCase(); const typeLowerCase = burialSiteType.toLowerCase();
@ -62,27 +56,19 @@ function clearBurialSiteTypesCache() {
*/ */
let contractTypes; let contractTypes;
let allContractTypeFields; let allContractTypeFields;
export async function getContractTypes() {
if (contractTypes === undefined) {
contractTypes = await getContractTypesFromDatabase();
}
return contractTypes;
}
export async function getAllContractTypeFields() { export async function getAllContractTypeFields() {
if (allContractTypeFields === undefined) { allContractTypeFields ??= await getContractTypeFieldsFromDatabase();
allContractTypeFields = await getContractTypeFieldsFromDatabase();
}
return allContractTypeFields; return allContractTypeFields;
} }
export async function getContractTypeById(contractTypeId) {
const cachedTypes = await getContractTypes();
return cachedTypes.find((currentType) => currentType.contractTypeId === contractTypeId);
}
export async function getContractTypeByContractType(contractTypeString) { export async function getContractTypeByContractType(contractTypeString) {
const cachedTypes = await getContractTypes(); const cachedTypes = await getContractTypes();
const typeLowerCase = contractTypeString.toLowerCase(); const typeLowerCase = contractTypeString.toLowerCase();
return cachedTypes.find((currentType) => currentType.contractType.toLowerCase() === typeLowerCase); 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) { export async function getContractTypePrintsById(contractTypeId) {
const contractType = await getContractTypeById(contractTypeId); const contractType = await getContractTypeById(contractTypeId);
if (contractType?.contractTypePrints === undefined || if (contractType?.contractTypePrints === undefined ||
@ -94,6 +80,10 @@ export async function getContractTypePrintsById(contractTypeId) {
} }
return contractType.contractTypePrints ?? []; return contractType.contractTypePrints ?? [];
} }
export async function getContractTypes() {
contractTypes ??= await getContractTypesFromDatabase();
return contractTypes;
}
function clearContractTypesCache() { function clearContractTypesCache() {
contractTypes = undefined; contractTypes = undefined;
allContractTypeFields = undefined; allContractTypeFields = undefined;
@ -102,16 +92,14 @@ function clearContractTypesCache() {
* Interment Container Types * Interment Container Types
*/ */
let intermentContainerTypes; let intermentContainerTypes;
export async function getIntermentContainerTypes() {
if (intermentContainerTypes === undefined) {
intermentContainerTypes = await getIntermentContainerTypesFromDatabase();
}
return intermentContainerTypes;
}
export async function getIntermentContainerTypeById(intermentContainerTypeId) { export async function getIntermentContainerTypeById(intermentContainerTypeId) {
const cachedContainerTypes = await getIntermentContainerTypes(); const cachedContainerTypes = await getIntermentContainerTypes();
return cachedContainerTypes.find((currentContainerType) => currentContainerType.intermentContainerTypeId === intermentContainerTypeId); return cachedContainerTypes.find((currentContainerType) => currentContainerType.intermentContainerTypeId === intermentContainerTypeId);
} }
export async function getIntermentContainerTypes() {
intermentContainerTypes ??= await getIntermentContainerTypesFromDatabase();
return intermentContainerTypes;
}
function clearIntermentContainerTypesCache() { function clearIntermentContainerTypesCache() {
intermentContainerTypes = undefined; intermentContainerTypes = undefined;
} }
@ -119,16 +107,14 @@ function clearIntermentContainerTypesCache() {
* Committal Types * Committal Types
*/ */
let committalTypes; let committalTypes;
export async function getCommittalTypes() {
if (committalTypes === undefined) {
committalTypes = await getCommittalTypesFromDatabase();
}
return committalTypes;
}
export async function getCommittalTypeById(committalTypeId) { export async function getCommittalTypeById(committalTypeId) {
const cachedCommittalTypes = await getCommittalTypes(); const cachedCommittalTypes = await getCommittalTypes();
return cachedCommittalTypes.find((currentCommittalType) => currentCommittalType.committalTypeId === committalTypeId); return cachedCommittalTypes.find((currentCommittalType) => currentCommittalType.committalTypeId === committalTypeId);
} }
export async function getCommittalTypes() {
committalTypes ??= await getCommittalTypesFromDatabase();
return committalTypes;
}
function clearCommittalTypesCache() { function clearCommittalTypesCache() {
committalTypes = undefined; committalTypes = undefined;
} }
@ -136,16 +122,14 @@ function clearCommittalTypesCache() {
* Work Order Types * Work Order Types
*/ */
let workOrderTypes; let workOrderTypes;
export async function getWorkOrderTypes() {
if (workOrderTypes === undefined) {
workOrderTypes = await getWorkOrderTypesFromDatabase();
}
return workOrderTypes;
}
export async function getWorkOrderTypeById(workOrderTypeId) { export async function getWorkOrderTypeById(workOrderTypeId) {
const cachedWorkOrderTypes = await getWorkOrderTypes(); const cachedWorkOrderTypes = await getWorkOrderTypes();
return cachedWorkOrderTypes.find((currentWorkOrderType) => currentWorkOrderType.workOrderTypeId === workOrderTypeId); return cachedWorkOrderTypes.find((currentWorkOrderType) => currentWorkOrderType.workOrderTypeId === workOrderTypeId);
} }
export async function getWorkOrderTypes() {
workOrderTypes ??= await getWorkOrderTypesFromDatabase();
return workOrderTypes;
}
function clearWorkOrderTypesCache() { function clearWorkOrderTypesCache() {
workOrderTypes = undefined; workOrderTypes = undefined;
} }
@ -153,59 +137,24 @@ function clearWorkOrderTypesCache() {
* Work Order Milestone Types * Work Order Milestone Types
*/ */
let workOrderMilestoneTypes; 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) { export function clearCacheByTableName(tableName, relayMessage = true) {
switch (tableName) { switch (tableName) {
case 'BurialSiteStatuses': { case 'BurialSiteStatuses': {
clearBurialSiteStatusesCache(); clearBurialSiteStatusesCache();
break; break;
} }
case 'BurialSiteTypes': case 'BurialSiteTypeFields':
case 'BurialSiteTypeFields': { case 'BurialSiteTypes': {
clearBurialSiteTypesCache(); clearBurialSiteTypesCache();
break; break;
} }
case 'ContractTypes': case 'CommittalTypes': {
clearCommittalTypesCache();
break;
}
case 'ContractTypeFields': case 'ContractTypeFields':
case 'ContractTypePrints': { case 'ContractTypePrints':
case 'ContractTypes': {
clearContractTypesCache(); clearContractTypesCache();
break; break;
} }
@ -213,10 +162,6 @@ export function clearCacheByTableName(tableName, relayMessage = true) {
clearIntermentContainerTypesCache(); clearIntermentContainerTypesCache();
break; break;
} }
case 'CommittalTypes': {
clearCommittalTypesCache();
break;
}
case 'WorkOrderMilestoneTypes': { case 'WorkOrderMilestoneTypes': {
clearWorkOrderMilestoneTypesCache(); clearWorkOrderMilestoneTypesCache();
break; break;
@ -247,6 +192,43 @@ export function clearCacheByTableName(tableName, relayMessage = true) {
// ignore // 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) => { process.on('message', (message) => {
if (message.messageType === 'clearCache' && message.pid !== process.pid) { if (message.messageType === 'clearCache' && message.pid !== process.pid) {
debug(`Clearing cache: ${message.tableName}`); debug(`Clearing cache: ${message.tableName}`);

View File

@ -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 cluster from 'node:cluster'
import Debug from 'debug' import Debug from 'debug'
@ -39,24 +36,6 @@ const debug = Debug(`${DEBUG_NAMESPACE}:functions.cache:${process.pid}`)
let burialSiteStatuses: BurialSiteStatus[] | undefined let burialSiteStatuses: BurialSiteStatus[] | undefined
export async function getBurialSiteStatuses(): Promise<BurialSiteStatus[]> {
if (burialSiteStatuses === undefined) {
burialSiteStatuses = await getBurialSiteStatusesFromDatabase()
}
return burialSiteStatuses
}
export async function getBurialSiteStatusById(
burialSiteStatusId: number
): Promise<BurialSiteStatus | undefined> {
const cachedStatuses = await getBurialSiteStatuses()
return cachedStatuses.find(
(currentStatus) => currentStatus.burialSiteStatusId === burialSiteStatusId
)
}
export async function getBurialSiteStatusByBurialSiteStatus( export async function getBurialSiteStatusByBurialSiteStatus(
burialSiteStatus: string burialSiteStatus: string
): Promise<BurialSiteStatus | undefined> { ): Promise<BurialSiteStatus | undefined> {
@ -70,6 +49,21 @@ export async function getBurialSiteStatusByBurialSiteStatus(
) )
} }
export async function getBurialSiteStatusById(
burialSiteStatusId: number
): Promise<BurialSiteStatus | undefined> {
const cachedStatuses = await getBurialSiteStatuses()
return cachedStatuses.find(
(currentStatus) => currentStatus.burialSiteStatusId === burialSiteStatusId
)
}
export async function getBurialSiteStatuses(): Promise<BurialSiteStatus[]> {
burialSiteStatuses ??= await getBurialSiteStatusesFromDatabase()
return burialSiteStatuses
}
function clearBurialSiteStatusesCache(): void { function clearBurialSiteStatusesCache(): void {
burialSiteStatuses = undefined burialSiteStatuses = undefined
} }
@ -80,14 +74,6 @@ function clearBurialSiteStatusesCache(): void {
let burialSiteTypes: BurialSiteType[] | undefined let burialSiteTypes: BurialSiteType[] | undefined
export async function getBurialSiteTypes(): Promise<BurialSiteType[]> {
if (burialSiteTypes === undefined) {
burialSiteTypes = await getBurialSiteTypesFromDatabase()
}
return burialSiteTypes
}
export async function getBurialSiteTypeById( export async function getBurialSiteTypeById(
burialSiteTypeId: number burialSiteTypeId: number
): Promise<BurialSiteType | undefined> { ): Promise<BurialSiteType | undefined> {
@ -98,6 +84,11 @@ export async function getBurialSiteTypeById(
) )
} }
export async function getBurialSiteTypes(): Promise<BurialSiteType[]> {
burialSiteTypes ??= await getBurialSiteTypesFromDatabase()
return burialSiteTypes
}
export async function getBurialSiteTypesByBurialSiteType( export async function getBurialSiteTypesByBurialSiteType(
burialSiteType: string burialSiteType: string
): Promise<BurialSiteType | undefined> { ): Promise<BurialSiteType | undefined> {
@ -121,31 +112,11 @@ function clearBurialSiteTypesCache(): void {
let contractTypes: ContractType[] | undefined let contractTypes: ContractType[] | undefined
let allContractTypeFields: ContractTypeField[] | undefined let allContractTypeFields: ContractTypeField[] | undefined
export async function getContractTypes(): Promise<ContractType[]> {
if (contractTypes === undefined) {
contractTypes = await getContractTypesFromDatabase()
}
return contractTypes
}
export async function getAllContractTypeFields(): Promise<ContractTypeField[]> { export async function getAllContractTypeFields(): Promise<ContractTypeField[]> {
if (allContractTypeFields === undefined) { allContractTypeFields ??= await getContractTypeFieldsFromDatabase()
allContractTypeFields = await getContractTypeFieldsFromDatabase()
}
return allContractTypeFields return allContractTypeFields
} }
export async function getContractTypeById(
contractTypeId: number
): Promise<ContractType | undefined> {
const cachedTypes = await getContractTypes()
return cachedTypes.find(
(currentType) => currentType.contractTypeId === contractTypeId
)
}
export async function getContractTypeByContractType( export async function getContractTypeByContractType(
contractTypeString: string contractTypeString: string
): Promise<ContractType | undefined> { ): Promise<ContractType | undefined> {
@ -158,6 +129,16 @@ export async function getContractTypeByContractType(
) )
} }
export async function getContractTypeById(
contractTypeId: number
): Promise<ContractType | undefined> {
const cachedTypes = await getContractTypes()
return cachedTypes.find(
(currentType) => currentType.contractTypeId === contractTypeId
)
}
export async function getContractTypePrintsById( export async function getContractTypePrintsById(
contractTypeId: number contractTypeId: number
): Promise<string[]> { ): Promise<string[]> {
@ -177,6 +158,11 @@ export async function getContractTypePrintsById(
return contractType.contractTypePrints ?? [] return contractType.contractTypePrints ?? []
} }
export async function getContractTypes(): Promise<ContractType[]> {
contractTypes ??= await getContractTypesFromDatabase()
return contractTypes
}
function clearContractTypesCache(): void { function clearContractTypesCache(): void {
contractTypes = undefined contractTypes = undefined
allContractTypeFields = undefined allContractTypeFields = undefined
@ -188,16 +174,6 @@ function clearContractTypesCache(): void {
let intermentContainerTypes: IntermentContainerType[] | undefined let intermentContainerTypes: IntermentContainerType[] | undefined
export async function getIntermentContainerTypes(): Promise<
IntermentContainerType[]
> {
if (intermentContainerTypes === undefined) {
intermentContainerTypes = await getIntermentContainerTypesFromDatabase()
}
return intermentContainerTypes
}
export async function getIntermentContainerTypeById( export async function getIntermentContainerTypeById(
intermentContainerTypeId: number intermentContainerTypeId: number
): Promise<IntermentContainerType | undefined> { ): Promise<IntermentContainerType | undefined> {
@ -209,6 +185,13 @@ export async function getIntermentContainerTypeById(
) )
} }
export async function getIntermentContainerTypes(): Promise<
IntermentContainerType[]
> {
intermentContainerTypes ??= await getIntermentContainerTypesFromDatabase()
return intermentContainerTypes
}
function clearIntermentContainerTypesCache(): void { function clearIntermentContainerTypesCache(): void {
intermentContainerTypes = undefined intermentContainerTypes = undefined
} }
@ -219,16 +202,6 @@ function clearIntermentContainerTypesCache(): void {
let committalTypes: CommittalType[] | undefined let committalTypes: CommittalType[] | undefined
export async function getCommittalTypes(): Promise<
CommittalType[]
> {
if (committalTypes === undefined) {
committalTypes = await getCommittalTypesFromDatabase()
}
return committalTypes
}
export async function getCommittalTypeById( export async function getCommittalTypeById(
committalTypeId: number committalTypeId: number
): Promise<CommittalType | undefined> { ): Promise<CommittalType | undefined> {
@ -240,6 +213,11 @@ export async function getCommittalTypeById(
) )
} }
export async function getCommittalTypes(): Promise<CommittalType[]> {
committalTypes ??= await getCommittalTypesFromDatabase()
return committalTypes
}
function clearCommittalTypesCache(): void { function clearCommittalTypesCache(): void {
committalTypes = undefined committalTypes = undefined
} }
@ -250,14 +228,6 @@ function clearCommittalTypesCache(): void {
let workOrderTypes: WorkOrderType[] | undefined let workOrderTypes: WorkOrderType[] | undefined
export async function getWorkOrderTypes(): Promise<WorkOrderType[]> {
if (workOrderTypes === undefined) {
workOrderTypes = await getWorkOrderTypesFromDatabase()
}
return workOrderTypes
}
export async function getWorkOrderTypeById( export async function getWorkOrderTypeById(
workOrderTypeId: number workOrderTypeId: number
): Promise<WorkOrderType | undefined> { ): Promise<WorkOrderType | undefined> {
@ -269,6 +239,11 @@ export async function getWorkOrderTypeById(
) )
} }
export async function getWorkOrderTypes(): Promise<WorkOrderType[]> {
workOrderTypes ??= await getWorkOrderTypesFromDatabase()
return workOrderTypes
}
function clearWorkOrderTypesCache(): void { function clearWorkOrderTypesCache(): void {
workOrderTypes = undefined workOrderTypes = undefined
} }
@ -279,81 +254,19 @@ function clearWorkOrderTypesCache(): void {
let workOrderMilestoneTypes: WorkOrderMilestoneType[] | undefined 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<WorkOrderMilestoneType | undefined> {
const cachedWorkOrderMilestoneTypes = await getWorkOrderMilestoneTypes()
return cachedWorkOrderMilestoneTypes.find(
(currentWorkOrderMilestoneType) =>
currentWorkOrderMilestoneType.workOrderMilestoneTypeId ===
workOrderMilestoneTypeId
)
}
export async function getWorkOrderMilestoneTypeByWorkOrderMilestoneType(
workOrderMilestoneTypeString: string
): Promise<WorkOrderMilestoneType | undefined> {
const cachedWorkOrderMilestoneTypes = await getWorkOrderMilestoneTypes()
const workOrderMilestoneTypeLowerCase =
workOrderMilestoneTypeString.toLowerCase()
return cachedWorkOrderMilestoneTypes.find(
(currentWorkOrderMilestoneType) =>
currentWorkOrderMilestoneType.workOrderMilestoneType.toLowerCase() ===
workOrderMilestoneTypeLowerCase
)
}
export async function preloadCaches(): Promise<void> {
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 = type CacheTableNames =
| 'BurialSiteStatuses' | 'BurialSiteStatuses'
| 'BurialSiteTypes'
| 'BurialSiteTypeFields' | 'BurialSiteTypeFields'
| 'ContractTypes' | 'BurialSiteTypes'
| 'CommittalTypes'
| 'ContractTypeFields' | 'ContractTypeFields'
| 'ContractTypePrints' | 'ContractTypePrints'
| 'IntermentContainerTypes' | 'ContractTypes'
| 'CommittalTypes'
| 'WorkOrderMilestoneTypes'
| 'WorkOrderTypes'
| 'FeeCategories' | 'FeeCategories'
| 'Fees' | 'Fees'
| 'IntermentContainerTypes'
| 'WorkOrderMilestoneTypes'
| 'WorkOrderTypes'
export function clearCacheByTableName( export function clearCacheByTableName(
tableName: CacheTableNames, tableName: CacheTableNames,
@ -365,15 +278,20 @@ export function clearCacheByTableName(
break break
} }
case 'BurialSiteTypes': case 'BurialSiteTypeFields':
case 'BurialSiteTypeFields': { case 'BurialSiteTypes': {
clearBurialSiteTypesCache() clearBurialSiteTypesCache()
break break
} }
case 'ContractTypes': case 'CommittalTypes': {
clearCommittalTypesCache()
break
}
case 'ContractTypeFields': case 'ContractTypeFields':
case 'ContractTypePrints': { case 'ContractTypePrints':
case 'ContractTypes': {
clearContractTypesCache() clearContractTypesCache()
break break
} }
@ -383,11 +301,6 @@ export function clearCacheByTableName(
break break
} }
case 'CommittalTypes': {
clearCommittalTypesCache()
break
}
case 'WorkOrderMilestoneTypes': { case 'WorkOrderMilestoneTypes': {
clearWorkOrderMilestoneTypesCache() clearWorkOrderMilestoneTypesCache()
break 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<WorkOrderMilestoneType | undefined> {
const cachedWorkOrderMilestoneTypes = await getWorkOrderMilestoneTypes()
return cachedWorkOrderMilestoneTypes.find(
(currentWorkOrderMilestoneType) =>
currentWorkOrderMilestoneType.workOrderMilestoneTypeId ===
workOrderMilestoneTypeId
)
}
export async function getWorkOrderMilestoneTypeByWorkOrderMilestoneType(
workOrderMilestoneTypeString: string
): Promise<WorkOrderMilestoneType | undefined> {
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<void> {
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) => { process.on('message', (message: WorkerMessage) => {
if (message.messageType === 'clearCache' && message.pid !== process.pid) { if (message.messageType === 'clearCache' && message.pid !== process.pid) {
debug(`Clearing cache: ${(message as ClearCacheWorkerMessage).tableName}`) debug(`Clearing cache: ${(message as ClearCacheWorkerMessage).tableName}`)

View File

@ -1,74 +1,25 @@
import { DynamicsGP } from '@cityssm/dynamics-gp'; import { DynamicsGP } from '@cityssm/dynamics-gp';
import { getConfigProperty } from './config.helpers.js'; import { getConfigProperty } from './config.helpers.js';
// eslint-disable-next-line @typescript-eslint/init-declarations
let gp; let gp;
if (getConfigProperty('settings.dynamicsGP.integrationIsEnabled')) { if (getConfigProperty('settings.dynamicsGP.integrationIsEnabled')) {
gp = new DynamicsGP(getConfigProperty('settings.dynamicsGP.mssqlConfig')); gp = new DynamicsGP(getConfigProperty('settings.dynamicsGP.mssqlConfig'));
} }
function filterCashReceipt(cashReceipt) { export async function getDynamicsGPDocument(documentNumber) {
const accountCodes = getConfigProperty('settings.dynamicsGP.accountCodes'); if (!getConfigProperty('settings.dynamicsGP.integrationIsEnabled')) {
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 undefined;
} }
return cashReceipt; let document;
} for (const lookupType of getConfigProperty('settings.dynamicsGP.lookupOrder')) {
function filterInvoice(invoice) { document = await _getDynamicsGPDocument(documentNumber, lookupType);
const itemNumbers = getConfigProperty('settings.dynamicsGP.itemNumbers'); if (document !== undefined) {
for (const itemNumber of itemNumbers) { break;
const found = invoice.lineItems.some((itemRecord) => itemRecord.itemNumber === itemNumber);
if (!found) {
return undefined;
} }
} }
return invoice; return document;
}
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;
} }
async function _getDynamicsGPDocument(documentNumber, lookupType) { async function _getDynamicsGPDocument(documentNumber, lookupType) {
let document; let document;
switch (lookupType) { 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': { case 'diamond/cashReceipt': {
let receipt = await gp.getDiamondCashReceiptByDocumentNumber(documentNumber); let receipt = await gp.getDiamondCashReceiptByDocumentNumber(documentNumber);
if (receipt !== undefined) { if (receipt !== undefined) {
@ -112,19 +63,67 @@ async function _getDynamicsGPDocument(documentNumber, lookupType) {
} }
break; break;
} }
case 'invoice': {
let invoice = await gp.getInvoiceByInvoiceNumber(documentNumber);
if (invoice !== undefined) {
invoice = filterInvoice(invoice);
} }
return document; if (invoice !== undefined) {
document = {
documentType: 'Invoice',
documentNumber: invoice.invoiceNumber,
documentDate: invoice.documentDate,
documentDescription: [
invoice.comment1,
invoice.comment2,
invoice.comment3,
invoice.comment4
],
documentTotal: invoice.documentAmount
};
} }
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) {
break; break;
} }
} }
return document; 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;
}

View File

@ -1,8 +1,8 @@
import { import {
type DiamondCashReceipt, type DiamondCashReceipt,
type DiamondExtendedGPInvoice, type DiamondExtendedGPInvoice,
DynamicsGP, type GPInvoice,
type GPInvoice DynamicsGP
} from '@cityssm/dynamics-gp' } from '@cityssm/dynamics-gp'
import type { DynamicsGPLookup } from '../types/configTypes.js' import type { DynamicsGPLookup } from '../types/configTypes.js'
@ -10,72 +10,32 @@ import type { DynamicsGPDocument } from '../types/recordTypes.js'
import { getConfigProperty } from './config.helpers.js' import { getConfigProperty } from './config.helpers.js'
// eslint-disable-next-line @typescript-eslint/init-declarations
let gp: DynamicsGP let gp: DynamicsGP
if (getConfigProperty('settings.dynamicsGP.integrationIsEnabled')) { if (getConfigProperty('settings.dynamicsGP.integrationIsEnabled')) {
gp = new DynamicsGP(getConfigProperty('settings.dynamicsGP.mssqlConfig')) gp = new DynamicsGP(getConfigProperty('settings.dynamicsGP.mssqlConfig'))
} }
function filterCashReceipt( export async function getDynamicsGPDocument(
cashReceipt: DiamondCashReceipt documentNumber: string
): DiamondCashReceipt | undefined { ): Promise<DynamicsGPDocument | undefined> {
const accountCodes = getConfigProperty('settings.dynamicsGP.accountCodes') if (!getConfigProperty('settings.dynamicsGP.integrationIsEnabled')) {
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 undefined
} }
return cashReceipt let document: DynamicsGPDocument | undefined
}
function filterInvoice(invoice: GPInvoice): GPInvoice | undefined { for (const lookupType of getConfigProperty(
const itemNumbers = getConfigProperty('settings.dynamicsGP.itemNumbers') 'settings.dynamicsGP.lookupOrder'
)) {
document = await _getDynamicsGPDocument(documentNumber, lookupType)
for (const itemNumber of itemNumbers) { if (document !== undefined) {
const found = invoice.lineItems.some((itemRecord) => itemRecord.itemNumber === itemNumber) break
if (!found) {
return undefined
} }
} }
return invoice return document
}
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
} }
async function _getDynamicsGPDocument( async function _getDynamicsGPDocument(
@ -85,30 +45,6 @@ async function _getDynamicsGPDocument(
let document: DynamicsGPDocument | undefined let document: DynamicsGPDocument | undefined
switch (lookupType) { 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': { case 'diamond/cashReceipt': {
let receipt: DiamondCashReceipt | undefined = let receipt: DiamondCashReceipt | undefined =
await gp.getDiamondCashReceiptByDocumentNumber(documentNumber) await gp.getDiamondCashReceiptByDocumentNumber(documentNumber)
@ -160,29 +96,94 @@ async function _getDynamicsGPDocument(
break break
} }
case 'invoice': {
let invoice = await gp.getInvoiceByInvoiceNumber(documentNumber)
if (invoice !== undefined) {
invoice = filterInvoice(invoice)
} }
return document if (invoice !== undefined) {
document = {
documentType: 'Invoice',
documentNumber: invoice.invoiceNumber,
documentDate: invoice.documentDate,
documentDescription: [
invoice.comment1,
invoice.comment2,
invoice.comment3,
invoice.comment4
],
documentTotal: invoice.documentAmount
}
} }
export async function getDynamicsGPDocument(
documentNumber: string
): Promise<DynamicsGPDocument | undefined> {
if (!getConfigProperty('settings.dynamicsGP.integrationIsEnabled')) {
return undefined
}
let document: DynamicsGPDocument | undefined
for (const lookupType of getConfigProperty(
'settings.dynamicsGP.lookupOrder'
)) {
document = await _getDynamicsGPDocument(documentNumber, lookupType)
if (document !== undefined) {
break break
} }
} }
return document 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
}

View File

@ -8,8 +8,8 @@ import * as configFunctions from './config.helpers.js';
import * as contractFunctions from './contracts.helpers.js'; import * as contractFunctions from './contracts.helpers.js';
const screenPrintConfigs = { const screenPrintConfigs = {
contract: { contract: {
title: "Burial Site Contract Print", params: ['contractId'],
params: ['contractId'] title: "Burial Site Contract Print"
} }
}; };
export function getScreenPrintConfig(printName) { export function getScreenPrintConfig(printName) {
@ -17,21 +17,21 @@ export function getScreenPrintConfig(printName) {
} }
const pdfPrintConfigs = { const pdfPrintConfigs = {
workOrder: { workOrder: {
title: 'Work Order Field Sheet', params: ['workOrderId'],
params: ['workOrderId'] title: 'Work Order Field Sheet'
}, },
'workOrder-commentLog': { 'workOrder-commentLog': {
title: 'Work Order Field Sheet - Comment Log', params: ['workOrderId'],
params: ['workOrderId'] title: 'Work Order Field Sheet - Comment Log'
}, },
// Occupancy // Occupancy
'ssm.cemetery.burialPermit': { 'ssm.cemetery.burialPermit': {
title: 'Burial Permit', params: ['contractId'],
params: ['contractId'] title: 'Burial Permit'
}, },
'ssm.cemetery.contract': { '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) { export function getPdfPrintConfig(printName) {

View File

@ -30,8 +30,8 @@ interface ReportData {
const screenPrintConfigs: Record<string, PrintConfig> = { const screenPrintConfigs: Record<string, PrintConfig> = {
contract: { 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<string, PrintConfig> = { const pdfPrintConfigs: Record<string, PrintConfig> = {
workOrder: { workOrder: {
title: 'Work Order Field Sheet', params: ['workOrderId'],
params: ['workOrderId'] title: 'Work Order Field Sheet'
}, },
'workOrder-commentLog': { 'workOrder-commentLog': {
title: 'Work Order Field Sheet - Comment Log', params: ['workOrderId'],
params: ['workOrderId'] title: 'Work Order Field Sheet - Comment Log'
}, },
// Occupancy // Occupancy
'ssm.cemetery.burialPermit': { 'ssm.cemetery.burialPermit': {
title: 'Burial Permit', params: ['contractId'],
params: ['contractId'] title: 'Burial Permit'
}, },
'ssm.cemetery.contract': { 'ssm.cemetery.contract': {
title: 'Contract for Purchase of Interment Rights', params: ['contractId'],
params: ['contractId'] title: 'Contract for Purchase of Interment Rights'
} }
} }

View File

@ -1,13 +1,13 @@
export interface UserRequest {
session?: {
user?: User;
};
}
export interface APIRequest { export interface APIRequest {
params?: { params?: {
apiKey?: string; apiKey?: string;
}; };
} }
export declare function userIsAdmin(request: UserRequest): boolean; export interface UserRequest {
export declare function userCanUpdate(request: UserRequest): boolean; session?: {
user?: User;
};
}
export declare function apiKeyIsValid(request: APIRequest): Promise<boolean>; export declare function apiKeyIsValid(request: APIRequest): Promise<boolean>;
export declare function userCanUpdate(request: UserRequest): boolean;
export declare function userIsAdmin(request: UserRequest): boolean;

View File

@ -1,11 +1,5 @@
import { getUserNameFromApiKey } from './functions.api.js';
import { getConfigProperty } from './config.helpers.js'; import { getConfigProperty } from './config.helpers.js';
export function userIsAdmin(request) { import { getUserNameFromApiKey } from './functions.api.js';
return request.session?.user?.userProperties?.isAdmin ?? false;
}
export function userCanUpdate(request) {
return request.session?.user?.userProperties?.canUpdate ?? false;
}
export async function apiKeyIsValid(request) { export async function apiKeyIsValid(request) {
const apiKey = request.params?.apiKey; const apiKey = request.params?.apiKey;
if (apiKey === undefined) { if (apiKey === undefined) {
@ -17,3 +11,9 @@ export async function apiKeyIsValid(request) {
} }
return getConfigProperty('users.canLogin').some((currentUserName) => userName === currentUserName.toLowerCase()); 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;
}

View File

@ -1,11 +1,5 @@
import { getUserNameFromApiKey } from './functions.api.js'
import { getConfigProperty } from './config.helpers.js' import { getConfigProperty } from './config.helpers.js'
import { getUserNameFromApiKey } from './functions.api.js'
export interface UserRequest {
session?: {
user?: User
}
}
export interface APIRequest { export interface APIRequest {
params?: { params?: {
@ -13,12 +7,10 @@ export interface APIRequest {
} }
} }
export function userIsAdmin(request: UserRequest): boolean { export interface UserRequest {
return request.session?.user?.userProperties?.isAdmin ?? false session?: {
user?: User
} }
export function userCanUpdate(request: UserRequest): boolean {
return request.session?.user?.userProperties?.canUpdate ?? false
} }
export async function apiKeyIsValid(request: APIRequest): Promise<boolean> { export async function apiKeyIsValid(request: APIRequest): Promise<boolean> {
@ -38,3 +30,11 @@ export async function apiKeyIsValid(request: APIRequest): Promise<boolean> {
(currentUserName) => userName === currentUserName.toLowerCase() (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
}

86
package-lock.json generated
View File

@ -65,7 +65,7 @@
"@types/randomcolor": "^0.5.9", "@types/randomcolor": "^0.5.9",
"@types/session-file-store": "^1.2.5", "@types/session-file-store": "^1.2.5",
"axe-core": "^4.10.3", "axe-core": "^4.10.3",
"cypress": "^14.2.0", "cypress": "^14.2.1",
"cypress-axe": "^1.6.0", "cypress-axe": "^1.6.0",
"eslint-config-cityssm": "^22.2.2", "eslint-config-cityssm": "^22.2.2",
"nodemon": "^3.1.9", "nodemon": "^3.1.9",
@ -334,15 +334,6 @@
"node": ">=16" "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": { "node_modules/@babel/code-frame": {
"version": "7.26.2", "version": "7.26.2",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
@ -1141,9 +1132,9 @@
} }
}, },
"node_modules/@cypress/request": { "node_modules/@cypress/request": {
"version": "3.0.7", "version": "3.0.8",
"resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.7.tgz", "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.8.tgz",
"integrity": "sha512-LzxlLEMbBOPYB85uXrDqvD4MgcenjRBLIns3zyhx7vTPj/0u2eQhzXvPiGcaJrV38Q9dbkExWp6cOHPJ+EtFYg==", "integrity": "sha512-h0NFgh1mJmm1nr4jCwkGHwKneVYKghUyWe6TMNrk0B9zsjAJxpg8C4/+BAcmLgCPa1vj1V8rNUaILl+zYRUWBQ==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
@ -1160,7 +1151,7 @@
"json-stringify-safe": "~5.0.1", "json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19", "mime-types": "~2.1.19",
"performance-now": "^2.1.0", "performance-now": "^2.1.0",
"qs": "6.13.1", "qs": "6.14.0",
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"tough-cookie": "^5.0.0", "tough-cookie": "^5.0.0",
"tunnel-agent": "^0.6.0", "tunnel-agent": "^0.6.0",
@ -1171,13 +1162,13 @@
} }
}, },
"node_modules/@cypress/request/node_modules/qs": { "node_modules/@cypress/request/node_modules/qs": {
"version": "6.13.1", "version": "6.14.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
"dev": true, "dev": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"side-channel": "^1.0.6" "side-channel": "^1.1.0"
}, },
"engines": { "engines": {
"node": ">=0.6" "node": ">=0.6"
@ -1186,16 +1177,6 @@
"url": "https://github.com/sponsors/ljharb" "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": { "node_modules/@cypress/xvfb": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz",
@ -4126,14 +4107,14 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/cypress": { "node_modules/cypress": {
"version": "14.2.0", "version": "14.2.1",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-14.2.0.tgz", "resolved": "https://registry.npmjs.org/cypress/-/cypress-14.2.1.tgz",
"integrity": "sha512-u7fuc9JEpSYLOdu8mzZDZ/JWsHUzR5pc8i1TeSqMz/bafXp+6IweMAeyphsEJ6/13qbB6nwTEY1m+GUAp6GqCQ==", "integrity": "sha512-5xd0E7fUp0pjjib1D7ljkmCwFDgMkWuW06jWiz8dKrI7MNRrDo0C65i4Sh+oZ9YHjMHZRJBR0XZk1DfekOhOUw==",
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@cypress/request": "^3.0.7", "@cypress/request": "^3.0.8",
"@cypress/xvfb": "^1.2.4", "@cypress/xvfb": "^1.2.4",
"@types/sinonjs__fake-timers": "8.1.1", "@types/sinonjs__fake-timers": "8.1.1",
"@types/sizzle": "^2.3.2", "@types/sizzle": "^2.3.2",
@ -4170,7 +4151,7 @@
"process": "^0.11.10", "process": "^0.11.10",
"proxy-from-env": "1.0.0", "proxy-from-env": "1.0.0",
"request-progress": "^3.0.0", "request-progress": "^3.0.0",
"semver": "^7.5.3", "semver": "^7.7.1",
"supports-color": "^8.1.1", "supports-color": "^8.1.1",
"tmp": "~0.2.3", "tmp": "~0.2.3",
"tree-kill": "1.2.2", "tree-kill": "1.2.2",
@ -5855,7 +5836,8 @@
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"dev": true "dev": true,
"license": "MIT"
}, },
"node_modules/extract-zip": { "node_modules/extract-zip": {
"version": "2.0.1", "version": "2.0.1",
@ -6145,14 +6127,15 @@
} }
}, },
"node_modules/form-data": { "node_modules/form-data": {
"version": "4.0.1", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
"integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
}, },
"engines": { "engines": {
@ -11813,22 +11796,22 @@
"dev": true "dev": true
}, },
"node_modules/tldts": { "node_modules/tldts": {
"version": "6.1.76", "version": "6.1.85",
"resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.76.tgz", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.85.tgz",
"integrity": "sha512-6U2ti64/nppsDxQs9hw8ephA3nO6nSQvVVfxwRw8wLQPFtLI1cFI1a1eP22g+LUP+1TA2pKKjUTwWB+K2coqmQ==", "integrity": "sha512-gBdZ1RjCSevRPFix/hpaUWeak2/RNUZB4/8frF1r5uYMHjFptkiT0JXIebWvgI/0ZHXvxaUDDJshiA0j6GdL3w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tldts-core": "^6.1.76" "tldts-core": "^6.1.85"
}, },
"bin": { "bin": {
"tldts": "bin/cli.js" "tldts": "bin/cli.js"
} }
}, },
"node_modules/tldts-core": { "node_modules/tldts-core": {
"version": "6.1.76", "version": "6.1.85",
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.76.tgz", "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.85.tgz",
"integrity": "sha512-uzhJ02RaMzgQR3yPoeE65DrcHI6LoM4saUqXOt/b5hmb3+mc4YWpdSeAQqVqRUlQ14q8ZuLRWyBR1ictK1dzzg==", "integrity": "sha512-DTjUVvxckL1fIoPSb3KE7ISNtkWSawZdpfxGxwiIrZoO6EbHVDXXUIlIuWympPaeS+BLGyggozX/HTMsRAdsoA==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
@ -11885,9 +11868,9 @@
} }
}, },
"node_modules/tough-cookie": { "node_modules/tough-cookie": {
"version": "5.1.0", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.0.tgz", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz",
"integrity": "sha512-rvZUv+7MoBYTiDmFPBrhL7Ujx9Sk+q9wwm22x8c8T5IJaR+Wsyc7TNxbVxo84kZoRJZZMazowFLqpankBEQrGg==", "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==",
"dev": true, "dev": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
@ -12338,6 +12321,15 @@
"node": ">= 0.4.0" "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": { "node_modules/uuid-random": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/uuid-random/-/uuid-random-1.3.2.tgz", "resolved": "https://registry.npmjs.org/uuid-random/-/uuid-random-1.3.2.tgz",

View File

@ -88,7 +88,7 @@
"@types/randomcolor": "^0.5.9", "@types/randomcolor": "^0.5.9",
"@types/session-file-store": "^1.2.5", "@types/session-file-store": "^1.2.5",
"axe-core": "^4.10.3", "axe-core": "^4.10.3",
"cypress": "^14.2.0", "cypress": "^14.2.1",
"cypress-axe": "^1.6.0", "cypress-axe": "^1.6.0",
"eslint-config-cityssm": "^22.2.2", "eslint-config-cityssm": "^22.2.2",
"nodemon": "^3.1.9", "nodemon": "^3.1.9",

View File

@ -82,6 +82,7 @@
name="deceasedCity" name="deceasedCity"
type="text" type="text"
maxlength="20" maxlength="20"
list="datalist--cityDefault"
/> />
</div> </div>
</div> </div>

View File

@ -89,6 +89,7 @@
name="deceasedCity" name="deceasedCity"
type="text" type="text"
maxlength="20" maxlength="20"
list="datalist--cityDefault"
/> />
</div> </div>
</div> </div>

View File

@ -64,9 +64,9 @@ async function postHandler(request, response) {
} }
else { else {
response.render('login', { response.render('login', {
userName,
message: 'Login Failed', message: 'Login Failed',
redirect: redirectURL, redirect: redirectURL,
userName,
useTestDatabases useTestDatabases
}); });
} }

View File

@ -40,7 +40,7 @@ async function postHandler(
request: Request< request: Request<
unknown, unknown,
unknown, unknown,
{ userName: string; password: string; redirect: string } { password: string; redirect: string; userName: string; }
>, >,
response: Response response: Response
): Promise<void> { ): Promise<void> {
@ -109,9 +109,9 @@ async function postHandler(
response.redirect(redirectURL) response.redirect(redirectURL)
} else { } else {
response.render('login', { response.render('login', {
userName,
message: 'Login Failed', message: 'Login Failed',
redirect: redirectURL, redirect: redirectURL,
userName,
useTestDatabases useTestDatabases
}) })
} }

View File

@ -33,16 +33,16 @@ export async function getCemeteryIdByKey(cemeteryKey, user) {
console.log(`Creating cemetery: ${cemeteryKey}`); console.log(`Creating cemetery: ${cemeteryKey}`);
const cemeteryId = await addCemetery({ const cemeteryId = await addCemetery({
cemeteryName: cemeteryToCemeteryName[cemeteryKey] ?? cemeteryKey, cemeteryName: cemeteryToCemeteryName[cemeteryKey] ?? cemeteryKey,
cemeteryKey,
cemeteryDescription: '', cemeteryDescription: '',
cemeteryKey,
cemeterySvg: '', cemeterySvg: '',
cemeteryLatitude: '', cemeteryLatitude: '',
cemeteryLongitude: '', cemeteryLongitude: '',
cemeteryAddress1: '', cemeteryAddress1: '',
cemeteryAddress2: '', cemeteryAddress2: '',
cemeteryCity: 'Sault Ste. Marie', cemeteryCity: 'Sault Ste. Marie',
cemeteryProvince: 'ON',
cemeteryPostalCode: '', cemeteryPostalCode: '',
cemeteryProvince: 'ON',
cemeteryPhoneNumber: '' cemeteryPhoneNumber: ''
}, user); }, user);
cemeteryCache.set(cemeteryKey, cemeteryId); cemeteryCache.set(cemeteryKey, cemeteryId);

View File

@ -45,16 +45,21 @@ export async function getCemeteryIdByKey(
const cemeteryId = await addCemetery( const cemeteryId = await addCemetery(
{ {
cemeteryName: cemeteryToCemeteryName[cemeteryKey] ?? cemeteryKey, cemeteryName: cemeteryToCemeteryName[cemeteryKey] ?? cemeteryKey,
cemeteryKey,
cemeteryDescription: '', cemeteryDescription: '',
cemeteryKey,
cemeterySvg: '', cemeterySvg: '',
cemeteryLatitude: '', cemeteryLatitude: '',
cemeteryLongitude: '', cemeteryLongitude: '',
cemeteryAddress1: '', cemeteryAddress1: '',
cemeteryAddress2: '', cemeteryAddress2: '',
cemeteryCity: 'Sault Ste. Marie', cemeteryCity: 'Sault Ste. Marie',
cemeteryProvince: 'ON',
cemeteryPostalCode: '', cemeteryPostalCode: '',
cemeteryProvince: 'ON',
cemeteryPhoneNumber: '' cemeteryPhoneNumber: ''
}, },
user user

View File

@ -1,5 +1,5 @@
// eslint-disable-next-line @eslint-community/eslint-comments/disable-enable-pair // 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 fs from 'node:fs';
import { dateIntegerToString, dateToString } from '@cityssm/utils-datetime'; import { dateIntegerToString, dateToString } from '@cityssm/utils-datetime';
import sqlite from 'better-sqlite3'; import sqlite from 'better-sqlite3';

View File

@ -1,5 +1,5 @@
// eslint-disable-next-line @eslint-community/eslint-comments/disable-enable-pair // 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 fs from 'node:fs'

View File

@ -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 { export interface CacheBurialSiteIdsWorkerMessage extends WorkerMessage {
messageType: 'cacheBurialSiteIds'; messageType: 'cacheBurialSiteIds';
burialSiteId: number; burialSiteId: number;
nextBurialSiteId: number; nextBurialSiteId: number;
} }
export interface ClearCacheWorkerMessage extends WorkerMessage {
messageType: 'clearCache';
tableName: string;
}
export interface ClearNextPreviousBurialSiteIdsCacheWorkerMessage extends WorkerMessage { export interface ClearNextPreviousBurialSiteIdsCacheWorkerMessage extends WorkerMessage {
messageType: 'clearNextPreviousBurialSiteIdCache'; messageType: 'clearNextPreviousBurialSiteIdCache';
burialSiteId: number; burialSiteId: number;
} }
export interface WorkerMessage {
messageType: string;
pid: number;
timeMillis: number;
}

View File

@ -1,23 +1,26 @@
export interface WorkerMessage { export interface CacheBurialSiteIdsWorkerMessage extends WorkerMessage {
messageType: string messageType: 'cacheBurialSiteIds'
timeMillis: number
pid: number burialSiteId: number
nextBurialSiteId: number
} }
export interface ClearCacheWorkerMessage extends WorkerMessage { export interface ClearCacheWorkerMessage extends WorkerMessage {
messageType: 'clearCache' messageType: 'clearCache'
tableName: string
}
export interface CacheBurialSiteIdsWorkerMessage extends WorkerMessage { tableName: string
messageType: 'cacheBurialSiteIds'
burialSiteId: number
nextBurialSiteId: number
} }
export interface ClearNextPreviousBurialSiteIdsCacheWorkerMessage export interface ClearNextPreviousBurialSiteIdsCacheWorkerMessage
extends WorkerMessage { extends WorkerMessage {
// eslint-disable-next-line no-secrets/no-secrets // eslint-disable-next-line no-secrets/no-secrets
messageType: 'clearNextPreviousBurialSiteIdCache' messageType: 'clearNextPreviousBurialSiteIdCache'
burialSiteId: number burialSiteId: number
} }
export interface WorkerMessage {
messageType: string
pid: number
timeMillis: number
}

View File

@ -35,16 +35,16 @@ export interface Config {
contracts: { contracts: {
burialSiteIdIsRequired?: boolean; burialSiteIdIsRequired?: boolean;
contractEndDateIsRequired?: boolean; contractEndDateIsRequired?: boolean;
purchaserRelationships?: string[];
deathAgePeriods?: string[]; deathAgePeriods?: string[];
prints?: string[]; prints?: string[];
purchaserRelationships?: string[];
}; };
workOrders: { workOrders: {
workOrderNumberLength?: number;
workOrderMilestoneDateRecentBeforeDays?: number;
workOrderMilestoneDateRecentAfterDays?: number;
calendarEmailAddress?: string; calendarEmailAddress?: string;
prints?: string[]; prints?: string[];
workOrderMilestoneDateRecentAfterDays?: number;
workOrderMilestoneDateRecentBeforeDays?: number;
workOrderNumberLength?: number;
}; };
adminCleanup: { adminCleanup: {
recordDeleteAgeDays?: number; recordDeleteAgeDays?: number;
@ -74,14 +74,14 @@ interface ConfigApplication {
maximumProcesses?: number; maximumProcesses?: number;
} }
export interface ConfigNtfyStartup { export interface ConfigNtfyStartup {
topic: string;
server?: string; server?: string;
topic: string;
} }
interface ConfigSession { interface ConfigSession {
cookieName?: string; cookieName?: string;
secret?: string;
maxAgeMillis?: number;
doKeepAlive?: boolean; doKeepAlive?: boolean;
maxAgeMillis?: number;
secret?: string;
} }
export interface ConfigActiveDirectory { export interface ConfigActiveDirectory {
url: string; url: string;
@ -90,7 +90,6 @@ export interface ConfigActiveDirectory {
password: string; password: string;
} }
export interface ConfigBurialSiteNameSegments { export interface ConfigBurialSiteNameSegments {
separator?: string;
includeCemeteryKey?: boolean; includeCemeteryKey?: boolean;
segments: Partial<Record<'1' | '2' | '3' | '4' | '5', { segments: Partial<Record<'1' | '2' | '3' | '4' | '5', {
isAvailable?: boolean; isAvailable?: boolean;
@ -101,5 +100,6 @@ export interface ConfigBurialSiteNameSegments {
prefix?: string; prefix?: string;
suffix?: string; suffix?: string;
}>>; }>>;
separator?: string;
} }
export {}; export {};

View File

@ -15,6 +15,7 @@ export interface Config {
users: { users: {
testing?: Array<`*${string}`> testing?: Array<`*${string}`>
canLogin?: string[] canLogin?: string[]
canUpdate?: string[] canUpdate?: string[]
isAdmin?: string[] isAdmin?: string[]
@ -46,17 +47,17 @@ export interface Config {
contracts: { contracts: {
burialSiteIdIsRequired?: boolean burialSiteIdIsRequired?: boolean
contractEndDateIsRequired?: boolean contractEndDateIsRequired?: boolean
purchaserRelationships?: string[]
deathAgePeriods?: string[] deathAgePeriods?: string[]
prints?: string[] prints?: string[]
purchaserRelationships?: string[]
} }
workOrders: { workOrders: {
workOrderNumberLength?: number
workOrderMilestoneDateRecentBeforeDays?: number
workOrderMilestoneDateRecentAfterDays?: number
calendarEmailAddress?: string calendarEmailAddress?: string
prints?: string[] prints?: string[]
workOrderMilestoneDateRecentAfterDays?: number
workOrderMilestoneDateRecentBeforeDays?: number
workOrderNumberLength?: number
} }
adminCleanup: { adminCleanup: {
@ -95,15 +96,15 @@ interface ConfigApplication {
} }
export interface ConfigNtfyStartup { export interface ConfigNtfyStartup {
topic: string
server?: string server?: string
topic: string
} }
interface ConfigSession { interface ConfigSession {
cookieName?: string cookieName?: string
secret?: string
maxAgeMillis?: number
doKeepAlive?: boolean doKeepAlive?: boolean
maxAgeMillis?: number
secret?: string
} }
export interface ConfigActiveDirectory { export interface ConfigActiveDirectory {
@ -114,7 +115,6 @@ export interface ConfigActiveDirectory {
} }
export interface ConfigBurialSiteNameSegments { export interface ConfigBurialSiteNameSegments {
separator?: string
includeCemeteryKey?: boolean includeCemeteryKey?: boolean
segments: Partial< segments: Partial<
Record< Record<
@ -130,4 +130,5 @@ export interface ConfigBurialSiteNameSegments {
} }
> >
> >
separator?: string
} }

View File

@ -8,5 +8,6 @@ export const serviceConfig: ServiceConfig = {
name: 'Sunrise CMS', name: 'Sunrise CMS',
description: description:
'Sunrise Cemetery Management System, a web-based application that allows cemetery managers to manage their cemetery records.', 'Sunrise Cemetery Management System, a web-based application that allows cemetery managers to manage their cemetery records.',
script: path.join(_dirname, 'bin', 'www.js') script: path.join(_dirname, 'bin', 'www.js')
} }