delete burial site and cemetery protection

pull/3/head
Dan Gowans 2025-03-25 14:03:22 -04:00
parent 7ccc56d5e0
commit beb57e70ab
38 changed files with 458 additions and 167 deletions

View File

@ -2,8 +2,8 @@ import { defineConfig } from 'cypress';
export default defineConfig({ export default defineConfig({
e2e: { e2e: {
baseUrl: 'http://localhost:9000', baseUrl: 'http://localhost:9000',
projectId: '26a4bi',
specPattern: 'cypress/e2e/**/*.cy.js', specPattern: 'cypress/e2e/**/*.cy.js',
supportFile: false, supportFile: false
projectId: '26a4bi'
} }
}); });

View File

@ -3,8 +3,8 @@ import { defineConfig } from 'cypress'
export default defineConfig({ export default defineConfig({
e2e: { e2e: {
baseUrl: 'http://localhost:9000', baseUrl: 'http://localhost:9000',
projectId: '26a4bi',
specPattern: 'cypress/e2e/**/*.cy.js', specPattern: 'cypress/e2e/**/*.cy.js',
supportFile: false, supportFile: false
projectId: '26a4bi'
} }
}) })

View File

@ -4,9 +4,9 @@ export interface AddBurialSiteForm {
burialSiteNameSegment3?: string; burialSiteNameSegment3?: string;
burialSiteNameSegment4?: string; burialSiteNameSegment4?: string;
burialSiteNameSegment5?: string; burialSiteNameSegment5?: string;
burialSiteTypeId: string | number; burialSiteStatusId: number | string;
burialSiteStatusId: string | number; burialSiteTypeId: number | string;
cemeteryId: string | number; cemeteryId: number | string;
cemeterySvgId: string; cemeterySvgId: string;
burialSiteLatitude: string; burialSiteLatitude: string;
burialSiteLongitude: string; burialSiteLongitude: string;

View File

@ -11,16 +11,17 @@ export interface AddBurialSiteForm {
burialSiteNameSegment4?: string burialSiteNameSegment4?: string
burialSiteNameSegment5?: string burialSiteNameSegment5?: string
burialSiteTypeId: string | number burialSiteStatusId: number | string
burialSiteStatusId: string | number burialSiteTypeId: number | string
cemeteryId: string | number cemeteryId: number | string
cemeterySvgId: string cemeterySvgId: string
burialSiteLatitude: string burialSiteLatitude: string
burialSiteLongitude: string burialSiteLongitude: string
burialSiteTypeFieldIds?: string burialSiteTypeFieldIds?: string
[fieldValue_burialSiteTypeFieldId: string]: unknown [fieldValue_burialSiteTypeFieldId: string]: unknown
} }

View File

@ -1,15 +1,15 @@
export interface AddCemeteryForm { export interface AddCemeteryForm {
cemeteryName: string;
cemeteryKey: string;
cemeteryDescription: string; cemeteryDescription: string;
cemeterySvg: string; cemeteryKey: string;
cemeteryName: string;
cemeteryLatitude: string; cemeteryLatitude: string;
cemeteryLongitude: string; cemeteryLongitude: string;
cemeterySvg: string;
cemeteryAddress1: string; cemeteryAddress1: string;
cemeteryAddress2: string; cemeteryAddress2: string;
cemeteryCity: string; cemeteryCity: string;
cemeteryProvince: string;
cemeteryPostalCode: string; cemeteryPostalCode: string;
cemeteryProvince: string;
cemeteryPhoneNumber: string; cemeteryPhoneNumber: string;
} }
export default function addCemetery(addForm: AddCemeteryForm, user: User): Promise<number>; export default function addCemetery(addForm: AddCemeteryForm, user: User): Promise<number>;

View File

@ -1,19 +1,20 @@
import { acquireConnection } from './pool.js' import { acquireConnection } from './pool.js'
export interface AddCemeteryForm { export interface AddCemeteryForm {
cemeteryName: string
cemeteryKey: string
cemeteryDescription: string cemeteryDescription: string
cemeteryKey: string
cemeteryName: string
cemeterySvg: string
cemeteryLatitude: string cemeteryLatitude: string
cemeteryLongitude: string cemeteryLongitude: string
cemeterySvg: string
cemeteryAddress1: string cemeteryAddress1: string
cemeteryAddress2: string cemeteryAddress2: string
cemeteryCity: string cemeteryCity: string
cemeteryProvince: string
cemeteryPostalCode: string cemeteryPostalCode: string
cemeteryProvince: string
cemeteryPhoneNumber: string cemeteryPhoneNumber: string
} }

View File

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

View File

