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 = { export const config = {
application: {},
session: {},
reverseProxy: {},
users: {},
aliases: {}, aliases: {},
application: {},
reverseProxy: {},
session: {},
settings: { settings: {
fees: {}, adminCleanup: {},
burialSites: {}, burialSites: {},
contracts: {}, contracts: {},
workOrders: {},
adminCleanup: {},
printPdf: {},
dynamicsGP: { dynamicsGP: {
integrationIsEnabled: false integrationIsEnabled: false
} },
} fees: {},
printPdf: {},
workOrders: {}
},
users: {}
}; };
export default config; export default config;

View File

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

View File

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

View File

@ -13,13 +13,13 @@ export const configDefaultValues = {
'reverseProxy.disableEtag': false, 'reverseProxy.disableEtag': false,
'reverseProxy.urlPrefix': '', 'reverseProxy.urlPrefix': '',
'session.cookieName': 'sunrise-user-sid', 'session.cookieName': 'sunrise-user-sid',
'session.secret': 'cityssm/sunrise',
'session.maxAgeMillis': hoursToMillis(1),
'session.doKeepAlive': false, 'session.doKeepAlive': false,
'users.testing': [], 'session.maxAgeMillis': hoursToMillis(1),
'session.secret': 'cityssm/sunrise',
'users.canLogin': ['administrator'], 'users.canLogin': ['administrator'],
'users.canUpdate': [], 'users.canUpdate': [],
'users.isAdmin': ['administrator'], 'users.isAdmin': ['administrator'],
'users.testing': [],
'aliases.externalReceiptNumber': 'External Receipt Number', 'aliases.externalReceiptNumber': 'External Receipt Number',
'aliases.workOrderOpenDate': 'Order Date', 'aliases.workOrderOpenDate': 'Order Date',
'aliases.workOrderCloseDate': 'Completion 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 type { config as MSSQLConfig } from 'mssql'
import { hoursToMillis } from '@cityssm/to-millis'
import type { import type {
ConfigActiveDirectory, ConfigActiveDirectory,
ConfigBurialSiteNameSegments, ConfigBurialSiteNameSegments,
@ -26,14 +27,14 @@ export const configDefaultValues = {
'reverseProxy.urlPrefix': '', 'reverseProxy.urlPrefix': '',
'session.cookieName': 'sunrise-user-sid', 'session.cookieName': 'sunrise-user-sid',
'session.secret': 'cityssm/sunrise',
'session.maxAgeMillis': hoursToMillis(1),
'session.doKeepAlive': false, 'session.doKeepAlive': false,
'session.maxAgeMillis': hoursToMillis(1),
'session.secret': 'cityssm/sunrise',
'users.testing': [] as string[],
'users.canLogin': ['administrator'], 'users.canLogin': ['administrator'],
'users.canUpdate': [] as string[], 'users.canUpdate': [] as string[],
'users.isAdmin': ['administrator'], 'users.isAdmin': ['administrator'],
'users.testing': [] as string[],
'aliases.externalReceiptNumber': 'External Receipt Number', 'aliases.externalReceiptNumber': 'External Receipt Number',
'aliases.workOrderOpenDate': 'Order Date', '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 { PoolConnection } from 'better-sqlite-pool';
import { type DateString, type TimeString } from '@cityssm/utils-datetime';
export interface AddContractForm { export interface AddContractForm {
contractTypeId: string | number;
burialSiteId: string | number;
contractStartDateString: DateString | '';
contractEndDateString: DateString | '';
contractTypeFieldIds?: string;
[fieldValue_contractTypeFieldId: `fieldValue_${string}`]: unknown; [fieldValue_contractTypeFieldId: `fieldValue_${string}`]: unknown;
purchaserName?: string; birthDateString?: '' | DateString;
purchaserAddress1?: string; birthPlace?: string;
purchaserAddress2?: string; burialSiteId: number | string;
purchaserCity?: string; committalTypeId?: number | string;
purchaserProvince?: string; contractEndDateString: '' | DateString;
purchaserPostalCode?: string; contractStartDateString: '' | DateString;
purchaserPhoneNumber?: string; contractTypeFieldIds?: string;
purchaserEmail?: string; contractTypeId: number | string;
purchaserRelationship?: string; deathAge?: string;
funeralHomeId?: string | number; deathAgePeriod?: string;
funeralDirectorName?: string; deathDateString?: '' | DateString;
funeralDateString?: DateString | ''; deathPlace?: string;
funeralTimeString?: TimeString | '';
committalTypeId?: string | number;
deceasedName?: string;
deceasedAddress1?: string; deceasedAddress1?: string;
deceasedAddress2?: string; deceasedAddress2?: string;
deceasedCity?: string; deceasedCity?: string;
deceasedProvince?: string; deceasedName?: string;
deceasedPostalCode?: string; deceasedPostalCode?: string;
birthDateString?: DateString | ''; deceasedProvince?: string;
birthPlace?: string; funeralDateString?: '' | DateString;
deathDateString?: DateString | ''; funeralDirectorName?: string;
deathPlace?: string; funeralHomeId?: number | string;
deathAge?: string; funeralTimeString?: '' | TimeString;
deathAgePeriod?: string; intermentContainerTypeId?: number | string;
intermentContainerTypeId?: string | number; 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>; 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 { import {
type DateString, type DateString,
type TimeString,
dateStringToInteger, dateStringToInteger,
type TimeString,
timeStringToInteger timeStringToInteger
} from '@cityssm/utils-datetime' } from '@cityssm/utils-datetime'
import type { PoolConnection } from 'better-sqlite-pool'
import addOrUpdateContractField from './addOrUpdateContractField.js' import addOrUpdateContractField from './addOrUpdateContractField.js'
import { acquireConnection } from './pool.js' import { acquireConnection } from './pool.js'
export interface AddContractForm { export interface AddContractForm {
contractTypeId: string | number
burialSiteId: string | number
contractStartDateString: DateString | ''
contractEndDateString: DateString | ''
contractTypeFieldIds?: string
[fieldValue_contractTypeFieldId: `fieldValue_${string}`]: unknown [fieldValue_contractTypeFieldId: `fieldValue_${string}`]: unknown
birthDateString?: '' | DateString
purchaserName?: string birthPlace?: string
purchaserAddress1?: string burialSiteId: number | string
purchaserAddress2?: string
purchaserCity?: string
purchaserProvince?: string
purchaserPostalCode?: string
purchaserPhoneNumber?: string
purchaserEmail?: string
purchaserRelationship?: string
funeralHomeId?: string | number committalTypeId?: number | string
funeralDirectorName?: string contractEndDateString: '' | DateString
funeralDateString?: DateString | ''
funeralTimeString?: TimeString | '' contractStartDateString: '' | DateString
committalTypeId?: string | number contractTypeFieldIds?: string
contractTypeId: number | string
deathAge?: string
deathAgePeriod?: string
deathDateString?: '' | DateString
deathPlace?: string
deceasedName?: string
deceasedAddress1?: string deceasedAddress1?: string
deceasedAddress2?: string deceasedAddress2?: string
deceasedCity?: string deceasedCity?: string
deceasedProvince?: string deceasedName?: string
deceasedPostalCode?: string deceasedPostalCode?: string
deceasedProvince?: string
birthDateString?: DateString | '' funeralDateString?: '' | DateString
birthPlace?: string funeralDirectorName?: string
deathDateString?: DateString | '' funeralHomeId?: number | string
deathPlace?: string funeralTimeString?: '' | TimeString
deathAge?: string intermentContainerTypeId?: number | string
deathAgePeriod?: string
intermentContainerTypeId?: string | number purchaserAddress1?: string
purchaserAddress2?: string
purchaserCity?: string
purchaserEmail?: string
purchaserName?: string
purchaserPhoneNumber?: string
purchaserPostalCode?: string
purchaserProvince?: string
purchaserRelationship?: string
} }
// eslint-disable-next-line complexity // 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 oldContract = (await getContract(oldContractId, database));
const newContractId = await addContract({ const newContractId = await addContract({
burialSiteId: oldContract.burialSiteId ?? '', burialSiteId: oldContract.burialSiteId ?? '',
contractTypeId: oldContract.contractTypeId,
contractStartDateString: dateToString(new Date()),
contractEndDateString: '', 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, purchaserAddress1: oldContract.purchaserAddress1,
purchaserAddress2: oldContract.purchaserAddress2, purchaserAddress2: oldContract.purchaserAddress2,
purchaserCity: oldContract.purchaserCity, purchaserCity: oldContract.purchaserCity,
purchaserProvince: oldContract.purchaserProvince,
purchaserPostalCode: oldContract.purchaserPostalCode,
purchaserPhoneNumber: oldContract.purchaserPhoneNumber,
purchaserEmail: oldContract.purchaserEmail, purchaserEmail: oldContract.purchaserEmail,
purchaserRelationship: oldContract.purchaserRelationship, purchaserName: oldContract.purchaserName,
funeralHomeId: oldContract.funeralHomeId, purchaserPhoneNumber: oldContract.purchaserPhoneNumber,
funeralDirectorName: oldContract.funeralDirectorName, purchaserPostalCode: oldContract.purchaserPostalCode,
funeralDateString: oldContract.funeralDateString ?? '', purchaserProvince: oldContract.purchaserProvince,
funeralTimeString: oldContract.funeralTimeString ?? '' purchaserRelationship: oldContract.purchaserRelationship
}, user, database); }, user, database);
/* /*
* Copy Fields * Copy Fields
@ -45,19 +45,19 @@ export default async function copyContract(oldContractId, user) {
*/ */
for (const interment of oldContract.contractInterments ?? []) { for (const interment of oldContract.contractInterments ?? []) {
await addContractInterment({ await addContractInterment({
birthDateString: interment.birthDateString ?? '',
birthPlace: interment.birthPlace ?? '',
contractId: newContractId, contractId: newContractId,
deceasedName: interment.deceasedName ?? '', deathAge: interment.deathAge ?? '',
deathAgePeriod: interment.deathAgePeriod ?? '',
deathDateString: interment.deathDateString ?? '',
deathPlace: interment.deathPlace ?? '',
deceasedAddress1: interment.deceasedAddress1 ?? '', deceasedAddress1: interment.deceasedAddress1 ?? '',
deceasedAddress2: interment.deceasedAddress2 ?? '', deceasedAddress2: interment.deceasedAddress2 ?? '',
deceasedCity: interment.deceasedCity ?? '', deceasedCity: interment.deceasedCity ?? '',
deceasedProvince: interment.deceasedProvince ?? '', deceasedName: interment.deceasedName ?? '',
deceasedPostalCode: interment.deceasedPostalCode ?? '', deceasedPostalCode: interment.deceasedPostalCode ?? '',
birthDateString: interment.birthDateString ?? '', deceasedProvince: interment.deceasedProvince ?? '',
birthPlace: interment.birthPlace ?? '',
deathDateString: interment.deathDateString ?? '',
deathPlace: interment.deathPlace ?? '',
deathAge: interment.deathAge ?? '',
deathAgePeriod: interment.deathAgePeriod ?? '',
intermentContainerTypeId: interment.intermentContainerTypeId ?? '' intermentContainerTypeId: interment.intermentContainerTypeId ?? ''
}, user, database); }, user, database);
} }
@ -65,8 +65,8 @@ export default async function copyContract(oldContractId, user) {
* Add Comment * Add Comment
*/ */
await addContractComment({ await addContractComment({
contractId: newContractId, comment: `New record copied from #${oldContractId}.`,
comment: `New record copied from #${oldContractId}.` contractId: newContractId
}, user); }, user);
database.release(); database.release();
return newContractId; return newContractId;

View File

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

View File

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

View File

@ -1,62 +1,62 @@
import { clearCacheByTableName } from '../helpers/functions.cache.js' import { clearCacheByTableName } from '../helpers/functions.cache.js'
import { acquireConnection } from './pool.js' import { acquireConnection } from './pool.js'
type RecordTable = type RecordTable =
| 'BurialSiteComments'
| 'BurialSites'
| 'BurialSiteStatuses'
| 'BurialSiteTypeFields'
| 'BurialSiteTypes'
| 'Cemeteries'
| 'ContractComments'
| 'Contracts'
| 'ContractTypeFields'
| 'ContractTypes'
| 'FeeCategories' | 'FeeCategories'
| 'Fees' | 'Fees'
| 'BurialSites'
| 'BurialSiteComments'
| 'Contracts'
| 'ContractComments'
| 'BurialSiteStatuses'
| 'BurialSiteTypes'
| 'BurialSiteTypeFields'
| 'Cemeteries'
| 'FuneralHomes' | 'FuneralHomes'
| 'ContractTypes'
| 'ContractTypeFields'
| 'WorkOrders'
| 'WorkOrderComments' | 'WorkOrderComments'
| 'WorkOrderMilestones' | 'WorkOrderMilestones'
| 'WorkOrderMilestoneTypes' | 'WorkOrderMilestoneTypes'
| 'WorkOrders'
| 'WorkOrderTypes' | 'WorkOrderTypes'
const recordIdColumns = new Map<RecordTable, string>() const recordIdColumns = new Map<RecordTable, string>([
recordIdColumns.set('FeeCategories', 'feeCategoryId') ['BurialSiteComments', 'burialSiteCommentId'],
recordIdColumns.set('Fees', 'feeId') ['BurialSites', 'burialSiteId'],
recordIdColumns.set('BurialSites', 'burialSiteId') ['BurialSiteStatuses', 'burialSiteStatusId'],
recordIdColumns.set('BurialSiteComments', 'burialSiteCommentId') ['BurialSiteTypeFields', 'burialSiteTypeFieldId'],
recordIdColumns.set('Contracts', 'contractId') ['BurialSiteTypes', 'burialSiteTypeId'],
recordIdColumns.set('ContractComments', 'contractCommentId') ['Cemeteries', 'cemeteryId'],
recordIdColumns.set('BurialSiteStatuses', 'burialSiteStatusId') ['ContractComments', 'contractCommentId'],
recordIdColumns.set('BurialSiteTypes', 'burialSiteTypeId') ['Contracts', 'contractId'],
recordIdColumns.set('BurialSiteTypeFields', 'burialSiteTypeFieldId') ['ContractTypeFields', 'contractTypeFieldId'],
recordIdColumns.set('Cemeteries', 'cemeteryId') ['ContractTypes', 'contractTypeId'],
recordIdColumns.set('FuneralHomes', 'funeralHomeId') ['FeeCategories', 'feeCategoryId'],
recordIdColumns.set('ContractTypes', 'contractTypeId') ['Fees', 'feeId'],
recordIdColumns.set('ContractTypeFields', 'contractTypeFieldId') ['FuneralHomes', 'funeralHomeId'],
recordIdColumns.set('WorkOrders', 'workOrderId') ['WorkOrderComments', 'workOrderCommentId'],
recordIdColumns.set('WorkOrderComments', 'workOrderCommentId') ['WorkOrderMilestones', 'workOrderMilestoneId'],
recordIdColumns.set('WorkOrderMilestones', 'workOrderMilestoneId') ['WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId'],
recordIdColumns.set('WorkOrderMilestoneTypes', 'workOrderMilestoneTypeId') ['WorkOrders', 'workOrderId'],
recordIdColumns.set('WorkOrderTypes', 'workOrderTypeId') ['WorkOrderTypes', 'workOrderTypeId']
const relatedTables = new Map<RecordTable, string[]>()
relatedTables.set('FeeCategories', ['Fees'])
relatedTables.set('BurialSites', ['BurialSiteFields', 'BurialSiteComments'])
relatedTables.set('Contracts', [
'ContractFields',
'ContractComments'
]) ])
relatedTables.set('BurialSiteTypes', ['BurialSiteTypeFields'])
relatedTables.set('Cemeteries', ['BurialSites']) const relatedTables = new Map<RecordTable, string[]>([
relatedTables.set('ContractTypes', ['ContractTypePrints', 'ContractTypeFields']) ['BurialSites', ['BurialSiteFields', 'BurialSiteComments']],
relatedTables.set('WorkOrders', [ ['BurialSiteTypes', ['BurialSiteTypeFields']],
'WorkOrderMilestones', ['Cemeteries', ['BurialSites']],
'WorkOrderLots', ['Contracts', ['ContractFields', 'ContractComments']],
'WorkOrderContracts', ['ContractTypes', ['ContractTypePrints', 'ContractTypeFields']],
'WorkOrderComments' [
'WorkOrders',
[
'WorkOrderMilestones',
'WorkOrderLots',
'WorkOrderContracts',
'WorkOrderComments'
]
]
]) ])
export async function deleteRecord( 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 // eslint-disable-next-line security/detect-object-injection
if (simpleReports[reportName] === undefined) { if (simpleReports[reportName] === undefined) {
switch (reportName) { 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': { case 'burialSites-byBurialSiteStatusId': {
sql = `select l.burialSiteId, sql = `select l.burialSiteId,
m.cemeteryName, m.cemeteryName,
@ -79,6 +64,21 @@ export default async function getReportData(reportName, reportParameters = {}) {
sqlParameters.push(reportParameters.burialSiteStatusId); sqlParameters.push(reportParameters.burialSiteStatusId);
break; 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': { case 'burialSites-byCemeteryId': {
sql = `select l.burialSiteId, sql = `select l.burialSiteId,
m.cemeteryName, m.cemeteryName,
@ -94,6 +94,20 @@ export default async function getReportData(reportName, reportParameters = {}) {
sqlParameters.push(reportParameters.cemeteryId); sqlParameters.push(reportParameters.cemeteryId);
break; 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': { case 'contracts-current-byCemeteryId': {
sql = `select o.contractId, sql = `select o.contractId,
l.burialSiteName, l.burialSiteName,
@ -111,20 +125,6 @@ export default async function getReportData(reportName, reportParameters = {}) {
sqlParameters.push(dateToInteger(new Date()), reportParameters.cemeteryId); sqlParameters.push(dateToInteger(new Date()), reportParameters.cemeteryId);
break; 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': { case 'contractTransactions-byTransactionDateString': {
sql = `select t.contractId, t.transactionIndex, sql = `select t.contractId, t.transactionIndex,
t.transactionDate, t.transactionTime, t.transactionDate, t.transactionTime,
@ -136,6 +136,20 @@ export default async function getReportData(reportName, reportParameters = {}) {
sqlParameters.push(dateStringToInteger(reportParameters.transactionDateString)); sqlParameters.push(dateStringToInteger(reportParameters.transactionDateString));
break; 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': { case 'workOrders-open': {
sql = `select w.workOrderId, w.workOrderNumber, sql = `select w.workOrderId, w.workOrderNumber,
t.workOrderType, w.workOrderDescription, t.workOrderType, w.workOrderDescription,
@ -155,20 +169,6 @@ export default async function getReportData(reportName, reportParameters = {}) {
and w.workOrderCloseDate is null`; and w.workOrderCloseDate is null`;
break; 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: { default: {
return undefined; return undefined;
} }

View File

@ -1,6 +1,6 @@
import { import {
type DateString,
dateIntegerToString, dateIntegerToString,
type DateString,
dateStringToInteger, dateStringToInteger,
dateToInteger, dateToInteger,
timeIntegerToString timeIntegerToString
@ -8,7 +8,7 @@ import {
import { acquireConnection } from './pool.js' 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> = { const simpleReports: Record<`${string}-all` | `${string}-formatted`, string> = {
'burialSiteComments-all': 'select * from BurialSiteComments', 'burialSiteComments-all': 'select * from BurialSiteComments',
@ -61,31 +61,13 @@ const simpleReports: Record<`${string}-all` | `${string}-formatted`, string> = {
export default async function getReportData( export default async function getReportData(
reportName: string, reportName: string,
reportParameters: ReportParameters = {} reportParameters: ReportParameters = {}
): Promise<unknown[] | undefined> { ): Promise<undefined | unknown[]> {
let sql = '' let sql = ''
const sqlParameters: unknown[] = [] const sqlParameters: unknown[] = []
// eslint-disable-next-line security/detect-object-injection // eslint-disable-next-line security/detect-object-injection
if (simpleReports[reportName] === undefined) { if (simpleReports[reportName] === undefined) {
switch (reportName) { 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': { case 'burialSites-byBurialSiteStatusId': {
sql = `select l.burialSiteId, sql = `select l.burialSiteId,
m.cemeteryName, m.cemeteryName,
@ -104,6 +86,24 @@ export default async function getReportData(
break 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': { case 'burialSites-byCemeteryId': {
sql = `select l.burialSiteId, sql = `select l.burialSiteId,
m.cemeteryName, m.cemeteryName,
@ -122,6 +122,23 @@ export default async function getReportData(
break 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': { case 'contracts-current-byCemeteryId': {
sql = `select o.contractId, sql = `select o.contractId,
l.burialSiteName, l.burialSiteName,
@ -145,23 +162,6 @@ export default async function getReportData(
break 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': { case 'contractTransactions-byTransactionDateString': {
sql = `select t.contractId, t.transactionIndex, sql = `select t.contractId, t.transactionIndex,
t.transactionDate, t.transactionTime, t.transactionDate, t.transactionTime,
@ -179,6 +179,22 @@ export default async function getReportData(
break 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': { case 'workOrders-open': {
sql = `select w.workOrderId, w.workOrderNumber, sql = `select w.workOrderId, w.workOrderNumber,
t.workOrderType, w.workOrderDescription, t.workOrderType, w.workOrderDescription,
@ -200,22 +216,6 @@ export default async function getReportData(
break 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: { default: {
return undefined return undefined
} }

View File

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

View File

@ -13,6 +13,16 @@ const baseSQL = `select w.workOrderId,
from WorkOrders w from WorkOrders w
left join WorkOrderTypes t on w.workOrderTypeId = t.workOrderTypeId left join WorkOrderTypes t on w.workOrderTypeId = t.workOrderTypeId
where w.recordDelete_timeMillis is null`; 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) { async function _getWorkOrder(sql, workOrderIdOrWorkOrderNumber, options, connectedDatabase) {
const database = connectedDatabase ?? (await acquireConnection()); const database = connectedDatabase ?? (await acquireConnection());
database.function('userFn_dateIntegerToString', dateIntegerToString); database.function('userFn_dateIntegerToString', dateIntegerToString);
@ -22,22 +32,21 @@ async function _getWorkOrder(sql, workOrderIdOrWorkOrderNumber, options, connect
const burialSiteResults = await getBurialSites({ const burialSiteResults = await getBurialSites({
workOrderId: workOrder.workOrderId workOrderId: workOrder.workOrderId
}, { }, {
includeContractCount: false,
limit: -1, limit: -1,
offset: 0, offset: 0
includeContractCount: false
}, database); }, database);
workOrder.workOrderBurialSites = burialSiteResults.burialSites; workOrder.workOrderBurialSites = burialSiteResults.burialSites;
const workOrderContractsResults = await getContracts({ const workOrderContractsResults = await getContracts({
workOrderId: workOrder.workOrderId workOrderId: workOrder.workOrderId
}, { }, {
limit: -1,
offset: 0,
includeInterments: true,
includeFees: false, includeFees: false,
includeTransactions: false includeInterments: true,
includeTransactions: false,
limit: -1,
offset: 0
}, database); }, database);
workOrder.workOrderContracts = workOrder.workOrderContracts = workOrderContractsResults.contracts;
workOrderContractsResults.contracts;
} }
if (options.includeComments) { if (options.includeComments) {
workOrder.workOrderComments = await getWorkOrderComments(workOrder.workOrderId, database); workOrder.workOrderComments = await getWorkOrderComments(workOrder.workOrderId, database);
@ -56,13 +65,3 @@ async function _getWorkOrder(sql, workOrderIdOrWorkOrderNumber, options, connect
} }
return workOrder; 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 type { PoolConnection } from 'better-sqlite-pool'
import { dateIntegerToString } from '@cityssm/utils-datetime'
import type { WorkOrder } from '../types/recordTypes.js' import type { WorkOrder } from '../types/recordTypes.js'
import getBurialSites from './getBurialSites.js' import getBurialSites from './getBurialSites.js'
@ -25,19 +26,46 @@ const baseSQL = `select w.workOrderId,
left join WorkOrderTypes t on w.workOrderTypeId = t.workOrderTypeId left join WorkOrderTypes t on w.workOrderTypeId = t.workOrderTypeId
where w.recordDelete_timeMillis is null` 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( async function _getWorkOrder(
sql: string, sql: string,
workOrderIdOrWorkOrderNumber: number | string, workOrderIdOrWorkOrderNumber: number | string,
options: WorkOrderOptions, options: WorkOrderOptions,
connectedDatabase?: PoolConnection connectedDatabase?: PoolConnection
): Promise<WorkOrder | undefined> { ): Promise<undefined | WorkOrder> {
const database = connectedDatabase ?? (await acquireConnection()) const database = connectedDatabase ?? (await acquireConnection())
database.function('userFn_dateIntegerToString', dateIntegerToString) database.function('userFn_dateIntegerToString', dateIntegerToString)
const workOrder = database.prepare(sql).get(workOrderIdOrWorkOrderNumber) as const workOrder = database.prepare(sql).get(workOrderIdOrWorkOrderNumber) as
| WorkOrder
| undefined | undefined
| WorkOrder
if (workOrder !== undefined) { if (workOrder !== undefined) {
if (options.includeBurialSites) { if (options.includeBurialSites) {
@ -46,9 +74,9 @@ async function _getWorkOrder(
workOrderId: workOrder.workOrderId workOrderId: workOrder.workOrderId
}, },
{ {
includeContractCount: false,
limit: -1, limit: -1,
offset: 0, offset: 0
includeContractCount: false
}, },
database database
) )
@ -60,17 +88,16 @@ async function _getWorkOrder(
workOrderId: workOrder.workOrderId workOrderId: workOrder.workOrderId
}, },
{ {
limit: -1,
offset: 0,
includeInterments: true,
includeFees: false, includeFees: false,
includeTransactions: false includeInterments: true,
includeTransactions: false,
limit: -1,
offset: 0
}, },
database database
) )
workOrder.workOrderContracts = workOrder.workOrderContracts = workOrderContractsResults.contracts
workOrderContractsResults.contracts
} }
if (options.includeComments) { if (options.includeComments) {
@ -100,30 +127,3 @@ async function _getWorkOrder(
return workOrder 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 getNextBurialSiteId(burialSiteId: number): Promise<number | undefined>;
export declare function getPreviousBurialSiteId(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: { export declare function buildBurialSiteName(cemeteryKey: string | undefined, segments: {
burialSiteNameSegment1?: string; burialSiteNameSegment1?: string;
burialSiteNameSegment2?: string; burialSiteNameSegment2?: string;

View File

@ -15,19 +15,32 @@ const cacheOptions = {
}; };
const previousBurialSiteIdCache = new NodeCache(cacheOptions); const previousBurialSiteIdCache = new NodeCache(cacheOptions);
const nextBurialSiteIdCache = new NodeCache(cacheOptions); const nextBurialSiteIdCache = new NodeCache(cacheOptions);
function cacheBurialSiteIds(burialSiteId, nextBurialSiteId, relayMessage = true) { export function clearNextPreviousBurialSiteIdCache(burialSiteId = -1, relayMessage = true) {
previousBurialSiteIdCache.set(nextBurialSiteId, burialSiteId); if (burialSiteId === -1) {
nextBurialSiteIdCache.set(burialSiteId, nextBurialSiteId); 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 { try {
if (relayMessage && cluster.isWorker && process.send !== undefined) { if (relayMessage && cluster.isWorker && process.send !== undefined) {
const workerMessage = { const workerMessage = {
messageType: 'cacheBurialSiteIds',
burialSiteId, burialSiteId,
nextBurialSiteId, // eslint-disable-next-line no-secrets/no-secrets
timeMillis: Date.now(), messageType: 'clearNextPreviousBurialSiteIdCache',
pid: process.pid 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); process.send(workerMessage);
} }
} }
@ -55,32 +68,19 @@ export async function getPreviousBurialSiteId(burialSiteId) {
} }
return previousBurialSiteId; return previousBurialSiteId;
} }
export function clearNextPreviousBurialSiteIdCache(burialSiteId = -1, relayMessage = true) { function cacheBurialSiteIds(burialSiteId, nextBurialSiteId, relayMessage = true) {
if (burialSiteId === -1) { previousBurialSiteIdCache.set(nextBurialSiteId, burialSiteId);
previousBurialSiteIdCache.flushAll(); nextBurialSiteIdCache.set(burialSiteId, nextBurialSiteId);
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 { try {
if (relayMessage && cluster.isWorker && process.send !== undefined) { if (relayMessage && cluster.isWorker && process.send !== undefined) {
const workerMessage = { const workerMessage = {
// eslint-disable-next-line no-secrets/no-secrets
messageType: 'clearNextPreviousBurialSiteIdCache',
burialSiteId, burialSiteId,
timeMillis: Date.now(), messageType: 'cacheBurialSiteIds',
pid: process.pid 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); process.send(workerMessage);
} }
} }

View File

@ -7,14 +7,14 @@ import { minutesToSeconds } from '@cityssm/to-millis'
import Debug from 'debug' import Debug from 'debug'
import NodeCache from 'node-cache' import NodeCache from 'node-cache'
import getNextBurialSiteIdFromDatabase from '../database/getNextBurialSiteId.js'
import getPreviousBurialSiteIdFromDatabase from '../database/getPreviousBurialSiteId.js'
import { DEBUG_NAMESPACE } from '../debug.config.js'
import type { import type {
CacheBurialSiteIdsWorkerMessage, CacheBurialSiteIdsWorkerMessage,
ClearNextPreviousBurialSiteIdsCacheWorkerMessage ClearNextPreviousBurialSiteIdsCacheWorkerMessage
} from '../types/applicationTypes.js' } from '../types/applicationTypes.js'
import getNextBurialSiteIdFromDatabase from '../database/getNextBurialSiteId.js'
import getPreviousBurialSiteIdFromDatabase from '../database/getPreviousBurialSiteId.js'
import { DEBUG_NAMESPACE } from '../debug.config.js'
import { getConfigProperty } from './config.helpers.js' import { getConfigProperty } from './config.helpers.js'
const debug = Debug(`${DEBUG_NAMESPACE}:burialSites.helpers:${process.pid}`) const debug = Debug(`${DEBUG_NAMESPACE}:burialSites.helpers:${process.pid}`)
@ -28,26 +28,44 @@ const previousBurialSiteIdCache = new NodeCache(cacheOptions)
const nextBurialSiteIdCache = new NodeCache(cacheOptions) const nextBurialSiteIdCache = new NodeCache(cacheOptions)
function cacheBurialSiteIds( export function clearNextPreviousBurialSiteIdCache(
burialSiteId: number, burialSiteId = -1,
nextBurialSiteId: number,
relayMessage = true relayMessage = true
): void { ): void {
previousBurialSiteIdCache.set(nextBurialSiteId, burialSiteId) if (burialSiteId === -1) {
nextBurialSiteIdCache.set(burialSiteId, nextBurialSiteId) 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 { try {
if (relayMessage && cluster.isWorker && process.send !== undefined) { if (relayMessage && cluster.isWorker && process.send !== undefined) {
const workerMessage: CacheBurialSiteIdsWorkerMessage = { const workerMessage: ClearNextPreviousBurialSiteIdsCacheWorkerMessage = {
messageType: 'cacheBurialSiteIds',
burialSiteId, burialSiteId,
nextBurialSiteId, // eslint-disable-next-line no-secrets/no-secrets
timeMillis: Date.now(), messageType: 'clearNextPreviousBurialSiteIdCache',
pid: process.pid pid: process.pid,
timeMillis: Date.now()
} }
debug( debug(
`Sending cache burial site ids from worker: (${burialSiteId}, ${nextBurialSiteId})` `Sending clear next/previous burial site cache from worker: ${burialSiteId}`
) )
process.send(workerMessage) process.send(workerMessage)
@ -91,44 +109,26 @@ export async function getPreviousBurialSiteId(
return previousBurialSiteId return previousBurialSiteId
} }
export function clearNextPreviousBurialSiteIdCache( function cacheBurialSiteIds(
burialSiteId = -1, burialSiteId: number,
nextBurialSiteId: number,
relayMessage = true relayMessage = true
): void { ): void {
if (burialSiteId === -1) { previousBurialSiteIdCache.set(nextBurialSiteId, burialSiteId)
previousBurialSiteIdCache.flushAll() nextBurialSiteIdCache.set(burialSiteId, nextBurialSiteId)
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 { try {
if (relayMessage && cluster.isWorker && process.send !== undefined) { if (relayMessage && cluster.isWorker && process.send !== undefined) {
const workerMessage: ClearNextPreviousBurialSiteIdsCacheWorkerMessage = { const workerMessage: CacheBurialSiteIdsWorkerMessage = {
// eslint-disable-next-line no-secrets/no-secrets
messageType: 'clearNextPreviousBurialSiteIdCache',
burialSiteId, burialSiteId,
timeMillis: Date.now(), messageType: 'cacheBurialSiteIds',
pid: process.pid nextBurialSiteId,
pid: process.pid,
timeMillis: Date.now()
} }
debug( debug(
`Sending clear next/previous burial site cache from worker: ${burialSiteId}` `Sending cache burial site ids from worker: (${burialSiteId}, ${nextBurialSiteId})`
) )
process.send(workerMessage) process.send(workerMessage)
@ -179,8 +179,8 @@ process.on(
'message', 'message',
( (
message: message:
| ClearNextPreviousBurialSiteIdsCacheWorkerMessage
| CacheBurialSiteIdsWorkerMessage | CacheBurialSiteIdsWorkerMessage
| ClearNextPreviousBurialSiteIdsCacheWorkerMessage
) => { ) => {
if (message.pid !== process.pid) { if (message.pid !== process.pid) {
switch (message.messageType) { 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 getApiKey(userName: string): Promise<string>;
export declare function getApiKeyFromUser(user: User): Promise<string>; export declare function getApiKeyFromUser(user: User): Promise<string>;
export declare function getUserNameFromApiKey(apiKey: string): Promise<string | undefined>; 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 debug = Debug(`${DEBUG_NAMESPACE}:functions.api`);
const apiKeyPath = 'data/apiKeys.json'; const apiKeyPath = 'data/apiKeys.json';
let apiKeys; 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) { export async function getApiKey(userName) {
if (apiKeys === undefined) { if (apiKeys === undefined) {
await loadApiKeys(); await loadApiKeys();
@ -53,3 +28,28 @@ export async function getUserNameFromApiKey(apiKey) {
} }
return undefined; 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' const apiKeyPath = 'data/apiKeys.json'
let apiKeys: Record<string, string> | undefined 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> { export async function getApiKey(userName: string): Promise<string> {
if (apiKeys === undefined) { if (apiKeys === undefined) {
await loadApiKeys() await loadApiKeys()
@ -68,3 +41,30 @@ export async function getUserNameFromApiKey(
return undefined 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", "axe-core": "^4.10.3",
"cypress": "^14.2.0", "cypress": "^14.2.0",
"cypress-axe": "^1.6.0", "cypress-axe": "^1.6.0",
"eslint-config-cityssm": "^21.0.0", "eslint-config-cityssm": "^22.1.0",
"nodemon": "^3.1.9", "nodemon": "^3.1.9",
"prettier-config-cityssm": "^1.0.0" "prettier-config-cityssm": "^1.0.0"
}, },
@ -2100,17 +2100,17 @@
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.27.0", "version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.28.0.tgz",
"integrity": "sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==", "integrity": "sha512-lvFK3TCGAHsItNdWZ/1FkvpzCxTHUVuFrdnOGLMa0GGCFIbCgQWVk3CzCGdA7kM3qGVc+dfW9tr0Z/sHnGDFyg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.27.0", "@typescript-eslint/scope-manager": "8.28.0",
"@typescript-eslint/type-utils": "8.27.0", "@typescript-eslint/type-utils": "8.28.0",
"@typescript-eslint/utils": "8.27.0", "@typescript-eslint/utils": "8.28.0",
"@typescript-eslint/visitor-keys": "8.27.0", "@typescript-eslint/visitor-keys": "8.28.0",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^5.3.1", "ignore": "^5.3.1",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
@ -2130,16 +2130,16 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.27.0", "version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.27.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.28.0.tgz",
"integrity": "sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==", "integrity": "sha512-LPcw1yHD3ToaDEoljFEfQ9j2xShY367h7FZ1sq5NJT9I3yj4LHer1Xd1yRSOdYy9BpsrxU7R+eoDokChYM53lQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.27.0", "@typescript-eslint/scope-manager": "8.28.0",
"@typescript-eslint/types": "8.27.0", "@typescript-eslint/types": "8.28.0",
"@typescript-eslint/typescript-estree": "8.27.0", "@typescript-eslint/typescript-estree": "8.28.0",
"@typescript-eslint/visitor-keys": "8.27.0", "@typescript-eslint/visitor-keys": "8.28.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@ -2155,14 +2155,14 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.27.0", "version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.28.0.tgz",
"integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==", "integrity": "sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.27.0", "@typescript-eslint/types": "8.28.0",
"@typescript-eslint/visitor-keys": "8.27.0" "@typescript-eslint/visitor-keys": "8.28.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -2173,14 +2173,14 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.27.0", "version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.27.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.28.0.tgz",
"integrity": "sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==", "integrity": "sha512-oRoXu2v0Rsy/VoOGhtWrOKDiIehvI+YNrDk5Oqj40Mwm0Yt01FC/Q7nFqg088d3yAsR1ZcZFVfPCTTFCe/KPwg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/typescript-estree": "8.27.0", "@typescript-eslint/typescript-estree": "8.28.0",
"@typescript-eslint/utils": "8.27.0", "@typescript-eslint/utils": "8.28.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^2.0.1" "ts-api-utils": "^2.0.1"
}, },
@ -2197,9 +2197,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.27.0", "version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.27.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.28.0.tgz",
"integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==", "integrity": "sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -2211,14 +2211,14 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.27.0", "version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.28.0.tgz",
"integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==", "integrity": "sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.27.0", "@typescript-eslint/types": "8.28.0",
"@typescript-eslint/visitor-keys": "8.27.0", "@typescript-eslint/visitor-keys": "8.28.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -2264,16 +2264,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.27.0", "version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.27.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.28.0.tgz",
"integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==", "integrity": "sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.4.0", "@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.27.0", "@typescript-eslint/scope-manager": "8.28.0",
"@typescript-eslint/types": "8.27.0", "@typescript-eslint/types": "8.28.0",
"@typescript-eslint/typescript-estree": "8.27.0" "@typescript-eslint/typescript-estree": "8.28.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -2288,13 +2288,13 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.27.0", "version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.28.0.tgz",
"integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==", "integrity": "sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.27.0", "@typescript-eslint/types": "8.28.0",
"eslint-visitor-keys": "^4.2.0" "eslint-visitor-keys": "^4.2.0"
}, },
"engines": { "engines": {
@ -4915,9 +4915,9 @@
} }
}, },
"node_modules/eslint-config-cityssm": { "node_modules/eslint-config-cityssm": {
"version": "21.0.0", "version": "22.1.0",
"resolved": "https://registry.npmjs.org/eslint-config-cityssm/-/eslint-config-cityssm-21.0.0.tgz", "resolved": "https://registry.npmjs.org/eslint-config-cityssm/-/eslint-config-cityssm-22.1.0.tgz",
"integrity": "sha512-9pwKXgD9VkZSqS9usa/pQzEmlE5oHY2M6dD7feiCA0wPW85qWP4w5b/A44Nhb+0WHi6TzjV+WSMIgSjC2nTR9A==", "integrity": "sha512-JfF7dzleImnd78sM0+NpvZpKgT+NvB4SlFXd/gXf0t1F1HQbaZftEL7zJ9eATWklF9lcj6tiYMDaZekHVuFaJw==",
"dev": true, "dev": true,
"license": "Unlicense", "license": "Unlicense",
"dependencies": { "dependencies": {
@ -4929,11 +4929,11 @@
"@eslint/markdown": "^6.3.0", "@eslint/markdown": "^6.3.0",
"eslint": "9.23.0", "eslint": "9.23.0",
"eslint-config-love": "^119.0.0", "eslint-config-love": "^119.0.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsdoc": "^50.6.9", "eslint-plugin-jsdoc": "^50.6.9",
"eslint-plugin-n": "^17.16.2", "eslint-plugin-n": "^17.16.2",
"eslint-plugin-no-secrets": "^2.2.1", "eslint-plugin-no-secrets": "^2.2.1",
"eslint-plugin-no-unsanitized": "^4.1.2", "eslint-plugin-no-unsanitized": "^4.1.2",
"eslint-plugin-perfectionist": "^4.10.1",
"eslint-plugin-promise": "^7.2.1", "eslint-plugin-promise": "^7.2.1",
"eslint-plugin-regexp": "^2.7.0", "eslint-plugin-regexp": "^2.7.0",
"eslint-plugin-security": "^3.0.1", "eslint-plugin-security": "^3.0.1",
@ -4941,7 +4941,7 @@
"eslint-plugin-unicorn": "^58.0.0", "eslint-plugin-unicorn": "^58.0.0",
"eslint-plugin-woke": "github:cityssm/eslint-plugin-woke", "eslint-plugin-woke": "github:cityssm/eslint-plugin-woke",
"eslint-plugin-write-good-comments": "^0.2.0", "eslint-plugin-write-good-comments": "^0.2.0",
"typescript-eslint": "^8.27.0" "typescript-eslint": "^8.28.0"
} }
}, },
"node_modules/eslint-config-love": { "node_modules/eslint-config-love": {
@ -5241,6 +5241,24 @@
"eslint": "^8 || ^9" "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": { "node_modules/eslint-plugin-promise": {
"version": "7.2.1", "version": "7.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-7.2.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-7.2.1.tgz",
@ -9187,6 +9205,16 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true "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": { "node_modules/negotiator": {
"version": "0.6.3", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
@ -12082,15 +12110,15 @@
} }
}, },
"node_modules/typescript-eslint": { "node_modules/typescript-eslint": {
"version": "8.27.0", "version": "8.28.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.27.0.tgz", "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.28.0.tgz",
"integrity": "sha512-ZZ/8+Y0rRUMuW1gJaPtLWe4ryHbsPLzzibk5Sq+IFa2aOH1Vo0gPr1fbA6pOnzBke7zC2Da4w8AyCgxKXo3lqA==", "integrity": "sha512-jfZtxJoHm59bvoCMYCe2BM0/baMswRhMmYhy+w6VfcyHrjxZ0OJe0tGasydCpIpA+A/WIJhTyZfb3EtwNC/kHQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/eslint-plugin": "8.27.0", "@typescript-eslint/eslint-plugin": "8.28.0",
"@typescript-eslint/parser": "8.27.0", "@typescript-eslint/parser": "8.28.0",
"@typescript-eslint/utils": "8.27.0" "@typescript-eslint/utils": "8.28.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"

View File

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

View File

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

View File

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

View File

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