brf/server/services/admissions/queries.ts
2025-12-18 07:31:37 +01:00

96 lines
2.8 KiB
TypeScript

import type EventEmitter from 'node:events'
import type { Knex } from 'knex'
import _ from 'lodash'
import RestQueriesFactory from '../../lib/knex_rest_queries.ts'
import type { NewAdmission } from './types.ts'
export const columns = ['id', 'regex', 'createdAt', 'createdById', 'modifiedAt', 'modifiedById']
export const Selects = (knex: Knex) => ({
roles: knex
.select(knex.raw('json_agg(roles)'))
.from(
knex
.select('id', 'name')
.from('role')
.innerJoin('admissions_roles', 'role.id', 'admissions_roles.role_id')
.where('admissions_roles.admission_id', knex.ref('admission.id'))
.orderBy('name')
.as('roles'),
),
createdBy: knex
.select(knex.raw('row_to_json("user")'))
.from(knex.select('id', 'email').from('user').where('id', knex.ref('admission.created_by_id')).as('user')),
})
export default ({ knex, emitter }: { emitter: EventEmitter; knex: Knex }) => {
const selects = Selects(knex)
const queries = RestQueriesFactory({
knex,
emitter,
table: 'admission',
columns,
selects,
})
return {
...queries,
create(json: NewAdmission, client = knex) {
return client.transaction(async (trx) => {
const admission = await queries.create(_.omit(json, 'roles'), trx)
const roles = json.roles.map((role) => ({
admission_id: admission.id,
role_id: role,
}))
await trx.table('admissions_roles').insert(roles)
return queries.findById(admission.id, trx)
})
},
update(id: number, json: NewAdmission, client = knex) {
return client.transaction(async (trx) => {
await queries.update(id, _.omit(json, ['roles']), trx)
// TODO decide how to handle this, ie should an empty array delete all?
if (json.roles?.length) {
await trx.table('admissions_roles').delete().where('admission_id', id).whereNotIn('role_id', json.roles)
await trx.raw(
`INSERT INTO admissions_roles(admission_id, role_id)
SELECT :admissionId, role_ids FROM unnest(:roleIds::int[]) AS role_ids WHERE NOT EXISTS
(SELECT 1 FROM admissions_roles WHERE admission_id = :admissionId AND role_id = role_ids)`,
{ admissionId: id, roleIds: json.roles },
)
}
return queries.findById(id, trx)
})
},
findMatches(email: string, client = knex) {
return client('admission')
.select([...columns, selects])
.then((admissions) => {
if (admissions) {
admissions = admissions.filter((admission) => {
const regex = new RegExp(admission.regex)
return regex.test(email)
})
// if (!admissions.length) admissions = undefined
}
return admissions
})
},
}
}