@ -2,8 +2,8 @@ import type { PoolConnection } from 'better-sqlite-pool'
import { import {
type DateString, type DateString,
dateStringToInteger,
type TimeString, type TimeString,
dateStringToInteger,
timeStringToInteger timeStringToInteger
} from '@cityssm/utils-datetime' } from '@cityssm/utils-datetime'
@ -11,35 +11,19 @@ import addOrUpdateContractField from './addOrUpdateContractField.js'
import { acquireConnection } from './pool.js' import { acquireConnection } from './pool.js'
export interface AddContractForm { export interface AddContractForm {
[fieldValue_contractTypeFieldId: `fieldValue_${string}`]: unknown
birthDateString?: '' | DateString
birthPlace?: string
burialSiteId: number | string burialSiteId: number | string
contractEndDateString: '' | DateString
contractStartDateString: '' | DateString
contractTypeId: number | string
[fieldValue_contractTypeFieldId: `fieldValue_${string}`]: unknown
contractTypeFieldIds?: string
committalTypeId?: 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
deceasedName?: string
deceasedPostalCode?: string
deceasedProvince?: string
funeralDateString?: '' | DateString funeralDateString?: '' | DateString
funeralDirectorName?: string funeralDirectorName?: string
funeralHomeId?: number | string funeralHomeId?: number | string
funeralTimeString?: '' | TimeString funeralTimeString?: '' | TimeString
intermentContainerTypeId?: number | string
purchaserAddress1?: string purchaserAddress1?: string
purchaserAddress2?: string purchaserAddress2?: string
@ -50,6 +34,20 @@ export interface AddContractForm {
purchaserPostalCode?: string purchaserPostalCode?: string
purchaserProvince?: string purchaserProvince?: string
purchaserRelationship?: string purchaserRelationship?: string
birthDateString?: '' | DateString
birthPlace?: string
deathAge?: string
deathAgePeriod?: string
deathDateString?: '' | DateString
deathPlace?: string
deceasedAddress1?: string
deceasedAddress2?: string
deceasedCity?: string
deceasedName?: string
deceasedPostalCode?: string
deceasedProvince?: string
intermentContainerTypeId?: number | string
} }
// eslint-disable-next-line complexity // eslint-disable-next-line complexity

View File

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

View File

@ -10,10 +10,10 @@ import {
import { acquireConnection } from './pool.js' import { acquireConnection } from './pool.js'
export interface AddContractCommentForm { export interface AddContractCommentForm {
contractId: string | number comment: string
commentDateString?: DateString commentDateString?: DateString
commentTimeString?: TimeString commentTimeString?: TimeString
comment: string contractId: number | string
} }
export default async function addContractComment( export default async function addContractComment(

View File

@ -2,8 +2,8 @@ import type { PoolConnection } from 'better-sqlite-pool';
export interface AddContractFeeForm { export interface AddContractFeeForm {
contractId: number | string; contractId: number | string;
feeId: number | string; feeId: number | string;
quantity: number | string;
feeAmount?: number | string; feeAmount?: number | string;
quantity: number | string;
taxAmount?: number | string; taxAmount?: number | string;
} }
export default function addContractFee(addFeeForm: AddContractFeeForm, user: User, connectedDatabase?: PoolConnection): Promise<boolean>; export default function addContractFee(addFeeForm: AddContractFeeForm, user: User, connectedDatabase?: PoolConnection): Promise<boolean>;

View File

@ -13,8 +13,9 @@ import { acquireConnection } from './pool.js'
export interface AddContractFeeForm { export interface AddContractFeeForm {
contractId: number | string contractId: number | string
feeId: number | string feeId: number | string
quantity: number | string
feeAmount?: number | string feeAmount?: number | string
quantity: number | string
taxAmount?: number | string taxAmount?: number | string
} }

1
database/deleteBurialSite.d.ts vendored 100644
View File

@ -0,0 +1 @@
export declare function deleteBurialSite(burialSiteId: number, user: User): Promise<boolean>;

View File

@ -0,0 +1,51 @@
import { dateToInteger } from '@cityssm/utils-datetime';
import { acquireConnection } from './pool.js';
export async function deleteBurialSite(burialSiteId, user) {
const database = await acquireConnection();
/*
* Ensure no active contracts reference the burial site
*/
const currentDateInteger = dateToInteger(new Date());
const activeContract = database
.prepare(`select contractId
from Contracts
where burialSiteId = ?
and recordDelete_timeMillis is null
and (contractEndDate is null or contractEndDate >= ?)`)
.pluck()
.get(burialSiteId, currentDateInteger);
if (activeContract !== undefined) {
database.release();
return false;
}
/*
* Delete the burial site
*/
const rightNowMillis = Date.now();
database
.prepare(`update BurialSites
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where burialSiteId = ?
and recordDelete_timeMillis is null`)
.run(user.userName, rightNowMillis, burialSiteId);
/*
* Delete fields and comments
*/
database
.prepare(`update BurialSiteFields
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where burialSiteId = ?
and recordDelete_timeMillis is null`)
.run(user.userName, rightNowMillis, burialSiteId);
database
.prepare(`update BurialSiteComments
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where burialSiteId = ?
and recordDelete_timeMillis is null`)
.run(user.userName, rightNowMillis, burialSiteId);
database.release();
return true;
}

View File

@ -0,0 +1,76 @@
import { dateToInteger } from '@cityssm/utils-datetime'
import { acquireConnection } from './pool.js'
export async function deleteBurialSite(
burialSiteId: number,
user: User
): Promise<boolean> {
const database = await acquireConnection()
/*
* Ensure no active contracts reference the burial site
*/
const currentDateInteger = dateToInteger(new Date())
const activeContract = database
.prepare(
`select contractId
from Contracts
where burialSiteId = ?
and recordDelete_timeMillis is null
and (contractEndDate is null or contractEndDate >= ?)`
)
.pluck()
.get(burialSiteId, currentDateInteger) as number | undefined
if (activeContract !== undefined) {
database.release()
return false
}
/*
* Delete the burial site
*/
const rightNowMillis = Date.now()
database
.prepare(
`update BurialSites
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where burialSiteId = ?
and recordDelete_timeMillis is null`
)
.run(user.userName, rightNowMillis, burialSiteId)
/*
* Delete fields and comments
*/
database
.prepare(
`update BurialSiteFields
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where burialSiteId = ?
and recordDelete_timeMillis is null`
)
.run(user.userName, rightNowMillis, burialSiteId)
database
.prepare(
`update BurialSiteComments
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where burialSiteId = ?
and recordDelete_timeMillis is null`
)
.run(user.userName, rightNowMillis, burialSiteId)
database.release()
return true
}

1
database/deleteCemetery.d.ts vendored 100644
View File

@ -0,0 +1 @@
export default function deleteCemetery(cemeteryId: number | string, user: User): Promise<boolean>;

View File

@ -0,0 +1,61 @@
import { dateToInteger } from '@cityssm/utils-datetime';
import { acquireConnection } from './pool.js';
export default async function deleteCemetery(cemeteryId, user) {
const database = await acquireConnection();
/*
* Ensure no active contracts reference the cemetery
*/
const currentDateInteger = dateToInteger(new Date());
const activeContract = database
.prepare(`select contractId
from Contracts
where burialSiteId in (
select burialSiteId from BurialSites where recordDelete_timeMillis is null and cemeteryId = ?)
and recordDelete_timeMillis is null
and (contractEndDate is null or contractEndDate >= ?)`)
.pluck()
.get(cemeteryId, currentDateInteger);
if (activeContract !== undefined) {
database.release();
return false;
}
/*
* Delete the cemetery
*/
const rightNowMillis = Date.now();
database
.prepare(`update Cemeteries
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where cemeteryId = ?
and recordDelete_timeMillis is null`)
.run(user.userName, rightNowMillis, cemeteryId);
/*
* Delete burial sites, fields, and comments
*/
database
.prepare(`update BurialSites
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where cemeteryId = ?
and recordDelete_timeMillis is null`)
.run(user.userName, rightNowMillis, cemeteryId);
database
.prepare(`update BurialSiteFields
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where burialSiteId in (
select burialSiteId from BurialSites where cemeteryId = ?)
and recordDelete_timeMillis is null`)
.run(user.userName, rightNowMillis, cemeteryId);
database
.prepare(`update BurialSiteComments
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where burialSiteId in (
select burialSiteId from BurialSites where cemeteryId = ?)
and recordDelete_timeMillis is null`)
.run(user.userName, rightNowMillis, cemeteryId);
database.release();
return true;
}

View File

@ -0,0 +1,89 @@
import { dateToInteger } from '@cityssm/utils-datetime'
import { acquireConnection } from './pool.js'
export default async function deleteCemetery(
cemeteryId: number | string,
user: User
): Promise<boolean> {
const database = await acquireConnection()
/*
* Ensure no active contracts reference the cemetery
*/
const currentDateInteger = dateToInteger(new Date())
const activeContract = database
.prepare(
`select contractId
from Contracts
where burialSiteId in (
select burialSiteId from BurialSites where recordDelete_timeMillis is null and cemeteryId = ?)
and recordDelete_timeMillis is null
and (contractEndDate is null or contractEndDate >= ?)`
)
.pluck()
.get(cemeteryId, currentDateInteger) as number | undefined
if (activeContract !== undefined) {
database.release()
return false
}
/*
* Delete the cemetery
*/
const rightNowMillis = Date.now()
database
.prepare(
`update Cemeteries
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where cemeteryId = ?
and recordDelete_timeMillis is null`
)
.run(user.userName, rightNowMillis, cemeteryId)
/*
* Delete burial sites, fields, and comments
*/
database
.prepare(
`update BurialSites
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where cemeteryId = ?
and recordDelete_timeMillis is null`
)
.run(user.userName, rightNowMillis, cemeteryId)
database
.prepare(
`update BurialSiteFields
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where burialSiteId in (
select burialSiteId from BurialSites where cemeteryId = ?)
and recordDelete_timeMillis is null`
)
.run(user.userName, rightNowMillis, cemeteryId)
database
.prepare(
`update BurialSiteComments
set recordDelete_userName = ?,
recordDelete_timeMillis = ?
where burialSiteId in (
select burialSiteId from BurialSites where cemeteryId = ?)
and recordDelete_timeMillis is null`
)
.run(user.userName, rightNowMillis, cemeteryId)
database.release()
return true
}

View File

@ -1,3 +1,3 @@
type RecordTable = 'BurialSiteComments' | 'BurialSites' | 'BurialSiteStatuses' | 'BurialSiteTypeFields' | 'BurialSiteTypes' | 'Cemeteries' | 'ContractComments' | 'Contracts' | 'ContractTypeFields' | 'ContractTypes' | 'FeeCategories' | 'Fees' | 'FuneralHomes' | 'WorkOrderComments' | 'WorkOrderMilestones' | 'WorkOrderMilestoneTypes' | 'WorkOrders' | 'WorkOrderTypes'; type RecordTable = 'BurialSiteComments' | 'BurialSiteStatuses' | 'BurialSiteTypeFields' | 'BurialSiteTypes' | '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

@ -2,11 +2,9 @@ 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([
['BurialSiteComments', 'burialSiteCommentId'], ['BurialSiteComments', 'burialSiteCommentId'],
['BurialSites', 'burialSiteId'],
['BurialSiteStatuses', 'burialSiteStatusId'], ['BurialSiteStatuses', 'burialSiteStatusId'],
['BurialSiteTypeFields', 'burialSiteTypeFieldId'], ['BurialSiteTypeFields', 'burialSiteTypeFieldId'],
['BurialSiteTypes', 'burialSiteTypeId'], ['BurialSiteTypes', 'burialSiteTypeId'],
['Cemeteries', 'cemeteryId'],
['ContractComments', 'contractCommentId'], ['ContractComments', 'contractCommentId'],
['Contracts', 'contractId'], ['Contracts', 'contractId'],
['ContractTypeFields', 'contractTypeFieldId'], ['ContractTypeFields', 'contractTypeFieldId'],
@ -21,9 +19,7 @@ const recordIdColumns = new Map([
['WorkOrderTypes', 'workOrderTypeId'] ['WorkOrderTypes', 'workOrderTypeId']
]); ]);
const relatedTables = new Map([ const relatedTables = new Map([
['BurialSites', ['BurialSiteFields', 'BurialSiteComments']],
['BurialSiteTypes', ['BurialSiteTypeFields']], ['BurialSiteTypes', ['BurialSiteTypeFields']],
['Cemeteries', ['BurialSites']],
['Contracts', ['ContractFields', 'ContractComments']], ['Contracts', ['ContractFields', 'ContractComments']],
['ContractTypes', ['ContractTypePrints', 'ContractTypeFields']], ['ContractTypes', ['ContractTypePrints', 'ContractTypeFields']],
[ [

View File

@ -1,13 +1,12 @@
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' | 'BurialSiteComments'
| 'BurialSites'
| 'BurialSiteStatuses' | 'BurialSiteStatuses'
| 'BurialSiteTypeFields' | 'BurialSiteTypeFields'
| 'BurialSiteTypes' | 'BurialSiteTypes'
| 'Cemeteries'
| 'ContractComments' | 'ContractComments'
| 'Contracts' | 'Contracts'
| 'ContractTypeFields' | 'ContractTypeFields'
@ -23,11 +22,9 @@ type RecordTable =
const recordIdColumns = new Map<RecordTable, string>([ const recordIdColumns = new Map<RecordTable, string>([
['BurialSiteComments', 'burialSiteCommentId'], ['BurialSiteComments', 'burialSiteCommentId'],
['BurialSites', 'burialSiteId'],
['BurialSiteStatuses', 'burialSiteStatusId'], ['BurialSiteStatuses', 'burialSiteStatusId'],
['BurialSiteTypeFields', 'burialSiteTypeFieldId'], ['BurialSiteTypeFields', 'burialSiteTypeFieldId'],
['BurialSiteTypes', 'burialSiteTypeId'], ['BurialSiteTypes', 'burialSiteTypeId'],
['Cemeteries', 'cemeteryId'],
['ContractComments', 'contractCommentId'], ['ContractComments', 'contractCommentId'],
['Contracts', 'contractId'], ['Contracts', 'contractId'],
['ContractTypeFields', 'contractTypeFieldId'], ['ContractTypeFields', 'contractTypeFieldId'],
@ -43,9 +40,7 @@ const recordIdColumns = new Map<RecordTable, string>([
]) ])
const relatedTables = new Map<RecordTable, string[]>([ const relatedTables = new Map<RecordTable, string[]>([
['BurialSites', ['BurialSiteFields', 'BurialSiteComments']],
['BurialSiteTypes', ['BurialSiteTypeFields']], ['BurialSiteTypes', ['BurialSiteTypeFields']],
['Cemeteries', ['BurialSites']],
['Contracts', ['ContractFields', 'ContractComments']], ['Contracts', ['ContractFields', 'ContractComments']],
['ContractTypes', ['ContractTypePrints', 'ContractTypeFields']], ['ContractTypes', ['ContractTypePrints', 'ContractTypeFields']],
[ [

View File

@ -1,12 +1,17 @@
import { deleteRecord } from '../../database/deleteRecord.js'; import { deleteBurialSite } from '../../database/deleteBurialSite.js';
import { clearNextPreviousBurialSiteIdCache } from '../../helpers/burialSites.helpers.js'; import { clearNextPreviousBurialSiteIdCache } from '../../helpers/burialSites.helpers.js';
export default async function handler(request, response) { export default async function handler(request, response) {
const burialSiteId = Number.parseInt(request.body.burialSiteId, 10); const burialSiteId = Number.parseInt(request.body.burialSiteId, 10);
const success = await deleteRecord('BurialSites', burialSiteId, request.session.user); const success = await deleteBurialSite(burialSiteId, request.session.user);
response.json({ response.json({
errorMessage: success
? ''
: 'Note that burial sites with active contracts cannot be deleted.',
success success
}); });
response.on('finish', () => { if (success) {
clearNextPreviousBurialSiteIdCache(burialSiteId); response.on('finish', () => {
}); clearNextPreviousBurialSiteIdCache(burialSiteId);
});
}
} }

View File

@ -1,6 +1,6 @@
import type { Request, Response } from 'express' import type { Request, Response } from 'express'
import { deleteRecord } from '../../database/deleteRecord.js' import { deleteBurialSite } from '../../database/deleteBurialSite.js'
import { clearNextPreviousBurialSiteIdCache } from '../../helpers/burialSites.helpers.js' import { clearNextPreviousBurialSiteIdCache } from '../../helpers/burialSites.helpers.js'
export default async function handler( export default async function handler(
@ -9,17 +9,21 @@ export default async function handler(
): Promise<void> { ): Promise<void> {
const burialSiteId = Number.parseInt(request.body.burialSiteId, 10) const burialSiteId = Number.parseInt(request.body.burialSiteId, 10)
const success = await deleteRecord( const success = await deleteBurialSite(
'BurialSites',
burialSiteId, burialSiteId,
request.session.user as User request.session.user as User
) )
response.json({ response.json({
errorMessage: success
? ''
: 'Note that burial sites with active contracts cannot be deleted.',
success success
}) })
response.on('finish', () => { if (success) {
clearNextPreviousBurialSiteIdCache(burialSiteId) response.on('finish', () => {
}) clearNextPreviousBurialSiteIdCache(burialSiteId)
})
}
} }

View File

@ -1,4 +1,4 @@
import type { Request, Response } from 'express'; import type { Request, Response } from 'express';
export default function handler(request: Request<unknown, unknown, { export default function handler(request: Request<unknown, unknown, {
cemeteryId: string | number; cemeteryId: number | string;
}>, response: Response): Promise<void>; }>, response: Response): Promise<void>;

View File

@ -1,11 +1,16 @@
import { deleteRecord } from '../../database/deleteRecord.js'; import deleteCemetery from '../../database/deleteCemetery.js';
import { clearNextPreviousBurialSiteIdCache } from '../../helpers/burialSites.helpers.js'; import { clearNextPreviousBurialSiteIdCache } from '../../helpers/burialSites.helpers.js';
export default async function handler(request, response) { export default async function handler(request, response) {
const success = await deleteRecord('Cemeteries', request.body.cemeteryId, request.session.user); const success = await deleteCemetery(request.body.cemeteryId, request.session.user);
response.json({ response.json({
errorMessage: success
? ''
: 'Note that cemeteries with active contracts cannot be deleted.',
success success
}); });
response.on('finish', () => { if (success) {
clearNextPreviousBurialSiteIdCache(-1); response.on('finish', () => {
}); clearNextPreviousBurialSiteIdCache(-1);
});
}
} }

View File

@ -1,23 +1,27 @@
import type { Request, Response } from 'express' import type { Request, Response } from 'express'
import { deleteRecord } from '../../database/deleteRecord.js' import deleteCemetery from '../../database/deleteCemetery.js'
import { clearNextPreviousBurialSiteIdCache } from '../../helpers/burialSites.helpers.js' import { clearNextPreviousBurialSiteIdCache } from '../../helpers/burialSites.helpers.js'
export default async function handler( export default async function handler(
request: Request<unknown, unknown, { cemeteryId: string | number }>, request: Request<unknown, unknown, { cemeteryId: number | string }>,
response: Response response: Response
): Promise<void> { ): Promise<void> {
const success = await deleteRecord( const success = await deleteCemetery(
'Cemeteries',
request.body.cemeteryId, request.body.cemeteryId,
request.session.user as User request.session.user as User
) )
response.json({ response.json({
errorMessage: success
? ''
: 'Note that cemeteries with active contracts cannot be deleted.',
success success
}) })
response.on('finish', () => { if (success) {
clearNextPreviousBurialSiteIdCache(-1) response.on('finish', () => {
}) clearNextPreviousBurialSiteIdCache(-1)
})
}
} }

View File

@ -1 +1 @@
export declare function backupDatabase(): Promise<string | false>; export declare function backupDatabase(): Promise<false | string>;

View File

@ -5,7 +5,7 @@ import {
sunriseDB as databasePath sunriseDB as databasePath
} from '../helpers/database.helpers.js' } from '../helpers/database.helpers.js'
export async function backupDatabase(): Promise<string | false> { export async function backupDatabase(): Promise<false | string> {
const databasePathSplit = databasePath.split(/[/\\]/) const databasePathSplit = databasePath.split(/[/\\]/)
const backupDatabasePath = `${backupFolder}/${databasePathSplit.at(-1)}.${Date.now().toString()}` const backupDatabasePath = `${backupFolder}/${databasePathSplit.at(-1)}.${Date.now().toString()}`

View File

@ -1,7 +1,7 @@
import type { BurialSite, Contract, WorkOrder } from '../types/recordTypes.js'; import type { BurialSite, Contract, WorkOrder } from '../types/recordTypes.js';
interface PrintConfig { interface PrintConfig {
title: string;
params: string[]; params: string[];
title: string;
} }
interface ReportData { interface ReportData {
headTitle: string; headTitle: string;
@ -9,8 +9,8 @@ interface ReportData {
contract?: Contract; contract?: Contract;
workOrder?: WorkOrder; workOrder?: WorkOrder;
configFunctions: unknown; configFunctions: unknown;
dateTimeFunctions: unknown;
contractFunctions: unknown; contractFunctions: unknown;
dateTimeFunctions: unknown;
} }
export declare function getScreenPrintConfig(printName: string): PrintConfig | undefined; export declare function getScreenPrintConfig(printName: string): PrintConfig | undefined;
export declare function getPdfPrintConfig(printName: string): PrintConfig | undefined; export declare function getPdfPrintConfig(printName: string): PrintConfig | undefined;

View File

@ -40,12 +40,12 @@ export function getPdfPrintConfig(printName) {
export function getPrintConfig(screenOrPdfPrintName) { export function getPrintConfig(screenOrPdfPrintName) {
const printNameSplit = screenOrPdfPrintName.split('/'); const printNameSplit = screenOrPdfPrintName.split('/');
switch (printNameSplit[0]) { switch (printNameSplit[0]) {
case 'screen': {
return getScreenPrintConfig(printNameSplit[1]);
}
case 'pdf': { case 'pdf': {
return getPdfPrintConfig(printNameSplit[1]); return getPdfPrintConfig(printNameSplit[1]);
} }
case 'screen': {
return getScreenPrintConfig(printNameSplit[1]);
}
} }
return undefined; return undefined;
} }
@ -53,8 +53,8 @@ export async function getReportData(printConfig, requestQuery) {
const reportData = { const reportData = {
headTitle: printConfig.title, headTitle: printConfig.title,
configFunctions, configFunctions,
dateTimeFunctions, contractFunctions,
contractFunctions dateTimeFunctions
}; };
if (printConfig.params.includes('contractId') && if (printConfig.params.includes('contractId') &&
typeof requestQuery.contractId === 'string') { typeof requestQuery.contractId === 'string') {

View File

@ -12,8 +12,8 @@ import * as configFunctions from './config.helpers.js'
import * as contractFunctions from './contracts.helpers.js' import * as contractFunctions from './contracts.helpers.js'
interface PrintConfig { interface PrintConfig {
title: string
params: string[] params: string[]
title: string
} }
interface ReportData { interface ReportData {
@ -24,8 +24,8 @@ interface ReportData {
workOrder?: WorkOrder workOrder?: WorkOrder
configFunctions: unknown configFunctions: unknown
dateTimeFunctions: unknown
contractFunctions: unknown contractFunctions: unknown
dateTimeFunctions: unknown
} }
const screenPrintConfigs: Record<string, PrintConfig> = { const screenPrintConfigs: Record<string, PrintConfig> = {
@ -72,12 +72,12 @@ export function getPrintConfig(
const printNameSplit = screenOrPdfPrintName.split('/') const printNameSplit = screenOrPdfPrintName.split('/')
switch (printNameSplit[0]) { switch (printNameSplit[0]) {
case 'screen': {
return getScreenPrintConfig(printNameSplit[1])
}
case 'pdf': { case 'pdf': {
return getPdfPrintConfig(printNameSplit[1]) return getPdfPrintConfig(printNameSplit[1])
} }
case 'screen': {
return getScreenPrintConfig(printNameSplit[1])
}
} }
return undefined return undefined
@ -89,9 +89,10 @@ export async function getReportData(
): Promise<ReportData> { ): Promise<ReportData> {
const reportData: ReportData = { const reportData: ReportData = {
headTitle: printConfig.title, headTitle: printConfig.title,
configFunctions, configFunctions,
dateTimeFunctions, contractFunctions,
contractFunctions dateTimeFunctions
} }
if ( if (

View File

@ -1,10 +1,10 @@
type BurialSiteNameSearchType = 'startsWith' | 'endsWith' | ''; type BurialSiteNameSearchType = '' | 'endsWith' | 'startsWith';
type ContractTime = '' | 'current' | 'future' | 'past';
interface WhereClauseReturn { interface WhereClauseReturn {
sqlWhereClause: string;
sqlParameters: unknown[]; sqlParameters: unknown[];
sqlWhereClause: string;
} }
export declare function getBurialSiteNameWhereClause(burialSiteName?: string, burialSiteNameSearchType?: BurialSiteNameSearchType, burialSitesTableAlias?: string): WhereClauseReturn; export declare function getBurialSiteNameWhereClause(burialSiteName?: string, burialSiteNameSearchType?: BurialSiteNameSearchType, burialSitesTableAlias?: string): WhereClauseReturn;
type ContractTime = '' | 'current' | 'past' | 'future';
export declare function getContractTimeWhereClause(contractTime: ContractTime | undefined, contractsTableAlias?: string): WhereClauseReturn; export declare function getContractTimeWhereClause(contractTime: ContractTime | undefined, contractsTableAlias?: string): WhereClauseReturn;
export declare function getDeceasedNameWhereClause(deceasedName?: string, tableAlias?: string): WhereClauseReturn; export declare function getDeceasedNameWhereClause(deceasedName?: string, tableAlias?: string): WhereClauseReturn;
export {}; export {};

View File

@ -4,13 +4,13 @@ export function getBurialSiteNameWhereClause(burialSiteName = '', burialSiteName
const sqlParameters = []; const sqlParameters = [];
if (burialSiteName !== '') { if (burialSiteName !== '') {
switch (burialSiteNameSearchType) { switch (burialSiteNameSearchType) {
case 'startsWith': { case 'endsWith': {
sqlWhereClause += ` and ${burialSitesTableAlias}.burialSiteName like ? || '%'`; sqlWhereClause += ` and ${burialSitesTableAlias}.burialSiteName like '%' || ?`;
sqlParameters.push(burialSiteName); sqlParameters.push(burialSiteName);
break; break;
} }
case 'endsWith': { case 'startsWith': {
sqlWhereClause += ` and ${burialSitesTableAlias}.burialSiteName like '%' || ?`; sqlWhereClause += ` and ${burialSitesTableAlias}.burialSiteName like ? || '%'`;
sqlParameters.push(burialSiteName); sqlParameters.push(burialSiteName);
break; break;
} }
@ -29,8 +29,8 @@ export function getBurialSiteNameWhereClause(burialSiteName = '', burialSiteName
} }
} }
return { return {
sqlWhereClause, sqlParameters,
sqlParameters sqlWhereClause
}; };
} }
export function getContractTimeWhereClause(contractTime, contractsTableAlias = 'o') { export function getContractTimeWhereClause(contractTime, contractsTableAlias = 'o') {
@ -45,22 +45,22 @@ export function getContractTimeWhereClause(contractTime, contractsTableAlias = '
sqlParameters.push(currentDateString, currentDateString); sqlParameters.push(currentDateString, currentDateString);
break; break;
} }
case 'past': {
sqlWhereClause +=
` and ${contractsTableAlias}.contractEndDate < ?`;
sqlParameters.push(currentDateString);
break;
}
case 'future': { case 'future': {
sqlWhereClause += sqlWhereClause +=
` and ${contractsTableAlias}.contractStartDate > ?`; ` and ${contractsTableAlias}.contractStartDate > ?`;
sqlParameters.push(currentDateString); sqlParameters.push(currentDateString);
break; break;
} }
case 'past': {
sqlWhereClause +=
` and ${contractsTableAlias}.contractEndDate < ?`;
sqlParameters.push(currentDateString);
break;
}
} }
return { return {
sqlWhereClause, sqlParameters,
sqlParameters sqlWhereClause
}; };
} }
export function getDeceasedNameWhereClause(deceasedName = '', tableAlias = 'o') { export function getDeceasedNameWhereClause(deceasedName = '', tableAlias = 'o') {
@ -77,7 +77,7 @@ export function getDeceasedNameWhereClause(deceasedName = '', tableAlias = 'o')
sqlParameters.push(namePiece); sqlParameters.push(namePiece);
} }
return { return {
sqlWhereClause, sqlParameters,
sqlParameters sqlWhereClause
}; };
} }

View File

@ -1,10 +1,12 @@
import { dateToInteger } from '@cityssm/utils-datetime' import { dateToInteger } from '@cityssm/utils-datetime'
type BurialSiteNameSearchType = 'startsWith' | 'endsWith' | '' type BurialSiteNameSearchType = '' | 'endsWith' | 'startsWith'
type ContractTime = '' | 'current' | 'future' | 'past'
interface WhereClauseReturn { interface WhereClauseReturn {
sqlWhereClause: string
sqlParameters: unknown[] sqlParameters: unknown[]
sqlWhereClause: string
} }
export function getBurialSiteNameWhereClause( export function getBurialSiteNameWhereClause(
@ -17,13 +19,13 @@ export function getBurialSiteNameWhereClause(
if (burialSiteName !== '') { if (burialSiteName !== '') {
switch (burialSiteNameSearchType) { switch (burialSiteNameSearchType) {
case 'startsWith': { case 'endsWith': {
sqlWhereClause += ` and ${burialSitesTableAlias}.burialSiteName like ? || '%'` sqlWhereClause += ` and ${burialSitesTableAlias}.burialSiteName like '%' || ?`
sqlParameters.push(burialSiteName) sqlParameters.push(burialSiteName)
break break
} }
case 'endsWith': { case 'startsWith': {
sqlWhereClause += ` and ${burialSitesTableAlias}.burialSiteName like '%' || ?` sqlWhereClause += ` and ${burialSitesTableAlias}.burialSiteName like ? || '%'`
sqlParameters.push(burialSiteName) sqlParameters.push(burialSiteName)
break break
} }
@ -47,13 +49,11 @@ export function getBurialSiteNameWhereClause(
} }
return { return {
sqlWhereClause, sqlParameters,
sqlParameters sqlWhereClause
} }
} }
type ContractTime = '' | 'current' | 'past' | 'future'
export function getContractTimeWhereClause( export function getContractTimeWhereClause(
contractTime: ContractTime | undefined, contractTime: ContractTime | undefined,
contractsTableAlias = 'o' contractsTableAlias = 'o'
@ -72,24 +72,24 @@ export function getContractTimeWhereClause(
break break
} }
case 'past': {
sqlWhereClause +=
` and ${contractsTableAlias}.contractEndDate < ?`
sqlParameters.push(currentDateString)
break
}
case 'future': { case 'future': {
sqlWhereClause += sqlWhereClause +=
` and ${contractsTableAlias}.contractStartDate > ?` ` and ${contractsTableAlias}.contractStartDate > ?`
sqlParameters.push(currentDateString) sqlParameters.push(currentDateString)
break break
} }
case 'past': {
sqlWhereClause +=
` and ${contractsTableAlias}.contractEndDate < ?`
sqlParameters.push(currentDateString)
break
}
} }
return { return {
sqlWhereClause, sqlParameters,
sqlParameters sqlWhereClause
} }
} }
@ -115,7 +115,7 @@ export function getDeceasedNameWhereClause(
} }
return { return {
sqlWhereClause, sqlParameters,
sqlParameters sqlWhereClause
} }
} }

8
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": "^22.1.0", "eslint-config-cityssm": "^22.2.2",
"nodemon": "^3.1.9", "nodemon": "^3.1.9",
"prettier-config-cityssm": "^1.0.0" "prettier-config-cityssm": "^1.0.0"
}, },
@ -4915,9 +4915,9 @@
} }
}, },
"node_modules/eslint-config-cityssm": { "node_modules/eslint-config-cityssm": {
"version": "22.1.0", "version": "22.2.2",
"resolved": "https://registry.npmjs.org/eslint-config-cityssm/-/eslint-config-cityssm-22.1.0.tgz", "resolved": "https://registry.npmjs.org/eslint-config-cityssm/-/eslint-config-cityssm-22.2.2.tgz",
"integrity": "sha512-JfF7dzleImnd78sM0+NpvZpKgT+NvB4SlFXd/gXf0t1F1HQbaZftEL7zJ9eATWklF9lcj6tiYMDaZekHVuFaJw==", "integrity": "sha512-gPPoAb1REP5Fob9poF6OEn/+fr4oflx7aa09gLZ7Nab28bl4Jsk/Pyr+KvAw39MXVdFRLPfCV1Rly0enpGlZmg==",
"dev": true, "dev": true,
"license": "Unlicense", "license": "Unlicense",
"dependencies": { "dependencies": {

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": "^22.1.0", "eslint-config-cityssm": "^22.2.2",
"nodemon": "^3.1.9", "nodemon": "^3.1.9",
"prettier-config-cityssm": "^1.0.0" "prettier-config-cityssm": "^1.0.0"
}, },

View File

@ -52,9 +52,9 @@ declare const exports: Record<string, unknown>
formElement, formElement,
(rawResponseJSON) => { (rawResponseJSON) => {
const responseJSON = rawResponseJSON as { const responseJSON = rawResponseJSON as {
success: boolean
burialSiteId?: number burialSiteId?: number
errorMessage?: string errorMessage?: string
success: boolean
} }
if (responseJSON.success) { if (responseJSON.success) {
@ -106,8 +106,8 @@ declare const exports: Record<string, unknown>
}, },
(rawResponseJSON) => { (rawResponseJSON) => {
const responseJSON = rawResponseJSON as { const responseJSON = rawResponseJSON as {
success: boolean
errorMessage?: string errorMessage?: string
success: boolean
} }
if (responseJSON.success) { if (responseJSON.success) {
@ -309,9 +309,9 @@ declare const exports: Record<string, unknown>
editFormElement, editFormElement,
(rawResponseJSON) => { (rawResponseJSON) => {
const responseJSON = rawResponseJSON as { const responseJSON = rawResponseJSON as {
success: boolean
errorMessage?: string
burialSiteComments: BurialSiteComment[] burialSiteComments: BurialSiteComment[]
errorMessage?: string
success: boolean
} }
if (responseJSON.success) { if (responseJSON.success) {

View File

@ -54,9 +54,10 @@ declare const exports: Record<string, unknown>
formElement, formElement,
(rawResponseJSON) => { (rawResponseJSON) => {
const responseJSON = rawResponseJSON as { const responseJSON = rawResponseJSON as {
success: boolean
contractId?: number
errorMessage?: string errorMessage?: string
success: boolean
contractId?: number
} }
if (responseJSON.success) { if (responseJSON.success) {