ensure burial site names remain distinct

pull/3/head
Dan Gowans 2025-03-21 09:12:31 -04:00
parent d7f4cb4d3b
commit 80fa36853d
12 changed files with 212 additions and 69 deletions

View File

@ -13,4 +13,11 @@ export interface AddBurialSiteForm {
burialSiteTypeFieldIds?: string; burialSiteTypeFieldIds?: string;
[fieldValue_burialSiteTypeFieldId: string]: unknown; [fieldValue_burialSiteTypeFieldId: string]: unknown;
} }
/**
* Creates a new burial site.
* @param burialSiteForm - The new burial site's information
* @param user - The user making the request
* @returns The new burial site's id.
* @throws If an active burial site with the same name already exists.
*/
export default function addBurialSite(burialSiteForm: AddBurialSiteForm, user: User): Promise<number>; export default function addBurialSite(burialSiteForm: AddBurialSiteForm, user: User): Promise<number>;

View File

@ -2,11 +2,32 @@ import { buildBurialSiteName } from '../helpers/burialSites.helpers.js';
import addOrUpdateBurialSiteField from './addOrUpdateBurialSiteField.js'; import addOrUpdateBurialSiteField from './addOrUpdateBurialSiteField.js';
import getCemetery from './getCemetery.js'; import getCemetery from './getCemetery.js';
import { acquireConnection } from './pool.js'; import { acquireConnection } from './pool.js';
/**
* Creates a new burial site.
* @param burialSiteForm - The new burial site's information
* @param user - The user making the request
* @returns The new burial site's id.
* @throws If an active burial site with the same name already exists.
*/
export default async function addBurialSite(burialSiteForm, user) { export default async function addBurialSite(burialSiteForm, user) {
const database = await acquireConnection(); const database = await acquireConnection();
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
const cemetery = burialSiteForm.cemeteryId === '' ? undefined : await getCemetery(burialSiteForm.cemeteryId, database); const cemetery = burialSiteForm.cemeteryId === ''
? undefined
: await getCemetery(burialSiteForm.cemeteryId, database);
const burialSiteName = buildBurialSiteName(cemetery?.cemeteryKey, burialSiteForm); const burialSiteName = buildBurialSiteName(cemetery?.cemeteryKey, burialSiteForm);
// Ensure no active burial sites share the same name
const existingBurialSite = database
.prepare(`select burialSiteId
from BurialSites
where burialSiteName = ?
and recordDelete_timeMillis is null`)
.pluck()
.get(burialSiteName);
if (existingBurialSite !== undefined) {
database.release();
throw new Error('An active burial site with that name already exists.');
}
const result = database const result = database
.prepare(`insert into BurialSites ( .prepare(`insert into BurialSites (
burialSiteNameSegment1, burialSiteNameSegment1,
@ -24,7 +45,13 @@ export default async function addBurialSite(burialSiteForm, user) {
values (?, ?, values (?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?)`) ?, ?, ?, ?)`)
.run(burialSiteForm.burialSiteNameSegment1, burialSiteForm.burialSiteNameSegment2 ?? '', burialSiteForm.burialSiteNameSegment3 ?? '', burialSiteForm.burialSiteNameSegment4 ?? '', burialSiteForm.burialSiteNameSegment5 ?? '', burialSiteName, burialSiteForm.burialSiteTypeId, burialSiteForm.burialSiteStatusId === '' ? undefined : burialSiteForm.burialSiteStatusId, burialSiteForm.cemeteryId === '' ? undefined : burialSiteForm.cemeteryId, burialSiteForm.cemeterySvgId, burialSiteForm.burialSiteLatitude === '' ? undefined : burialSiteForm.burialSiteLatitude, burialSiteForm.burialSiteLongitude === '' ? undefined : burialSiteForm.burialSiteLongitude, user.userName, rightNowMillis, user.userName, rightNowMillis); .run(burialSiteForm.burialSiteNameSegment1, burialSiteForm.burialSiteNameSegment2 ?? '', burialSiteForm.burialSiteNameSegment3 ?? '', burialSiteForm.burialSiteNameSegment4 ?? '', burialSiteForm.burialSiteNameSegment5 ?? '', burialSiteName, burialSiteForm.burialSiteTypeId, burialSiteForm.burialSiteStatusId === ''
? undefined
: burialSiteForm.burialSiteStatusId, burialSiteForm.cemeteryId === '' ? undefined : burialSiteForm.cemeteryId, burialSiteForm.cemeterySvgId, burialSiteForm.burialSiteLatitude === ''
? undefined
: burialSiteForm.burialSiteLatitude, burialSiteForm.burialSiteLongitude === ''
? undefined
: burialSiteForm.burialSiteLongitude, user.userName, rightNowMillis, user.userName, rightNowMillis);
const burialSiteId = result.lastInsertRowid; const burialSiteId = result.lastInsertRowid;
const burialSiteTypeFieldIds = (burialSiteForm.burialSiteTypeFieldIds ?? '').split(','); const burialSiteTypeFieldIds = (burialSiteForm.burialSiteTypeFieldIds ?? '').split(',');
for (const burialSiteTypeFieldId of burialSiteTypeFieldIds) { for (const burialSiteTypeFieldId of burialSiteTypeFieldIds) {

View File

@ -24,6 +24,13 @@ export interface AddBurialSiteForm {
[fieldValue_burialSiteTypeFieldId: string]: unknown [fieldValue_burialSiteTypeFieldId: string]: unknown
} }
/**
* Creates a new burial site.
* @param burialSiteForm - The new burial site's information
* @param user - The user making the request
* @returns The new burial site's id.
* @throws If an active burial site with the same name already exists.
*/
export default async function addBurialSite( export default async function addBurialSite(
burialSiteForm: AddBurialSiteForm, burialSiteForm: AddBurialSiteForm,
user: User user: User
@ -32,11 +39,32 @@ export default async function addBurialSite(
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
const cemetery = burialSiteForm.cemeteryId === '' ? undefined : await getCemetery(burialSiteForm.cemeteryId, database) const cemetery =
burialSiteForm.cemeteryId === ''
? undefined
: await getCemetery(burialSiteForm.cemeteryId, database)
const burialSiteName = buildBurialSiteName( const burialSiteName = buildBurialSiteName(
cemetery?.cemeteryKey, cemetery?.cemeteryKey,
burialSiteForm) burialSiteForm
)
// Ensure no active burial sites share the same name
const existingBurialSite = database
.prepare(
`select burialSiteId
from BurialSites
where burialSiteName = ?
and recordDelete_timeMillis is null`
)
.pluck()
.get(burialSiteName) as number | undefined
if (existingBurialSite !== undefined) {
database.release()
throw new Error('An active burial site with that name already exists.')
}
const result = database const result = database
.prepare( .prepare(
@ -65,11 +93,17 @@ export default async function addBurialSite(
burialSiteForm.burialSiteNameSegment5 ?? '', burialSiteForm.burialSiteNameSegment5 ?? '',
burialSiteName, burialSiteName,
burialSiteForm.burialSiteTypeId, burialSiteForm.burialSiteTypeId,
burialSiteForm.burialSiteStatusId === '' ? undefined : burialSiteForm.burialSiteStatusId, burialSiteForm.burialSiteStatusId === ''
? undefined
: burialSiteForm.burialSiteStatusId,
burialSiteForm.cemeteryId === '' ? undefined : burialSiteForm.cemeteryId, burialSiteForm.cemeteryId === '' ? undefined : burialSiteForm.cemeteryId,
burialSiteForm.cemeterySvgId, burialSiteForm.cemeterySvgId,
burialSiteForm.burialSiteLatitude === '' ? undefined : burialSiteForm.burialSiteLatitude, burialSiteForm.burialSiteLatitude === ''
burialSiteForm.burialSiteLongitude === '' ? undefined : burialSiteForm.burialSiteLongitude, ? undefined
: burialSiteForm.burialSiteLatitude,
burialSiteForm.burialSiteLongitude === ''
? undefined
: burialSiteForm.burialSiteLongitude,
user.userName, user.userName,
rightNowMillis, rightNowMillis,
user.userName, user.userName,
@ -78,10 +112,14 @@ export default async function addBurialSite(
const burialSiteId = result.lastInsertRowid as number const burialSiteId = result.lastInsertRowid as number
const burialSiteTypeFieldIds = (burialSiteForm.burialSiteTypeFieldIds ?? '').split(',') const burialSiteTypeFieldIds = (
burialSiteForm.burialSiteTypeFieldIds ?? ''
).split(',')
for (const burialSiteTypeFieldId of burialSiteTypeFieldIds) { for (const burialSiteTypeFieldId of burialSiteTypeFieldIds) {
const fieldValue = burialSiteForm[`burialSiteFieldValue_${burialSiteTypeFieldId}`] as string | undefined const fieldValue = burialSiteForm[
`burialSiteFieldValue_${burialSiteTypeFieldId}`
] as string | undefined
if ((fieldValue ?? '') !== '') { if ((fieldValue ?? '') !== '') {
await addOrUpdateBurialSiteField( await addOrUpdateBurialSiteField(

View File

@ -91,11 +91,7 @@ export default async function getBurialSites(filters, options, connectedDatabase
group by burialSiteId) o on l.burialSiteId = o.burialSiteId` group by burialSiteId) o on l.burialSiteId = o.burialSiteId`
: ''} : ''}
${sqlWhereClause} ${sqlWhereClause}
order by l.burialSiteNameSegment1, order by l.burialSiteName,
l.burialSiteNameSegment2,
l.burialSiteNameSegment3,
l.burialSiteNameSegment4,
l.burialSiteNameSegment5,
l.burialSiteId l.burialSiteId
${options.limit === -1 ${options.limit === -1
? '' ? ''

View File

@ -148,11 +148,7 @@ export default async function getBurialSites(
: '' : ''
} }
${sqlWhereClause} ${sqlWhereClause}
order by l.burialSiteNameSegment1, order by l.burialSiteName,
l.burialSiteNameSegment2,
l.burialSiteNameSegment3,
l.burialSiteNameSegment4,
l.burialSiteNameSegment5,
l.burialSiteId l.burialSiteId
${ ${
options.limit === -1 options.limit === -1

View File

@ -14,5 +14,12 @@ export interface UpdateBurialSiteForm {
burialSiteTypeFieldIds?: string; burialSiteTypeFieldIds?: string;
[fieldValue_burialSiteTypeFieldId: string]: unknown; [fieldValue_burialSiteTypeFieldId: string]: unknown;
} }
/**
* Updates a burial site.
* @param updateForm - The burial site's updated information
* @param user - The user making the request
* @returns True if the burial site was updated.
* @throws If an active burial site with the same name already exists.
*/
export default function updateBurialSite(updateForm: UpdateBurialSiteForm, user: User): Promise<boolean>; export default function updateBurialSite(updateForm: UpdateBurialSiteForm, user: User): Promise<boolean>;
export declare function updateBurialSiteStatus(burialSiteId: number | string, burialSiteStatusId: number | string, user: User): Promise<boolean>; export declare function updateBurialSiteStatus(burialSiteId: number | string, burialSiteStatusId: number | string, user: User): Promise<boolean>;

View File

@ -3,12 +3,32 @@ import addOrUpdateBurialSiteField from './addOrUpdateBurialSiteField.js';
import deleteBurialSiteField from './deleteBurialSiteField.js'; import deleteBurialSiteField from './deleteBurialSiteField.js';
import getCemetery from './getCemetery.js'; import getCemetery from './getCemetery.js';
import { acquireConnection } from './pool.js'; import { acquireConnection } from './pool.js';
/**
* Updates a burial site.
* @param updateForm - The burial site's updated information
* @param user - The user making the request
* @returns True if the burial site was updated.
* @throws If an active burial site with the same name already exists.
*/
export default async function updateBurialSite(updateForm, user) { export default async function updateBurialSite(updateForm, user) {
const database = await acquireConnection(); const database = await acquireConnection();
const cemetery = updateForm.cemeteryId === '' const cemetery = updateForm.cemeteryId === ''
? undefined ? undefined
: await getCemetery(updateForm.cemeteryId, database); : await getCemetery(updateForm.cemeteryId, database);
const burialSiteName = buildBurialSiteName(cemetery?.cemeteryKey, updateForm); const burialSiteName = buildBurialSiteName(cemetery?.cemeteryKey, updateForm);
// Ensure no active burial sites share the same name
const existingBurialSite = database
.prepare(`select burialSiteId
from BurialSites
where burialSiteName = ?
and burialSiteId <> ?
and recordDelete_timeMillis is null`)
.pluck()
.get(burialSiteName, updateForm.burialSiteId);
if (existingBurialSite !== undefined) {
database.release();
throw new Error('An active burial site with that name already exists.');
}
const result = database const result = database
.prepare(`update BurialSites .prepare(`update BurialSites
set burialSiteNameSegment1 = ?, set burialSiteNameSegment1 = ?,

View File

@ -27,6 +27,13 @@ export interface UpdateBurialSiteForm {
[fieldValue_burialSiteTypeFieldId: string]: unknown [fieldValue_burialSiteTypeFieldId: string]: unknown
} }
/**
* Updates a burial site.
* @param updateForm - The burial site's updated information
* @param user - The user making the request
* @returns True if the burial site was updated.
* @throws If an active burial site with the same name already exists.
*/
export default async function updateBurialSite( export default async function updateBurialSite(
updateForm: UpdateBurialSiteForm, updateForm: UpdateBurialSiteForm,
user: User user: User
@ -34,14 +41,29 @@ export default async function updateBurialSite(
const database = await acquireConnection() const database = await acquireConnection()
const cemetery = const cemetery =
updateForm.cemeteryId === '' updateForm.cemeteryId === ''
? undefined ? undefined
: await getCemetery(updateForm.cemeteryId, database) : await getCemetery(updateForm.cemeteryId, database)
const burialSiteName = buildBurialSiteName( const burialSiteName = buildBurialSiteName(cemetery?.cemeteryKey, updateForm)
cemetery?.cemeteryKey,
updateForm // Ensure no active burial sites share the same name
)
const existingBurialSite = database
.prepare(
`select burialSiteId
from BurialSites
where burialSiteName = ?
and burialSiteId <> ?
and recordDelete_timeMillis is null`
)
.pluck()
.get(burialSiteName, updateForm.burialSiteId) as number | undefined
if (existingBurialSite !== undefined) {
database.release()
throw new Error('An active burial site with that name already exists.')
}
const result = database const result = database
.prepare( .prepare(

View File

@ -1,12 +1,20 @@
import addBurialSite from '../../database/addBurialSite.js'; import addBurialSite from '../../database/addBurialSite.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 = await addBurialSite(request.body, request.session.user); try {
response.json({ const burialSiteId = await addBurialSite(request.body, request.session.user);
success: true, response.json({
burialSiteId success: true,
}); burialSiteId
response.on('finish', () => { });
clearNextPreviousBurialSiteIdCache(-1); response.on('finish', () => {
}); clearNextPreviousBurialSiteIdCache(-1);
});
}
catch (error) {
response.json({
success: false,
errorMessage: error.message
});
}
} }

View File

@ -9,17 +9,24 @@ export default async function handler(
request: Request<unknown, unknown, AddBurialSiteForm>, request: Request<unknown, unknown, AddBurialSiteForm>,
response: Response response: Response
): Promise<void> { ): Promise<void> {
const burialSiteId = await addBurialSite( try {
request.body, const burialSiteId = await addBurialSite(
request.session.user as User request.body,
) request.session.user as User
)
response.json({ response.json({
success: true, success: true,
burialSiteId burialSiteId
}) })
response.on('finish', () => { response.on('finish', () => {
clearNextPreviousBurialSiteIdCache(-1) clearNextPreviousBurialSiteIdCache(-1)
}) })
} catch (error) {
response.json({
success: false,
errorMessage: (error as Error).message
})
}
} }

View File

@ -1,15 +1,23 @@
import updateBurialSite from '../../database/updateBurialSite.js'; import updateBurialSite from '../../database/updateBurialSite.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 updateBurialSite(request.body, request.session.user); try {
const burialSiteId = typeof request.body.burialSiteId === 'string' const success = await updateBurialSite(request.body, request.session.user);
? Number.parseInt(request.body.burialSiteId, 10) const burialSiteId = typeof request.body.burialSiteId === 'string'
: request.body.burialSiteId; ? Number.parseInt(request.body.burialSiteId, 10)
response.json({ : request.body.burialSiteId;
success, response.json({
burialSiteId success,
}); burialSiteId
response.on('finish', () => { });
clearNextPreviousBurialSiteIdCache(burialSiteId); response.on('finish', () => {
}); clearNextPreviousBurialSiteIdCache(burialSiteId);
});
}
catch (error) {
response.json({
success: false,
errorMessage: error.message
});
}
} }

View File

@ -9,22 +9,29 @@ export default async function handler(
request: Request<unknown, unknown, UpdateBurialSiteForm>, request: Request<unknown, unknown, UpdateBurialSiteForm>,
response: Response response: Response
): Promise<void> { ): Promise<void> {
const success = await updateBurialSite( try {
request.body, const success = await updateBurialSite(
request.session.user as User request.body,
) request.session.user as User
)
const burialSiteId = const burialSiteId =
typeof request.body.burialSiteId === 'string' typeof request.body.burialSiteId === 'string'
? Number.parseInt(request.body.burialSiteId, 10) ? Number.parseInt(request.body.burialSiteId, 10)
: request.body.burialSiteId : request.body.burialSiteId
response.json({ response.json({
success, success,
burialSiteId burialSiteId
}) })
response.on('finish', () => { response.on('finish', () => {
clearNextPreviousBurialSiteIdCache(burialSiteId) clearNextPreviousBurialSiteIdCache(burialSiteId)
}) })
} catch (error) {
response.json({
success: false,
errorMessage: (error as Error).message
})
}
} }