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

44
app.ts
View File

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

View File

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

View File

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

View File

@ -1,3 +1,3 @@
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 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 Cemeteries m on l.cemeteryId = m.cemeteryId
where l.recordDelete_timeMillis is null`;
export default async function getBurialSite(burialSiteId) {
return await _getBurialSite(`${baseSQL} and l.burialSiteId = ?`, burialSiteId);
}
export async function getBurialSiteByBurialSiteName(burialSiteName) {
return await _getBurialSite(`${baseSQL} and l.burialSiteName = ?`, burialSiteName);
}
async function _getBurialSite(sql, burialSiteIdOrLotName) {
const database = await acquireConnection();
const burialSite = database.prepare(sql).get(burialSiteIdOrLotName);
@ -27,11 +33,11 @@ async function _getBurialSite(sql, burialSiteIdOrLotName) {
const contracts = await getContracts({
burialSiteId: burialSite.burialSiteId
}, {
includeInterments: true,
includeFees: false,
includeTransactions: false,
limit: -1,
offset: 0
offset: 0,
includeFees: false,
includeInterments: true,
includeTransactions: false
}, database);
burialSite.contracts = contracts.contracts;
burialSite.burialSiteFields = await getBurialSiteFields(burialSite.burialSiteId, database);
@ -40,9 +46,3 @@ async function _getBurialSite(sql, burialSiteIdOrLotName) {
database.release();
return burialSite;
}
export async function getBurialSiteByBurialSiteName(burialSiteName) {
return await _getBurialSite(`${baseSQL} and l.burialSiteName = ?`, burialSiteName);
}
export default async function getBurialSite(burialSiteId) {
return await _getBurialSite(`${baseSQL} and l.burialSiteId = ?`, burialSiteId);
}

View File

@ -24,13 +24,30 @@ const baseSQL = `select l.burialSiteId,
left join Cemeteries m on l.cemeteryId = m.cemeteryId
where l.recordDelete_timeMillis is null`
export default async function getBurialSite(
burialSiteId: number | string
): Promise<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(
sql: string,
burialSiteIdOrLotName: number | string
): Promise<BurialSite | undefined> {
const database = await acquireConnection()
const burialSite = database.prepare(sql).get(burialSiteIdOrLotName) as BurialSite | undefined
const burialSite = database.prepare(sql).get(burialSiteIdOrLotName) as
| BurialSite
| undefined
if (burialSite !== undefined) {
const contracts = await getContracts(
@ -38,35 +55,30 @@ async function _getBurialSite(
burialSiteId: burialSite.burialSiteId
},
{
includeInterments: true,
includeFees: false,
includeTransactions: false,
limit: -1,
offset: 0
offset: 0,
includeFees: false,
includeInterments: true,
includeTransactions: false
},
database
)
burialSite.contracts = contracts.contracts
burialSite.burialSiteFields = await getBurialSiteFields(burialSite.burialSiteId, database)
burialSite.burialSiteFields = await getBurialSiteFields(
burialSite.burialSiteId,
database
)
burialSite.burialSiteComments = await getBurialSiteComments(burialSite.burialSiteId, database)
burialSite.burialSiteComments = await getBurialSiteComments(
burialSite.burialSiteId,
database
)
}
database.release()
return burialSite
}
export async function getBurialSiteByBurialSiteName(
burialSiteName: string
): Promise<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 moveRecordDownToBottom(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 { acquireConnection } from './pool.js';
import { updateRecordOrderNumber } from './updateRecordOrderNumber.js';
const recordIdColumns = new Map();
recordIdColumns.set('FeeCategories', 'feeCategoryId');
recordIdColumns.set('BurialSiteStatuses', 'burialSiteStatusId');
recordIdColumns.set('BurialSiteTypes', 'burialSiteTypeId');
recordIdColumns.set('ContractTypes', 'contractTypeId');
recordIdColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId');
recordIdColumns.set('WorkOrderTypes', 'workOrderTypeId');
function getCurrentOrderNumber(recordTable, recordId, database) {
const currentOrderNumber = database
.prepare(`select orderNumber
from ${recordTable}
where ${recordIdColumns.get(recordTable)} = ?`)
.get(recordId).orderNumber;
return currentOrderNumber;
}
const recordIdColumns = new Map([
['BurialSiteStatuses', 'burialSiteStatusId'],
['BurialSiteTypes', 'burialSiteTypeId'],
['ContractTypes', 'contractTypeId'],
['FeeCategories', 'feeCategoryId'],
['WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'],
['WorkOrderTypes', 'workOrderTypeId']
]);
export async function moveRecordDown(recordTable, recordId) {
const database = await acquireConnection();
const currentOrderNumber = getCurrentOrderNumber(recordTable, recordId, database);
@ -85,3 +78,11 @@ export async function moveRecordUpToTop(recordTable, recordId) {
clearCacheByTableName(recordTable);
return true;
}
function getCurrentOrderNumber(recordTable, recordId, database) {
const currentOrderNumber = database
.prepare(`select orderNumber
from ${recordTable}
where ${recordIdColumns.get(recordTable)} = ?`)
.get(recordId).orderNumber;
return currentOrderNumber;
}

View File

@ -6,38 +6,21 @@ import { acquireConnection } from './pool.js'
import { updateRecordOrderNumber } from './updateRecordOrderNumber.js'
type RecordTable =
| 'FeeCategories'
| 'BurialSiteStatuses'
| 'BurialSiteTypes'
| 'ContractTypes'
| 'FeeCategories'
| 'WorkOrderMilestoneTypes'
| 'WorkOrderTypes'
const recordIdColumns = new Map<RecordTable, string>()
recordIdColumns.set('FeeCategories', 'feeCategoryId')
recordIdColumns.set('BurialSiteStatuses', 'burialSiteStatusId')
recordIdColumns.set('BurialSiteTypes', 'burialSiteTypeId')
recordIdColumns.set('ContractTypes', 'contractTypeId')
recordIdColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId')
recordIdColumns.set('WorkOrderTypes', 'workOrderTypeId')
function getCurrentOrderNumber(
recordTable: RecordTable,
recordId: number | string,
database: sqlite.Database
): number {
const currentOrderNumber: number = (
database
.prepare(
`select orderNumber
from ${recordTable}
where ${recordIdColumns.get(recordTable)} = ?`
)
.get(recordId) as { orderNumber: number }
).orderNumber
return currentOrderNumber
}
const recordIdColumns = new Map<RecordTable, string>([
['BurialSiteStatuses', 'burialSiteStatusId'],
['BurialSiteTypes', 'burialSiteTypeId'],
['ContractTypes', 'contractTypeId'],
['FeeCategories', 'feeCategoryId'],
['WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'],
['WorkOrderTypes', 'workOrderTypeId']
])
export async function moveRecordDown(
recordTable: RecordTable,
@ -187,3 +170,21 @@ export async function moveRecordUpToTop(
return true
}
function getCurrentOrderNumber(
recordTable: RecordTable,
recordId: number | string,
database: sqlite.Database
): number {
const currentOrderNumber: number = (
database
.prepare(
`select orderNumber
from ${recordTable}
where ${recordIdColumns.get(recordTable)} = ?`
)
.get(recordId) as { orderNumber: number }
).orderNumber
return currentOrderNumber
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,19 +1,14 @@
import { clearCacheByTableName } from '../helpers/functions.cache.js';
import { acquireConnection } from './pool.js';
const recordNameIdColumns = new Map();
recordNameIdColumns.set('BurialSiteStatuses', [
'burialSiteStatus',
'burialSiteStatusId'
const recordNameIdColumns = new Map([
['BurialSiteStatuses', ['burialSiteStatus', 'burialSiteStatusId']],
['BurialSiteTypes', ['burialSiteType', 'burialSiteTypeId']],
[
'WorkOrderMilestoneTypes',
['workOrderMilestoneType', 'workOrderMilestoneTypeId']
],
['WorkOrderTypes', ['workOrderType', 'workOrderTypeId']]
]);
recordNameIdColumns.set('BurialSiteTypes', [
'burialSiteType',
'burialSiteTypeId'
]);
recordNameIdColumns.set('WorkOrderMilestoneTypes', [
'workOrderMilestoneType',
'workOrderMilestoneTypeId'
]);
recordNameIdColumns.set('WorkOrderTypes', ['workOrderType', 'workOrderTypeId']);
export async function updateRecord(recordTable, recordId, recordName, user) {
const database = await acquireConnection();
const result = database

View File

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

View File

@ -1,4 +1,4 @@
import type { PoolConnection } from 'better-sqlite-pool';
type RecordTable = 'FeeCategories' | 'Fees' | 'BurialSiteStatuses' | 'BurialSiteTypes' | 'BurialSiteTypeFields' | 'IntermentContainerTypes' | 'CommittalTypes' | 'ContractTypes' | 'ContractTypeFields' | 'WorkOrderMilestoneTypes' | 'WorkOrderTypes';
type RecordTable = 'BurialSiteStatuses' | 'BurialSiteTypeFields' | 'BurialSiteTypes' | 'CommittalTypes' | 'ContractTypeFields' | 'ContractTypes' | 'FeeCategories' | 'Fees' | 'IntermentContainerTypes' | 'WorkOrderMilestoneTypes' | 'WorkOrderTypes';
export declare function updateRecordOrderNumber(recordTable: RecordTable, recordId: number | string, orderNumber: number | string, connectedDatabase: PoolConnection): boolean;
export {};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,8 +12,8 @@ const urlPrefix = getConfigProperty('reverseProxy.urlPrefix')
const forbiddenStatus = 403
const forbiddenJSON = {
success: false,
message: 'Forbidden'
message: 'Forbidden',
success: false
}
const forbiddenRedirectURL = `${urlPrefix}/dashboard/?error=accessDenied`
@ -44,6 +44,18 @@ export function adminPostHandler(
response.status(forbiddenStatus).json(forbiddenJSON)
}
export async function apiGetHandler(
request: Request,
response: Response,
next: NextFunction
): Promise<void> {
if (await apiKeyIsValid(request)) {
next()
} else {
response.redirect(`${urlPrefix}/login`)
}
}
export function updateGetHandler(
request: Request,
response: Response,
@ -69,15 +81,3 @@ export function updatePostHandler(
response.status(forbiddenStatus).json(forbiddenJSON)
}
export async function apiGetHandler(
request: Request,
response: Response,
next: NextFunction
): Promise<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 NodeCache from 'node-cache'
import getNextBurialSiteIdFromDatabase from '../database/getNextBurialSiteId.js'
import getPreviousBurialSiteIdFromDatabase from '../database/getPreviousBurialSiteId.js'
import { DEBUG_NAMESPACE } from '../debug.config.js'
import type {
CacheBurialSiteIdsWorkerMessage,
ClearNextPreviousBurialSiteIdsCacheWorkerMessage
} from '../types/applicationTypes.js'
import getNextBurialSiteIdFromDatabase from '../database/getNextBurialSiteId.js'
import getPreviousBurialSiteIdFromDatabase from '../database/getPreviousBurialSiteId.js'
import { DEBUG_NAMESPACE } from '../debug.config.js'
import { getConfigProperty } from './config.helpers.js'
const debug = Debug(`${DEBUG_NAMESPACE}:burialSites.helpers:${process.pid}`)

View File

@ -1,4 +1,4 @@
import type { Contract, ContractFee } from '../types/recordTypes.js';
export declare function getFieldValueByContractTypeField(contract: Contract, contractTypeField: string): string | undefined;
export declare function getFeesByFeeCategory(contract: Contract, feeCategory: string, feeCategoryContains?: boolean): ContractFee[];
export declare function getFieldValueByContractTypeField(contract: Contract, contractTypeField: string): string | undefined;
export declare function getTransactionTotal(contract: Contract): number;

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) {
const feeCategoryLowerCase = feeCategory.toLowerCase();
return (contract.contractFees ?? []).filter((possibleFee) => feeCategoryContains
@ -16,6 +7,15 @@ export function getFeesByFeeCategory(contract, feeCategory, feeCategoryContains
: possibleFee.feeCategory.toLowerCase() ===
feeCategoryLowerCase);
}
export function getFieldValueByContractTypeField(contract, contractTypeField) {
const contractTypeFieldLowerCase = contractTypeField.toLowerCase();
const field = (contract.contractFields ?? []).find((possibleField) => possibleField.contractTypeField.toLowerCase() ===
contractTypeFieldLowerCase);
if (field === undefined) {
return undefined;
}
return field.fieldValue;
}
export function getTransactionTotal(contract) {
let transactionTotal = 0;
for (const transaction of contract.contractTransactions ??

View File

@ -3,6 +3,24 @@ import type {
ContractFee
} from '../types/recordTypes.js'
export function getFeesByFeeCategory(
contract: Contract,
feeCategory: string,
feeCategoryContains = false
): ContractFee[] {
const feeCategoryLowerCase = feeCategory.toLowerCase()
return (contract.contractFees ?? []).filter(
(possibleFee) =>
feeCategoryContains
? (possibleFee.feeCategory as string)
.toLowerCase()
.includes(feeCategoryLowerCase)
: (possibleFee.feeCategory as string).toLowerCase() ===
feeCategoryLowerCase
)
}
export function getFieldValueByContractTypeField(
contract: Contract,
contractTypeField: string
@ -22,24 +40,6 @@ export function getFieldValueByContractTypeField(
return field.fieldValue
}
export function getFeesByFeeCategory(
contract: Contract,
feeCategory: string,
feeCategoryContains = false
): ContractFee[] {
const feeCategoryLowerCase = feeCategory.toLowerCase()
return (contract.contractFees ?? []).filter(
(possibleFee) =>
feeCategoryContains
? (possibleFee.feeCategory as string)
.toLowerCase()
.includes(feeCategoryLowerCase)
: (possibleFee.feeCategory as string).toLowerCase() ===
feeCategoryLowerCase
)
}
export function getTransactionTotal(
contract: Contract
): number {

View File

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

View File

@ -6,6 +6,17 @@ const userDomain = getConfigProperty('application.userDomain')
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(
userName: 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 */
const safeRedirects = new Set([
'/admin/cleanup',
'/admin/fees',
'/admin/burialsitetypes',
'/admin/cleanup',
'/admin/contracttypes',
'/admin/fees',
'/admin/tables',
'/contracts',
'/contracts/new',
'/burialSites',
'/burialSites/new',
'/burialsites',
'/burialsites/new',
'/cemeteries',
'/cemeteries/new',
'/contracts',
'/contracts/new',
'/reports',
'/workorders',
'/workorders/new',
'/workorders/milestonecalendar',
'/workorders/outlook',
'/reports'
'/workorders/new',
'/workorders/outlook'
])
/* eslint-enable @cspell/spellchecker */
const recordUrl = /^\/(?:cemeteries|burialSites|contracts|workorders)\/\d+(?:\/edit)?$/
const recordUrl = /^\/(?:cemeteries|burialsites|contracts|workorders)\/\d+(?:\/edit)?$/
const printUrl = /^\/print\/(?:pdf|screen)\/[\d/=?A-Za-z-]+$/

View File

@ -1,26 +1,26 @@
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 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 getBurialSiteTypes(): Promise<BurialSiteType[]>;
export declare function getBurialSiteTypesByBurialSiteType(burialSiteType: string): Promise<BurialSiteType | undefined>;
export declare function getContractTypes(): Promise<ContractType[]>;
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 getContractTypeById(contractTypeId: number): Promise<ContractType | undefined>;
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 getCommittalTypes(): Promise<CommittalType[]>;
export declare function getIntermentContainerTypes(): Promise<IntermentContainerType[]>;
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 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 getWorkOrderMilestoneTypeByWorkOrderMilestoneType(workOrderMilestoneTypeString: string): Promise<WorkOrderMilestoneType | undefined>;
export declare function getWorkOrderMilestoneTypes(): Promise<WorkOrderMilestoneType[]>;
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 {};

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

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 Debug from 'debug'
@ -39,24 +36,6 @@ const debug = Debug(`${DEBUG_NAMESPACE}:functions.cache:${process.pid}`)
let burialSiteStatuses: BurialSiteStatus[] | undefined
export async function getBurialSiteStatuses(): Promise<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(
burialSiteStatus: string
): 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 {
burialSiteStatuses = undefined
}
@ -80,14 +74,6 @@ function clearBurialSiteStatusesCache(): void {
let burialSiteTypes: BurialSiteType[] | undefined
export async function getBurialSiteTypes(): Promise<BurialSiteType[]> {
if (burialSiteTypes === undefined) {
burialSiteTypes = await getBurialSiteTypesFromDatabase()
}
return burialSiteTypes
}
export async function getBurialSiteTypeById(
burialSiteTypeId: number
): 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(
burialSiteType: string
): Promise<BurialSiteType | undefined> {
@ -121,31 +112,11 @@ function clearBurialSiteTypesCache(): void {
let contractTypes: ContractType[] | 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[]> {
if (allContractTypeFields === undefined) {
allContractTypeFields = await getContractTypeFieldsFromDatabase()
}
allContractTypeFields ??= await getContractTypeFieldsFromDatabase()
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(
contractTypeString: string
): 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(
contractTypeId: number
): Promise<string[]> {
@ -177,6 +158,11 @@ export async function getContractTypePrintsById(
return contractType.contractTypePrints ?? []
}
export async function getContractTypes(): Promise<ContractType[]> {
contractTypes ??= await getContractTypesFromDatabase()
return contractTypes
}
function clearContractTypesCache(): void {
contractTypes = undefined
allContractTypeFields = undefined
@ -188,16 +174,6 @@ function clearContractTypesCache(): void {
let intermentContainerTypes: IntermentContainerType[] | undefined
export async function getIntermentContainerTypes(): Promise<
IntermentContainerType[]
> {
if (intermentContainerTypes === undefined) {
intermentContainerTypes = await getIntermentContainerTypesFromDatabase()
}
return intermentContainerTypes
}
export async function getIntermentContainerTypeById(
intermentContainerTypeId: number
): Promise<IntermentContainerType | undefined> {
@ -209,6 +185,13 @@ export async function getIntermentContainerTypeById(
)
}
export async function getIntermentContainerTypes(): Promise<
IntermentContainerType[]
> {
intermentContainerTypes ??= await getIntermentContainerTypesFromDatabase()
return intermentContainerTypes
}
function clearIntermentContainerTypesCache(): void {
intermentContainerTypes = undefined
}
@ -219,16 +202,6 @@ function clearIntermentContainerTypesCache(): void {
let committalTypes: CommittalType[] | undefined
export async function getCommittalTypes(): Promise<
CommittalType[]
> {
if (committalTypes === undefined) {
committalTypes = await getCommittalTypesFromDatabase()
}
return committalTypes
}
export async function getCommittalTypeById(
committalTypeId: number
): Promise<CommittalType | undefined> {
@ -240,6 +213,11 @@ export async function getCommittalTypeById(
)
}
export async function getCommittalTypes(): Promise<CommittalType[]> {
committalTypes ??= await getCommittalTypesFromDatabase()
return committalTypes
}
function clearCommittalTypesCache(): void {
committalTypes = undefined
}
@ -250,14 +228,6 @@ function clearCommittalTypesCache(): void {
let workOrderTypes: WorkOrderType[] | undefined
export async function getWorkOrderTypes(): Promise<WorkOrderType[]> {
if (workOrderTypes === undefined) {
workOrderTypes = await getWorkOrderTypesFromDatabase()
}
return workOrderTypes
}
export async function getWorkOrderTypeById(
workOrderTypeId: number
): 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 {
workOrderTypes = undefined
}
@ -279,81 +254,19 @@ function clearWorkOrderTypesCache(): void {
let workOrderMilestoneTypes: WorkOrderMilestoneType[] | undefined
export async function getWorkOrderMilestoneTypes(): Promise<
WorkOrderMilestoneType[]
> {
if (workOrderMilestoneTypes === undefined) {
workOrderMilestoneTypes = await getWorkOrderMilestoneTypesFromDatabase()
}
return workOrderMilestoneTypes
}
export async function getWorkOrderMilestoneTypeById(
workOrderMilestoneTypeId: number
): Promise<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 =
| 'BurialSiteStatuses'
| 'BurialSiteTypes'
| 'BurialSiteTypeFields'
| 'ContractTypes'
| 'BurialSiteTypes'
| 'CommittalTypes'
| 'ContractTypeFields'
| 'ContractTypePrints'
| 'IntermentContainerTypes'
| 'CommittalTypes'
| 'WorkOrderMilestoneTypes'
| 'WorkOrderTypes'
| 'ContractTypes'
| 'FeeCategories'
| 'Fees'
| 'IntermentContainerTypes'
| 'WorkOrderMilestoneTypes'
| 'WorkOrderTypes'
export function clearCacheByTableName(
tableName: CacheTableNames,
@ -365,15 +278,20 @@ export function clearCacheByTableName(
break
}
case 'BurialSiteTypes':
case 'BurialSiteTypeFields': {
case 'BurialSiteTypeFields':
case 'BurialSiteTypes': {
clearBurialSiteTypesCache()
break
}
case 'ContractTypes':
case 'CommittalTypes': {
clearCommittalTypesCache()
break
}
case 'ContractTypeFields':
case 'ContractTypePrints': {
case 'ContractTypePrints':
case 'ContractTypes': {
clearContractTypesCache()
break
}
@ -383,11 +301,6 @@ export function clearCacheByTableName(
break
}
case 'CommittalTypes': {
clearCommittalTypesCache()
break
}
case 'WorkOrderMilestoneTypes': {
clearWorkOrderMilestoneTypesCache()
break
@ -423,6 +336,65 @@ export function clearCacheByTableName(
}
}
export function clearCaches(): void {
clearBurialSiteStatusesCache()
clearBurialSiteTypesCache()
clearContractTypesCache()
clearCommittalTypesCache()
clearIntermentContainerTypesCache()
clearWorkOrderTypesCache()
clearWorkOrderMilestoneTypesCache()
}
export async function getWorkOrderMilestoneTypeById(
workOrderMilestoneTypeId: number
): Promise<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) => {
if (message.messageType === 'clearCache' && message.pid !== process.pid) {
debug(`Clearing cache: ${(message as ClearCacheWorkerMessage).tableName}`)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
// eslint-disable-next-line @eslint-community/eslint-comments/disable-enable-pair
/* eslint-disable @cspell/spellchecker, @typescript-eslint/no-non-null-assertion, no-console, max-lines */
/* eslint-disable @cspell/spellchecker, @typescript-eslint/no-non-null-assertion, no-console, max-lines, perfectionist/sort-interfaces */
import fs from 'node:fs';
import { dateIntegerToString, dateToString } from '@cityssm/utils-datetime';
import sqlite from 'better-sqlite3';

View File

@ -1,5 +1,5 @@
// eslint-disable-next-line @eslint-community/eslint-comments/disable-enable-pair
/* eslint-disable @cspell/spellchecker, @typescript-eslint/no-non-null-assertion, no-console, max-lines */
/* eslint-disable @cspell/spellchecker, @typescript-eslint/no-non-null-assertion, no-console, max-lines, perfectionist/sort-interfaces */
import fs from 'node:fs'

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

View File

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

View File

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

View File

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

View File

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