pull/3/head
Dan Gowans 2025-03-25 12:20:42 -04:00
parent b48bc3b677
commit 2d3b8042a0
28 changed files with 594 additions and 562 deletions

View File

@ -1,19 +1,19 @@
export const config = {
application: {},
session: {},
reverseProxy: {},
users: {},
aliases: {},
application: {},
reverseProxy: {},
session: {},
settings: {
fees: {},
adminCleanup: {},
burialSites: {},
contracts: {},
workOrders: {},
adminCleanup: {},
printPdf: {},
dynamicsGP: {
integrationIsEnabled: false
}
}
},
fees: {},
printPdf: {},
workOrders: {}
},
users: {}
};
export default config;

View File

@ -1,22 +1,22 @@
import type { Config } from '../types/configTypes.js'
export const config: Config = {
application: {},
session: {},
reverseProxy: {},
users: {},
aliases: {},
application: {},
reverseProxy: {},
session: {},
settings: {
fees: {},
adminCleanup: {},
burialSites: {},
contracts: {},
workOrders: {},
adminCleanup: {},
printPdf: {},
dynamicsGP: {
integrationIsEnabled: false
}
}
},
fees: {},
printPdf: {},
workOrders: {}
},
users: {}
}
export default config

View File

@ -14,13 +14,13 @@ export declare const configDefaultValues: {
'reverseProxy.disableEtag': boolean;
'reverseProxy.urlPrefix': string;
'session.cookieName': string;
'session.secret': string;
'session.maxAgeMillis': number;
'session.doKeepAlive': boolean;
'users.testing': string[];
'session.maxAgeMillis': number;
'session.secret': string;
'users.canLogin': string[];
'users.canUpdate': string[];
'users.isAdmin': string[];
'users.testing': string[];
'aliases.externalReceiptNumber': string;
'aliases.workOrderOpenDate': string;
'aliases.workOrderCloseDate': string;

View File

@ -13,13 +13,13 @@ export const configDefaultValues = {
'reverseProxy.disableEtag': false,
'reverseProxy.urlPrefix': '',
'session.cookieName': 'sunrise-user-sid',
'session.secret': 'cityssm/sunrise',
'session.maxAgeMillis': hoursToMillis(1),
'session.doKeepAlive': false,
'users.testing': [],
'session.maxAgeMillis': hoursToMillis(1),
'session.secret': 'cityssm/sunrise',
'users.canLogin': ['administrator'],
'users.canUpdate': [],
'users.isAdmin': ['administrator'],
'users.testing': [],
'aliases.externalReceiptNumber': 'External Receipt Number',
'aliases.workOrderOpenDate': 'Order Date',
'aliases.workOrderCloseDate': 'Completion Date',

View File

@ -1,6 +1,7 @@
import { hoursToMillis } from '@cityssm/to-millis'
import type { config as MSSQLConfig } from 'mssql'
import { hoursToMillis } from '@cityssm/to-millis'
import type {
ConfigActiveDirectory,
ConfigBurialSiteNameSegments,
@ -26,14 +27,14 @@ export const configDefaultValues = {
'reverseProxy.urlPrefix': '',
'session.cookieName': 'sunrise-user-sid',
'session.secret': 'cityssm/sunrise',
'session.maxAgeMillis': hoursToMillis(1),
'session.doKeepAlive': false,
'session.maxAgeMillis': hoursToMillis(1),
'session.secret': 'cityssm/sunrise',
'users.testing': [] as string[],
'users.canLogin': ['administrator'],
'users.canUpdate': [] as string[],
'users.isAdmin': ['administrator'],
'users.testing': [] as string[],
'aliases.externalReceiptNumber': 'External Receipt Number',
'aliases.workOrderOpenDate': 'Order Date',

View File

@ -1,38 +1,38 @@
import { type DateString, type TimeString } from '@cityssm/utils-datetime';
import type { PoolConnection } from 'better-sqlite-pool';
import { type DateString, type TimeString } from '@cityssm/utils-datetime';
export interface AddContractForm {
contractTypeId: string | number;
burialSiteId: string | number;
contractStartDateString: DateString | '';
contractEndDateString: DateString | '';
contractTypeFieldIds?: string;
[fieldValue_contractTypeFieldId: `fieldValue_${string}`]: unknown;
purchaserName?: string;
purchaserAddress1?: string;
purchaserAddress2?: string;
purchaserCity?: string;
purchaserProvince?: string;
purchaserPostalCode?: string;
purchaserPhoneNumber?: string;
purchaserEmail?: string;
purchaserRelationship?: string;
funeralHomeId?: string | number;
funeralDirectorName?: string;
funeralDateString?: DateString | '';
funeralTimeString?: TimeString | '';
committalTypeId?: string | number;
deceasedName?: string;
birthDateString?: '' | DateString;
birthPlace?: string;
burialSiteId: number | string;
committalTypeId?: number | string;
contractEndDateString: '' | DateString;
contractStartDateString: '' | DateString;
contractTypeFieldIds?: string;
contractTypeId: number | string;
deathAge?: string;
deathAgePeriod?: string;
deathDateString?: '' | DateString;
deathPlace?: string;
deceasedAddress1?: string;
deceasedAddress2?: string;
deceasedCity?: string;
deceasedProvince?: string;
deceasedName?: string;
deceasedPostalCode?: string;
birthDateString?: DateString | '';
birthPlace?: string;
deathDateString?: DateString | '';
deathPlace?: string;
deathAge?: string;
deathAgePeriod?: string;
intermentContainerTypeId?: string | number;
deceasedProvince?: string;
funeralDateString?: '' | DateString;
funeralDirectorName?: string;
funeralHomeId?: number | string;
funeralTimeString?: '' | TimeString;
intermentContainerTypeId?: number | string;
purchaserAddress1?: string;
purchaserAddress2?: string;
purchaserCity?: string;
purchaserEmail?: string;
purchaserName?: string;
purchaserPhoneNumber?: string;
purchaserPostalCode?: string;
purchaserProvince?: string;
purchaserRelationship?: string;
}
export default function addContract(addForm: AddContractForm, user: User, connectedDatabase?: PoolConnection): Promise<number>;

View File

@ -1,54 +1,55 @@
import type { PoolConnection } from 'better-sqlite-pool'
import {
type DateString,
type TimeString,
dateStringToInteger,
type TimeString,
timeStringToInteger
} from '@cityssm/utils-datetime'
import type { PoolConnection } from 'better-sqlite-pool'
import addOrUpdateContractField from './addOrUpdateContractField.js'
import { acquireConnection } from './pool.js'
export interface AddContractForm {
contractTypeId: string | number
burialSiteId: string | number
contractStartDateString: DateString | ''
contractEndDateString: DateString | ''
contractTypeFieldIds?: string
[fieldValue_contractTypeFieldId: `fieldValue_${string}`]: unknown
birthDateString?: '' | DateString
purchaserName?: string
purchaserAddress1?: string
purchaserAddress2?: string
purchaserCity?: string
purchaserProvince?: string
purchaserPostalCode?: string
purchaserPhoneNumber?: string
purchaserEmail?: string
purchaserRelationship?: string
birthPlace?: string
burialSiteId: number | string
funeralHomeId?: string | number
funeralDirectorName?: string
funeralDateString?: DateString | ''
funeralTimeString?: TimeString | ''
committalTypeId?: string | number
committalTypeId?: number | string
contractEndDateString: '' | DateString
contractStartDateString: '' | DateString
contractTypeFieldIds?: string
contractTypeId: number | string
deathAge?: string
deathAgePeriod?: string
deathDateString?: '' | DateString
deathPlace?: string
deceasedName?: string
deceasedAddress1?: string
deceasedAddress2?: string
deceasedCity?: string
deceasedProvince?: string
deceasedName?: string
deceasedPostalCode?: string
deceasedProvince?: string
birthDateString?: DateString | ''
birthPlace?: string
deathDateString?: DateString | ''
deathPlace?: string
deathAge?: string
deathAgePeriod?: string
intermentContainerTypeId?: string | number
funeralDateString?: '' | DateString
funeralDirectorName?: string
funeralHomeId?: number | string
funeralTimeString?: '' | TimeString
intermentContainerTypeId?: number | string
purchaserAddress1?: string
purchaserAddress2?: string
purchaserCity?: string
purchaserEmail?: string
purchaserName?: string
purchaserPhoneNumber?: string
purchaserPostalCode?: string
purchaserProvince?: string
purchaserRelationship?: string
}
// eslint-disable-next-line complexity

View File

@ -10,22 +10,22 @@ export default async function copyContract(oldContractId, user) {
const oldContract = (await getContract(oldContractId, database));
const newContractId = await addContract({
burialSiteId: oldContract.burialSiteId ?? '',
contractTypeId: oldContract.contractTypeId,
contractStartDateString: dateToString(new Date()),
contractEndDateString: '',
purchaserName: oldContract.purchaserName,
contractStartDateString: dateToString(new Date()),
contractTypeId: oldContract.contractTypeId,
funeralDateString: oldContract.funeralDateString ?? '',
funeralDirectorName: oldContract.funeralDirectorName,
funeralHomeId: oldContract.funeralHomeId ?? '',
funeralTimeString: oldContract.funeralTimeString ?? '',
purchaserAddress1: oldContract.purchaserAddress1,
purchaserAddress2: oldContract.purchaserAddress2,
purchaserCity: oldContract.purchaserCity,
purchaserProvince: oldContract.purchaserProvince,
purchaserPostalCode: oldContract.purchaserPostalCode,
purchaserPhoneNumber: oldContract.purchaserPhoneNumber,
purchaserEmail: oldContract.purchaserEmail,
purchaserRelationship: oldContract.purchaserRelationship,
funeralHomeId: oldContract.funeralHomeId,
funeralDirectorName: oldContract.funeralDirectorName,
funeralDateString: oldContract.funeralDateString ?? '',
funeralTimeString: oldContract.funeralTimeString ?? ''
purchaserName: oldContract.purchaserName,
purchaserPhoneNumber: oldContract.purchaserPhoneNumber,
purchaserPostalCode: oldContract.purchaserPostalCode,
purchaserProvince: oldContract.purchaserProvince,
purchaserRelationship: oldContract.purchaserRelationship
}, user, database);
/*
* Copy Fields
@ -45,19 +45,19 @@ export default async function copyContract(oldContractId, user) {
*/
for (const interment of oldContract.contractInterments ?? []) {
await addContractInterment({
birthDateString: interment.birthDateString ?? '',
birthPlace: interment.birthPlace ?? '',
contractId: newContractId,
deceasedName: interment.deceasedName ?? '',
deathAge: interment.deathAge ?? '',
deathAgePeriod: interment.deathAgePeriod ?? '',
deathDateString: interment.deathDateString ?? '',
deathPlace: interment.deathPlace ?? '',
deceasedAddress1: interment.deceasedAddress1 ?? '',
deceasedAddress2: interment.deceasedAddress2 ?? '',
deceasedCity: interment.deceasedCity ?? '',
deceasedProvince: interment.deceasedProvince ?? '',
deceasedName: interment.deceasedName ?? '',
deceasedPostalCode: interment.deceasedPostalCode ?? '',
birthDateString: interment.birthDateString ?? '',
birthPlace: interment.birthPlace ?? '',
deathDateString: interment.deathDateString ?? '',
deathPlace: interment.deathPlace ?? '',
deathAge: interment.deathAge ?? '',
deathAgePeriod: interment.deathAgePeriod ?? '',
deceasedProvince: interment.deceasedProvince ?? '',
intermentContainerTypeId: interment.intermentContainerTypeId ?? ''
}, user, database);
}
@ -65,8 +65,8 @@ export default async function copyContract(oldContractId, user) {
* Add Comment
*/
await addContractComment({
contractId: newContractId,
comment: `New record copied from #${oldContractId}.`
comment: `New record copied from #${oldContractId}.`,
contractId: newContractId
}, user);
database.release();
return newContractId;

View File

@ -20,24 +20,24 @@ export default async function copyContract(
const newContractId = await addContract(
{
burialSiteId: oldContract.burialSiteId ?? '',
contractTypeId: oldContract.contractTypeId,
contractStartDateString: dateToString(new Date()),
contractEndDateString: '',
contractStartDateString: dateToString(new Date()),
contractTypeId: oldContract.contractTypeId,
purchaserName: oldContract.purchaserName,
funeralDateString: oldContract.funeralDateString ?? '',
funeralDirectorName: oldContract.funeralDirectorName,
funeralHomeId: oldContract.funeralHomeId ?? '',
funeralTimeString: oldContract.funeralTimeString ?? '',
purchaserAddress1: oldContract.purchaserAddress1,
purchaserAddress2: oldContract.purchaserAddress2,
purchaserCity: oldContract.purchaserCity,
purchaserProvince: oldContract.purchaserProvince,
purchaserPostalCode: oldContract.purchaserPostalCode,
purchaserPhoneNumber: oldContract.purchaserPhoneNumber,
purchaserEmail: oldContract.purchaserEmail,
purchaserRelationship: oldContract.purchaserRelationship,
purchaserName: oldContract.purchaserName,
funeralHomeId: oldContract.funeralHomeId,
funeralDirectorName: oldContract.funeralDirectorName,
funeralDateString: oldContract.funeralDateString ?? '',
funeralTimeString: oldContract.funeralTimeString ?? ''
purchaserPhoneNumber: oldContract.purchaserPhoneNumber,
purchaserPostalCode: oldContract.purchaserPostalCode,
purchaserProvince: oldContract.purchaserProvince,
purchaserRelationship: oldContract.purchaserRelationship
},
user,
database
@ -76,21 +76,21 @@ export default async function copyContract(
for (const interment of oldContract.contractInterments ?? []) {
await addContractInterment(
{
contractId: newContractId,
deceasedName: interment.deceasedName ?? '',
deceasedAddress1: interment.deceasedAddress1 ?? '',
deceasedAddress2: interment.deceasedAddress2 ?? '',
deceasedCity: interment.deceasedCity ?? '',
deceasedProvince: interment.deceasedProvince ?? '',
deceasedPostalCode: interment.deceasedPostalCode ?? '',
birthDateString: interment.birthDateString ?? '',
birthPlace: interment.birthPlace ?? '',
contractId: newContractId,
deathAge: interment.deathAge ?? '',
deathAgePeriod: interment.deathAgePeriod ?? '',
deathDateString: interment.deathDateString ?? '',
deathPlace: interment.deathPlace ?? '',
deathAge: interment.deathAge ?? '',
deathAgePeriod: interment.deathAgePeriod ?? '',
deceasedAddress1: interment.deceasedAddress1 ?? '',
deceasedAddress2: interment.deceasedAddress2 ?? '',
deceasedCity: interment.deceasedCity ?? '',
deceasedName: interment.deceasedName ?? '',
deceasedPostalCode: interment.deceasedPostalCode ?? '',
deceasedProvince: interment.deceasedProvince ?? '',
intermentContainerTypeId: interment.intermentContainerTypeId ?? ''
},
user,
@ -104,8 +104,8 @@ export default async function copyContract(
await addContractComment(
{
contractId: newContractId,
comment: `New record copied from #${oldContractId}.`
comment: `New record copied from #${oldContractId}.`,
contractId: newContractId
},
user
)

View File

@ -1,3 +1,3 @@
type RecordTable = 'FeeCategories' | 'Fees' | 'BurialSites' | 'BurialSiteComments' | 'Contracts' | 'ContractComments' | 'BurialSiteStatuses' | 'BurialSiteTypes' | 'BurialSiteTypeFields' | 'Cemeteries' | 'FuneralHomes' | 'ContractTypes' | 'ContractTypeFields' | 'WorkOrders' | 'WorkOrderComments' | 'WorkOrderMilestones' | 'WorkOrderMilestoneTypes' | 'WorkOrderTypes';
type RecordTable = 'BurialSiteComments' | 'BurialSites' | 'BurialSiteStatuses' | 'BurialSiteTypeFields' | 'BurialSiteTypes' | 'Cemeteries' | 'ContractComments' | 'Contracts' | 'ContractTypeFields' | 'ContractTypes' | 'FeeCategories' | 'Fees' | 'FuneralHomes' | 'WorkOrderComments' | 'WorkOrderMilestones' | 'WorkOrderMilestoneTypes' | 'WorkOrders' | 'WorkOrderTypes';
export declare function deleteRecord(recordTable: RecordTable, recordId: number | string, user: User): Promise<boolean>;
export {};

View File

@ -1,39 +1,40 @@
import { clearCacheByTableName } from '../helpers/functions.cache.js';
import { acquireConnection } from './pool.js';
const recordIdColumns = new Map();
recordIdColumns.set('FeeCategories', 'feeCategoryId');
recordIdColumns.set('Fees', 'feeId');
recordIdColumns.set('BurialSites', 'burialSiteId');
recordIdColumns.set('BurialSiteComments', 'burialSiteCommentId');
recordIdColumns.set('Contracts', 'contractId');
recordIdColumns.set('ContractComments', 'contractCommentId');
recordIdColumns.set('BurialSiteStatuses', 'burialSiteStatusId');
recordIdColumns.set('BurialSiteTypes', 'burialSiteTypeId');
recordIdColumns.set('BurialSiteTypeFields', 'burialSiteTypeFieldId');
recordIdColumns.set('Cemeteries', 'cemeteryId');
recordIdColumns.set('FuneralHomes', 'funeralHomeId');
recordIdColumns.set('ContractTypes', 'contractTypeId');
recordIdColumns.set('ContractTypeFields', 'contractTypeFieldId');
recordIdColumns.set('WorkOrders', 'workOrderId');
recordIdColumns.set('WorkOrderComments', 'workOrderCommentId');
recordIdColumns.set('WorkOrderMilestones', 'workOrderMilestoneId');
recordIdColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId');
recordIdColumns.set('WorkOrderTypes', 'workOrderTypeId');
const relatedTables = new Map();
relatedTables.set('FeeCategories', ['Fees']);
relatedTables.set('BurialSites', ['BurialSiteFields', 'BurialSiteComments']);
relatedTables.set('Contracts', [
'ContractFields',
'ContractComments'
const recordIdColumns = new Map([
['BurialSiteComments', 'burialSiteCommentId'],
['BurialSites', 'burialSiteId'],
['BurialSiteStatuses', 'burialSiteStatusId'],
['BurialSiteTypeFields', 'burialSiteTypeFieldId'],
['BurialSiteTypes', 'burialSiteTypeId'],
['Cemeteries', 'cemeteryId'],
['ContractComments', 'contractCommentId'],
['Contracts', 'contractId'],
['ContractTypeFields', 'contractTypeFieldId'],
['ContractTypes', 'contractTypeId'],
['FeeCategories', 'feeCategoryId'],
['Fees', 'feeId'],
['FuneralHomes', 'funeralHomeId'],
['WorkOrderComments', 'workOrderCommentId'],
['WorkOrderMilestones', 'workOrderMilestoneId'],
['WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'],
['WorkOrders', 'workOrderId'],
['WorkOrderTypes', 'workOrderTypeId']
]);
relatedTables.set('BurialSiteTypes', ['BurialSiteTypeFields']);
relatedTables.set('Cemeteries', ['BurialSites']);
relatedTables.set('ContractTypes', ['ContractTypePrints', 'ContractTypeFields']);
relatedTables.set('WorkOrders', [
const relatedTables = new Map([
['BurialSites', ['BurialSiteFields', 'BurialSiteComments']],
['BurialSiteTypes', ['BurialSiteTypeFields']],
['Cemeteries', ['BurialSites']],
['Contracts', ['ContractFields', 'ContractComments']],
['ContractTypes', ['ContractTypePrints', 'ContractTypeFields']],
[
'WorkOrders',
[
'WorkOrderMilestones',
'WorkOrderLots',
'WorkOrderContracts',
'WorkOrderComments'
]
]
]);
export async function deleteRecord(recordTable, recordId, user) {
const database = await acquireConnection();

View File

@ -1,62 +1,62 @@
import { clearCacheByTableName } from '../helpers/functions.cache.js'
import { acquireConnection } from './pool.js'
type RecordTable =
| 'BurialSiteComments'
| 'BurialSites'
| 'BurialSiteStatuses'
| 'BurialSiteTypeFields'
| 'BurialSiteTypes'
| 'Cemeteries'
| 'ContractComments'
| 'Contracts'
| 'ContractTypeFields'
| 'ContractTypes'
| 'FeeCategories'
| 'Fees'
| 'BurialSites'
| 'BurialSiteComments'
| 'Contracts'
| 'ContractComments'
| 'BurialSiteStatuses'
| 'BurialSiteTypes'
| 'BurialSiteTypeFields'
| 'Cemeteries'
| 'FuneralHomes'
| 'ContractTypes'
| 'ContractTypeFields'
| 'WorkOrders'
| 'WorkOrderComments'
| 'WorkOrderMilestones'
| 'WorkOrderMilestoneTypes'
| 'WorkOrders'
| 'WorkOrderTypes'
const recordIdColumns = new Map<RecordTable, string>()
recordIdColumns.set('FeeCategories', 'feeCategoryId')
recordIdColumns.set('Fees', 'feeId')
recordIdColumns.set('BurialSites', 'burialSiteId')
recordIdColumns.set('BurialSiteComments', 'burialSiteCommentId')
recordIdColumns.set('Contracts', 'contractId')
recordIdColumns.set('ContractComments', 'contractCommentId')
recordIdColumns.set('BurialSiteStatuses', 'burialSiteStatusId')
recordIdColumns.set('BurialSiteTypes', 'burialSiteTypeId')
recordIdColumns.set('BurialSiteTypeFields', 'burialSiteTypeFieldId')
recordIdColumns.set('Cemeteries', 'cemeteryId')
recordIdColumns.set('FuneralHomes', 'funeralHomeId')
recordIdColumns.set('ContractTypes', 'contractTypeId')
recordIdColumns.set('ContractTypeFields', 'contractTypeFieldId')
recordIdColumns.set('WorkOrders', 'workOrderId')
recordIdColumns.set('WorkOrderComments', 'workOrderCommentId')
recordIdColumns.set('WorkOrderMilestones', 'workOrderMilestoneId')
recordIdColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId')
recordIdColumns.set('WorkOrderTypes', 'workOrderTypeId')
const relatedTables = new Map<RecordTable, string[]>()
relatedTables.set('FeeCategories', ['Fees'])
relatedTables.set('BurialSites', ['BurialSiteFields', 'BurialSiteComments'])
relatedTables.set('Contracts', [
'ContractFields',
'ContractComments'
const recordIdColumns = new Map<RecordTable, string>([
['BurialSiteComments', 'burialSiteCommentId'],
['BurialSites', 'burialSiteId'],
['BurialSiteStatuses', 'burialSiteStatusId'],
['BurialSiteTypeFields', 'burialSiteTypeFieldId'],
['BurialSiteTypes', 'burialSiteTypeId'],
['Cemeteries', 'cemeteryId'],
['ContractComments', 'contractCommentId'],
['Contracts', 'contractId'],
['ContractTypeFields', 'contractTypeFieldId'],
['ContractTypes', 'contractTypeId'],
['FeeCategories', 'feeCategoryId'],
['Fees', 'feeId'],
['FuneralHomes', 'funeralHomeId'],
['WorkOrderComments', 'workOrderCommentId'],
['WorkOrderMilestones', 'workOrderMilestoneId'],
['WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'],
['WorkOrders', 'workOrderId'],
['WorkOrderTypes', 'workOrderTypeId']
])
relatedTables.set('BurialSiteTypes', ['BurialSiteTypeFields'])
relatedTables.set('Cemeteries', ['BurialSites'])
relatedTables.set('ContractTypes', ['ContractTypePrints', 'ContractTypeFields'])
relatedTables.set('WorkOrders', [
const relatedTables = new Map<RecordTable, string[]>([
['BurialSites', ['BurialSiteFields', 'BurialSiteComments']],
['BurialSiteTypes', ['BurialSiteTypeFields']],
['Cemeteries', ['BurialSites']],
['Contracts', ['ContractFields', 'ContractComments']],
['ContractTypes', ['ContractTypePrints', 'ContractTypeFields']],
[
'WorkOrders',
[
'WorkOrderMilestones',
'WorkOrderLots',
'WorkOrderContracts',
'WorkOrderComments'
]
]
])
export async function deleteRecord(

View File

@ -49,21 +49,6 @@ export default async function getReportData(reportName, reportParameters = {}) {
// eslint-disable-next-line security/detect-object-injection
if (simpleReports[reportName] === undefined) {
switch (reportName) {
case 'burialSites-byBurialSiteTypeId': {
sql = `select l.burialSiteId,
m.cemeteryName,
l.burialSiteName,
t.burialSiteType,
s.burialSiteStatus
from BurialSites l
left join BurialSiteTypes t on l.burialSiteTypeId = t.burialSiteTypeId
left join BurialSiteStatuses s on l.burialSiteStatusId = s.burialSiteStatusId
left join Cemeteries m on l.cemeteryId = m.cemeteryId
where l.recordDelete_timeMillis is null
and l.burialSiteTypeId = ?`;
sqlParameters.push(reportParameters.burialSiteTypeId);
break;
}
case 'burialSites-byBurialSiteStatusId': {
sql = `select l.burialSiteId,
m.cemeteryName,
@ -79,6 +64,21 @@ export default async function getReportData(reportName, reportParameters = {}) {
sqlParameters.push(reportParameters.burialSiteStatusId);
break;
}
case 'burialSites-byBurialSiteTypeId': {
sql = `select l.burialSiteId,
m.cemeteryName,
l.burialSiteName,
t.burialSiteType,
s.burialSiteStatus
from BurialSites l
left join BurialSiteTypes t on l.burialSiteTypeId = t.burialSiteTypeId
left join BurialSiteStatuses s on l.burialSiteStatusId = s.burialSiteStatusId
left join Cemeteries m on l.cemeteryId = m.cemeteryId
where l.recordDelete_timeMillis is null
and l.burialSiteTypeId = ?`;
sqlParameters.push(reportParameters.burialSiteTypeId);
break;
}
case 'burialSites-byCemeteryId': {
sql = `select l.burialSiteId,
m.cemeteryName,
@ -94,6 +94,20 @@ export default async function getReportData(reportName, reportParameters = {}) {
sqlParameters.push(reportParameters.cemeteryId);
break;
}
case 'contractInterments-byContractId': {
sql = `select i.contractId, i.intermentNumber,
i.deceasedName, i.deceasedAddress1, i.deceasedAddress2,
i.deceasedCity, i.deceasedProvince, i.deceasedPostalCode,
i.birthDate, i.birthPlace,
i.deathDate, i.deathPlace,
i.deathAge, i.deathAgePeriod
from ContractInterments i
left join IntermentContainerTypes t on i.intermentContainerTypeId = t.intermentContainerTypeId
where i.recordDelete_timeMillis is null
and i.contractId = ?`;
sqlParameters.push(reportParameters.contractId);
break;
}
case 'contracts-current-byCemeteryId': {
sql = `select o.contractId,
l.burialSiteName,
@ -111,20 +125,6 @@ export default async function getReportData(reportName, reportParameters = {}) {
sqlParameters.push(dateToInteger(new Date()), reportParameters.cemeteryId);
break;
}
case 'contractInterments-byContractId': {
sql = `select i.contractId, i.intermentNumber,
i.deceasedName, i.deceasedAddress1, i.deceasedAddress2,
i.deceasedCity, i.deceasedProvince, i.deceasedPostalCode,
i.birthDate, i.birthPlace,
i.deathDate, i.deathPlace,
i.deathAge, i.deathAgePeriod
from ContractInterments i
left join IntermentContainerTypes t on i.intermentContainerTypeId = t.intermentContainerTypeId
where i.recordDelete_timeMillis is null
and i.contractId = ?`;
sqlParameters.push(reportParameters.contractId);
break;
}
case 'contractTransactions-byTransactionDateString': {
sql = `select t.contractId, t.transactionIndex,
t.transactionDate, t.transactionTime,
@ -136,6 +136,20 @@ export default async function getReportData(reportName, reportParameters = {}) {
sqlParameters.push(dateStringToInteger(reportParameters.transactionDateString));
break;
}
case 'workOrderMilestones-byWorkOrderId': {
sql = `select t.workOrderMilestoneType,
m.workOrderMilestoneDate,
m.workOrderMilestoneTime,
m.workOrderMilestoneDescription,
m.workOrderMilestoneCompletionDate,
m.workOrderMilestoneCompletionTime
from WorkOrderMilestones m
left join WorkOrderMilestoneTypes t on m.workOrderMilestoneTypeId = t.workOrderMilestoneTypeId
where m.recordDelete_timeMillis is null
and m.workOrderId = ?`;
sqlParameters.push(reportParameters.workOrderId);
break;
}
case 'workOrders-open': {
sql = `select w.workOrderId, w.workOrderNumber,
t.workOrderType, w.workOrderDescription,
@ -155,20 +169,6 @@ export default async function getReportData(reportName, reportParameters = {}) {
and w.workOrderCloseDate is null`;
break;
}
case 'workOrderMilestones-byWorkOrderId': {
sql = `select t.workOrderMilestoneType,
m.workOrderMilestoneDate,
m.workOrderMilestoneTime,
m.workOrderMilestoneDescription,
m.workOrderMilestoneCompletionDate,
m.workOrderMilestoneCompletionTime
from WorkOrderMilestones m
left join WorkOrderMilestoneTypes t on m.workOrderMilestoneTypeId = t.workOrderMilestoneTypeId
where m.recordDelete_timeMillis is null
and m.workOrderId = ?`;
sqlParameters.push(reportParameters.workOrderId);
break;
}
default: {
return undefined;
}

View File

@ -1,6 +1,6 @@
import {
type DateString,
dateIntegerToString,
type DateString,
dateStringToInteger,
dateToInteger,
timeIntegerToString
@ -8,7 +8,7 @@ import {
import { acquireConnection } from './pool.js'
export type ReportParameters = Record<string, string | number>
export type ReportParameters = Record<string, number | string>
const simpleReports: Record<`${string}-all` | `${string}-formatted`, string> = {
'burialSiteComments-all': 'select * from BurialSiteComments',
@ -61,31 +61,13 @@ const simpleReports: Record<`${string}-all` | `${string}-formatted`, string> = {
export default async function getReportData(
reportName: string,
reportParameters: ReportParameters = {}
): Promise<unknown[] | undefined> {
): Promise<undefined | unknown[]> {
let sql = ''
const sqlParameters: unknown[] = []
// eslint-disable-next-line security/detect-object-injection
if (simpleReports[reportName] === undefined) {
switch (reportName) {
case 'burialSites-byBurialSiteTypeId': {
sql = `select l.burialSiteId,
m.cemeteryName,
l.burialSiteName,
t.burialSiteType,
s.burialSiteStatus
from BurialSites l
left join BurialSiteTypes t on l.burialSiteTypeId = t.burialSiteTypeId
left join BurialSiteStatuses s on l.burialSiteStatusId = s.burialSiteStatusId
left join Cemeteries m on l.cemeteryId = m.cemeteryId
where l.recordDelete_timeMillis is null
and l.burialSiteTypeId = ?`
sqlParameters.push(reportParameters.burialSiteTypeId)
break
}
case 'burialSites-byBurialSiteStatusId': {
sql = `select l.burialSiteId,
m.cemeteryName,
@ -104,6 +86,24 @@ export default async function getReportData(
break
}
case 'burialSites-byBurialSiteTypeId': {
sql = `select l.burialSiteId,
m.cemeteryName,
l.burialSiteName,
t.burialSiteType,
s.burialSiteStatus
from BurialSites l
left join BurialSiteTypes t on l.burialSiteTypeId = t.burialSiteTypeId
left join BurialSiteStatuses s on l.burialSiteStatusId = s.burialSiteStatusId
left join Cemeteries m on l.cemeteryId = m.cemeteryId
where l.recordDelete_timeMillis is null
and l.burialSiteTypeId = ?`
sqlParameters.push(reportParameters.burialSiteTypeId)
break
}
case 'burialSites-byCemeteryId': {
sql = `select l.burialSiteId,
m.cemeteryName,
@ -122,6 +122,23 @@ export default async function getReportData(
break
}
case 'contractInterments-byContractId': {
sql = `select i.contractId, i.intermentNumber,
i.deceasedName, i.deceasedAddress1, i.deceasedAddress2,
i.deceasedCity, i.deceasedProvince, i.deceasedPostalCode,
i.birthDate, i.birthPlace,
i.deathDate, i.deathPlace,
i.deathAge, i.deathAgePeriod
from ContractInterments i
left join IntermentContainerTypes t on i.intermentContainerTypeId = t.intermentContainerTypeId
where i.recordDelete_timeMillis is null
and i.contractId = ?`
sqlParameters.push(reportParameters.contractId)
break
}
case 'contracts-current-byCemeteryId': {
sql = `select o.contractId,
l.burialSiteName,
@ -145,23 +162,6 @@ export default async function getReportData(
break
}
case 'contractInterments-byContractId': {
sql = `select i.contractId, i.intermentNumber,
i.deceasedName, i.deceasedAddress1, i.deceasedAddress2,
i.deceasedCity, i.deceasedProvince, i.deceasedPostalCode,
i.birthDate, i.birthPlace,
i.deathDate, i.deathPlace,
i.deathAge, i.deathAgePeriod
from ContractInterments i
left join IntermentContainerTypes t on i.intermentContainerTypeId = t.intermentContainerTypeId
where i.recordDelete_timeMillis is null
and i.contractId = ?`
sqlParameters.push(reportParameters.contractId)
break
}
case 'contractTransactions-byTransactionDateString': {
sql = `select t.contractId, t.transactionIndex,
t.transactionDate, t.transactionTime,
@ -179,6 +179,22 @@ export default async function getReportData(
break
}
case 'workOrderMilestones-byWorkOrderId': {
sql = `select t.workOrderMilestoneType,
m.workOrderMilestoneDate,
m.workOrderMilestoneTime,
m.workOrderMilestoneDescription,
m.workOrderMilestoneCompletionDate,
m.workOrderMilestoneCompletionTime
from WorkOrderMilestones m
left join WorkOrderMilestoneTypes t on m.workOrderMilestoneTypeId = t.workOrderMilestoneTypeId
where m.recordDelete_timeMillis is null
and m.workOrderId = ?`
sqlParameters.push(reportParameters.workOrderId)
break
}
case 'workOrders-open': {
sql = `select w.workOrderId, w.workOrderNumber,
t.workOrderType, w.workOrderDescription,
@ -200,22 +216,6 @@ export default async function getReportData(
break
}
case 'workOrderMilestones-byWorkOrderId': {
sql = `select t.workOrderMilestoneType,
m.workOrderMilestoneDate,
m.workOrderMilestoneTime,
m.workOrderMilestoneDescription,
m.workOrderMilestoneCompletionDate,
m.workOrderMilestoneCompletionTime
from WorkOrderMilestones m
left join WorkOrderMilestoneTypes t on m.workOrderMilestoneTypeId = t.workOrderMilestoneTypeId
where m.recordDelete_timeMillis is null
and m.workOrderId = ?`
sqlParameters.push(reportParameters.workOrderId)
break
}
default: {
return undefined
}

View File

@ -5,6 +5,6 @@ interface WorkOrderOptions {
includeComments: boolean;
includeMilestones: boolean;
}
export declare function getWorkOrderByWorkOrderNumber(workOrderNumber: string): Promise<WorkOrder | undefined>;
export default function getWorkOrder(workOrderId: number | string, options: WorkOrderOptions, connectedDatabase?: PoolConnection): Promise<WorkOrder | undefined>;
export default function getWorkOrder(workOrderId: number | string, options: WorkOrderOptions, connectedDatabase?: PoolConnection): Promise<undefined | WorkOrder>;
export declare function getWorkOrderByWorkOrderNumber(workOrderNumber: string): Promise<undefined | WorkOrder>;
export {};

View File

@ -13,6 +13,16 @@ const baseSQL = `select w.workOrderId,
from WorkOrders w
left join WorkOrderTypes t on w.workOrderTypeId = t.workOrderTypeId
where w.recordDelete_timeMillis is null`;
export default async function getWorkOrder(workOrderId, options, connectedDatabase) {
return await _getWorkOrder(`${baseSQL} and w.workOrderId = ?`, workOrderId, options, connectedDatabase);
}
export async function getWorkOrderByWorkOrderNumber(workOrderNumber) {
return await _getWorkOrder(`${baseSQL} and w.workOrderNumber = ?`, workOrderNumber, {
includeBurialSites: true,
includeComments: true,
includeMilestones: true
});
}
async function _getWorkOrder(sql, workOrderIdOrWorkOrderNumber, options, connectedDatabase) {
const database = connectedDatabase ?? (await acquireConnection());
database.function('userFn_dateIntegerToString', dateIntegerToString);
@ -22,22 +32,21 @@ async function _getWorkOrder(sql, workOrderIdOrWorkOrderNumber, options, connect
const burialSiteResults = await getBurialSites({
workOrderId: workOrder.workOrderId
}, {
includeContractCount: false,
limit: -1,
offset: 0,
includeContractCount: false
offset: 0
}, database);
workOrder.workOrderBurialSites = burialSiteResults.burialSites;
const workOrderContractsResults = await getContracts({
workOrderId: workOrder.workOrderId
}, {
limit: -1,
offset: 0,
includeInterments: true,
includeFees: false,
includeTransactions: false
includeInterments: true,
includeTransactions: false,
limit: -1,
offset: 0
}, database);
workOrder.workOrderContracts =
workOrderContractsResults.contracts;
workOrder.workOrderContracts = workOrderContractsResults.contracts;
}
if (options.includeComments) {
workOrder.workOrderComments = await getWorkOrderComments(workOrder.workOrderId, database);
@ -56,13 +65,3 @@ async function _getWorkOrder(sql, workOrderIdOrWorkOrderNumber, options, connect
}
return workOrder;
}
export async function getWorkOrderByWorkOrderNumber(workOrderNumber) {
return await _getWorkOrder(`${baseSQL} and w.workOrderNumber = ?`, workOrderNumber, {
includeBurialSites: true,
includeComments: true,
includeMilestones: true
});
}
export default async function getWorkOrder(workOrderId, options, connectedDatabase) {
return await _getWorkOrder(`${baseSQL} and w.workOrderId = ?`, workOrderId, options, connectedDatabase);
}

View File

@ -1,6 +1,7 @@
import { dateIntegerToString } from '@cityssm/utils-datetime'
import type { PoolConnection } from 'better-sqlite-pool'
import { dateIntegerToString } from '@cityssm/utils-datetime'
import type { WorkOrder } from '../types/recordTypes.js'
import getBurialSites from './getBurialSites.js'
@ -25,19 +26,46 @@ const baseSQL = `select w.workOrderId,
left join WorkOrderTypes t on w.workOrderTypeId = t.workOrderTypeId
where w.recordDelete_timeMillis is null`
export default async function getWorkOrder(
workOrderId: number | string,
options: WorkOrderOptions,
connectedDatabase?: PoolConnection
): Promise<undefined | WorkOrder> {
return await _getWorkOrder(
`${baseSQL} and w.workOrderId = ?`,
workOrderId,
options,
connectedDatabase
)
}
export async function getWorkOrderByWorkOrderNumber(
workOrderNumber: string
): Promise<undefined | WorkOrder> {
return await _getWorkOrder(
`${baseSQL} and w.workOrderNumber = ?`,
workOrderNumber,
{
includeBurialSites: true,
includeComments: true,
includeMilestones: true
}
)
}
async function _getWorkOrder(
sql: string,
workOrderIdOrWorkOrderNumber: number | string,
options: WorkOrderOptions,
connectedDatabase?: PoolConnection
): Promise<WorkOrder | undefined> {
): Promise<undefined | WorkOrder> {
const database = connectedDatabase ?? (await acquireConnection())
database.function('userFn_dateIntegerToString', dateIntegerToString)
const workOrder = database.prepare(sql).get(workOrderIdOrWorkOrderNumber) as
| WorkOrder
| undefined
| WorkOrder
if (workOrder !== undefined) {
if (options.includeBurialSites) {
@ -46,9 +74,9 @@ async function _getWorkOrder(
workOrderId: workOrder.workOrderId
},
{
includeContractCount: false,
limit: -1,
offset: 0,
includeContractCount: false
offset: 0
},
database
)
@ -60,17 +88,16 @@ async function _getWorkOrder(
workOrderId: workOrder.workOrderId
},
{
limit: -1,
offset: 0,
includeInterments: true,
includeFees: false,
includeTransactions: false
includeInterments: true,
includeTransactions: false,
limit: -1,
offset: 0
},
database
)
workOrder.workOrderContracts =
workOrderContractsResults.contracts
workOrder.workOrderContracts = workOrderContractsResults.contracts
}
if (options.includeComments) {
@ -100,30 +127,3 @@ async function _getWorkOrder(
return workOrder
}
export async function getWorkOrderByWorkOrderNumber(
workOrderNumber: string
): Promise<WorkOrder | undefined> {
return await _getWorkOrder(
`${baseSQL} and w.workOrderNumber = ?`,
workOrderNumber,
{
includeBurialSites: true,
includeComments: true,
includeMilestones: true
}
)
}
export default async function getWorkOrder(
workOrderId: number | string,
options: WorkOrderOptions,
connectedDatabase?: PoolConnection
): Promise<WorkOrder | undefined> {
return await _getWorkOrder(
`${baseSQL} and w.workOrderId = ?`,
workOrderId,
options,
connectedDatabase
)
}

View File

@ -1,6 +1,6 @@
export declare function clearNextPreviousBurialSiteIdCache(burialSiteId?: number, relayMessage?: boolean): void;
export declare function getNextBurialSiteId(burialSiteId: number): Promise<number | undefined>;
export declare function getPreviousBurialSiteId(burialSiteId: number): Promise<number | undefined>;
export declare function clearNextPreviousBurialSiteIdCache(burialSiteId?: number, relayMessage?: boolean): void;
export declare function buildBurialSiteName(cemeteryKey: string | undefined, segments: {
burialSiteNameSegment1?: string;
burialSiteNameSegment2?: string;

View File

@ -15,19 +15,32 @@ const cacheOptions = {
};
const previousBurialSiteIdCache = new NodeCache(cacheOptions);
const nextBurialSiteIdCache = new NodeCache(cacheOptions);
function cacheBurialSiteIds(burialSiteId, nextBurialSiteId, relayMessage = true) {
previousBurialSiteIdCache.set(nextBurialSiteId, burialSiteId);
nextBurialSiteIdCache.set(burialSiteId, nextBurialSiteId);
export function clearNextPreviousBurialSiteIdCache(burialSiteId = -1, relayMessage = true) {
if (burialSiteId === -1) {
previousBurialSiteIdCache.flushAll();
nextBurialSiteIdCache.flushAll();
return;
}
const previousBurialSiteId = previousBurialSiteIdCache.get(burialSiteId);
if (previousBurialSiteId !== undefined) {
nextBurialSiteIdCache.del(previousBurialSiteId);
previousBurialSiteIdCache.del(burialSiteId);
}
const nextBurialSiteId = nextBurialSiteIdCache.get(burialSiteId);
if (nextBurialSiteId !== undefined) {
previousBurialSiteIdCache.del(nextBurialSiteId);
nextBurialSiteIdCache.del(burialSiteId);
}
try {
if (relayMessage && cluster.isWorker && process.send !== undefined) {
const workerMessage = {
messageType: 'cacheBurialSiteIds',
burialSiteId,
nextBurialSiteId,
timeMillis: Date.now(),
pid: process.pid
// eslint-disable-next-line no-secrets/no-secrets
messageType: 'clearNextPreviousBurialSiteIdCache',
pid: process.pid,
timeMillis: Date.now()
};
debug(`Sending cache burial site ids from worker: (${burialSiteId}, ${nextBurialSiteId})`);
debug(`Sending clear next/previous burial site cache from worker: ${burialSiteId}`);
process.send(workerMessage);
}
}
@ -55,32 +68,19 @@ export async function getPreviousBurialSiteId(burialSiteId) {
}
return previousBurialSiteId;
}
export function clearNextPreviousBurialSiteIdCache(burialSiteId = -1, relayMessage = true) {
if (burialSiteId === -1) {
previousBurialSiteIdCache.flushAll();
nextBurialSiteIdCache.flushAll();
return;
}
const previousBurialSiteId = previousBurialSiteIdCache.get(burialSiteId);
if (previousBurialSiteId !== undefined) {
nextBurialSiteIdCache.del(previousBurialSiteId);
previousBurialSiteIdCache.del(burialSiteId);
}
const nextBurialSiteId = nextBurialSiteIdCache.get(burialSiteId);
if (nextBurialSiteId !== undefined) {
previousBurialSiteIdCache.del(nextBurialSiteId);
nextBurialSiteIdCache.del(burialSiteId);
}
function cacheBurialSiteIds(burialSiteId, nextBurialSiteId, relayMessage = true) {
previousBurialSiteIdCache.set(nextBurialSiteId, burialSiteId);
nextBurialSiteIdCache.set(burialSiteId, nextBurialSiteId);
try {
if (relayMessage && cluster.isWorker && process.send !== undefined) {
const workerMessage = {
// eslint-disable-next-line no-secrets/no-secrets
messageType: 'clearNextPreviousBurialSiteIdCache',
burialSiteId,
timeMillis: Date.now(),
pid: process.pid
messageType: 'cacheBurialSiteIds',
nextBurialSiteId,
pid: process.pid,
timeMillis: Date.now()
};
debug(`Sending clear next/previous burial site cache from worker: ${burialSiteId}`);
debug(`Sending cache burial site ids from worker: (${burialSiteId}, ${nextBurialSiteId})`);
process.send(workerMessage);
}
}

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}`)
@ -28,26 +28,44 @@ const previousBurialSiteIdCache = new NodeCache(cacheOptions)
const nextBurialSiteIdCache = new NodeCache(cacheOptions)
function cacheBurialSiteIds(
burialSiteId: number,
nextBurialSiteId: number,
export function clearNextPreviousBurialSiteIdCache(
burialSiteId = -1,
relayMessage = true
): void {
previousBurialSiteIdCache.set(nextBurialSiteId, burialSiteId)
nextBurialSiteIdCache.set(burialSiteId, nextBurialSiteId)
if (burialSiteId === -1) {
previousBurialSiteIdCache.flushAll()
nextBurialSiteIdCache.flushAll()
return
}
const previousBurialSiteId: number | undefined =
previousBurialSiteIdCache.get(burialSiteId)
if (previousBurialSiteId !== undefined) {
nextBurialSiteIdCache.del(previousBurialSiteId)
previousBurialSiteIdCache.del(burialSiteId)
}
const nextBurialSiteId: number | undefined =
nextBurialSiteIdCache.get(burialSiteId)
if (nextBurialSiteId !== undefined) {
previousBurialSiteIdCache.del(nextBurialSiteId)
nextBurialSiteIdCache.del(burialSiteId)
}
try {
if (relayMessage && cluster.isWorker && process.send !== undefined) {
const workerMessage: CacheBurialSiteIdsWorkerMessage = {
messageType: 'cacheBurialSiteIds',
const workerMessage: ClearNextPreviousBurialSiteIdsCacheWorkerMessage = {
burialSiteId,
nextBurialSiteId,
timeMillis: Date.now(),
pid: process.pid
// eslint-disable-next-line no-secrets/no-secrets
messageType: 'clearNextPreviousBurialSiteIdCache',
pid: process.pid,
timeMillis: Date.now()
}
debug(
`Sending cache burial site ids from worker: (${burialSiteId}, ${nextBurialSiteId})`
`Sending clear next/previous burial site cache from worker: ${burialSiteId}`
)
process.send(workerMessage)
@ -91,44 +109,26 @@ export async function getPreviousBurialSiteId(
return previousBurialSiteId
}
export function clearNextPreviousBurialSiteIdCache(
burialSiteId = -1,
function cacheBurialSiteIds(
burialSiteId: number,
nextBurialSiteId: number,
relayMessage = true
): void {
if (burialSiteId === -1) {
previousBurialSiteIdCache.flushAll()
nextBurialSiteIdCache.flushAll()
return
}
const previousBurialSiteId: number | undefined =
previousBurialSiteIdCache.get(burialSiteId)
if (previousBurialSiteId !== undefined) {
nextBurialSiteIdCache.del(previousBurialSiteId)
previousBurialSiteIdCache.del(burialSiteId)
}
const nextBurialSiteId: number | undefined =
nextBurialSiteIdCache.get(burialSiteId)
if (nextBurialSiteId !== undefined) {
previousBurialSiteIdCache.del(nextBurialSiteId)
nextBurialSiteIdCache.del(burialSiteId)
}
previousBurialSiteIdCache.set(nextBurialSiteId, burialSiteId)
nextBurialSiteIdCache.set(burialSiteId, nextBurialSiteId)
try {
if (relayMessage && cluster.isWorker && process.send !== undefined) {
const workerMessage: ClearNextPreviousBurialSiteIdsCacheWorkerMessage = {
// eslint-disable-next-line no-secrets/no-secrets
messageType: 'clearNextPreviousBurialSiteIdCache',
const workerMessage: CacheBurialSiteIdsWorkerMessage = {
burialSiteId,
timeMillis: Date.now(),
pid: process.pid
messageType: 'cacheBurialSiteIds',
nextBurialSiteId,
pid: process.pid,
timeMillis: Date.now()
}
debug(
`Sending clear next/previous burial site cache from worker: ${burialSiteId}`
`Sending cache burial site ids from worker: (${burialSiteId}, ${nextBurialSiteId})`
)
process.send(workerMessage)
@ -179,8 +179,8 @@ process.on(
'message',
(
message:
| ClearNextPreviousBurialSiteIdsCacheWorkerMessage
| CacheBurialSiteIdsWorkerMessage
| ClearNextPreviousBurialSiteIdsCacheWorkerMessage
) => {
if (message.pid !== process.pid) {
switch (message.messageType) {

View File

@ -1,4 +1,4 @@
export declare function regenerateApiKey(userName: string): Promise<void>;
export declare function getApiKey(userName: string): Promise<string>;
export declare function getApiKeyFromUser(user: User): Promise<string>;
export declare function getUserNameFromApiKey(apiKey: string): Promise<string | undefined>;
export declare function regenerateApiKey(userName: string): Promise<void>;

View File

@ -5,31 +5,6 @@ import { DEBUG_NAMESPACE } from '../debug.config.js';
const debug = Debug(`${DEBUG_NAMESPACE}:functions.api`);
const apiKeyPath = 'data/apiKeys.json';
let apiKeys;
async function loadApiKeys() {
try {
const fileData = await fs.readFile(apiKeyPath, 'utf8');
apiKeys = JSON.parse(fileData);
}
catch (error) {
debug(error);
apiKeys = {};
}
}
async function saveApiKeys() {
try {
await fs.writeFile(apiKeyPath, JSON.stringify(apiKeys), 'utf8');
}
catch (error) {
debug(error);
}
}
function generateApiKey(apiKeyPrefix) {
return `${apiKeyPrefix}-${randomUUID()}-${Date.now().toString()}`;
}
export async function regenerateApiKey(userName) {
apiKeys[userName] = generateApiKey(userName);
await saveApiKeys();
}
export async function getApiKey(userName) {
if (apiKeys === undefined) {
await loadApiKeys();
@ -53,3 +28,28 @@ export async function getUserNameFromApiKey(apiKey) {
}
return undefined;
}
export async function regenerateApiKey(userName) {
apiKeys[userName] = generateApiKey(userName);
await saveApiKeys();
}
function generateApiKey(apiKeyPrefix) {
return `${apiKeyPrefix}-${randomUUID()}-${Date.now().toString()}`;
}
async function loadApiKeys() {
try {
const fileData = await fs.readFile(apiKeyPath, 'utf8');
apiKeys = JSON.parse(fileData);
}
catch (error) {
debug(error);
apiKeys = {};
}
}
async function saveApiKeys() {
try {
await fs.writeFile(apiKeyPath, JSON.stringify(apiKeys), 'utf8');
}
catch (error) {
debug(error);
}
}

View File

@ -10,33 +10,6 @@ const debug = Debug(`${DEBUG_NAMESPACE}:functions.api`)
const apiKeyPath = 'data/apiKeys.json'
let apiKeys: Record<string, string> | undefined
async function loadApiKeys(): Promise<void> {
try {
const fileData = await fs.readFile(apiKeyPath, 'utf8')
apiKeys = JSON.parse(fileData) as Record<string, string>
} catch (error) {
debug(error)
apiKeys = {}
}
}
async function saveApiKeys(): Promise<void> {
try {
await fs.writeFile(apiKeyPath, JSON.stringify(apiKeys), 'utf8')
} catch (error) {
debug(error)
}
}
function generateApiKey(apiKeyPrefix: string): string {
return `${apiKeyPrefix}-${randomUUID()}-${Date.now().toString()}`
}
export async function regenerateApiKey(userName: string): Promise<void> {
apiKeys[userName] = generateApiKey(userName)
await saveApiKeys()
}
export async function getApiKey(userName: string): Promise<string> {
if (apiKeys === undefined) {
await loadApiKeys()
@ -68,3 +41,30 @@ export async function getUserNameFromApiKey(
return undefined
}
export async function regenerateApiKey(userName: string): Promise<void> {
apiKeys[userName] = generateApiKey(userName)
await saveApiKeys()
}
function generateApiKey(apiKeyPrefix: string): string {
return `${apiKeyPrefix}-${randomUUID()}-${Date.now().toString()}`
}
async function loadApiKeys(): Promise<void> {
try {
const fileData = await fs.readFile(apiKeyPath, 'utf8')
apiKeys = JSON.parse(fileData) as Record<string, string>
} catch (error) {
debug(error)
apiKeys = {}
}
}
async function saveApiKeys(): Promise<void> {
try {
await fs.writeFile(apiKeyPath, JSON.stringify(apiKeys), 'utf8')
} catch (error) {
debug(error)
}
}

136
package-lock.json generated
View File

@ -67,7 +67,7 @@
"axe-core": "^4.10.3",
"cypress": "^14.2.0",
"cypress-axe": "^1.6.0",
"eslint-config-cityssm": "^21.0.0",
"eslint-config-cityssm": "^22.1.0",
"nodemon": "^3.1.9",
"prettier-config-cityssm": "^1.0.0"
},
@ -2100,17 +2100,17 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz",
"integrity": "sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.28.0.tgz",
"integrity": "sha512-lvFK3TCGAHsItNdWZ/1FkvpzCxTHUVuFrdnOGLMa0GGCFIbCgQWVk3CzCGdA7kM3qGVc+dfW9tr0Z/sHnGDFyg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.27.0",
"@typescript-eslint/type-utils": "8.27.0",
"@typescript-eslint/utils": "8.27.0",
"@typescript-eslint/visitor-keys": "8.27.0",
"@typescript-eslint/scope-manager": "8.28.0",
"@typescript-eslint/type-utils": "8.28.0",
"@typescript-eslint/utils": "8.28.0",
"@typescript-eslint/visitor-keys": "8.28.0",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
@ -2130,16 +2130,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.27.0.tgz",
"integrity": "sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.28.0.tgz",
"integrity": "sha512-LPcw1yHD3ToaDEoljFEfQ9j2xShY367h7FZ1sq5NJT9I3yj4LHer1Xd1yRSOdYy9BpsrxU7R+eoDokChYM53lQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/scope-manager": "8.27.0",
"@typescript-eslint/types": "8.27.0",
"@typescript-eslint/typescript-estree": "8.27.0",
"@typescript-eslint/visitor-keys": "8.27.0",
"@typescript-eslint/scope-manager": "8.28.0",
"@typescript-eslint/types": "8.28.0",
"@typescript-eslint/typescript-estree": "8.28.0",
"@typescript-eslint/visitor-keys": "8.28.0",
"debug": "^4.3.4"
},
"engines": {
@ -2155,14 +2155,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz",
"integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.28.0.tgz",
"integrity": "sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.27.0",
"@typescript-eslint/visitor-keys": "8.27.0"
"@typescript-eslint/types": "8.28.0",
"@typescript-eslint/visitor-keys": "8.28.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -2173,14 +2173,14 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.27.0.tgz",
"integrity": "sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.28.0.tgz",
"integrity": "sha512-oRoXu2v0Rsy/VoOGhtWrOKDiIehvI+YNrDk5Oqj40Mwm0Yt01FC/Q7nFqg088d3yAsR1ZcZFVfPCTTFCe/KPwg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/typescript-estree": "8.27.0",
"@typescript-eslint/utils": "8.27.0",
"@typescript-eslint/typescript-estree": "8.28.0",
"@typescript-eslint/utils": "8.28.0",
"debug": "^4.3.4",
"ts-api-utils": "^2.0.1"
},
@ -2197,9 +2197,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.27.0.tgz",
"integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.28.0.tgz",
"integrity": "sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==",
"dev": true,
"license": "MIT",
"engines": {
@ -2211,14 +2211,14 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz",
"integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.28.0.tgz",
"integrity": "sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.27.0",
"@typescript-eslint/visitor-keys": "8.27.0",
"@typescript-eslint/types": "8.28.0",
"@typescript-eslint/visitor-keys": "8.28.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@ -2264,16 +2264,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.27.0.tgz",
"integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.28.0.tgz",
"integrity": "sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.27.0",
"@typescript-eslint/types": "8.27.0",
"@typescript-eslint/typescript-estree": "8.27.0"
"@typescript-eslint/scope-manager": "8.28.0",
"@typescript-eslint/types": "8.28.0",
"@typescript-eslint/typescript-estree": "8.28.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -2288,13 +2288,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz",
"integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.28.0.tgz",
"integrity": "sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.27.0",
"@typescript-eslint/types": "8.28.0",
"eslint-visitor-keys": "^4.2.0"
},
"engines": {
@ -4915,9 +4915,9 @@
}
},
"node_modules/eslint-config-cityssm": {
"version": "21.0.0",
"resolved": "https://registry.npmjs.org/eslint-config-cityssm/-/eslint-config-cityssm-21.0.0.tgz",
"integrity": "sha512-9pwKXgD9VkZSqS9usa/pQzEmlE5oHY2M6dD7feiCA0wPW85qWP4w5b/A44Nhb+0WHi6TzjV+WSMIgSjC2nTR9A==",
"version": "22.1.0",
"resolved": "https://registry.npmjs.org/eslint-config-cityssm/-/eslint-config-cityssm-22.1.0.tgz",
"integrity": "sha512-JfF7dzleImnd78sM0+NpvZpKgT+NvB4SlFXd/gXf0t1F1HQbaZftEL7zJ9eATWklF9lcj6tiYMDaZekHVuFaJw==",
"dev": true,
"license": "Unlicense",
"dependencies": {
@ -4929,11 +4929,11 @@
"@eslint/markdown": "^6.3.0",
"eslint": "9.23.0",
"eslint-config-love": "^119.0.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsdoc": "^50.6.9",
"eslint-plugin-n": "^17.16.2",
"eslint-plugin-no-secrets": "^2.2.1",
"eslint-plugin-no-unsanitized": "^4.1.2",
"eslint-plugin-perfectionist": "^4.10.1",
"eslint-plugin-promise": "^7.2.1",
"eslint-plugin-regexp": "^2.7.0",
"eslint-plugin-security": "^3.0.1",
@ -4941,7 +4941,7 @@
"eslint-plugin-unicorn": "^58.0.0",
"eslint-plugin-woke": "github:cityssm/eslint-plugin-woke",
"eslint-plugin-write-good-comments": "^0.2.0",
"typescript-eslint": "^8.27.0"
"typescript-eslint": "^8.28.0"
}
},
"node_modules/eslint-config-love": {
@ -5241,6 +5241,24 @@
"eslint": "^8 || ^9"
}
},
"node_modules/eslint-plugin-perfectionist": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.10.1.tgz",
"integrity": "sha512-GXwFfL47RfBLZRGQdrvGZw9Ali2T2GPW8p4Gyj2fyWQ9396R/HgJMf0m9kn7D6WXRwrINfTDGLS+QYIeok9qEg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "^8.26.0",
"@typescript-eslint/utils": "^8.26.0",
"natural-orderby": "^5.0.0"
},
"engines": {
"node": "^18.0.0 || >=20.0.0"
},
"peerDependencies": {
"eslint": ">=8.45.0"
}
},
"node_modules/eslint-plugin-promise": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-7.2.1.tgz",
@ -9187,6 +9205,16 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
"node_modules/natural-orderby": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-5.0.0.tgz",
"integrity": "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
@ -12082,15 +12110,15 @@
}
},
"node_modules/typescript-eslint": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.27.0.tgz",
"integrity": "sha512-ZZ/8+Y0rRUMuW1gJaPtLWe4ryHbsPLzzibk5Sq+IFa2aOH1Vo0gPr1fbA6pOnzBke7zC2Da4w8AyCgxKXo3lqA==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.28.0.tgz",
"integrity": "sha512-jfZtxJoHm59bvoCMYCe2BM0/baMswRhMmYhy+w6VfcyHrjxZ0OJe0tGasydCpIpA+A/WIJhTyZfb3EtwNC/kHQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.27.0",
"@typescript-eslint/parser": "8.27.0",
"@typescript-eslint/utils": "8.27.0"
"@typescript-eslint/eslint-plugin": "8.28.0",
"@typescript-eslint/parser": "8.28.0",
"@typescript-eslint/utils": "8.28.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"

View File

@ -90,7 +90,7 @@
"axe-core": "^4.10.3",
"cypress": "^14.2.0",
"cypress-axe": "^1.6.0",
"eslint-config-cityssm": "^21.0.0",
"eslint-config-cityssm": "^22.1.0",
"nodemon": "^3.1.9",
"prettier-config-cityssm": "^1.0.0"
},

View File

@ -148,6 +148,7 @@ span.button.is-static {
}
.input[type='number'] {
appearance: textfield;
-moz-appearance: textfield;
&::-webkit-inner-spin-button,

View File

@ -225,8 +225,8 @@ export interface ContractField extends ContractTypeField, Record {
export interface Contract extends Record {
contractId: number;
contractTypeId: number;
contractType?: string;
isPreneed?: boolean;
contractType: string;
isPreneed: boolean;
printEJS?: string;
burialSiteId?: number;
burialSiteTypeId?: number;
@ -247,10 +247,10 @@ export interface Contract extends Record {
purchaserPhoneNumber: string;
purchaserEmail: string;
purchaserRelationship: string;
funeralHomeId?: number;
funeralHomeId: number | null;
funeralDirectorName: string;
funeralHomeName: string | null;
funeralHomeKey?: string;
funeralHomeName?: string;
funeralDirectorName?: string;
funeralHomeAddress1?: string;
funeralHomeAddress2?: string;
funeralHomeCity?: string;

View File

@ -290,8 +290,8 @@ export interface Contract extends Record {
contractId: number
contractTypeId: number
contractType?: string
isPreneed?: boolean
contractType: string
isPreneed: boolean
printEJS?: string
@ -319,10 +319,11 @@ export interface Contract extends Record {
purchaserEmail: string
purchaserRelationship: string
funeralHomeId?: number
funeralHomeId: number | null
funeralDirectorName: string
funeralHomeName: string | null
funeralHomeKey?: string
funeralHomeName?: string
funeralDirectorName?: string
funeralHomeAddress1?: string
funeralHomeAddress2?: string
funeralHomeCity?: string